calendar: Add type other+repeat
parent
5da64a5f83
commit
044fc173c5
|
|
@ -10,7 +10,7 @@ Basic calendar
|
||||||
- Swipe down (Bangle.js 2 only) to go to the next year
|
- Swipe down (Bangle.js 2 only) to go to the next year
|
||||||
- Touch to display events for current month
|
- Touch to display events for current month
|
||||||
- Press the button (button 3 on Bangle.js 1) to exit
|
- Press the button (button 3 on Bangle.js 1) to exit
|
||||||
- Holidays have same color as weekends and can be edited with the 'Download'-interface
|
- Holidays have same color as weekends and can be edited with the 'Download'-interface, e.g. by uploading an iCalendar file.
|
||||||
|
|
||||||
## Settings
|
## Settings
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -38,12 +38,15 @@ const events = (require("Storage").readJSON("sched.json",1) || []).filter(a => a
|
||||||
date.setSeconds(time.s);
|
date.setSeconds(time.s);
|
||||||
return {date: date, msg: a.msg, type: "e"};
|
return {date: date, msg: a.msg, type: "e"};
|
||||||
});
|
});
|
||||||
// add holidays
|
// add holidays & other events
|
||||||
(require("Storage").readJSON("calendar.holiday.json",1) || []).forEach(h => {
|
(require("Storage").readJSON("calendar.days.json",1) || []).forEach(d => {
|
||||||
const date = new Date(h.date);
|
const date = new Date(d.date);
|
||||||
events.push({date: date, msg: h.name, type: "h"});
|
const o = {date: date, msg: d.name, type: d.type};
|
||||||
|
if (d.repeat) {
|
||||||
|
o.repeat = d.repeat;
|
||||||
|
}
|
||||||
|
events.push(o);
|
||||||
});
|
});
|
||||||
events.sort((a,b) => a.date - b.date);
|
|
||||||
|
|
||||||
if (settings.ndColors === undefined) {
|
if (settings.ndColors === undefined) {
|
||||||
settings.ndColors = !g.theme.dark;
|
settings.ndColors = !g.theme.dark;
|
||||||
|
|
@ -158,8 +161,12 @@ function drawCalendar(date) {
|
||||||
weekBeforeMonth.setDate(weekBeforeMonth.getDate() - 7);
|
weekBeforeMonth.setDate(weekBeforeMonth.getDate() - 7);
|
||||||
const week2AfterMonth = new Date(date.getFullYear(), date.getMonth()+1, 0);
|
const week2AfterMonth = new Date(date.getFullYear(), date.getMonth()+1, 0);
|
||||||
week2AfterMonth.setDate(week2AfterMonth.getDate() + 14);
|
week2AfterMonth.setDate(week2AfterMonth.getDate() + 14);
|
||||||
|
events.forEach(ev => {
|
||||||
|
if (ev.repeat === "y") {
|
||||||
|
ev.date.setFullYear(date.getFullYear());
|
||||||
|
}
|
||||||
|
});
|
||||||
const eventsThisMonth = events.filter(ev => ev.date > weekBeforeMonth && ev.date < week2AfterMonth);
|
const eventsThisMonth = events.filter(ev => ev.date > weekBeforeMonth && ev.date < week2AfterMonth);
|
||||||
|
|
||||||
let i = 0;
|
let i = 0;
|
||||||
for (y = 0; y < rowN - 1; y++) {
|
for (y = 0; y < rowN - 1; y++) {
|
||||||
for (x = 0; x < colN; x++) {
|
for (x = 0; x < colN; x++) {
|
||||||
|
|
@ -177,15 +184,21 @@ function drawCalendar(date) {
|
||||||
// Display events for this day
|
// Display events for this day
|
||||||
eventsThisMonth.forEach((ev, idx) => {
|
eventsThisMonth.forEach((ev, idx) => {
|
||||||
if (sameDay(ev.date, curDay)) {
|
if (sameDay(ev.date, curDay)) {
|
||||||
if (ev.type === "e") { // alarm/event
|
switch(ev.type) {
|
||||||
const hour = ev.date.getHours() + ev.date.getMinutes()/60.0;
|
case "e": // alarm/event
|
||||||
const slice = hour/24*(eventsPerDay-1); // slice 0 for 0:00 up to eventsPerDay for 23:59
|
const hour = ev.date.getHours() + ev.date.getMinutes()/60.0;
|
||||||
const height = (y2-2) - (y1+2); // height of a cell
|
const slice = hour/24*(eventsPerDay-1); // slice 0 for 0:00 up to eventsPerDay for 23:59
|
||||||
const sliceHeight = height/eventsPerDay;
|
const height = (y2-2) - (y1+2); // height of a cell
|
||||||
const ystart = (y1+2) + slice*sliceHeight;
|
const sliceHeight = height/eventsPerDay;
|
||||||
g.setColor(bgEvent).fillRect(x1+1, ystart, x2-2, ystart+sliceHeight);
|
const ystart = (y1+2) + slice*sliceHeight;
|
||||||
} else if (ev.type === "h") { // holiday
|
g.setColor(bgEvent).fillRect(x1+1, ystart, x2-2, ystart+sliceHeight);
|
||||||
g.setColor(bgColorWeekend).fillRect(x1+1, y1+1, x2-1, y2-1);
|
break;
|
||||||
|
case "h": // holiday
|
||||||
|
g.setColor(bgColorWeekend).fillRect(x1+1, y1+1, x2-1, y2-1);
|
||||||
|
break;
|
||||||
|
case "o": // other
|
||||||
|
g.setColor("#88ff00").fillRect(x1+1, y1+1, x2-1, y2-1);
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
eventsThisMonth.splice(idx, 1); // this event is no longer needed
|
eventsThisMonth.splice(idx, 1); // this event is no longer needed
|
||||||
|
|
@ -242,6 +255,7 @@ function setUI() {
|
||||||
},
|
},
|
||||||
btn: (n) => n === (process.env.HWVERSION === 2 ? 1 : 3) && load(),
|
btn: (n) => n === (process.env.HWVERSION === 2 ? 1 : 3) && load(),
|
||||||
touch: (n,e) => {
|
touch: (n,e) => {
|
||||||
|
events.sort((a,b) => a.date - b.date);
|
||||||
const menu = events.filter(ev => ev.date.getFullYear() === date.getFullYear() && ev.date.getMonth() === date.getMonth()).map(e => {
|
const menu = events.filter(ev => ev.date.getFullYear() === date.getFullYear() && ev.date.getMonth() === date.getMonth()).map(e => {
|
||||||
const dateStr = require("locale").date(e.date, 1);
|
const dateStr = require("locale").date(e.date, 1);
|
||||||
const timeStr = require("locale").time(e.date, 1);
|
const timeStr = require("locale").time(e.date, 1);
|
||||||
|
|
|
||||||
|
|
@ -53,6 +53,7 @@ function eventToHoliday(event) {
|
||||||
const holiday = {
|
const holiday = {
|
||||||
date: formatDate(date),
|
date: formatDate(date),
|
||||||
name: event.summary,
|
name: event.summary,
|
||||||
|
type: 'h',
|
||||||
};
|
};
|
||||||
return holiday;
|
return holiday;
|
||||||
}
|
}
|
||||||
|
|
@ -63,7 +64,7 @@ function formatDate(d) {
|
||||||
|
|
||||||
function upload() {
|
function upload() {
|
||||||
Util.showModal("Saving...");
|
Util.showModal("Saving...");
|
||||||
Util.writeStorage("calendar.holiday.json", JSON.stringify(holidays), () => {
|
Util.writeStorage("calendar.days.json", JSON.stringify(holidays), () => {
|
||||||
location.reload(); // reload so we see current data
|
location.reload(); // reload so we see current data
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
@ -82,7 +83,7 @@ function renderHoliday(holiday) {
|
||||||
inputTime.value = formatDate(localDate)
|
inputTime.value = formatDate(localDate)
|
||||||
inputTime.onchange = (e => {
|
inputTime.onchange = (e => {
|
||||||
const date = new Date(inputTime.value);
|
const date = new Date(inputTime.value);
|
||||||
holiday.date = formatDate(date.toISOString())
|
holiday.date = formatDate(date);
|
||||||
});
|
});
|
||||||
tdTime.appendChild(inputTime);
|
tdTime.appendChild(inputTime);
|
||||||
|
|
||||||
|
|
@ -101,13 +102,50 @@ function renderHoliday(holiday) {
|
||||||
tdSummary.appendChild(inputSummary);
|
tdSummary.appendChild(inputSummary);
|
||||||
inputSummary.onchange();
|
inputSummary.onchange();
|
||||||
|
|
||||||
const tdInfo = document.createElement('td');
|
const tdType = document.createElement('td');
|
||||||
tr.appendChild(tdInfo);
|
tr.appendChild(tdType);
|
||||||
|
const selectType = document.createElement("select");
|
||||||
|
selectType.classList.add('form-select');
|
||||||
|
tdType.prepend(selectType);
|
||||||
|
const optionHoliday = document.createElement("option");
|
||||||
|
optionHoliday.text = "Holiday";
|
||||||
|
optionHoliday.value = "h";
|
||||||
|
optionHoliday.selected = holiday.type === "h";
|
||||||
|
selectType.add(optionHoliday);
|
||||||
|
const optionOther = document.createElement("option");
|
||||||
|
optionOther.text = "Other";
|
||||||
|
optionOther.value = "o";
|
||||||
|
optionOther.selected = holiday.type === "o";
|
||||||
|
selectType.add(optionOther);
|
||||||
|
selectType.onchange = (e => {
|
||||||
|
holiday.type = e.target.value;
|
||||||
|
});
|
||||||
|
|
||||||
|
const tdRepeat = document.createElement('td');
|
||||||
|
tr.appendChild(tdRepeat);
|
||||||
|
const selectRepeat = document.createElement("select");
|
||||||
|
selectRepeat.classList.add('form-select');
|
||||||
|
tdRepeat.prepend(selectRepeat);
|
||||||
|
const optionNever = document.createElement("option");
|
||||||
|
optionNever.text = "Never";
|
||||||
|
optionNever.selected = !holiday.repeat;
|
||||||
|
selectRepeat.add(optionNever);
|
||||||
|
const optionYearly = document.createElement("option");
|
||||||
|
optionYearly.text = "Yearly";
|
||||||
|
optionYearly.value = "y";
|
||||||
|
optionYearly.selected = holiday.repeat === "y";
|
||||||
|
selectRepeat.add(optionYearly);
|
||||||
|
selectRepeat.onchange = (e => {
|
||||||
|
holiday.repeat = e.target.value;
|
||||||
|
});
|
||||||
|
|
||||||
|
const tdAction = document.createElement('td');
|
||||||
|
tr.appendChild(tdAction);
|
||||||
|
|
||||||
const buttonDelete = document.createElement('button');
|
const buttonDelete = document.createElement('button');
|
||||||
buttonDelete.classList.add('btn');
|
buttonDelete.classList.add('btn');
|
||||||
buttonDelete.classList.add('btn-action');
|
buttonDelete.classList.add('btn-action');
|
||||||
tdInfo.prepend(buttonDelete);
|
tdAction.prepend(buttonDelete);
|
||||||
const iconDelete = document.createElement('i');
|
const iconDelete = document.createElement('i');
|
||||||
iconDelete.classList.add('icon');
|
iconDelete.classList.add('icon');
|
||||||
iconDelete.classList.add('icon-delete');
|
iconDelete.classList.add('icon-delete');
|
||||||
|
|
@ -129,22 +167,21 @@ function addHoliday() {
|
||||||
}
|
}
|
||||||
|
|
||||||
function getData() {
|
function getData() {
|
||||||
|
Util.showModal("Loading...");
|
||||||
Puck.write(`\x10(function() {
|
Puck.write(`\x10(function() {
|
||||||
Bluetooth.print(JSON.stringify(require("Storage").list("calendar.holiday.json").sort()));
|
Bluetooth.print(JSON.stringify(require("Storage").list("calendar.days.json").sort()));
|
||||||
})()\n`, contents => {
|
})()\n`, contents => {
|
||||||
const fileNames = JSON.parse(contents);
|
const fileNames = JSON.parse(contents);
|
||||||
if (fileNames.length > 0) {
|
if (fileNames.length > 0) {
|
||||||
Util.showModal("Loading...");
|
Util.readStorage('calendar.days.json',data=>{
|
||||||
Util.readStorage('calendar.holiday.json',data=>{
|
|
||||||
holidays = JSON.parse(data || "[]") || [];
|
holidays = JSON.parse(data || "[]") || [];
|
||||||
|
|
||||||
Util.hideModal();
|
Util.hideModal();
|
||||||
holidays.forEach(holiday => {
|
render();
|
||||||
renderHoliday(holiday);
|
|
||||||
});
|
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
holidays = [];
|
holidays = [];
|
||||||
|
Util.hideModal();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
@ -156,7 +193,7 @@ function onInit() {
|
||||||
</script>
|
</script>
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<h4>Holidays</h4>
|
<h4 class="float-left">Holidays</h4>
|
||||||
|
|
||||||
<div class="float-right">
|
<div class="float-right">
|
||||||
<button class="btn" onclick="addHoliday();">
|
<button class="btn" onclick="addHoliday();">
|
||||||
|
|
@ -164,11 +201,13 @@ function onInit() {
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<table class="table">
|
<table class="table table-scroll" style="clear:both;">
|
||||||
<thead>
|
<thead>
|
||||||
<tr>
|
<tr>
|
||||||
<th>Date</th>
|
<th>Date</th>
|
||||||
<th>Holiday</th>
|
<th>Holiday</th>
|
||||||
|
<th>Type</th>
|
||||||
|
<th>Repeat</th>
|
||||||
<th></th>
|
<th></th>
|
||||||
</tr>
|
</tr>
|
||||||
</thead>
|
</thead>
|
||||||
|
|
|
||||||
|
|
@ -15,5 +15,5 @@
|
||||||
{"name":"calendar.settings.js","url":"settings.js"},
|
{"name":"calendar.settings.js","url":"settings.js"},
|
||||||
{"name":"calendar.img","url":"calendar-icon.js","evaluate":true}
|
{"name":"calendar.img","url":"calendar-icon.js","evaluate":true}
|
||||||
],
|
],
|
||||||
"data": [{"name":"calendar.json"}, {"name":"calendar.holiday.json"}]
|
"data": [{"name":"calendar.json"}, {"name":"calendar.days.json"}]
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue