From d1520e4058e940a8203d7e8f137184e6525dec88 Mon Sep 17 00:00:00 2001 From: Arthur Araujo Date: Fri, 31 Jul 2020 20:55:23 -0300 Subject: [PATCH 1/4] Renaming all time balance functions --- __tests__/__main__/time-balance.js | 84 +++++++++++++++--------------- js/classes/Calendar.js | 4 +- js/time-balance.js | 10 ++-- 3 files changed, 49 insertions(+), 49 deletions(-) diff --git a/__tests__/__main__/time-balance.js b/__tests__/__main__/time-balance.js index 92deb5fba..61eb93ae4 100644 --- a/__tests__/__main__/time-balance.js +++ b/__tests__/__main__/time-balance.js @@ -1,7 +1,7 @@ /* eslint-disable no-undef */ const Store = require('electron-store'); const { - computeAllTimeBalancelUntil, + computeAllTimeBalanceUntil, getFirstInputInDb } = require('../../js/time-balance'); @@ -94,15 +94,15 @@ describe('Time Balance', () => { expect(getFirstInputInDb()).toBe('2020-6-6-day-begin'); }); - test('computeAllTimeBalancelUntil: no input', () => { + test('computeAllTimeBalanceUntil: no input', () => { const store = new Store(); const waivedWorkdays = new Store({ name: 'waived-workdays' }); store.clear(); waivedWorkdays.clear(); - expect(computeAllTimeBalancelUntil(new Date())).resolves.toBe('00:00'); + expect(computeAllTimeBalanceUntil(new Date())).resolves.toBe('00:00'); }); - test('computeAllTimeBalancelUntil: only regular days', () => { + test('computeAllTimeBalanceUntil: only regular days', () => { const store = new Store(); const waivedWorkdays = new Store({ name: 'waived-workdays' }); store.clear(); @@ -112,20 +112,20 @@ describe('Time Balance', () => { }; store.set(entryEx); // time balance until thu (excluding thu) - expect(computeAllTimeBalancelUntil(new Date(2020, 6, 2))).resolves.toBe('00:00'); + expect(computeAllTimeBalanceUntil(new Date(2020, 6, 2))).resolves.toBe('00:00'); // time balance until fri (excluding fri) - expect(computeAllTimeBalancelUntil(new Date(2020, 6, 3))).resolves.toBe('-08:00'); + expect(computeAllTimeBalanceUntil(new Date(2020, 6, 3))).resolves.toBe('-08:00'); // time balance until sat (excluding sat) - expect(computeAllTimeBalancelUntil(new Date(2020, 6, 4))).resolves.toBe('-16:00'); + expect(computeAllTimeBalanceUntil(new Date(2020, 6, 4))).resolves.toBe('-16:00'); // time balance until sun (excluding sun) - expect(computeAllTimeBalancelUntil(new Date(2020, 6, 5))).resolves.toBe('-16:00'); + expect(computeAllTimeBalanceUntil(new Date(2020, 6, 5))).resolves.toBe('-16:00'); // time balance until mon (excluding mon) - expect(computeAllTimeBalancelUntil(new Date(2020, 6, 6))).resolves.toBe('-16:00'); + expect(computeAllTimeBalanceUntil(new Date(2020, 6, 6))).resolves.toBe('-16:00'); // time balance until tue (excluding tue) - expect(computeAllTimeBalancelUntil(new Date(2020, 6, 7))).resolves.toBe('-24:00'); + expect(computeAllTimeBalanceUntil(new Date(2020, 6, 7))).resolves.toBe('-24:00'); }); - test('computeAllTimeBalancelUntil: only regular days (with overtime)', () => { + test('computeAllTimeBalanceUntil: only regular days (with overtime)', () => { const store = new Store(); const waivedWorkdays = new Store({ name: 'waived-workdays' }); store.clear(); @@ -135,14 +135,14 @@ describe('Time Balance', () => { }; store.set(entryEx); // time balance until thu (excluding thu) - expect(computeAllTimeBalancelUntil(new Date(2020, 6, 2))).resolves.toBe('01:30'); + expect(computeAllTimeBalanceUntil(new Date(2020, 6, 2))).resolves.toBe('01:30'); // time balance until fri (excluding fri) - expect(computeAllTimeBalancelUntil(new Date(2020, 6, 3))).resolves.toBe('-06:30'); + expect(computeAllTimeBalanceUntil(new Date(2020, 6, 3))).resolves.toBe('-06:30'); // time balance until sat (excluding sat) - expect(computeAllTimeBalancelUntil(new Date(2020, 6, 4))).resolves.toBe('-14:30'); + expect(computeAllTimeBalanceUntil(new Date(2020, 6, 4))).resolves.toBe('-14:30'); }); - test('computeAllTimeBalancelUntil: only regular days (with undertime)', () => { + test('computeAllTimeBalanceUntil: only regular days (with undertime)', () => { const store = new Store(); const waivedWorkdays = new Store({ name: 'waived-workdays' }); store.clear(); @@ -152,14 +152,14 @@ describe('Time Balance', () => { }; store.set(entryEx); // time balance until thu (excluding thu) - expect(computeAllTimeBalancelUntil(new Date(2020, 6, 2))).resolves.toBe('-01:45'); + expect(computeAllTimeBalanceUntil(new Date(2020, 6, 2))).resolves.toBe('-01:45'); // time balance until fri (excluding fri) - expect(computeAllTimeBalancelUntil(new Date(2020, 6, 3))).resolves.toBe('-09:45'); + expect(computeAllTimeBalanceUntil(new Date(2020, 6, 3))).resolves.toBe('-09:45'); // time balance until sat (excluding sat) - expect(computeAllTimeBalancelUntil(new Date(2020, 6, 4))).resolves.toBe('-17:45'); + expect(computeAllTimeBalanceUntil(new Date(2020, 6, 4))).resolves.toBe('-17:45'); }); - test('computeAllTimeBalancelUntil: only regular days (with mixed time)', () => { + test('computeAllTimeBalanceUntil: only regular days (with mixed time)', () => { const store = new Store(); const waivedWorkdays = new Store({ name: 'waived-workdays' }); store.clear(); @@ -171,14 +171,14 @@ describe('Time Balance', () => { }; store.set(entryEx); // time balance until thu (excluding thu) - expect(computeAllTimeBalancelUntil(new Date(2020, 6, 2))).resolves.toBe('-01:45'); + expect(computeAllTimeBalanceUntil(new Date(2020, 6, 2))).resolves.toBe('-01:45'); // time balance until fri (excluding fri) - expect(computeAllTimeBalancelUntil(new Date(2020, 6, 3))).resolves.toBe('-00:30'); + expect(computeAllTimeBalanceUntil(new Date(2020, 6, 3))).resolves.toBe('-00:30'); // time balance until sat (excluding sat) - expect(computeAllTimeBalancelUntil(new Date(2020, 6, 4))).resolves.toBe('-02:15'); + expect(computeAllTimeBalanceUntil(new Date(2020, 6, 4))).resolves.toBe('-02:15'); }); - test('computeAllTimeBalancelUntil: missing entries', () => { + test('computeAllTimeBalanceUntil: missing entries', () => { const store = new Store(); const waivedWorkdays = new Store({ name: 'waived-workdays' }); store.clear(); @@ -189,16 +189,16 @@ describe('Time Balance', () => { }; store.set(entryEx); // time balance until thu (excluding thu) - expect(computeAllTimeBalancelUntil(new Date(2020, 6, 2))).resolves.toBe('00:00'); + expect(computeAllTimeBalanceUntil(new Date(2020, 6, 2))).resolves.toBe('00:00'); // time balance until fri (excluding fri) - expect(computeAllTimeBalancelUntil(new Date(2020, 6, 3))).resolves.toBe('-08:00'); + expect(computeAllTimeBalanceUntil(new Date(2020, 6, 3))).resolves.toBe('-08:00'); // time balance until sat (excluding sat) - expect(computeAllTimeBalancelUntil(new Date(2020, 6, 4))).resolves.toBe('-08:00'); + expect(computeAllTimeBalanceUntil(new Date(2020, 6, 4))).resolves.toBe('-08:00'); // time balance until sun (excluding sun) - expect(computeAllTimeBalancelUntil(new Date(2020, 6, 5))).resolves.toBe('-08:00'); + expect(computeAllTimeBalanceUntil(new Date(2020, 6, 5))).resolves.toBe('-08:00'); }); - test('computeAllTimeBalancelUntil: with waived days', () => { + test('computeAllTimeBalanceUntil: with waived days', () => { const store = new Store(); const waivedWorkdays = new Store({ name: 'waived-workdays' }); store.clear(); @@ -213,14 +213,14 @@ describe('Time Balance', () => { }; waivedWorkdays.set(waivedEntries); // time balance until thu (excluding thu) - expect(computeAllTimeBalancelUntil(new Date(2020, 6, 2))).resolves.toBe('00:00'); + expect(computeAllTimeBalanceUntil(new Date(2020, 6, 2))).resolves.toBe('00:00'); // time balance until fri (excluding fri) - expect(computeAllTimeBalancelUntil(new Date(2020, 6, 3))).resolves.toBe('00:00'); + expect(computeAllTimeBalanceUntil(new Date(2020, 6, 3))).resolves.toBe('00:00'); // time balance until sat (excluding sat) - expect(computeAllTimeBalancelUntil(new Date(2020, 6, 4))).resolves.toBe('00:00'); + expect(computeAllTimeBalanceUntil(new Date(2020, 6, 4))).resolves.toBe('00:00'); }); - test('computeAllTimeBalancelUntil: with waived days 2', () => { + test('computeAllTimeBalanceUntil: with waived days 2', () => { const store = new Store(); const waivedWorkdays = new Store({ name: 'waived-workdays' }); store.clear(); @@ -235,16 +235,16 @@ describe('Time Balance', () => { }; waivedWorkdays.set(waivedEntries); // time balance until wed (excluding wed) - expect(computeAllTimeBalancelUntil(new Date(2020, 6, 8))).resolves.toBe('00:00'); + expect(computeAllTimeBalanceUntil(new Date(2020, 6, 8))).resolves.toBe('00:00'); // time balance until tue (excluding tue) - expect(computeAllTimeBalancelUntil(new Date(2020, 6, 9))).resolves.toBe('00:00'); + expect(computeAllTimeBalanceUntil(new Date(2020, 6, 9))).resolves.toBe('00:00'); // time balance until fri (excluding fri) - expect(computeAllTimeBalancelUntil(new Date(2020, 6, 10))).resolves.toBe('00:00'); + expect(computeAllTimeBalanceUntil(new Date(2020, 6, 10))).resolves.toBe('00:00'); // time balance until sat (excluding sat) - expect(computeAllTimeBalancelUntil(new Date(2020, 6, 11))).resolves.toBe('00:00'); + expect(computeAllTimeBalanceUntil(new Date(2020, 6, 11))).resolves.toBe('00:00'); }); - test('computeAllTimeBalancelUntil: with waived days (not full)', () => { + test('computeAllTimeBalanceUntil: with waived days (not full)', () => { const store = new Store(); const waivedWorkdays = new Store({ name: 'waived-workdays' }); store.clear(); @@ -259,14 +259,14 @@ describe('Time Balance', () => { }; waivedWorkdays.set(waivedEntries); // time balance until tue (excluding tue) - expect(computeAllTimeBalancelUntil(new Date(2020, 6, 2))).resolves.toBe('00:00'); + expect(computeAllTimeBalanceUntil(new Date(2020, 6, 2))).resolves.toBe('00:00'); // time balance until fri (excluding fri) - expect(computeAllTimeBalancelUntil(new Date(2020, 6, 3))).resolves.toBe('-06:00'); + expect(computeAllTimeBalanceUntil(new Date(2020, 6, 3))).resolves.toBe('-06:00'); // time balance until sat (excluding sat) - expect(computeAllTimeBalancelUntil(new Date(2020, 6, 4))).resolves.toBe('-06:00'); + expect(computeAllTimeBalanceUntil(new Date(2020, 6, 4))).resolves.toBe('-06:00'); }); - test('computeAllTimeBalancelUntil: target date in the past of entries', () => { + test('computeAllTimeBalanceUntil: target date in the past of entries', () => { const store = new Store(); const waivedWorkdays = new Store({ name: 'waived-workdays' }); store.clear(); @@ -280,6 +280,6 @@ describe('Time Balance', () => { '2020-07-02': { reason: 'Waiver', hours: '02:00' }, // tue }; waivedWorkdays.set(waivedEntries); - expect(computeAllTimeBalancelUntil(new Date(2020, 5, 1))).resolves.toBe('00:00'); + expect(computeAllTimeBalanceUntil(new Date(2020, 5, 1))).resolves.toBe('00:00'); }); }); \ No newline at end of file diff --git a/js/classes/Calendar.js b/js/classes/Calendar.js index b0af7e2eb..eb23414f1 100644 --- a/js/classes/Calendar.js +++ b/js/classes/Calendar.js @@ -17,7 +17,7 @@ const { sendWaiverDay, displayWaiverWindow } = require('../workday-waiver-aux.js'); -const { computeAllTimeBalancelUntilAsync } = require('../time-balance.js'); +const { computeAllTimeBalanceUntilAsync } = require('../time-balance.js'); // Global values for calendar const store = new Store(); @@ -97,7 +97,7 @@ class Calendar { if (isCurrentMonth && this._getCountToday()) { targetDate.setDate(targetDate.getDate() + 1); } - computeAllTimeBalancelUntilAsync(targetDate).then(balance => { + computeAllTimeBalanceUntilAsync(targetDate).then(balance => { var balanceElement = $('#overall-balance'); if (balanceElement) { balanceElement.val(balance); diff --git a/js/time-balance.js b/js/time-balance.js index b5942ec60..0abd25863 100644 --- a/js/time-balance.js +++ b/js/time-balance.js @@ -53,7 +53,7 @@ function _getBalanceForDay(date, hoursPerDay) { return dayBalance; } -async function computeAllTimeBalancelUntil(day) { +async function computeAllTimeBalanceUntil(day) { const preferences = getUserPreferences(); const firstInput = getFirstInputInDb(); if (firstInput === '') { @@ -74,16 +74,16 @@ async function computeAllTimeBalancelUntil(day) { return allTimeTotal; } -async function computeAllTimeBalancelUntilAsync(day) { +async function computeAllTimeBalanceUntilAsync(day) { return new Promise(resolve => { setTimeout(() => { - resolve(computeAllTimeBalancelUntil(day)); + resolve(computeAllTimeBalanceUntil(day)); }, 1); }); } module.exports = { - computeAllTimeBalancelUntilAsync, - computeAllTimeBalancelUntil, + computeAllTimeBalanceUntilAsync, + computeAllTimeBalanceUntil, getFirstInputInDb }; \ No newline at end of file From f6644acba99592551fe653a713d100588ba5bf91 Mon Sep 17 00:00:00 2001 From: Arthur Araujo Date: Fri, 31 Jul 2020 21:58:40 -0300 Subject: [PATCH 2/4] Target date for all time balance to use today's date --- js/classes/Calendar.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/js/classes/Calendar.js b/js/classes/Calendar.js index eb23414f1..5e54d8642 100644 --- a/js/classes/Calendar.js +++ b/js/classes/Calendar.js @@ -92,7 +92,7 @@ class Calendar { // last day of the month. To do so we move to the first day of the following month isCurrentMonth = targetYear === this._getTodayYear() && targetMonth === this._getTodayMonth(), targetDate = isCurrentMonth ? - new Date(targetYear, targetMonth, this._getCalendarDate()) : + new Date(targetYear, targetMonth, this._getTodayDate()) : new Date(targetYear, targetMonth + 1, 1); if (isCurrentMonth && this._getCountToday()) { targetDate.setDate(targetDate.getDate() + 1); From 3c9ff935f864b6a5243886c6f8a9a43330680c60 Mon Sep 17 00:00:00 2001 From: Arthur Araujo Date: Fri, 31 Jul 2020 22:12:44 -0300 Subject: [PATCH 3/4] Fix #334: Improving performance of all time balance by avoiding store.get --- js/time-balance.js | 92 +++++++++++++++++++++++++++++++++------------- 1 file changed, 67 insertions(+), 25 deletions(-) diff --git a/js/time-balance.js b/js/time-balance.js index 0abd25863..5fe560e2d 100644 --- a/js/time-balance.js +++ b/js/time-balance.js @@ -23,13 +23,23 @@ function getFirstInputInDb() { return inputs.length ? inputs[0] : ''; } -function _formatDateForWaivedWorkdayDb(year, month, day) { +/** +* @param {string} dbKey given key of the db +*/ +function _getDateFromStoreDb(dbKey) { + // Normal Store is formated with month described by 0-11 (jan - dec) + const [year, month, day] = dbKey.split('-'); + return new Date(year, month, day); +} + +/** +* @param {string} dbKey given key of the db +*/ +function _getDateFromWaivedWorkdayDb(dbKey) { // WaivedWorkday are formated with two digits for the month/day (01 instead of 1) // and has the month described by 1-12 (jan - dec) - function twoDigitNumber(num) { - return num < 10 ? `0${num}` : `${num}`; - } - return `${year}-${twoDigitNumber(month + 1)}-${twoDigitNumber(day)}`; + const [year, month, day] = dbKey.split('-'); + return new Date(year, month-1, day); } function _getHoursPerDay() { @@ -37,47 +47,79 @@ function _getHoursPerDay() { return savedPreferences['hours-per-day']; } -function _getBalanceForDay(date, hoursPerDay) { - const totalForDay = store.get(`${date.getFullYear()}-${date.getMonth()}-${date.getDate()}-day-total`); - const waivedDay = waivedWorkdays.get(_formatDateForWaivedWorkdayDb(date.getFullYear(), date.getMonth(), date.getDate())); - // add worked/waived count - var dayBalance = '00:00'; - if (waivedDay !== undefined) { - dayBalance = waivedDay['hours']; - } else if (totalForDay !== undefined) { - dayBalance = totalForDay; +/** +* Iterates over stores and returns total balance. +* Since waiver store precedes normal store, must not get from normal store if day is waived. +* @param {Date} firstDate +* @param {Date} limitDate +*/ +function _getDayTotalsFromStores(firstDate, limitDate) { + const preferences = getUserPreferences(); + + let totals = {}; + for (let value of waivedWorkdays) { + let date = _getDateFromWaivedWorkdayDb(value[0]); + const dateShown = showDay(date.getFullYear(), date.getMonth(), date.getDate(), preferences); + if (date >= firstDate && date <= limitDate && dateShown) { + totals[getDateStr(date)] = value[1]['hours']; + } + } + for (let value of store) { + if (value[0].endsWith('-day-total')) { + let date = _getDateFromStoreDb(value[0]); + if (!(getDateStr(date) in totals)) { + const dateShown = showDay(date.getFullYear(), date.getMonth(), date.getDate(), preferences); + if (date >= firstDate && date <= limitDate && dateShown) { + const totalForDay = value[1]; + totals[getDateStr(date)] = totalForDay; + } + } + } } - // From the worked/waived count, subtract the expected work time for the day - dayBalance = subtractTime(hoursPerDay, dayBalance); - return dayBalance; + return totals; } -async function computeAllTimeBalanceUntil(day) { - const preferences = getUserPreferences(); +/** +* Computation of all time balance, including limitDay. +* @param {Date} limitDate +*/ +async function computeAllTimeBalanceUntil(limitDate) { const firstInput = getFirstInputInDb(); if (firstInput === '') { return '00:00'; } var [firstYear, firstMonth, firstDay] = firstInput.split('-'); - var date = new Date(firstYear, firstMonth, firstDay); + var firstDate = new Date(firstYear, firstMonth, firstDay); + + let totals = _getDayTotalsFromStores(firstDate, limitDate); - var allTimeTotal = '00:00'; + const preferences = getUserPreferences(); const hoursPerDay = _getHoursPerDay(); - while (getDateStr(date) !== getDateStr(day) && day > date) { + let allTimeTotal = '00:00'; + let date = new Date(firstDate); + const limitDateStr = getDateStr(limitDate); + let dateStr = getDateStr(date); + while (dateStr !== limitDateStr && limitDate > date) { if (showDay(date.getFullYear(), date.getMonth(), date.getDate(), preferences)) { - const dayBalance = _getBalanceForDay(date, hoursPerDay); + const dayTotal = dateStr in totals ? totals[dateStr] : '00:00'; + const dayBalance = subtractTime(hoursPerDay, dayTotal); allTimeTotal = sumTime(dayBalance, allTimeTotal); } date.setDate(date.getDate() + 1); + dateStr = getDateStr(date); } return allTimeTotal; } -async function computeAllTimeBalanceUntilAsync(day) { +/** +* Computes all time balance using an async promise. +* @param {Date} limitDate +*/ +async function computeAllTimeBalanceUntilAsync(limitDate) { return new Promise(resolve => { setTimeout(() => { - resolve(computeAllTimeBalanceUntil(day)); + resolve(computeAllTimeBalanceUntil(limitDate)); }, 1); }); } From 033da66a372b311dc1bacedb29792acec9c2401b Mon Sep 17 00:00:00 2001 From: Arthur Araujo Date: Thu, 6 Aug 2020 20:15:57 -0300 Subject: [PATCH 4/4] All time balance target dates for Month and Day Calendar --- changelog.txt | 1 + js/classes/Calendar.js | 28 ++++++++++++++++++++++++++-- 2 files changed, 27 insertions(+), 2 deletions(-) diff --git a/changelog.txt b/changelog.txt index d3407a0f3..91ce92971 100644 --- a/changelog.txt +++ b/changelog.txt @@ -1,6 +1,7 @@ 1.5.6 (in development) ------------------------------------------------------------------------ - Fix: Fixed behavior of calendar when moving to next/previous month when current day is in the range of 29-31. +- Fix: [#334] Improving performance of overall balance calculation and fixing balance target date after month change - Enhancement: [#328] Swap position for overall and month balance on day view Who built 1.5.6: diff --git a/js/classes/Calendar.js b/js/classes/Calendar.js index 5e54d8642..1a11a1c88 100644 --- a/js/classes/Calendar.js +++ b/js/classes/Calendar.js @@ -85,8 +85,13 @@ class Calendar { this._draw(); } - _updateAllTimeBalance() { - var targetYear = this._getCalendarYear(), + /** + * Returns a date object for which the all time balance will be calculated. + * If current month, returns the actual day. If not, first day of following month. + * @return {Date} + */ + _getTargetDayForAllTimeBalance() { + let targetYear = this._getCalendarYear(), targetMonth = this._getCalendarMonth(), // If we are not displaying the current month we need to compute the balance including the // last day of the month. To do so we move to the first day of the following month @@ -97,6 +102,11 @@ class Calendar { if (isCurrentMonth && this._getCountToday()) { targetDate.setDate(targetDate.getDate() + 1); } + return targetDate; + } + + _updateAllTimeBalance() { + const targetDate = this._getTargetDayForAllTimeBalance(); computeAllTimeBalanceUntilAsync(targetDate).then(balance => { var balanceElement = $('#overall-balance'); if (balanceElement) { @@ -1255,6 +1265,20 @@ class DayCalendar extends Calendar { this._updateLeaveBy(); } + + /** + * Returns a date object for which the all time balance will be calculated. + * For DayCalendar, it's the day of CalendarDate => the day being displayed. + * If "count_today" is active, the following day. + * @return {Date} + */ + _getTargetDayForAllTimeBalance() { + let targetDate = new Date(this._getCalendarYear(), this._getCalendarMonth(), this._getCalendarDate()); + if (this._getCountToday()) { + targetDate.setDate(targetDate.getDate() + 1); + } + return targetDate; + } } module.exports = {