Skip to content
Snippets Groups Projects
Verified Commit eb2ba070 authored by Miniontoby's avatar Miniontoby :writing_hand_tone1:
Browse files

Updated test files and integrated some of it

parent ecc413d6
No related branches found
No related tags found
No related merge requests found
Pipeline #122674 passed
...@@ -33,19 +33,25 @@ class Modal { ...@@ -33,19 +33,25 @@ class Modal {
let { id, title, body, extrabutton, closebutton, opener } = opts; let { id, title, body, extrabutton, closebutton, opener } = opts;
if (extrabutton != '') body += `<button id="${extrabutton.toLowerCase()}Button">${extrabutton}</button>` if (extrabutton != '') body += `<button id="${extrabutton.toLowerCase()}Button">${extrabutton}</button>`
let modalText = `<div id="${id}Modal" class="modal"><h2>${title}</h2>${body}<button id="${closebutton.toLowerCase()}Button">${closebutton}</button></div>`; let modalText = `<div id="${id}Modal" class="modal"><h2>${title}</h2>${body}<button id="${closebutton.toLowerCase()}Button">${closebutton}</button></div>`;
document.body.insertAdjacentHTML('beforeEnd', modalText); this.element = document.querySelector(`#${id}Modal`);
if (this.element) this.element.outerHTML = modalText;
else document.body.insertAdjacentHTML('beforeEnd', modalText);
this.element = document.querySelector(`#${id}Modal`); this.element = document.querySelector(`#${id}Modal`);
if (opener) document.querySelector(opener).addEventListener('click', () => this.open()); if (opener) document.querySelector(opener).addEventListener('click', () => this.open());
this.element.querySelector(`#${closebutton.toLowerCase()}Button`)?.addEventListener('click', () => this.close()); this.element.querySelector(`#${closebutton.toLowerCase()}Button`)?.addEventListener('click', () => this.close());
this.opened = false;
} }
open () { open () {
this.element.style.display = 'block'; this.element.style.display = 'block';
document.querySelector('#modalBackDrop').style.display = 'block'; document.querySelector('#modalBackDrop').style.display = 'block';
this.opened = true;
} }
close () { close () {
this.element.style.display = 'none'; this.element.style.display = 'none';
document.querySelector('#modalBackDrop').style.display = 'none'; document.querySelector('#modalBackDrop').style.display = 'none';
this.opened = false;
} }
} }
...@@ -55,7 +61,9 @@ window.modals['settings'] = new Modal({ id: "settings", title: "Settings", body: ...@@ -55,7 +61,9 @@ window.modals['settings'] = new Modal({ id: "settings", title: "Settings", body:
document.body.insertAdjacentHTML('beforeEnd', '<div id="modalBackDrop"></div>'); document.body.insertAdjacentHTML('beforeEnd', '<div id="modalBackDrop"></div>');
document.querySelector("#exportCalendar").addEventListener("click", () => ical_download()); document.querySelector("#exportCalendar").addEventListener("click", () => ical_download());
const eventTitleInput = document.getElementById('eventTitleInput'); const uppercaseFirstChar = (string) => string[0].toLocaleUpperCase() + string.substring(1);
let eventTitleInput = document.getElementById('eventTitleInput');
function openModal(date) { function openModal(date) {
clicked = date; clicked = date;
...@@ -91,7 +99,7 @@ function load() { ...@@ -91,7 +99,7 @@ function load() {
const paddingDays = weekdays.indexOf(dateString.split(', ')[0]); const paddingDays = weekdays.indexOf(dateString.split(', ')[0]);
document.getElementById('monthDisplay').innerText = document.getElementById('monthDisplay').innerText =
`${dt.toLocaleDateString('en-us', { month: 'long' })} ${year}`; `${uppercaseFirstChar(dt.toLocaleDateString(undefined, { month: 'long' }))} ${year}`; // undefined = fallback to user language
calendar.innerHTML = ''; calendar.innerHTML = '';
...@@ -126,14 +134,15 @@ function load() { ...@@ -126,14 +134,15 @@ function load() {
} }
function closeModal() { function closeModal() {
eventTitleInput?.classList?.remove('error'); let inputs = Array.from(document.querySelectorAll("input")).filter(e=>e.id!="checkbox");
inputs.forEach(e=>{ e.classList.remove('error'); e.value=''; });
Object.keys(window.modals).forEach((k) => window.modals[k].close()); Object.keys(window.modals).forEach((k) => window.modals[k].close());
eventTitleInput.value = '';
clicked = null; clicked = null;
load(); load();
} }
function saveEvent() { function saveEvent() {
eventTitleInput = document.getElementById('eventTitleInput');
if (eventTitleInput.value) { if (eventTitleInput.value) {
eventTitleInput.classList.remove('error'); eventTitleInput.classList.remove('error');
...@@ -176,12 +185,12 @@ function initButtons() { ...@@ -176,12 +185,12 @@ function initButtons() {
load(); load();
}); });
document.getElementById('saveButton').addEventListener('click', saveEvent); document.querySelectorAll('#saveButton') .forEach(e=>e.addEventListener('click', (e) => saveEvent(e)));
document.getElementById('cancelButton').addEventListener('click', closeModal); document.querySelectorAll('#cancelButton').forEach(e=>e.addEventListener('click', () => closeModal()));
document.getElementById('deleteButton').addEventListener('click', deleteEvent); document.getElementById('deleteButton').addEventListener('click', () => deleteEvent());
document.getElementById('closeButton').addEventListener('click', closeModal); document.getElementById('closeButton').addEventListener('click', () => closeModal());
document.getElementById('modalBackDrop').addEventListener("click",() => closeModal());
document.getElementById('modalBackDrop').addEventListener("click",closeModal);
document.addEventListener('keyup', (e) => {if (("key" in e && e.key === "Escape") || (e.keyCode == 27)) closeModal();}); document.addEventListener('keyup', (e) => {if (("key" in e && e.key === "Escape") || (e.keyCode == 27)) closeModal();});
} }
......
...@@ -66,6 +66,7 @@ ...@@ -66,6 +66,7 @@
</table> </table>
</div> </div>
<script src="../pwa.js"></script>
<script src="./test.js"></script> <script src="./test.js"></script>
<script src="./script.js"></script> <script src="./script.js"></script>
</body> </body>
......
function getWeekDays(locale=undefined) { function migrateData(){
const baseDate = new Date(Date.UTC(2017, 0, 2)); // just a Monday if (!localStorage.getItem("events")) return;
const weekDays = []; let items = JSON.parse(localStorage.getItem("events"));
for(let i=0;i<7;i++) { items.forEach(e => {
weekDays.push(baseDate.toLocaleDateString(locale, { weekday: 'long' })); if (!e.startDate) {
baseDate.setDate(baseDate.getDate() + 1); const date = new Date(new Date(e.date).setHours(1));
e.startDate = date.toLocaleString('en-US');
e.endDate = new Date(date.setHours(24)).toLocaleString('en-US');
} }
return weekDays; })
localStorage.setItem("events", JSON.stringify(items));
return items;
}
migrateData();
function getWeekDays(locale=undefined) {
const baseDate = new Date(Date.UTC(2017, 0, 2)); // just a Monday
const weekDays = [];
for(let i=0;i<7;i++) {
weekDays.push(uppercaseFirstChar(baseDate.toLocaleDateString(locale, { weekday: 'long' })));
baseDate.setDate(baseDate.getDate() + 1);
}
return weekDays;
} }
const load2 = () => { const load2 = () => {
const dt = new Date(); const dt = new Date();
if (nav !== 0) dt.setMonth(new Date().getMonth() + nav); if (nav !== 0) dt.setMonth(dt.getMonth() + nav);
const day = dt.getDate(); const day = dt.getDate();
const month = dt.getMonth(); const month = dt.getMonth();
...@@ -28,11 +43,9 @@ const load2 = () => { ...@@ -28,11 +43,9 @@ const load2 = () => {
}); });
const paddingDays = weekdays.indexOf(dateString.split(', ')[0]); const paddingDays = weekdays.indexOf(dateString.split(', ')[0]);
document.getElementById('monthDisplay').innerText = document.getElementById('monthDisplay').innerText = dt.toLocaleDateString(undefined, { month: 'long', year: 'numeric' }); // undefined = fallback to user language
`${dt.toLocaleDateString(undefined, { month: 'long' })} ${year}`; // undefined = fallback to user language
document.getElementById('header').style.width = "780px"; // 800 - (10px margin * 2) document.getElementById('header').style.width = "780px"; // 800 - (10px margin * 2)
let calendar2 = document.querySelector("#tableing"); let calendar2 = document.querySelector("#tableing");
calendar2.innerHTML = ''; calendar2.innerHTML = '';
let tr = document.createElement("tr"); let tr = document.createElement("tr");
...@@ -61,16 +74,16 @@ const load2 = () => { ...@@ -61,16 +74,16 @@ const load2 = () => {
if (i > paddingDays) { if (i > paddingDays) {
daySquare.innerText = i - paddingDays; daySquare.innerText = i - paddingDays;
const eventForDay = events.find(e => e.date === dayString);
if (i - paddingDays === day && nav === 0) daySquare.id = 'currentDay'; if (i - paddingDays === day && nav === 0) daySquare.id = 'currentDay';
if (eventForDay) { events.filter(e => e.date === dayString).forEach((eventForDay, i) => {
if (i >= 2) return;
const eventDiv = document.createElement('div'); const eventDiv = document.createElement('div');
eventDiv.classList.add('event'); eventDiv.classList.add('event');
eventDiv.innerText = eventForDay.title; eventDiv.innerText = `${new Date(eventForDay.startDate).toLocaleTimeString(undefined,{hour:'numeric',minute:'numeric'})}-${new Date(eventForDay.endDate).toLocaleTimeString(undefined,{hour:'numeric',minute:'numeric'})} ${eventForDay.title}`;
eventDiv.addEventListener('click', (e) => { e.stopPropagation(); openModal(dayString, eventForDay) });
daySquare.appendChild(eventDiv); daySquare.appendChild(eventDiv);
} });
daySquare.addEventListener('click', () => openModal(dayString)); daySquare.addEventListener('click', () => openModal(dayString));
} else { } else {
...@@ -84,4 +97,154 @@ const load2 = () => { ...@@ -84,4 +97,154 @@ const load2 = () => {
} }
calendar2.appendChild(cal); calendar2.appendChild(cal);
}; };
setTimeout(() => {globalThis.load = () => load2(); load2()}, 0) // override the function after it has been declared (since this is loaded FIRST)
function saveEvent2(e) {
let inputs = Array.from(e.target.parentElement.childNodes).filter(e=>e.nodeName=='INPUT')
console.log(inputs);
eventTitleInput = document.getElementById('eventTitleInput');
if (inputs.filter(e=>e.value=='').length == 0) {
inputs.forEach(e=>e.classList.remove('error'));
events.push({
date: clicked,
title: inputs[0].value,
startDate: new Date(clicked + " " + inputs[1].value).toLocaleString('en-US'), //.toISOString(),
endDate: new Date(clicked + " " + inputs[2].value).toLocaleString('en-US'), //.toISOString(),
});
localStorage.setItem('events', JSON.stringify(events));
closeModal();
} else {
inputs.filter(e=>e.value=='').forEach(e=>e.classList.add('error'));
}
}
function openModal2(date, eventForDay = null) {
clicked = date;
//if (eventForDay == null) eventForDay = events.find(e => e.date === clicked);
if (eventForDay) {
document.getElementById('eventText').innerText = `Title: ${eventForDay.title}\nFrom: ${new Date(eventForDay.startDate).toLocaleString('en-US')}\nTo: ${new Date(eventForDay.endDate).toLocaleString('en-US')}`; // SHOULD STAY 'en-US' since else the delete parser doesn't work
window.modals['deleteEvent'].open();
} else {
window.modals['newEvent'].open()
}
}
function deleteEvent2() {
const regex = /Title: ([a-zA-Z0-9_\-\.]+)\nFrom: ([0-9-\ :\/,APM]+)\nTo: ([0-9- :\/\,APM]+)/;
const eventText = document.getElementById('eventText').innerText;
let m;
if ((m = regex.exec(eventText)) !== null) {
let [_, title, startDate, endDate] = m;
events = events.filter(e => !(e.date == clicked && e.title == title && e.startDate == startDate && e.endDate == endDate));
localStorage.setItem('events', JSON.stringify(events));
closeModal();
}
}
function ical_download2(download=true){
var comp = new ICAL.Component(['vcalendar', [["prodid",{},"text","-//Plan2Go Calendar"]], []]);
const events = JSON.parse(localStorage.events);
for (let i=0; i<events.length; i++) {
let vevent = new ICAL.Component('vevent'), event = new ICAL.Event(vevent);
event.summary = events[i].title;
event.uid = 'abcdef...';
event.startDate = ICAL.Time.fromJSDate(new Date(events[i].startDate), false);
event.endDate = ICAL.Time.fromJSDate(new Date(events[i].endDate), false);
comp.addSubcomponent(vevent);
}
const iCalendarData = comp.toString();
this.fileName = "Plan2Go_export.ics";
this._save = function(fileURL){
if (!window.ActiveXObject) {
let save = document.createElement('a');
save.href = fileURL;
save.target = '_blank';
save.download = this.fileName || 'unknown';
const evt = new MouseEvent('click', {
'view': window,
'bubbles': true,
'cancelable': false
});
save.dispatchEvent(evt);
(window.URL || window.webkitURL).revokeObjectURL(save.href);
}
// for IE < 11
else if ( !! window.ActiveXObject && document.execCommand) {
let _window = window.open(fileURL, '_blank');
_window.document.close();
_window.document.execCommand('SaveAs', true, this.fileName || fileURL)
_window.close();
}
}
if (download) this._save( "data:text/calendar;charset=utf8," + escape(iCalendarData));
else return iCalendarData;
}
// Credits to https://stackoverflow.com/a/70679783
const arrayContainsObject = (array, object) => array.some(item => Object.keys(item).every(key => item[key] === object[key]))
function ical_load(iCalendarData) {
const jcalData = ICAL.parse(iCalendarData);
const vcalendar = new ICAL.Component(jcalData);
const vevents = vcalendar.getAllSubcomponents('vevent');
vevents.forEach((vevent) => {
const event = new ICAL.Event(vevent);
const eventObject = {
"title": event.summary,
"date": event.startDate.toJSDate().toLocaleDateString('en-US'),
"startDate": event.startDate.toJSDate().toLocaleString('en-US'),
"endDate": event.endDate.toJSDate().toLocaleString('en-US')
}
if (!arrayContainsObject(events, eventObject)) events.push(eventObject);
})
localStorage.setItem('events', JSON.stringify(events));
load();
console.log("Done!");
return events;
}
function start_ical_loader() {
document.querySelector('#file-selector')?.click();
}
document.body.insertAdjacentHTML("beforeend", '<input type="file" id="file-selector" accept=".ics" hidden>');
const fileSelector = document.querySelector('#file-selector')
fileSelector.addEventListener('change', (event) => {
const fileList = event.target.files;
const reader = new FileReader();
reader.addEventListener('load', (event) => {
const result = event.target.result;
ical_load(atob(unescape(result.replace("data:text/calendar;base64,",""))));
});
reader.readAsDataURL(fileList[0]);
});
setTimeout(() => {
globalThis.load = () => load2();
globalThis.ical_download = () => ical_download2();
globalThis.saveEvent = (e) => saveEvent2(e);
globalThis.openModal = (date, ed=null) => openModal2(date, ed)
globalThis.deleteEvent = () => deleteEvent2()
window.modals['newEvent'] = new Modal({ id: "newEvent", title: "New Event", body: '<input id="eventTitleInput" placeholder="Event Title" /><label for="eventStartInput">Event Start: </label><input id="eventStartInput" type="time" /><br><label for="eventEndInput">Event End: </label><input id="eventEndInput" type="time" /><br>', extrabutton: "Save", closebutton: "Cancel" });
window.modals['newEvent'].element.querySelector('#saveButton').addEventListener('click', (e) => saveEvent(e));
window.modals['newEvent'].element.querySelector('#cancelButton').addEventListener('click', () => closeModal());
window.modals['settings'] = new Modal({ id: "settings", title: "Settings", body: '<p>Needs to be done!</p><button id="exportCalendar">Export</button><button id="importCalendar">Import</button><br><br>', extrabutton: "Save", opener: "#setting > i" });
window.modals['settings'].element.querySelector("#exportCalendar").addEventListener("click", () => ical_download());
window.modals['settings'].element.querySelector("#importCalendar").addEventListener("click", () => start_ical_loader());
//initButtons();
load2();
if (events) {
cancelNotifications();
const notpassed = events.filter(a => new Date(a.startDate) > new Date());
notpassed.forEach(e=>sendNotificationAfter(0, 'Event started: ' + e.title, new Date(e.startDate)));
}
}, 1) // override the function after it has been declared (since this is loaded FIRST)
...@@ -3,18 +3,18 @@ ...@@ -3,18 +3,18 @@
"name": "Plan2Go: What do I have in my planning?", "name": "Plan2Go: What do I have in my planning?",
"icons": [ "icons": [
{ {
"src": "/plan2go/images/icon.png", "src": "/images/icon.png",
"type": "image/png", "type": "image/png",
"sizes": "115x115", "sizes": "115x115",
"purpose": "any maskable" "purpose": "any maskable"
}, },
{ {
"src": "/plan2go/images/Plan2Go.png", "src": "/images/Plan2Go.png",
"type": "image/png", "type": "image/png",
"sizes": "692x450" "sizes": "692x450"
}, },
{ {
"src": "/plan2go/images/Plan2GoBanner.png", "src": "/images/Plan2GoBanner.png",
"type": "image/png", "type": "image/png",
"sizes": "512x512" "sizes": "512x512"
} }
......
window.addEventListener("load", () => { window.addEventListener("load", () => {
if ("serviceWorker" in navigator) { if ("serviceWorker" in navigator) {
navigator.serviceWorker.register("service-worker.js"); let root = location.pathname.replace(/\/demo\/.*/,'')
navigator.serviceWorker.register(root + "/service-worker.js");
navigator.serviceWorker.addEventListener('message', event => console.log(event.data)); navigator.serviceWorker.addEventListener('message', event => console.log(event.data));
} }
if ("__TAURI__" in window) { if ("__TAURI__" in window) {
...@@ -15,19 +18,19 @@ window.addEventListener("load", () => { ...@@ -15,19 +18,19 @@ window.addEventListener("load", () => {
} }
}); });
document.querySelector('#notification-button').onclick = async () => { async function sendNotificationAfter(seconds=5, body='Hello World', timestamp=null) {
let reg = await navigator.serviceWorker.getRegistration(); let reg = await navigator.serviceWorker.getRegistration();
if ("__TAURI__" in window) reg = Notification; if ("__TAURI__" in window) reg = Notification;
Notification.requestPermission().then(permission => { Notification.requestPermission().then(permission => {
if (permission !== 'granted') { if (permission !== 'granted') {
alert('you need to allow push notifications'); alert('you need to allow push notifications');
} else { } else {
const timestamp = new Date().getTime() + 5 * 1000; // now plus 5000ms if (!timestamp) timestamp = new Date().getTime() + seconds * 1000; // now plus 5000ms
reg.showNotification( reg.showNotification(
'Demo Push Notification', 'Demo Push Notification',
{ {
tag: timestamp, // a unique ID tag: timestamp, // a unique ID
body: 'Hello World', // content of the push notification body: body, // content of the push notification
showTrigger: new TimestampTrigger(timestamp), // set the time for the push notification showTrigger: new TimestampTrigger(timestamp), // set the time for the push notification
data: { data: {
url: window.location.href, // pass the current url to the notification url: window.location.href, // pass the current url to the notification
...@@ -48,15 +51,17 @@ document.querySelector('#notification-button').onclick = async () => { ...@@ -48,15 +51,17 @@ document.querySelector('#notification-button').onclick = async () => {
); );
} }
}); });
}; }
document.querySelector('#notification-cancel').onclick = async () => { async function cancelNotifications() {
if (!("__TAURI__" in window)) { if (!("__TAURI__" in window)) {
const reg = await navigator.serviceWorker.getRegistration(); const reg = await navigator.serviceWorker.getRegistration();
const notifications = await reg.getNotifications({ const notifications = await reg.getNotifications({
includeTriggered: true includeTriggered: true
}); });
notifications.forEach(notification => notification.close()); notifications.forEach(notification => notification.close());
alert(`${notifications.length} notification(s) cancelled`); return `${notifications.length} notification(s) cancelled`;
} }
}; }
document.querySelector('#notification-button')?.addEventListener("click", () => sendNotificationAfter(5))
document.querySelector('#notification-cancel')?.addEventListener("click", () => alert(cancelNotifications()))
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment