WIP timesheet timers: do not allow to enter a time before the last time entered

eg. a stop- or pause-time before the start-time or a start-time before the last stop- or pause-time
This commit is contained in:
ralf 2022-10-11 16:19:58 +02:00
parent 11a4e21cb8
commit 075ba0f330
4 changed files with 77 additions and 11 deletions

View File

@ -55,6 +55,7 @@ egw.extend('timer', egw.MODULE_GLOBAL, function()
{ {
stopTimer(overall); stopTimer(overall);
} }
overall.last = _state.overall.last ? new Date(_state.overall.last) : undefined;
// initiate specific timer, only if running or paused // initiate specific timer, only if running or paused
if (_state.specific?.start || _state.specific?.paused) if (_state.specific?.start || _state.specific?.paused)
@ -70,6 +71,7 @@ egw.extend('timer', egw.MODULE_GLOBAL, function()
stopTimer(specific); stopTimer(specific);
} }
} }
specific.last = _state.specific.last ? new Date(_state.specific.last) : undefined;
} }
/** /**
@ -256,15 +258,14 @@ egw.extend('timer', egw.MODULE_GLOBAL, function()
*/ */
function startTimer(_timer, _start, _offset) function startTimer(_timer, _start, _offset)
{ {
const time = _start ? new Date(_start) : new Date();
if (_timer.last && time.valueOf() < _timer.last.valueOf())
{
throw egw.lang('Start-time can not be before last stop- or pause-time %1!', formatUTCTime(_timer.last));
}
// update _timer state object // update _timer state object
if (_start) _timer.last = _timer.start = time;
{
_timer.start = new Date(_start);
}
else if(typeof _timer.start === 'undefined')
{
_timer.start = new Date();
}
if (_offset || _timer.offset && _timer.paused) if (_offset || _timer.offset && _timer.paused)
{ {
_timer.start.setMilliseconds(_timer.start.getMilliseconds()-(_offset || _timer.offset)); _timer.start.setMilliseconds(_timer.start.getMilliseconds()-(_offset || _timer.offset));
@ -296,17 +297,29 @@ egw.extend('timer', egw.MODULE_GLOBAL, function()
function stopTimer(_timer, _pause, _time) function stopTimer(_timer, _pause, _time)
{ {
const time = _time ? new Date(_time) : new Date(); const time = _time ? new Date(_time) : new Date();
if (time.valueOf() < _timer.last.valueOf())
{
const last_time = formatUTCTime(_timer.last);
if (_timer.start)
{
throw egw.lang('Stop- or pause-time can not be before the start-time %1!', last_time);
}
else
{
throw egw.lang('Start-time can not be before last stop- or pause-time %1!', last_time);
}
}
// update _timer state object // update _timer state object
if (_timer.start) if (_timer.start)
{ {
if (time.valueOf() < _timer.start.valueOf()) if (time.valueOf() < _timer.start.valueOf())
{ {
throw egw.lang('Stop- or pause-time can not be before the start-time!');
} }
_timer.offset = time.valueOf() - _timer.start.valueOf(); _timer.offset = time.valueOf() - _timer.start.valueOf();
_timer.start = undefined; _timer.start = undefined;
} }
_timer.paused = _pause || false; _timer.paused = _pause || false;
_timer.last = time;
// update timer display // update timer display
updateTimer(timer, _timer); updateTimer(timer, _timer);
@ -333,6 +346,50 @@ egw.extend('timer', egw.MODULE_GLOBAL, function()
} }
} }
/**
* Format a time according to user preference
*
* Cant import from DateTime.ts, gives an error ;)
*
* @param {Date} date
* @param {Object|undefined} options object containing attribute timeFormat=12|24, default user preference
* @returns {string}
*/
function formatTime(date, options)
{
if(!date || !(date instanceof Date))
{
return "";
}
let _value = '';
let timeformat = options?.timeFormat || egw.preference("timeformat") || "24";
let hours = (timeformat == "12" && date.getUTCHours() > 12) ? (date.getUTCHours() - 12) : date.getUTCHours();
if(timeformat == "12" && hours == 0)
{
// 00:00 is 12:00 am
hours = 12;
}
_value = (timeformat == "24" && hours < 10 ? "0" : "") + hours + ":" +
(date.getUTCMinutes() < 10 ? "0" : "") + (date.getUTCMinutes()) +
(timeformat == "24" ? "" : (date.getUTCHours() < 12 ? " am" : " pm"));
return _value;
}
/**
* Format a UTC time according to user preference
*
* @param {Date} date
* @returns {string}
*/
function formatUTCTime(date)
{
// eT2 operates in user-time, while timers here always operate in UTC
return formatTime(new Date(date.valueOf() - egw.getTimezoneOffset() * 60000));
}
return { return {
/** /**
* Start timer for given app and id * Start timer for given app and id

View File

@ -131,6 +131,7 @@ skip record timesheet de Eintrag überspringen
start timesheet de Start start timesheet de Start
start & stop timer common de Zeitnehmer starten & stoppen start & stop timer common de Zeitnehmer starten & stoppen
start timer common de Zeitnehmer starten start timer common de Zeitnehmer starten
start-time can not be before last stop- or pause-time %1! common de Start-Zeit kann nicht vor der letzen Stop- oder Pausen-Zeit %1 liegen!
starttime timesheet de Startzeit starttime timesheet de Startzeit
starttime has to be before endtime !!! timesheet de Startzeit muss vor der Endzeit liegen !!! starttime has to be before endtime !!! timesheet de Startzeit muss vor der Endzeit liegen !!!
status timesheet de Status status timesheet de Status
@ -138,7 +139,7 @@ status deleted. timesheet de Status gelöscht
status of created timesheets timesheet de Status für neue Stundenzettel status of created timesheets timesheet de Status für neue Stundenzettel
status updated. timesheet de Status geändert status updated. timesheet de Status geändert
stop common de Stop stop common de Stop
stop- or pause-time can not be before the start-time! common de Stop- oder Pause-Zeit kann nicht vor der Start-Zeit liegen! stop- or pause-time can not be before the start-time %1! common de Stop- oder Pausen-Zeit kann nicht for der Start-Zeit %1 liegen!
sum timesheet de Summe sum timesheet de Summe
sum %1: timesheet de Summe %1: sum %1: timesheet de Summe %1:
tag to mark positions for address labels timesheet de Platzhalter, um die Position der Adresslabels festzulegen tag to mark positions for address labels timesheet de Platzhalter, um die Position der Adresslabels festzulegen

View File

@ -131,6 +131,7 @@ skip record timesheet en Skip record
start timesheet en Start start timesheet en Start
start & stop timer common en Start & stop timer start & stop timer common en Start & stop timer
start timer common en Start timer start timer common en Start timer
start-time can not be before last stop- or pause-time %1! common en Start-time can not be before last stop- or pause-time %1!
starttime timesheet en Start time starttime timesheet en Start time
starttime has to be before endtime !!! timesheet en Start time has to be before endtime! starttime has to be before endtime !!! timesheet en Start time has to be before endtime!
status timesheet en Status status timesheet en Status
@ -138,7 +139,7 @@ status deleted. timesheet en Status deleted.
status of created timesheets timesheet en Status of created timesheets status of created timesheets timesheet en Status of created timesheets
status updated. timesheet en Status updated. status updated. timesheet en Status updated.
stop common en Stop stop common en Stop
stop- or pause-time can not be before the start-time! common en Stop- or pause-time can not be before the start-time! stop- or pause-time can not be before the start-time %1! common en Stop- or pause-time can not be before the start-time %1!
sum timesheet en Sum sum timesheet en Sum
sum %1: timesheet en Sum %1: sum %1: timesheet en Sum %1:
tag to mark positions for address labels timesheet en Tag to mark positions for address labels tag to mark positions for address labels timesheet en Tag to mark positions for address labels

View File

@ -201,11 +201,13 @@ class Events extends Api\Storage\Base
'offset' => 0, 'offset' => 0,
'start' => null, 'start' => null,
'paused' => false, 'paused' => false,
'last' => null,
], ],
'specific' => [ 'specific' => [
'offset' => 0, 'offset' => 0,
'start' => null, 'start' => null,
'paused' => false, 'paused' => false,
'last' => null,
], ],
]; ];
foreach(self::getInstance()->search('', false, 'tse_id', '', '', false, 'AND', false, [ foreach(self::getInstance()->search('', false, 'tse_id', '', '', false, 'AND', false, [
@ -244,6 +246,10 @@ class Events extends Api\Storage\Base
{ {
$timer['start'] = (new Api\DateTime($timer['start'], new \DateTimeZone('UTC')))->format(Api\DateTime::ET2); $timer['start'] = (new Api\DateTime($timer['start'], new \DateTimeZone('UTC')))->format(Api\DateTime::ET2);
} }
if (isset($timer['last']))
{
$timer['last'] = (new Api\DateTime($timer['last'], new \DateTimeZone('UTC')))->format(Api\DateTime::ET2);
}
} }
// send timer configuration to client-side // send timer configuration to client-side
$config = Api\Config::read(self::APP); $config = Api\Config::read(self::APP);
@ -280,6 +286,7 @@ class Events extends Api\Storage\Base
{ {
$timer['paused'] = ($row['tse_type'] & self::PAUSE) === self::PAUSE; $timer['paused'] = ($row['tse_type'] & self::PAUSE) === self::PAUSE;
} }
$timer['last'] = $row['tse_time'];
return $time ?? null; return $time ?? null;
} }