Compare commits
2 Commits
729b477d44
...
763a6a77c5
Author | SHA1 | Date | |
---|---|---|---|
763a6a77c5 | |||
b9f2254c87 |
86
www/app.js
86
www/app.js
|
@ -117,20 +117,54 @@ async function cloneSchedule(includeAssignments) {
|
|||
}
|
||||
|
||||
document.getElementById('cloneSch').addEventListener('click', async e => {
|
||||
cloneSchedule(true);
|
||||
await cloneSchedule(true);
|
||||
});
|
||||
|
||||
document.getElementById('cloneSchNoAssignments').addEventListener('click', async e => {
|
||||
cloneSchedule(false);
|
||||
await cloneSchedule(false);
|
||||
});
|
||||
|
||||
const titleInput = document.getElementById('title');
|
||||
const schStartTime = document.getElementById('sch_start_time')
|
||||
const schEndTime = document.getElementById('sch_end_time')
|
||||
const schGranularity = document.getElementById('granularity')
|
||||
let allowEdits = false;
|
||||
async function updateScheduleSettings() {
|
||||
await updateBackupsList();
|
||||
|
||||
titleInput.value = schedule.base_title;
|
||||
titleInput.disabled = !allowEdits;
|
||||
schStartTime.value = schedule.start_time.inputValue;
|
||||
schEndTime.value = schedule.end_time.inputValue;
|
||||
schGranularity.value = schedule.granularity.inputValue;
|
||||
|
||||
const daysSpan = document.getElementById('sch-days');
|
||||
utils.clearChildren(daysSpan);
|
||||
for (const day of utils.allDays) {
|
||||
const dayLabel = document.createElement('label');
|
||||
const dayName = utils.DayString(day);
|
||||
const dayCheckbox = document.createElement('input');
|
||||
|
||||
dayCheckbox.type = 'checkbox';
|
||||
dayCheckbox.checked = schedule.all_days.includes(day);
|
||||
dayCheckbox.addEventListener('change', async e => {
|
||||
if (!e.target.checked) {
|
||||
if (schedule.assignments.some(a => day in a.people_by_day)) {
|
||||
alert("Cannot remove schedule for " + dayName
|
||||
+ " because there are events on that day.");
|
||||
e.target.checked = true;
|
||||
return;
|
||||
}
|
||||
schedule.all_days.splice(schedule.all_days.indexOf(day), 1);
|
||||
} else {
|
||||
schedule.all_days = utils.allDays.filter(d => schedule.all_days.includes(d) || d === day)
|
||||
}
|
||||
await saveSchedule();
|
||||
});
|
||||
|
||||
dayLabel.appendChild(dayCheckbox);
|
||||
dayLabel.appendChild(document.createTextNode(dayName));
|
||||
daysSpan.appendChild(dayLabel);
|
||||
}
|
||||
|
||||
document.getElementById('scheduleMetadata')
|
||||
.querySelectorAll('*')
|
||||
|
@ -292,6 +326,52 @@ document.getElementById('changeTitle').addEventListener('click', async e => {
|
|||
await saveSchedule();
|
||||
});
|
||||
|
||||
schStartTime.addEventListener('change', async e => {
|
||||
const newStartTime = utils.Time.fromInputValue(e.target.value);
|
||||
if (schedule.assignments) {
|
||||
const earliestStart = schedule.assignments.map(a => a.start_time).sort((a, b) => a.cmp(b))[0];
|
||||
if (earliestStart.cmp(newStartTime) < 0) {
|
||||
alert("Cannot change start time to " + newStartTime.to12HourString()
|
||||
+ " because it is after the earliest assignment starts at "
|
||||
+ earliestStart.to12HourString() + ".");
|
||||
return;
|
||||
}
|
||||
}
|
||||
schedule.start_time = newStartTime;
|
||||
await saveSchedule();
|
||||
});
|
||||
|
||||
schEndTime.addEventListener('change', async e => {
|
||||
const newEndTime = utils.Time.fromInputValue(e.target.value);
|
||||
if (schedule.assignments) {
|
||||
const latestEnd = schedule.assignments.map(a => a.end_time).sort((a, b) => b.cmp(a))[0];
|
||||
if (latestEnd.cmp(newEndTime) > 0) {
|
||||
alert("Cannot change end time to " + newEndTime.to12HourString()
|
||||
+ " because it is before the latest assignment ends at "
|
||||
+ latestEnd.to12HourString() + ".");
|
||||
return;
|
||||
}
|
||||
}
|
||||
schedule.end_time = newEndTime;
|
||||
await saveSchedule();
|
||||
});
|
||||
|
||||
schGranularity.addEventListener('change', async e => {
|
||||
const newGranularity = utils.Time.fromInputValue(e.target.value)
|
||||
.durationSinceMidnight;
|
||||
const schDuration = schedule.timeRange.duration;
|
||||
const newNumRows = schDuration.dividedBy(newGranularity);
|
||||
if (!Number.isInteger(newNumRows)) {
|
||||
alert("Cannot change granularity to " + newGranularity.toString()
|
||||
+ " because it is does not divide the " + schDuration.toString()
|
||||
+ " duration from " + schedule.start_time.to12HourString()
|
||||
+ " to " + schedule.end_time.to12HourString() + ".");
|
||||
return;
|
||||
}
|
||||
schedule.granularity = newGranularity;
|
||||
await saveSchedule();
|
||||
});
|
||||
|
||||
const personInput = document.getElementById('person');
|
||||
|
||||
document.getElementById('addStudent').addEventListener('click', async e => {
|
||||
|
|
|
@ -39,6 +39,10 @@
|
|||
<div id="scheduleMetadata">
|
||||
<label>Title: <input id="title"></label>
|
||||
<button id="changeTitle">Change Title</button><br>
|
||||
<label>Start time: <input type="time" id="sch_start_time"></label><br>
|
||||
<label>End time: <input type="time" id="sch_end_time"></label><br>
|
||||
<label>Granularity: <input type="time" id="granularity"></label><br>
|
||||
Days: <span id="sch-days"></span><br>
|
||||
<label>Name: <input id="person"></label>
|
||||
<button id="addTeacher">Add Teacher</button>
|
||||
<button id="addStaff">Add Staff</button>
|
||||
|
|
|
@ -57,6 +57,10 @@ export default class Schedule {
|
|||
}
|
||||
}
|
||||
|
||||
get timeRange() {
|
||||
return new utils.TimeRange(this);
|
||||
}
|
||||
|
||||
fullGridFor(day) {
|
||||
function timestampString(date) {
|
||||
function f(format) {
|
||||
|
|
50
www/utils.js
50
www/utils.js
|
@ -57,10 +57,17 @@ export class Time {
|
|||
|
||||
export class Duration {
|
||||
constructor(obj) {
|
||||
this.hour = obj.hour ?? 0;
|
||||
this.minute = obj.minute ?? 0;
|
||||
this.second = obj.second ?? 0;
|
||||
this.total_seconds = ((this.hour * 60) + this.minute) * 60 + this.second;
|
||||
if (obj.total_seconds) {
|
||||
this.total_seconds = obj.total_seconds;
|
||||
this.hour = Math.floor(obj.total_seconds / 60 / 60);
|
||||
this.minute = Math.floor(obj.total_seconds / 60) % 60;
|
||||
this.second = obj.total_seconds % 60;
|
||||
} else {
|
||||
this.hour = obj.hour ?? 0;
|
||||
this.minute = obj.minute ?? 0;
|
||||
this.second = obj.second ?? 0;
|
||||
this.total_seconds = ((this.hour * 60) + this.minute) * 60 + this.second;
|
||||
}
|
||||
}
|
||||
|
||||
asJsonObject() {
|
||||
|
@ -82,6 +89,25 @@ export class Duration {
|
|||
const hour = Math.floor(total / 60 / 60);
|
||||
return new Duration({hour, minute, second});
|
||||
}
|
||||
|
||||
toString() {
|
||||
let res = "";
|
||||
if (this.hour) {
|
||||
res += this.hour + (this.hour === 1 ? " hour" : " hours ");
|
||||
}
|
||||
if (this.minute) {
|
||||
res += this.minute + (this.minute === 1 ? " minute" : " minutes ");
|
||||
}
|
||||
if (this.second) {
|
||||
res += this.second + (this.second === 1 ? " second" : " seconds");
|
||||
}
|
||||
|
||||
return this.total_seconds === 0 ? "0 seconds" : res.trimEnd();
|
||||
}
|
||||
|
||||
get inputValue() {
|
||||
return new Time({}).plus(this).inputValue;
|
||||
}
|
||||
}
|
||||
|
||||
export class TimeRange {
|
||||
|
@ -92,9 +118,9 @@ export class TimeRange {
|
|||
|
||||
get duration() {
|
||||
return new Duration({
|
||||
'hour': this.end_time.hour - this.start_time.hour,
|
||||
'minute': this.end_time.minute - this.start_time.minute,
|
||||
'second': this.end_time.second - this.start_time.second,
|
||||
'total_seconds': 60 * 60 * (this.end_time.hour - this.start_time.hour)
|
||||
+ 60 * (this.end_time.minute - this.start_time.minute)
|
||||
+ this.end_time.second - this.start_time.second,
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -106,8 +132,7 @@ export class TimeRange {
|
|||
}
|
||||
}
|
||||
|
||||
export function DayString(day) {
|
||||
return {
|
||||
const dayDictionary = {
|
||||
'M': 'Monday',
|
||||
'T': 'Tuesday',
|
||||
'W': 'Wednesday',
|
||||
|
@ -115,9 +140,14 @@ export function DayString(day) {
|
|||
'F': 'Friday',
|
||||
'S': 'Saturday',
|
||||
'U': 'Sunday',
|
||||
}[day];
|
||||
};
|
||||
|
||||
export function DayString(day) {
|
||||
return dayDictionary[day];
|
||||
}
|
||||
|
||||
export const allDays = Object.keys(dayDictionary);
|
||||
|
||||
export function clearChildren(el) {
|
||||
while (el.firstChild) el.removeChild(el.lastChild);
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue
Block a user