diff --git a/js/calendar.js b/js/calendar.js
index 7c6ea0050..c6a6e688f 100644
--- a/js/calendar.js
+++ b/js/calendar.js
@@ -25,6 +25,14 @@ ipcRenderer.on('PREFERENCE_SAVED', function(event, inputs) {
applyTheme(preferences.theme);
});
+/*
+ * Get nofified when waivers get updated.
+ */
+ipcRenderer.on('WAIVER_SAVED', function() {
+ calendar.loadInternalWaiveStore();
+ calendar.redraw();
+});
+
/*
* Returns true if the notification is enabled in preferences.
*/
diff --git a/js/classes/Calendar.js b/js/classes/Calendar.js
index e56c70aa3..bc36c0c8b 100644
--- a/js/classes/Calendar.js
+++ b/js/classes/Calendar.js
@@ -11,7 +11,7 @@ const {
validateTime
} = require('../time-math.js');
const { showDay } = require('../user-preferences.js');
-const { getDateStr } = require('../date-aux.js');
+const { getDateStr, getMonthLength } = require('../date-aux.js');
const {
formatDayId,
sendWaiverDay,
@@ -36,6 +36,8 @@ class Calendar {
this.month = this.today.getMonth();
this.year = this.today.getFullYear();
this.workingDays = 0;
+ this.loadInternalStore();
+ this.loadInternalWaiveStore();
this.updatePreferences(preferences);
this._initCalendar();
}
@@ -45,9 +47,24 @@ class Calendar {
*/
_initCalendar() {
this._generateTemplate();
+
+ $('#punch-button').click(() => { this.punchDate(); });
+ $('#next-month').click(() => { this.nextMonth(); });
+ $('#prev-month').click(() => { this.prevMonth(); });
+ $('#current-month').click(() => { this.goToCurrentDate(); });
+
+ this._draw();
+ }
+
+ /*
+ * Draws elements of the Calendar that depend on data.
+ */
+ _draw() {
+ this.updateTableHeader();
+ this.updateTableBody();
this.updateBasedOnDB();
- if (!showDay(this.today.getFullYear(), this.today.getMonth(), this.today.getDate())) {
+ if (!this.showDay(this.today.getFullYear(), this.today.getMonth(), this.today.getDate())) {
$('#punch-button').prop('disabled', true);
ipcRenderer.send('TOGGLE_TRAY_PUNCH_TIME', false);
} else {
@@ -62,22 +79,6 @@ class Calendar {
calendar.updateTimeDayCallback(this.id, this.value);
});
- $('#punch-button').off('click').on('click', function() {
- calendar.punchDate();
- });
-
- $('#next-month').off('click').on('click', function() {
- calendar.nextMonth();
- });
-
- $('#prev-month').off('click').on('click', function() {
- calendar.prevMonth();
- });
-
- $('#current-month').off('click').on('click', function() {
- calendar.goToCurrentDate();
- });
-
$('.waiver-trigger').off('click').on('click', function() {
const dayId = $(this).closest('tr').attr('id').substr(3);
const waiverDay = formatDayId(dayId);
@@ -89,15 +90,55 @@ class Calendar {
/*
* Updates data displayed based on the database.
*/
- _setData(key) {
- var value = '';
- if (store.has(key)) {
- value = store.get(key);
+ _setTableData(day, month, key) {
+ var idTag = this.year + '-' + month + '-' + day + '-' + key;
+
+ var value = this._getStore(day, month, this.year, key);
+ if (value === undefined) {
+ value = '';
}
- $('#' + key).val(value);
+ $('#' + idTag).val(value);
return value;
}
+ /*
+ * Gets value from internal store.
+ */
+ _getStore(day, month, year, key) {
+ var idTag = year + '-' + month + '-' + day + '-' + key;
+
+ return this.internalStore[idTag];
+ }
+
+ /*
+ * Saves value on store and updates internal store.
+ */
+ _setStore(day, month, year, key, newValue) {
+ var idTag = year + '-' + month + '-' + day + '-' + key;
+
+ this.internalStore[idTag] = newValue;
+ store.set(idTag, newValue);
+ }
+
+ /*
+ * Removes value from store and from internal store.
+ */
+ _removeStore(day, month, year, key) {
+ var idTag = year + '-' + month + '-' + day + '-' + key;
+
+ this.internalStore[idTag] = undefined;
+ store.delete(idTag);
+ }
+
+ /*
+ * Gets value from internal waiver store.
+ */
+ _getWaiverStore(day, month, year) {
+ let dayKey = getDateStr(new Date(year, month, day));
+
+ return this.internalWaiverStore[dayKey];
+ }
+
/*
* Generates the calendar HTML view.
*/
@@ -175,10 +216,9 @@ class Calendar {
weekDay = currentDay.getDay(),
today = new Date(),
isToday = (today.getDate() === day && today.getMonth() === month && today.getFullYear() === year),
- trID = ('tr-' + year + '-' + month + '-' + day),
- dateStr = getDateStr(currentDay);
+ trID = ('tr-' + year + '-' + month + '-' + day);
- if (!showDay(year, month, day)) {
+ if (!this.showDay(year, month, day)) {
if (!this.hideNonWorkingDays) {
return '
' +
'
' + this.options.dayAbbrs[weekDay] + '
' +
@@ -190,8 +230,8 @@ class Calendar {
}
}
- if (waivedWorkdays.has(dateStr)) {
- var waivedInfo = waivedWorkdays.get(dateStr);
+ var waivedInfo = this._getWaiverStore(day, month, year);
+ if (waivedInfo !== undefined) {
var summaryStr = 'Waived day: ' + waivedInfo['reason'];
var waivedLineHtmlCode =
'
' +
@@ -228,10 +268,10 @@ class Calendar {
/*
* Returns the header of the page, with the image, name and a message.
*/
- _getPageHeader(year, month) {
+ _getPageHeader() {
var todayBut = '';
var leftBut = '';
- var rigthBut = '';
+ var rightBut = '';
return '
'+
'
' +
'
Time to Leave
' +
@@ -239,8 +279,8 @@ class Calendar {
'
' +
'
' +
'
' + leftBut + '
' +
- '
' + this.options.months[month] + ' ' + year + '
' +
- '
' + rigthBut + '
' +
+ '
' +
+ '
' + rightBut + '
' +
'
' + todayBut + '
' +
'
';
}
@@ -267,12 +307,12 @@ class Calendar {
*/
_getBalanceRowPosition() {
if (this.year !== this.today.getFullYear() || this.month !== this.today.getMonth()) {
- return this.getMonthLength();
+ return getMonthLength(this.year, this.month);
}
var balanceRowPosition = 0;
for (var day = 1; day < this.today.getDate(); ++day) {
- if (showDay(this.year, this.month, day)) {
+ if (this.showDay(this.year, this.month, day)) {
balanceRowPosition = day;
}
}
@@ -281,14 +321,27 @@ class Calendar {
}
/*
- * Returns the code of the body of the page.
+ * Returns the template code of the body of the page.
*/
_getBody() {
- var monthLength = this.getMonthLength();
var html = '
';
html += this._getPageHeader(this.year, this.month);
html += '
';
html += Calendar._getTableHeaderCode();
+ html += '';
+ html += '';
+ html += '
';
+ html += '
';
+
+ return html;
+ }
+
+ /*
+ * Returns the code of the table body of the calendar.
+ */
+ generateTableBody() {
+ var html;
+ var monthLength = getMonthLength(this.year, this.month);
var balanceRowPosition = this._getBalanceRowPosition();
for (var day = 1; day <= monthLength; ++day) {
@@ -297,14 +350,31 @@ class Calendar {
html += Calendar._getBalanceRowCode();
}
}
- html += ' ';
- html += '';
-
return html;
}
+ /*
+ * Updates the code of the table header of the calendar, to be called on demand.
+ */
+ updateTableHeader() {
+ $('#month-year').html(this.options.months[this.month] + ' ' + this.year);
+ }
+
+ /*
+ * Updates the code of the table body of the calendar, to be called on demand.
+ */
+ updateTableBody() {
+ $('#calendar-table-body').html(this.generateTableBody());
+ }
+
+ reload() {
+ this.loadInternalStore();
+ this.loadInternalWaiveStore();
+ this.redraw();
+ }
+
redraw() {
- this._initCalendar();
+ this._draw();
}
/*
@@ -317,7 +387,7 @@ class Calendar {
} else {
this.month += 1;
}
- this._initCalendar(this.month, this.year);
+ this.redraw();
}
/*
@@ -330,7 +400,7 @@ class Calendar {
} else {
this.month -= 1;
}
- this._initCalendar(this.month, this.year);
+ this.redraw();
}
/*
@@ -339,7 +409,7 @@ class Calendar {
goToCurrentDate() {
this.month = this.today.getMonth();
this.year = this.today.getFullYear();
- this._initCalendar(this.month, this.year);
+ this.redraw();
}
/*
@@ -356,14 +426,6 @@ class Calendar {
return this.month;
}
- /*
- * Gets month length of displayed calendar.
- */
- getMonthLength() {
- var d = new Date(this.year, this.month+1, 0);
- return d.getDate();
- }
-
/*
* Returns how many "hours per day" were set in preferences.
*/
@@ -376,11 +438,51 @@ class Calendar {
* @param {Object.} preferences
*/
updatePreferences(preferences) {
+ this.preferences = preferences;
this.countToday = preferences['count-today'];
this.hideNonWorkingDays = preferences['hide-non-working-days'];
this.hoursPerDay = preferences['hours-per-day'];
}
+ /**
+ * Stores year data in memory to make operations faster
+ */
+ loadInternalStore() {
+ this.internalStore = {};
+
+ for (const entry of store) {
+ const key = entry[0];
+ const value = entry[1];
+
+ this.internalStore[key] = value;
+ }
+ }
+
+ /**
+ * Stores waiver data in memory to make operations faster
+ */
+ loadInternalWaiveStore() {
+ this.internalWaiverStore = {};
+
+ for (const entry of waivedWorkdays) {
+ const date = entry[0];
+ const reason = entry[1]['reason'];
+ const hours = entry[1]['hours'];
+
+ this.internalWaiverStore[date] = {
+ 'hours': hours,
+ 'reason': reason
+ };
+ }
+ }
+
+ /*
+ * Calls showDay from user-preferences.js passing the last preferences set.
+ */
+ showDay(year, month, day) {
+ return showDay(year, month, day, this.preferences);
+ }
+
/*
* Adds the next missing entry on the actual day and updates calendar.
*/
@@ -394,7 +496,7 @@ class Calendar {
if (this.getMonth() !== month ||
this.getYear() !== year ||
- !showDay(year, month, day)) {
+ !this.showDay(year, month, day)) {
return;
}
@@ -425,13 +527,13 @@ class Calendar {
*/
updateBalance() {
var now = new Date(),
- monthLength = this.getMonthLength(),
+ monthLength = getMonthLength(this.year, this.month),
workingDaysToCompute = 0,
monthTotalWorked = '00:00';
var countDays = false;
for (var day = 1; day <= monthLength; ++day) {
- if (!showDay(this.year, this.month, day)) {
+ if (!this.showDay(this.year, this.month, day)) {
continue;
}
var isToday = (now.getDate() === day && now.getMonth() === this.month && now.getFullYear() === this.year);
@@ -465,33 +567,30 @@ class Calendar {
* Updates data displayed based on the database.
*/
updateBasedOnDB() {
- var monthLength = this.getMonthLength();
+ var monthLength = getMonthLength(this.year, this.month);
var monthTotal = '00:00';
this.workingDays = 0;
var stopCountingMonthStats = false;
for (var day = 1; day <= monthLength; ++day) {
- if (!showDay(this.year, this.month, day)) {
+ if (!this.showDay(this.year, this.month, day)) {
continue;
}
- var currentDay = new Date(this.year, this.month, day),
- dateStr = getDateStr(currentDay);
-
var dayTotal = null;
var dayStr = this.year + '-' + this.month + '-' + day + '-';
- if (waivedWorkdays.has(dateStr)) {
- var waivedInfo = waivedWorkdays.get(dateStr);
+ var waivedInfo = this._getWaiverStore(day, this.month, this.year);
+ if (waivedInfo !== undefined) {
var waivedDayTotal = waivedInfo['hours'];
$('#' + dayStr + 'day-total').val(waivedDayTotal);
dayTotal = waivedDayTotal;
} else {
- var lunchBegin = this._setData(dayStr + 'lunch-begin');
- var lunchEnd = this._setData(dayStr + 'lunch-end');
- this._setData(dayStr + 'lunch-total');
- var dayBegin = this._setData(dayStr + 'day-begin');
- var dayEnd = this._setData(dayStr + 'day-end');
- dayTotal = this._setData(dayStr + 'day-total');
+ var lunchBegin = this._setTableData(day, this.month, 'lunch-begin');
+ var lunchEnd = this._setTableData(day, this.month, 'lunch-end');
+ this._setTableData(day, this.month, 'lunch-total');
+ var dayBegin = this._setTableData(day, this.month, 'day-begin');
+ var dayEnd = this._setTableData(day, this.month, 'day-end');
+ dayTotal = this._setTableData(day, this.month, 'day-total');
this.colorErrorLine(this.year, this.month, day, dayBegin, lunchBegin, lunchEnd, dayEnd);
}
@@ -531,13 +630,13 @@ class Calendar {
* Update contents of the "time to leave" bar.
*/
updateLeaveBy() {
- if (!showDay(this.today.getFullYear(), this.today.getMonth(), this.today.getDate()) ||
+ if (!this.showDay(this.today.getFullYear(), this.today.getMonth(), this.today.getDate()) ||
this.today.getMonth() !== this.getMonth() ||
this.today.getFullYear() !== this.getYear() ||
- waivedWorkdays.has(getDateStr(this.today))) {
+ this._getWaiverStore(this.today.getDate(), this.month, this.year)) {
return;
}
- var [dayBegin, lunchBegin, lunchEnd, dayEnd] = this.getDaysEntriesFromHTML(this.today.getFullYear(), this.today.getMonth(), this.today.getDate());
+ var [dayBegin, lunchBegin, lunchEnd, dayEnd] = this.getDaysEntries(this.today.getMonth(), this.today.getDate());
var dayKey = this.today.getFullYear() + '-' + this.today.getMonth() + '-' + this.today.getDate() + '-';
if (validateTime(dayBegin)) {
var leaveBy = sumTime(dayBegin, this.getHoursPerDay());
@@ -550,7 +649,7 @@ class Calendar {
$('#leave-by').val('');
}
- if (dayBegin.length && lunchBegin.length && lunchEnd.length && dayEnd.length) {
+ if (dayBegin !== undefined && lunchBegin !== undefined && lunchEnd !== undefined && dayEnd !== undefined) {
//All entries computed
$('#punch-button').prop('disabled', true);
ipcRenderer.send('TOGGLE_TRAY_PUNCH_TIME', false);
@@ -593,19 +692,18 @@ class Calendar {
*/
updateTimeDay(year, month, day, key, newValue) {
var baseStr = year + '-' + month + '-' + day + '-';
- var dayStr = baseStr + key;
- var oldValue = store.get(dayStr);
+ var oldValue = this._getStore(day, month, year, key);
if (validateTime(newValue)) {
- store.set(dayStr, newValue);
+ this._setStore(day, month, year, key, newValue);
} else if (oldValue && validateTime(oldValue)) {
- store.delete(dayStr);
+ this._removeStore(day, month, year, key);
}
- var oldDayTotal = store.get(baseStr + 'day-total');
+ var oldDayTotal = this._getStore(day, month, year, 'day-total');
//update totals
- var [dayBegin, lunchBegin, lunchEnd, dayEnd] = this.getDaysEntries(year, month, day);
+ var [dayBegin, lunchBegin, lunchEnd, dayEnd] = this.getDaysEntries(month, day);
//compute lunch time
var lunchTime = '';
@@ -628,16 +726,16 @@ class Calendar {
}
if (lunchTime.length > 0) {
- store.set(baseStr + 'lunch-total', lunchTime);
+ this._setStore(day, month, year, 'lunch-total', lunchTime);
} else {
- store.delete(baseStr + 'lunch-total');
+ this._removeStore(day, month, year, 'lunch-total');
}
$('#' + baseStr + 'lunch-total').val(lunchTime);
if (dayTotal.length > 0) {
- store.set(baseStr + 'day-total', dayTotal);
+ this._setStore(day, month, year, 'day-total', dayTotal);
} else {
- store.delete(baseStr + 'day-total');
+ this._removeStore(day, month, year, 'day-total');
}
$('#' + baseStr + 'day-total').val(dayTotal);
@@ -655,25 +753,13 @@ class Calendar {
}
/*
- * Returns the entry values for the day, from the DB.
- */
- getDaysEntries(year, month, day) {
- var dayStr = year + '-' + month + '-' + day + '-';
- return [store.get(dayStr + 'day-begin'),
- store.get(dayStr + 'lunch-begin'),
- store.get(dayStr + 'lunch-end'),
- store.get(dayStr + 'day-end')];
- }
-
- /*
- * Returns the entry values for the day, from HTML (for performance).
+ * Returns the entry values for the day, from the internal store.
*/
- getDaysEntriesFromHTML(year, month, day) {
- var dayStr = year + '-' + month + '-' + day + '-';
- return [$('#' + dayStr + 'day-begin').val(),
- $('#' + dayStr + 'lunch-begin').val(),
- $('#' + dayStr + 'lunch-end').val(),
- $('#' + dayStr + 'day-end').val()];
+ getDaysEntries(month, day) {
+ return [this._getStore(day, month, this.year, 'day-begin'),
+ this._getStore(day, month, this.year, 'lunch-begin'),
+ this._getStore(day, month, this.year, 'lunch-end'),
+ this._getStore(day, month, this.year, 'day-end')];
}
/*
diff --git a/js/date-aux.js b/js/date-aux.js
index d6ba8816f..51bcc6447 100644
--- a/js/date-aux.js
+++ b/js/date-aux.js
@@ -9,6 +9,14 @@ function getDateStr(date) {
}
}
+/*
+ * Given a a year and month, returns how many days the month has
+ */
+function getMonthLength(year, month) {
+ var d = new Date(year, month+1, 0);
+ return d.getDate();
+}
+
module.exports = {
- getDateStr
+ getDateStr, getMonthLength
};
diff --git a/js/user-preferences.js b/js/user-preferences.js
index 1225d91ce..e54d39ef7 100644
--- a/js/user-preferences.js
+++ b/js/user-preferences.js
@@ -145,8 +145,10 @@ function getLoadedOrDerivedUserPreferences() {
/*
* Returns true if we should display week day.
*/
-function showWeekDay(weekDay) {
- var preferences = getLoadedOrDerivedUserPreferences();
+function showWeekDay(weekDay, preferences = undefined) {
+ if (preferences === undefined) {
+ preferences = getLoadedOrDerivedUserPreferences();
+ }
switch (weekDay) {
case 0: return preferences['working-days-sunday'];
case 1: return preferences['working-days-monday'];
@@ -162,9 +164,9 @@ function showWeekDay(weekDay) {
* Returns true if we should display day.
* @note: The month should be 0-based (i.e.: 0 is Jan, 11 is Dec).
*/
-function showDay(year, month, day) {
+function showDay(year, month, day, preferences = undefined) {
var currentDay = new Date(year, month, day), weekDay = currentDay.getDay();
- return showWeekDay(weekDay);
+ return showWeekDay(weekDay, preferences);
}
module.exports = {
diff --git a/main.js b/main.js
index b187f016d..ac6dd3b17 100644
--- a/main.js
+++ b/main.js
@@ -141,8 +141,7 @@ function createWindow() {
waiverWindow.show();
waiverWindow.on('close', function() {
waiverWindow = null;
- // Reload only the calendar itself to avoid a flash
- win.webContents.executeJavaScript('calendar.redraw()');
+ win.webContents.send('WAIVER_SAVED');
});
},
},
@@ -259,7 +258,7 @@ function createWindow() {
const importResult = importDatabaseFromFile(response);
if (importResult['result']) {
// Reload only the calendar itself to avoid a flash
- win.webContents.executeJavaScript('calendar.redraw()');
+ win.webContents.executeJavaScript('calendar.reload()');
dialog.showMessageBox(BrowserWindow.getFocusedWindow(),
{
title: 'Time to Leave',
@@ -304,7 +303,7 @@ function createWindow() {
store.clear();
waivedWorkdays.clear();
// Reload only the calendar itself to avoid a flash
- win.webContents.executeJavaScript('calendar.redraw()');
+ win.webContents.executeJavaScript('calendar.reload()');
dialog.showMessageBox(BrowserWindow.getFocusedWindow(),
{
title: 'Time to Leave',