Skip to content

Commit 71cc4ac

Browse files
authored
Merge pull request #591 from Flodgar/prefill-break-time
added option to prefill break time
2 parents 57b8520 + 9b97a4a commit 71cc4ac

25 files changed

+186
-29
lines changed

__tests__/__main__/time-math.js

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -162,8 +162,9 @@ describe('Time Math Functions', () =>
162162
expect(validateTime('00:11')).toBeTruthy();
163163
expect(validateTime('01:11')).toBeTruthy();
164164
expect(validateTime('11:11')).toBeTruthy();
165-
expect(validateTime('24:00')).toBeTruthy();
165+
expect(validateTime('23:59')).toBeTruthy();
166166
expect(validateTime('-04:00')).toBeTruthy();
167+
expect(validateTime('24:00')).not.toBeTruthy();
167168
expect(validateTime('34:00')).not.toBeTruthy();
168169
expect(validateTime('4:00')).not.toBeTruthy();
169170
expect(validateTime('00:1')).not.toBeTruthy();

__tests__/__renderer__/user-preferences.js

Lines changed: 19 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ const {
77
getUserPreferences,
88
savePreferences,
99
isNotBoolean,
10-
isValidPreferenceTime,
10+
isNotificationInterval,
1111
} = require('../../js/user-preferences');
1212
const fs = require('fs');
1313

@@ -23,19 +23,31 @@ describe('Should return false if the value is not boolean type', () =>
2323
});
2424
});
2525

26-
describe('Should return true if the value is a valid time', () =>
26+
describe('Should return true if the value is a valid notification interval', () =>
2727
{
28-
test('Value as time format (hh:mm)', () =>
28+
test('Value as number (val >= 1 || val <= 30)', () =>
2929
{
30-
expect(isValidPreferenceTime('00:35')).toBe(true);
30+
expect(isNotificationInterval(1)).toBe(true);
31+
expect(isNotificationInterval(15)).toBe(true);
32+
expect(isNotificationInterval(30)).toBe(true);
33+
expect(isNotificationInterval(-5)).not.toBe(true);
34+
expect(isNotificationInterval(0)).not.toBe(true);
35+
expect(isNotificationInterval(31)).not.toBe(true);
36+
expect(isNotificationInterval(60)).not.toBe(true);
3137
});
32-
test('Value as number type (val < 1 || val > 30)', () =>
38+
test('Value as string (val >= 1 || val <= 30)', () =>
3339
{
34-
expect(isValidPreferenceTime(60)).toBe(true);
40+
expect(isNotificationInterval('1')).toBe(true);
41+
expect(isNotificationInterval('30')).toBe(true);
42+
expect(isNotificationInterval('-5')).not.toBe(true);
43+
expect(isNotificationInterval('31')).not.toBe(true);
44+
expect(isNotificationInterval('A')).not.toBe(true);
45+
expect(isNotificationInterval('abc')).not.toBe(true);
3546
});
3647
test('Value as boolean type', () =>
3748
{
38-
expect(isValidPreferenceTime(true)).toBe(false);
49+
expect(isNotificationInterval(true)).not.toBe(true);
50+
expect(isNotificationInterval(false)).not.toBe(true);
3951
});
4052
});
4153

css/styles.css

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -535,6 +535,7 @@ input:checked + .slider::before {
535535
/* Notification settings */
536536

537537
#notifications-interval:disabled,
538+
#break-time-interval:disabled,
538539
input:disabled + .slider {
539540
background-color: var(--disabled-input-bground);
540541
}
@@ -659,7 +660,7 @@ input:disabled + .slider {
659660
left: 25px;
660661
}
661662

662-
#preferences-window #hours-per-day {
663+
#preferences-window #hours-per-day, #break-time-interval {
663664
text-align: right;
664665
}
665666

js/classes/BaseCalendar.js

Lines changed: 61 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,7 @@ class BaseCalendar
5050
/**
5151
* Returns a date object for which the all time balance will be calculated.
5252
* If current month, returns the actual day. If not, first day of following month.
53+
* // deepcode ignore valid-jsdoc: <not yet implemented>
5354
* @return {Date}
5455
*/
5556
_getTargetDayForAllTimeBalance()
@@ -274,6 +275,24 @@ class BaseCalendar
274275
return this._preferences['hide-non-working-days'];
275276
}
276277

278+
/**
279+
* Returns if "enable prefill break time" was set in preferences
280+
* @return {Boolean}
281+
*/
282+
_getEnablePrefillBreakTime()
283+
{
284+
return this._preferences['enable-prefill-break-time'];
285+
}
286+
287+
/**
288+
* Returns "break time interval" set in preferences
289+
* @return {string}
290+
*/
291+
_getBreakTimeInterval()
292+
{
293+
return this._preferences['break-time-interval'];
294+
}
295+
277296
/**
278297
* Returns if "count today" was set in preferences.
279298
* @return {Boolean}
@@ -388,6 +407,20 @@ class BaseCalendar
388407
this._togglePunchButton(enableButton);
389408
}
390409

410+
/**
411+
* Calculates time for break end based on break interval
412+
* @param {string} breakBegin
413+
* @return {string}
414+
*/
415+
_calculateBreakEnd(breakBegin)
416+
{
417+
let breakInterval = this._getBreakTimeInterval();
418+
let breakEnd = sumTime(breakBegin, breakInterval);
419+
420+
breakEnd = validateTime(breakEnd) ? breakEnd : '23:59';
421+
return breakEnd;
422+
}
423+
391424
/**
392425
* Adds the next missing entry on the actual day and updates calendar.
393426
*/
@@ -410,17 +443,42 @@ class BaseCalendar
410443
const value = hourMinToHourFormatted(hour, min);
411444
const key = generateKey(year, month, day);
412445
const inputs = $('#' + key + ' input[type="time"]');
413-
for (const element of inputs)
446+
447+
for (let i = 0; i < inputs.length; i++)
414448
{
415-
if ($(element).val().length === 0)
449+
if ($(inputs[i]).val().length === 0)
416450
{
417-
$(element).val(value);
451+
$(inputs[i]).val(value);
452+
453+
//Prefill break time
454+
if (this._prefillEntryIndex(i, inputs))
455+
{
456+
const breakEnd = this._calculateBreakEnd(value);
457+
$(inputs[i + 1]).val(breakEnd);
458+
}
418459
this._updateTimeDayCallback(key);
419460
break;
420461
}
421462
}
422463
}
423464

465+
/**
466+
* Returns true if next entry should be prefilled based on break interval
467+
* @param {number} idx
468+
* @param {array} inputs
469+
* @return {Boolean}
470+
*/
471+
_prefillEntryIndex(idx, inputs)
472+
{
473+
if (this._getEnablePrefillBreakTime() &&
474+
idx !== inputs.length - 1 &&
475+
idx % 2 === 1)
476+
{
477+
return true;
478+
}
479+
return false;
480+
}
481+
424482
/**
425483
* Based on the key of the input, updates the values for total in DB and display it on page.
426484
* @param {string} key

js/time-math.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -90,7 +90,7 @@ function sumTime(t1, t2)
9090
*/
9191
function validateTime(time)
9292
{
93-
let re = new RegExp('[0-2][0-9]:[0-5][0-9]');
93+
let re = new RegExp('^-?(0[0-9]|1[0-9]|2[0-3]):[0-5][0-9]$');
9494
return re.test(time);
9595
}
9696

js/user-preferences.js

Lines changed: 13 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,8 @@ const defaultPreferences = {
1818
'minimize-to-tray': true,
1919
'hide-non-working-days': false,
2020
'hours-per-day': '08:00',
21+
'enable-prefill-break-time': false,
22+
'break-time-interval': '00:30',
2123
'notification': true,
2224
'repetition': true,
2325
'notifications-interval': '5',
@@ -42,6 +44,7 @@ const booleanInputs = [
4244
'close-to-tray',
4345
'minimize-to-tray',
4446
'hide-non-working-days',
47+
'enable-prefill-break-time',
4548
'notification',
4649
'repetition',
4750
'start-at-login',
@@ -57,10 +60,11 @@ const booleanInputs = [
5760
const timeInputs = [
5861
'notifications-interval',
5962
'hours-per-day',
63+
'break-time-interval',
6064
];
6165

6266
const isNotBoolean = (val) => typeof val !== 'boolean';
63-
const isValidPreferenceTime = (val) => validateTime(val) || Number.isNaN(Number(val)) || val < 1 || val > 30;
67+
const isNotificationInterval = (val) => !Number.isNaN(Number(val)) && isNotBoolean(val) && val >= 1 && val <= 30;
6468

6569
/*
6670
* Returns the preference file path, considering the userData path
@@ -151,10 +155,14 @@ function initPreferencesFileIfNotExistsOrInvalid()
151155
shouldSaveDerivedPrefs = true;
152156
}
153157

154-
if (timeInputs.includes(key) && isValidPreferenceTime(value))
158+
if (timeInputs.includes(key))
155159
{
156-
derivedPrefs[key] = defaultPreferences[key];
157-
shouldSaveDerivedPrefs = true;
160+
// Set default preference value if notification or time interval is not valid
161+
if ((key === 'notifications-interval' && !isNotificationInterval(value)) || !validateTime(value))
162+
{
163+
derivedPrefs[key] = defaultPreferences[key];
164+
shouldSaveDerivedPrefs = true;
165+
}
158166
}
159167

160168
const inputEnum = {
@@ -290,7 +298,7 @@ module.exports = {
290298
showDay,
291299
switchCalendarView,
292300
isNotBoolean,
293-
isValidPreferenceTime,
301+
isNotificationInterval,
294302
notificationIsEnabled,
295303
repetitionIsEnabled
296304
};

locales/ca-CA/translation.json

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -140,6 +140,8 @@
140140
"hideNonWorkingDay": "Ocultar els dies no laborables (Vista mensual)",
141141
"hours-per-day": "HH:mm",
142142
"hoursPerDay": "Hores per dia",
143+
"enablePrefillBreakTime": "Enable prefilling of break time",
144+
"breakTimeInterval": "Break time interval",
143145
"language": "Llenguatge",
144146
"light": "Clar",
145147
"minimizeToTray": "El botó de minimitzar hauria de minimitzar a la safata",

locales/de-DE/translation.json

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -140,6 +140,8 @@
140140
"hideNonWorkingDay": "Arbeitsfreie Tage ausblenden (Monatsansicht)",
141141
"hours-per-day": "HH:mm",
142142
"hoursPerDay": "Stunden pro Tag",
143+
"enablePrefillBreakTime": "Enable prefilling of break time",
144+
"breakTimeInterval": "Break time interval",
143145
"language": "Sprache",
144146
"light": "Hell",
145147
"minimizeToTray": "Minimieren Button minimiert Fenster in den Tray",

locales/dev/translation.json

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -140,6 +140,8 @@
140140
"hideNonWorkingDay": "Ocultar dias não úteis (Visão de mês)",
141141
"hours-per-day": "HH:mm",
142142
"hoursPerDay": "Horas por dia",
143+
"enablePrefillBreakTime": "Enable prefilling of break time",
144+
"breakTimeInterval": "Break time interval",
143145
"language": "Idioma",
144146
"light": "Claro",
145147
"minimizeToTray": "Clicá no tracin isconde",

locales/en/translation.json

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -140,6 +140,8 @@
140140
"hideNonWorkingDay": "Hide non-working days (Month View)",
141141
"hours-per-day": "HH:mm",
142142
"hoursPerDay": "Hours per day",
143+
"enablePrefillBreakTime": "Enable prefilling of break time",
144+
"breakTimeInterval": "Break time interval",
143145
"language": "Language",
144146
"light": "Light",
145147
"minimizeToTray": "Minimize button should minimize to tray",

0 commit comments

Comments
 (0)