WIP timesheet timer: start, pause and stop now via a dialog showing both timers and all buttons

This commit is contained in:
ralf 2022-10-05 12:51:59 +02:00
parent ed05a8b6ee
commit 8fad43b705
8 changed files with 417 additions and 297 deletions

View File

@ -82,7 +82,7 @@ egw.extend('calendar', egw.MODULE_WND_LOCAL, function(_app, _wnd)
* *
* If browser / OS is configured correct, identical to: (new Date()).getTimezoneOffset() * If browser / OS is configured correct, identical to: (new Date()).getTimezoneOffset()
* *
* @return {number} offset to UTC in seconds * @return {number} offset to UTC in minutes
*/ */
getTimezoneOffset: function() { getTimezoneOffset: function() {
return isNaN(egw.preference('timezoneoffset')) ? (new Date()).getTimezoneOffset() : parseInt(egw.preference('timezoneoffset')); return isNaN(egw.preference('timezoneoffset')) ? (new Date()).getTimezoneOffset() : parseInt(egw.preference('timezoneoffset'));

View File

@ -32,6 +32,11 @@ egw.extend('timer', egw.MODULE_GLOBAL, function()
* Reference from setInterval to stop periodic update * Reference from setInterval to stop periodic update
*/ */
let timer_interval; let timer_interval;
/**
* Reference to open dialog or undefined if not open
* @type {Et2-dialog}
*/
let dialog;
/** /**
* Set state of timer * Set state of timer
@ -40,7 +45,7 @@ egw.extend('timer', egw.MODULE_GLOBAL, function()
*/ */
function setState(_state) function setState(_state)
{ {
// initiate overall timr // initiate overall timer
startTimer(overall, _state.overall?.start, _state.overall?.offset); // to show offset / paused time startTimer(overall, _state.overall?.start, _state.overall?.offset); // to show offset / paused time
if (_state.overall?.paused) if (_state.overall?.paused)
{ {
@ -54,7 +59,7 @@ egw.extend('timer', egw.MODULE_GLOBAL, function()
// 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)
{ {
startTimer(specific, _state.specific?.start, _state.specifc?.offset); // to show offset / paused time startTimer(specific, _state.specific?.start, _state.specific?.offset); // to show offset / paused time
if (_state.specific?.paused) if (_state.specific?.paused)
{ {
stopTimer(specific, true); stopTimer(specific, true);
@ -85,8 +90,9 @@ egw.extend('timer', egw.MODULE_GLOBAL, function()
* Run timer action eg. start/stop * Run timer action eg. start/stop
* *
* @param {string} _action * @param {string} _action
* @param {string} _time
*/ */
function timerAction(_action) function timerAction(_action, _time)
{ {
switch(_action) switch(_action)
{ {
@ -127,53 +133,96 @@ egw.extend('timer', egw.MODULE_GLOBAL, function()
} }
/** /**
* Enable/disable menu items based on timer state * Enable/disable buttons based on timer state
*/ */
function setMenuState() function setButtonState()
{ {
const menu = document.querySelector('et2-select#timer_selectbox').menu; if (!dialog) return;
// disable not matching / available menu-items // disable not matching / available menu-items
menu.getAllItems('et2-selectbox#timer_selecbox sl-menu-item').forEach(item => dialog._overlayContentNode.querySelectorAll('et2-button').forEach(button =>
{ {
if (item.value.substring(0, 8) === 'overall-') if (button.id.substring(0, 7) === 'overall')
{ {
// timer running: disable only start, enable pause and stop // timer running: disable only start, enable pause and stop
if (overall?.start) if (overall?.start)
{ {
item.disabled = item.value === 'overall-start'; button.disabled = button.id === 'overall[start]';
} }
// timer paused: disable pause, enable start and stop // timer paused: disable pause, enable start and stop
else if (overall?.paused) else if (overall?.paused)
{ {
item.disabled = item.value === 'overall-pause'; button.disabled = button.id === 'overall[pause]';
} }
// timer stopped: disable stop and pause, enable start // timer stopped: disable stop and pause, enable start
else else
{ {
item.disabled = item.value !== 'overall-start'; button.disabled = button.id !== 'overall[start]';
} }
} }
else if (item.value.substring(0, 9) === 'specific-') else if (button.id.substring(0, 8) === 'specific')
{ {
// timer running: disable only start, enable pause and stop // timer running: disable only start, enable pause and stop
if (specific?.start) if (specific?.start)
{ {
item.disabled = item.value === 'specific-start'; button.disabled = button.id === 'specific[start]';
} }
// timer paused: disable pause, enable start and stop // timer paused: disable pause, enable start and stop
else if (specific?.paused) else if (specific?.paused)
{ {
item.disabled = item.value === 'specific-pause'; button.disabled = button.id === 'specific[pause]';
} }
// timer stopped: disable stop and pause, enable start // timer stopped: disable stop and pause, enable start
else else
{ {
item.disabled = item.value !== 'specific-start'; button.disabled = button.id !== 'specific[start]';
} }
} }
}); });
} }
/**
* Update the timer DOM node according to _timer state
*
* @param {DOMNode} _node
* @param {object} _timer
*/
function updateTimer(_node, _timer)
{
let sep = ':';
let diff = Math.round((_timer.offset || 0) / 60000.0)
if (_timer.start)
{
const now = Math.round((new Date()).valueOf() / 1000.0);
sep = now % 2 ? ' ' : ':';
diff = Math.round((now - Math.round(_timer.start.valueOf() / 1000.0)) / 60.0);
}
_node.textContent = sprintf('%d%s%02d', Math.round(diff / 60), sep, diff % 60);
// set CSS classes accordingly
_node.classList.toggle('running', !!_timer.start);
_node.classList.toggle('paused', _timer.paused || false);
_node.classList.toggle('overall', _timer === overall);
}
/**
* Update all timers: topmenu and dialog (if open)
*/
function update()
{
// topmenu only shows either specific, if running or paused, or the overall timer
updateTimer(timer, specific.start || specific.paused ? specific : overall);
// if dialog is open, it shows both timers
if (dialog)
{
const specific_timer = dialog._overlayContentNode.querySelector('div#_specific_timer');
const overall_timer = dialog._overlayContentNode.querySelector('div#_overall_timer');
if (specific_timer) updateTimer(specific_timer, specific);
if (overall_timer) updateTimer(overall_timer, overall);
}
}
/** /**
* Start given timer * Start given timer
* *
@ -199,22 +248,12 @@ egw.extend('timer', egw.MODULE_GLOBAL, function()
_timer.offset = 0; // it's now set in start-time _timer.offset = 0; // it's now set in start-time
_timer.paused = false; _timer.paused = false;
// only initiate periodic update, for specific timer, or overall, when specific is not started or paused // update now
if (_timer === specific || _timer === overall && !(specific?.start || specific?.paused)) update();
// initiate periodic update, if not already runing
if (!timer_interval)
{ {
const update = () => {
let diff = Math.round(((new Date()).valueOf() - _timer.start.valueOf()) / 1000.0);
const sep = diff % 2 ? ' ' : ':';
diff = Math.round(diff / 60.0);
timer.textContent = sprintf('%d%s%02d', Math.round(diff / 60), sep, diff % 60);
}
timer.classList.add('running');
timer.classList.remove('paused');
timer.classList.toggle('overall', _timer === overall);
update();
if (timer_interval) {
window.clearInterval(timer_interval);
}
timer_interval = window.setInterval(update, 1000); timer_interval = window.setInterval(update, 1000);
} }
} }
@ -229,17 +268,6 @@ egw.extend('timer', egw.MODULE_GLOBAL, function()
*/ */
function stopTimer(_timer, _pause) function stopTimer(_timer, _pause)
{ {
// stop periodic update
if (timer_interval)
{
window.clearInterval(timer_interval);
}
// update timer of stopped/paused state
timer.classList.remove('running');
timer.classList.toggle('paused', _pause || false);
timer.textContent = timer.textContent.replace(' ', ':');
// update _timer state object // update _timer state object
_timer.paused = _pause || false; _timer.paused = _pause || false;
if (_timer.start) if (_timer.start)
@ -247,13 +275,29 @@ egw.extend('timer', egw.MODULE_GLOBAL, function()
_timer.offset = (new Date()).valueOf() - _timer.start.valueOf(); _timer.offset = (new Date()).valueOf() - _timer.start.valueOf();
_timer.start = undefined; _timer.start = undefined;
} }
// update timer display
updateTimer(timer, _timer);
// if specific timer is stopped AND overall timer is running or paused, re-start overall to display it again // if dialog is shown, update its timer(s) too
if (!_pause && _timer === specific && (overall.start || overall.paused)) if (dialog)
{ {
const paused = overall.paused; const specific_timer = dialog._overlayContentNode.querySelector('div#_specific_timer');
startTimer(overall); const overall_timer = dialog?._overlayContentNode.querySelector('div#_overall_timer');
if (paused) stopTimer(overall, true); if (specific_timer && _timer === specific)
{
updateTimer(specific_timer, specific)
}
if (overall_timer && _timer === overall)
{
updateTimer(overall_timer, overall);
}
}
// stop periodic update, only if NO more timer is running
if (timer_interval && !specific.start && !overall.start)
{
window.clearInterval(timer_interval);
timer_interval = undefined;
} }
} }
@ -270,59 +314,53 @@ egw.extend('timer', egw.MODULE_GLOBAL, function()
// set state if given // set state if given
const timer = document.getElementById('topmenu_timer'); const timer = document.getElementById('topmenu_timer');
if (timer && timer.getAttribute('data-state')) if (timer && timer.getAttribute('data-state')) {
{
setState(JSON.parse(timer.getAttribute('data-state'))); setState(JSON.parse(timer.getAttribute('data-state')));
} }
// create selectbox / menu
const select = document.createElement('et2-select');
select.id = 'timer_selectbox';
timer_container.append(select);
// bind change handler
select.addEventListener('change', () =>
{
if (select.value) timerAction(select.value);
select.value = '';
});
select.addEventListener('sl-hide', (e) => {
if (e.currentTarget.nodeName === 'ET2-SELECT')
{
e.stopImmediatePropagation();
}
});
// bind click handler // bind click handler
timer_container.addEventListener('click', (ev) => timer_container.addEventListener('click', (ev) => {
{ // Pass egw in the constructor
ev.stopImmediatePropagation(); dialog = new Et2Dialog(egw);
if (select.dropdown.open)
{ // Set attributes. They can be set in any way, but this is convenient.
select.dropdown.hide(); dialog.transformAttributes({
} // If you use a template, the second parameter will be the value of the template, as if it were submitted.
else callback: (button_id, value) => // return false to prevent dialog closing
{ {
setMenuState(); if (button_id !== 'close') {
select.dropdown.show(); timerAction(button_id.replace(/_([a-z]+)\[([a-z]+)\]/, '$1-$2'), value.time);
} setButtonState();
}); return false;
// need to load timesheet translations for app-names }
this.langRequire(window, [{app: 'timesheet', lang: this.preference('lang')}], () => dialog = undefined;
{ },
select.select_options = [ title: 'Start & stop timer',
{ value:'', label: this.lang('Select one...')}, template: egw.webserverUrl + '/timesheet/templates/default/timer.xet',
{ value: 'specific-start', label: this.lang('Start specific time'), icon: 'timesheet/play-blue'}, buttons: [
{ value: 'specific-pause', label: this.lang('Pause specific time'), icon: 'timesheet/pause-orange'}, {label: egw.lang("Close"), id: "close", default: true, image: "cancel"},
{ value: 'specific-stop', label: this.lang('Stop specific time'), icon: 'timesheet/stop'}, ],
{ value: 'overall-start', label: this.lang('Start working time'), icon: 'timesheet/play'}, value: {
{ value: 'overall-pause', label: this.lang('Pause working time'), icon: 'timesheet/pause-orange'}, content: {
{ value: 'overall-stop', label: this.lang('Stop working time'), icon: 'timesheet/stop'}, disable: 'overwrite'
]; },
select.updateComplete.then(() => sel_options: {}
{ }
select.dropdown.trigger.style.visibility = 'hidden'; });
select.dropdown.trigger.style.height = '0px'; // Add to DOM, dialog will auto-open
document.body.appendChild(dialog);
dialog.getUpdateComplete().then(() => {
// add default content to timer-divs
dialog._overlayContentNode.querySelectorAll('div.timesheet_timer').forEach(timer => {
timer.textContent = '0:00';
});
// enable/disable buttons based on timer state
setButtonState();
// update Timers
update();
// set current time for overwrite time input
let now = new Date((new Date).valueOf() - egw.getTimezoneOffset() * 60000);
//dialog._overlayContentNode.querySelector('et2-date-time').value = now;
}); });
}); });
} }

View File

@ -5271,6 +5271,29 @@ span.overlayContainer img.overlay {
Created on : 23.07.2014, 13:25:11 Created on : 23.07.2014, 13:25:11
Author : stefanreinhardt Author : stefanreinhardt
*/ */
.timesheet_timer,
#egw_fw_topmenu_info_items #topmenu_info_timer #topmenu_timer {
text-align: center;
font-size: 20px;
white-space: nowrap;
color: #606060;
}
.timesheet_timer.running,
#egw_fw_topmenu_info_items #topmenu_info_timer #topmenu_timer.running {
color: blue;
}
.timesheet_timer.running.overall,
#egw_fw_topmenu_info_items #topmenu_info_timer #topmenu_timer.running.overall {
color: black;
}
.timesheet_timer.paused,
#egw_fw_topmenu_info_items #topmenu_info_timer #topmenu_timer.paused {
color: orange;
}
div.timesheet_timer {
width: 60px;
text-align: right;
}
#egw_fw_topmenu_info_items { #egw_fw_topmenu_info_items {
display: flex !important; display: flex !important;
flex-direction: row-reverse; flex-direction: row-reverse;
@ -5307,6 +5330,33 @@ span.overlayContainer img.overlay {
#egw_fw_topmenu_info_items .topmenu_info_item:hover { #egw_fw_topmenu_info_items .topmenu_info_item:hover {
background-color: rgba(153, 204, 255, 0.4); background-color: rgba(153, 204, 255, 0.4);
} }
#egw_fw_topmenu_info_items #topmenu_info_timer {
order: 1;
position: relative;
}
#egw_fw_topmenu_info_items #topmenu_info_timer #topmenu_timer {
position: relative;
top: 10px !important;
display: block;
height: 45px;
width: 45px;
}
#egw_fw_topmenu_info_items #topmenu_info_timer:hover {
cursor: pointer;
}
#egw_fw_topmenu_info_items #topmenu_info_timer:before {
content: "";
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
background-image: url(../../timesheet/templates/default/images/navbar.svg);
background-repeat: no-repeat;
background-size: 32px;
background-position: center center;
filter: opacity(0.3);
}
#egw_fw_topmenu_info_items #topmenu_info_user_avatar span.fw_avatar_stat { #egw_fw_topmenu_info_items #topmenu_info_user_avatar span.fw_avatar_stat {
position: absolute; position: absolute;
} }
@ -5479,46 +5529,6 @@ span.overlayContainer img.overlay {
line-height: 0.6em; line-height: 0.6em;
background-color: white; background-color: white;
} }
#egw_fw_topmenu_info_items #topmenu_info_timer {
order: 1;
position: relative;
}
#egw_fw_topmenu_info_items #topmenu_info_timer #topmenu_timer {
text-align: center;
font-size: 20px;
position: relative;
top: 10px !important;
display: block;
white-space: nowrap;
color: #606060;
height: 45px;
width: 45px;
}
#egw_fw_topmenu_info_items #topmenu_info_timer #topmenu_timer.running {
color: blue;
}
#egw_fw_topmenu_info_items #topmenu_info_timer #topmenu_timer.running.overall {
color: black;
}
#egw_fw_topmenu_info_items #topmenu_info_timer #topmenu_timer.paused {
color: orange;
}
#egw_fw_topmenu_info_items #topmenu_info_timer:hover {
cursor: pointer;
}
#egw_fw_topmenu_info_items #topmenu_info_timer:before {
content: "";
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
background-image: url(../../timesheet/templates/default/images/navbar.svg);
background-repeat: no-repeat;
background-size: 32px;
background-position: center center;
filter: opacity(0.3);
}
#egw_fw_topmenu_info_items #topmenu_info_quick_add #quick_add_selectbox, #egw_fw_topmenu_info_items #topmenu_info_quick_add #quick_add_selectbox,
#egw_fw_topmenu_info_items #topmenu_info_timer #quick_add_selectbox, #egw_fw_topmenu_info_items #topmenu_info_timer #quick_add_selectbox,
#egw_fw_topmenu_info_items #topmenu_info_quick_add #timer_selectbox, #egw_fw_topmenu_info_items #topmenu_info_quick_add #timer_selectbox,

View File

@ -5251,6 +5251,29 @@ span.overlayContainer img.overlay {
Created on : 23.07.2014, 13:25:11 Created on : 23.07.2014, 13:25:11
Author : stefanreinhardt Author : stefanreinhardt
*/ */
.timesheet_timer,
#egw_fw_topmenu_info_items #topmenu_info_timer #topmenu_timer {
text-align: center;
font-size: 20px;
white-space: nowrap;
color: #606060;
}
.timesheet_timer.running,
#egw_fw_topmenu_info_items #topmenu_info_timer #topmenu_timer.running {
color: blue;
}
.timesheet_timer.running.overall,
#egw_fw_topmenu_info_items #topmenu_info_timer #topmenu_timer.running.overall {
color: black;
}
.timesheet_timer.paused,
#egw_fw_topmenu_info_items #topmenu_info_timer #topmenu_timer.paused {
color: orange;
}
div.timesheet_timer {
width: 60px;
text-align: right;
}
#egw_fw_topmenu_info_items { #egw_fw_topmenu_info_items {
display: flex !important; display: flex !important;
flex-direction: row-reverse; flex-direction: row-reverse;
@ -5287,6 +5310,33 @@ span.overlayContainer img.overlay {
#egw_fw_topmenu_info_items .topmenu_info_item:hover { #egw_fw_topmenu_info_items .topmenu_info_item:hover {
background-color: rgba(153, 204, 255, 0.4); background-color: rgba(153, 204, 255, 0.4);
} }
#egw_fw_topmenu_info_items #topmenu_info_timer {
order: 1;
position: relative;
}
#egw_fw_topmenu_info_items #topmenu_info_timer #topmenu_timer {
position: relative;
top: 10px !important;
display: block;
height: 45px;
width: 45px;
}
#egw_fw_topmenu_info_items #topmenu_info_timer:hover {
cursor: pointer;
}
#egw_fw_topmenu_info_items #topmenu_info_timer:before {
content: "";
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
background-image: url(../../timesheet/templates/default/images/navbar.svg);
background-repeat: no-repeat;
background-size: 32px;
background-position: center center;
filter: opacity(0.3);
}
#egw_fw_topmenu_info_items #topmenu_info_user_avatar span.fw_avatar_stat { #egw_fw_topmenu_info_items #topmenu_info_user_avatar span.fw_avatar_stat {
position: absolute; position: absolute;
} }
@ -5459,46 +5509,6 @@ span.overlayContainer img.overlay {
line-height: 0.6em; line-height: 0.6em;
background-color: white; background-color: white;
} }
#egw_fw_topmenu_info_items #topmenu_info_timer {
order: 1;
position: relative;
}
#egw_fw_topmenu_info_items #topmenu_info_timer #topmenu_timer {
text-align: center;
font-size: 20px;
position: relative;
top: 10px !important;
display: block;
white-space: nowrap;
color: #606060;
height: 45px;
width: 45px;
}
#egw_fw_topmenu_info_items #topmenu_info_timer #topmenu_timer.running {
color: blue;
}
#egw_fw_topmenu_info_items #topmenu_info_timer #topmenu_timer.running.overall {
color: black;
}
#egw_fw_topmenu_info_items #topmenu_info_timer #topmenu_timer.paused {
color: orange;
}
#egw_fw_topmenu_info_items #topmenu_info_timer:hover {
cursor: pointer;
}
#egw_fw_topmenu_info_items #topmenu_info_timer:before {
content: "";
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
background-image: url(../../timesheet/templates/default/images/navbar.svg);
background-repeat: no-repeat;
background-size: 32px;
background-position: center center;
filter: opacity(0.3);
}
#egw_fw_topmenu_info_items #topmenu_info_quick_add #quick_add_selectbox, #egw_fw_topmenu_info_items #topmenu_info_quick_add #quick_add_selectbox,
#egw_fw_topmenu_info_items #topmenu_info_timer #quick_add_selectbox, #egw_fw_topmenu_info_items #topmenu_info_timer #quick_add_selectbox,
#egw_fw_topmenu_info_items #topmenu_info_quick_add #timer_selectbox, #egw_fw_topmenu_info_items #topmenu_info_quick_add #timer_selectbox,

View File

@ -5261,6 +5261,29 @@ span.overlayContainer img.overlay {
Created on : 23.07.2014, 13:25:11 Created on : 23.07.2014, 13:25:11
Author : stefanreinhardt Author : stefanreinhardt
*/ */
.timesheet_timer,
#egw_fw_topmenu_info_items #topmenu_info_timer #topmenu_timer {
text-align: center;
font-size: 20px;
white-space: nowrap;
color: #606060;
}
.timesheet_timer.running,
#egw_fw_topmenu_info_items #topmenu_info_timer #topmenu_timer.running {
color: blue;
}
.timesheet_timer.running.overall,
#egw_fw_topmenu_info_items #topmenu_info_timer #topmenu_timer.running.overall {
color: black;
}
.timesheet_timer.paused,
#egw_fw_topmenu_info_items #topmenu_info_timer #topmenu_timer.paused {
color: orange;
}
div.timesheet_timer {
width: 60px;
text-align: right;
}
#egw_fw_topmenu_info_items { #egw_fw_topmenu_info_items {
display: flex !important; display: flex !important;
flex-direction: row-reverse; flex-direction: row-reverse;
@ -5297,6 +5320,33 @@ span.overlayContainer img.overlay {
#egw_fw_topmenu_info_items .topmenu_info_item:hover { #egw_fw_topmenu_info_items .topmenu_info_item:hover {
background-color: rgba(153, 204, 255, 0.4); background-color: rgba(153, 204, 255, 0.4);
} }
#egw_fw_topmenu_info_items #topmenu_info_timer {
order: 1;
position: relative;
}
#egw_fw_topmenu_info_items #topmenu_info_timer #topmenu_timer {
position: relative;
top: 10px !important;
display: block;
height: 45px;
width: 45px;
}
#egw_fw_topmenu_info_items #topmenu_info_timer:hover {
cursor: pointer;
}
#egw_fw_topmenu_info_items #topmenu_info_timer:before {
content: "";
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
background-image: url(../../timesheet/templates/default/images/navbar.svg);
background-repeat: no-repeat;
background-size: 32px;
background-position: center center;
filter: opacity(0.3);
}
#egw_fw_topmenu_info_items #topmenu_info_user_avatar span.fw_avatar_stat { #egw_fw_topmenu_info_items #topmenu_info_user_avatar span.fw_avatar_stat {
position: absolute; position: absolute;
} }
@ -5469,46 +5519,6 @@ span.overlayContainer img.overlay {
line-height: 0.6em; line-height: 0.6em;
background-color: white; background-color: white;
} }
#egw_fw_topmenu_info_items #topmenu_info_timer {
order: 1;
position: relative;
}
#egw_fw_topmenu_info_items #topmenu_info_timer #topmenu_timer {
text-align: center;
font-size: 20px;
position: relative;
top: 10px !important;
display: block;
white-space: nowrap;
color: #606060;
height: 45px;
width: 45px;
}
#egw_fw_topmenu_info_items #topmenu_info_timer #topmenu_timer.running {
color: blue;
}
#egw_fw_topmenu_info_items #topmenu_info_timer #topmenu_timer.running.overall {
color: black;
}
#egw_fw_topmenu_info_items #topmenu_info_timer #topmenu_timer.paused {
color: orange;
}
#egw_fw_topmenu_info_items #topmenu_info_timer:hover {
cursor: pointer;
}
#egw_fw_topmenu_info_items #topmenu_info_timer:before {
content: "";
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
background-image: url(../../timesheet/templates/default/images/navbar.svg);
background-repeat: no-repeat;
background-size: 32px;
background-position: center center;
filter: opacity(0.3);
}
#egw_fw_topmenu_info_items #topmenu_info_quick_add #quick_add_selectbox, #egw_fw_topmenu_info_items #topmenu_info_quick_add #quick_add_selectbox,
#egw_fw_topmenu_info_items #topmenu_info_timer #quick_add_selectbox, #egw_fw_topmenu_info_items #topmenu_info_timer #quick_add_selectbox,
#egw_fw_topmenu_info_items #topmenu_info_quick_add #timer_selectbox, #egw_fw_topmenu_info_items #topmenu_info_quick_add #timer_selectbox,

View File

@ -18,6 +18,25 @@
@import (reference) "definitions.less"; @import (reference) "definitions.less";
.timesheet_timer, #egw_fw_topmenu_info_items #topmenu_info_timer #topmenu_timer {
text-align: center;
font-size: 20px;
white-space: nowrap;
color: #606060;
&.running {
color: blue;
}
&.running.overall {
color: black;
}
&.paused {
color: orange;
}
}
div.timesheet_timer {
width: 60px;
text-align: right;
}
#egw_fw_topmenu_info_items { #egw_fw_topmenu_info_items {
display: flex !important; display: flex !important;
flex-direction: row-reverse; flex-direction: row-reverse;
@ -42,6 +61,35 @@
background-color: @color_hover_row; background-color: @color_hover_row;
} }
} }
#topmenu_info_timer {
order: 1;
position: relative;
#topmenu_timer {
position: relative;
top: 10px !important;
display: block;
height: 45px;
width: 45px;
}
&:hover {
cursor: pointer;
}
&:before {
content: "";
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
background-image: url(../../timesheet/templates/default/images/navbar.svg);
background-repeat: no-repeat;
background-size: 32px;
background-position: center center;
filter: opacity(0.3);
}
}
#topmenu_info_user_avatar { #topmenu_info_user_avatar {
span.fw_avatar_stat { span.fw_avatar_stat {
position: absolute; position: absolute;
@ -233,47 +281,6 @@
} }
} }
#topmenu_info_timer {
order: 1;
position: relative;
#topmenu_timer {
text-align: center;
font-size: 20px;
position: relative;
top: 10px !important;
display: block;
white-space: nowrap;
color: #606060;
height: 45px;
width: 45px;
}
#topmenu_timer.running {
color: blue;
}
#topmenu_timer.running.overall {
color: black;
}
#topmenu_timer.paused {
color: orange;
}
&:hover {
cursor: pointer;
}
&:before {
content: "";
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
background-image: url(../../timesheet/templates/default/images/navbar.svg);
background-repeat: no-repeat;
background-size: 32px;
background-position: center center;
filter: opacity(0.3);
}
}
// quick_add and timer selectbox / menu // quick_add and timer selectbox / menu
#topmenu_info_quick_add, #topmenu_info_timer { #topmenu_info_quick_add, #topmenu_info_timer {
#quick_add_selectbox, #timer_selectbox { #quick_add_selectbox, #timer_selectbox {

View File

@ -5282,6 +5282,29 @@ span.overlayContainer img.overlay {
Created on : 23.07.2014, 13:25:11 Created on : 23.07.2014, 13:25:11
Author : stefanreinhardt Author : stefanreinhardt
*/ */
.timesheet_timer,
#egw_fw_topmenu_info_items #topmenu_info_timer #topmenu_timer {
text-align: center;
font-size: 20px;
white-space: nowrap;
color: #606060;
}
.timesheet_timer.running,
#egw_fw_topmenu_info_items #topmenu_info_timer #topmenu_timer.running {
color: blue;
}
.timesheet_timer.running.overall,
#egw_fw_topmenu_info_items #topmenu_info_timer #topmenu_timer.running.overall {
color: black;
}
.timesheet_timer.paused,
#egw_fw_topmenu_info_items #topmenu_info_timer #topmenu_timer.paused {
color: orange;
}
div.timesheet_timer {
width: 60px;
text-align: right;
}
#egw_fw_topmenu_info_items { #egw_fw_topmenu_info_items {
display: flex !important; display: flex !important;
flex-direction: row-reverse; flex-direction: row-reverse;
@ -5318,6 +5341,33 @@ span.overlayContainer img.overlay {
#egw_fw_topmenu_info_items .topmenu_info_item:hover { #egw_fw_topmenu_info_items .topmenu_info_item:hover {
background-color: rgba(153, 204, 255, 0.4); background-color: rgba(153, 204, 255, 0.4);
} }
#egw_fw_topmenu_info_items #topmenu_info_timer {
order: 1;
position: relative;
}
#egw_fw_topmenu_info_items #topmenu_info_timer #topmenu_timer {
position: relative;
top: 10px !important;
display: block;
height: 45px;
width: 45px;
}
#egw_fw_topmenu_info_items #topmenu_info_timer:hover {
cursor: pointer;
}
#egw_fw_topmenu_info_items #topmenu_info_timer:before {
content: "";
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
background-image: url(../../timesheet/templates/default/images/navbar.svg);
background-repeat: no-repeat;
background-size: 32px;
background-position: center center;
filter: opacity(0.3);
}
#egw_fw_topmenu_info_items #topmenu_info_user_avatar span.fw_avatar_stat { #egw_fw_topmenu_info_items #topmenu_info_user_avatar span.fw_avatar_stat {
position: absolute; position: absolute;
} }
@ -5490,46 +5540,6 @@ span.overlayContainer img.overlay {
line-height: 0.6em; line-height: 0.6em;
background-color: white; background-color: white;
} }
#egw_fw_topmenu_info_items #topmenu_info_timer {
order: 1;
position: relative;
}
#egw_fw_topmenu_info_items #topmenu_info_timer #topmenu_timer {
text-align: center;
font-size: 20px;
position: relative;
top: 10px !important;
display: block;
white-space: nowrap;
color: #606060;
height: 45px;
width: 45px;
}
#egw_fw_topmenu_info_items #topmenu_info_timer #topmenu_timer.running {
color: blue;
}
#egw_fw_topmenu_info_items #topmenu_info_timer #topmenu_timer.running.overall {
color: black;
}
#egw_fw_topmenu_info_items #topmenu_info_timer #topmenu_timer.paused {
color: orange;
}
#egw_fw_topmenu_info_items #topmenu_info_timer:hover {
cursor: pointer;
}
#egw_fw_topmenu_info_items #topmenu_info_timer:before {
content: "";
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
background-image: url(../../timesheet/templates/default/images/navbar.svg);
background-repeat: no-repeat;
background-size: 32px;
background-position: center center;
filter: opacity(0.3);
}
#egw_fw_topmenu_info_items #topmenu_info_quick_add #quick_add_selectbox, #egw_fw_topmenu_info_items #topmenu_info_quick_add #quick_add_selectbox,
#egw_fw_topmenu_info_items #topmenu_info_timer #quick_add_selectbox, #egw_fw_topmenu_info_items #topmenu_info_timer #quick_add_selectbox,
#egw_fw_topmenu_info_items #topmenu_info_quick_add #timer_selectbox, #egw_fw_topmenu_info_items #topmenu_info_quick_add #timer_selectbox,

View File

@ -0,0 +1,35 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE overlay PUBLIC "-//EGroupware GmbH//eTemplate 2//EN" "http://www.egroupware.org/etemplate2.dtd">
<overlay>
<template id="timesheet.timer" template="" lang="" group="0" version="1.7.002">
<grid width="100%" >
<columns>
<column/>
<column/>
<column/>
<column/>
<column/>
</columns>
<rows>
<row disabled="@disable=/overwrite/">
<description value="Overwrite" span="2"/>
<et2-date-time id="time" span="all"/>
</row>
<row disabled="@disable=/specific/">
<description value="Timer"/>
<old-box id="specific_timer" value="00:00" class="timesheet_timer"/>
<et2-button id="specific[start]" label="Start" image="timesheet/play-blue"/>
<et2-button id="specific[pause]" label="Pause" image="timesheet/pause-orange" disabled="true"/>
<et2-button id="specific[stop]" label="Stop" image="timesheet/stop" disabled="true"/>
</row>
<row disabled="@disable=/overall/">
<description value="Working time"/>
<old-box id="overall_timer" value="00:00" class="timesheet_timer overall"/>
<et2-button id="overall[start]" label="Start" image="timesheet/play"/>
<et2-button id="overall[pause]" label="Pause" image="timesheet/pause-orange" disabled="true"/>
<et2-button id="overall[stop]" label="Stop" image="timesheet/stop" disabled="true"/>
</row>
</rows>
</grid>
</template>
</overlay>