diff --git a/api/js/jsapi/egw_links.js b/api/js/jsapi/egw_links.js index 997859d657..8b3a4fb984 100644 --- a/api/js/jsapi/egw_links.js +++ b/api/js/jsapi/egw_links.js @@ -515,7 +515,6 @@ egw.extend('links', egw.MODULE_GLOBAL, function() { select.dropdown.trigger.style.visibility = 'hidden'; select.dropdown.trigger.style.height = '0px'; - select.querySelector('sl-menu-item[value=""]').style.display = 'none'; }); }); } diff --git a/api/js/jsapi/egw_modules.js b/api/js/jsapi/egw_modules.js index d588359e29..bc935587b1 100644 --- a/api/js/jsapi/egw_modules.js +++ b/api/js/jsapi/egw_modules.js @@ -29,4 +29,5 @@ import "./egw_tail.js"; import "./egw_inheritance.js"; import "./egw_message.js"; import "./egw_notification.js"; -import "./jsapi.js"; +import "./egw_timer.js"; +import "./jsapi.js"; \ No newline at end of file diff --git a/api/js/jsapi/egw_timer.js b/api/js/jsapi/egw_timer.js new file mode 100644 index 0000000000..57e745227b --- /dev/null +++ b/api/js/jsapi/egw_timer.js @@ -0,0 +1,184 @@ +/** + * EGroupware clientside API object + * + * @license http://opensource.org/licenses/gpl-license.php GPL - GNU General Public License + * @package etemplate + * @subpackage api + * @link https://www.egroupware.org + * @author Ralf Becker + */ + +import './egw_core.js'; +import {sprintf} from "../egw_action/egw_action_common"; + +egw.extend('timer', egw.MODULE_GLOBAL, function() +{ + "use strict"; + + /** + * Timer state + */ + let timer_start; + let timer_offset = 0; + let timer_paused = false; + + const timer = document.querySelector('#topmenu_timer'); + let timer_interval; + + function setState(_state) + { + timer_start = _state.start ? new Date(_state.start) : undefined; + timer_offset = _state.offset || 0; + if (timer_offset && timer_start) + { + timer_start.setMilliseconds(timer_start.getMilliseconds()-timer_offset); + } + if (timer_start || _state.paused) + { + startTimer(); + + if (_state.paused) stopTimer(true); // sets timer_paused + } + } + + function getState() + { + return { + start: timer_start, + offset: timer_offset, + paused: timer_paused + } + } + + /** + * Run timer action eg. start/stop + * + * @param {string} _action + */ + function timerAction(_action) + { + switch(_action) + { + case 'overall-start': + startTimer(); + break; + + case 'overall-pause': + stopTimer(true); + break; + + case 'overall-stop': + stopTimer(); + break; + } + // persist state + let state = getState(); + state.action = _action; + egw.request('timesheet.timesheet_bo.ajax_event', [state]) + } + + function startTimer() + { + timer_paused = false; + timer_start = new Date(); + if (timer_offset > 0) + { + timer_start.setMilliseconds(timer_start.getMilliseconds()-timer_offset); + } + const update = () => + { + if (!timer_start) + { + timer.textContent = '0:00'; + } + else if (timer_paused) + { + // do nothing + } + else + { + 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'); + update(); + timer_interval = window.setInterval(update, 1000); + } + + function stopTimer(_pause) + { + if (timer_interval) + { + window.clearInterval(timer_interval); + } + timer.classList.remove('running'); + timer.textContent = timer.textContent.replace(' ', ':'); + + if (_pause) + { + timer.classList.add('paused'); + timer_paused = true; + } + timer_offset = (new Date()).valueOf() - timer_start.valueOf(); + if (!_pause) + { + timer_start = undefined; + } + } + + return { + /** + * Create timer in top-menu + * + * @param {string} _parent parent to create selectbox in + */ + add_timer: function(_parent) + { + const timer_container = document.getElementById(_parent); + if (!timer_container) return; + + // set state if given + const timer = document.getElementById('topmenu_timer'); + if (timer && timer.getAttribute('data-state')) + { + setState(JSON.parse(timer.getAttribute('data-state'))); + } + + // create selectbox / menu + const select = document.createElement('et2-select', {id: 'timer_selectbox'}); + timer_container.append(select); + + // bind change handler + select.addEventListener('change', () => + { + if (select.value) timerAction(select.value); + select.value = ''; + }); + // bind click handler + timer_container.addEventListener('click', (ev) => + { + select.dropdown.open = !select.dropdown.open ? true : false; + ev.stopPropagation(); + }); + // need to load timesheet translations for app-names + this.langRequire(window, [{app: 'timesheet', lang: this.preference('lang')}], () => + { + select.select_options = [ + { value:'', label: this.lang('Select one...')}, + { value: 'overall-start', label: this.lang('Start working time')}, + { value: 'overall-pause', label: this.lang('Pause working time')}, + { value: 'overall-stop', label: this.lang('Stop working time')}, + ]; + select.updateComplete.then(() => + { + select.dropdown.trigger.style.visibility = 'hidden'; + select.dropdown.trigger.style.height = '0px'; + }); + }); + } + }; +}); \ No newline at end of file diff --git a/pixelegg/css/mobile.css b/pixelegg/css/mobile.css index b581c46ae7..ceaaa7ea80 100644 --- a/pixelegg/css/mobile.css +++ b/pixelegg/css/mobile.css @@ -5268,7 +5268,8 @@ span.overlayContainer img.overlay { Author : stefanreinhardt */ #egw_fw_topmenu_info_items { - display: inline-block; + display: flex !important; + flex-direction: row-reverse; height: 45px; position: absolute; padding-right: 2px; @@ -5456,7 +5457,6 @@ span.overlayContainer img.overlay { } #egw_fw_topmenu_info_items #topmenu_info_quick_add { position: relative; - /* do NOT show empty label */ } #egw_fw_topmenu_info_items #topmenu_info_quick_add span#quick_add { float: right; @@ -5475,23 +5475,71 @@ span.overlayContainer img.overlay { line-height: 0.6em; background-color: white; } -#egw_fw_topmenu_info_items #topmenu_info_quick_add #quick_add_selectbox { +#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; +} +#egw_fw_topmenu_info_items #topmenu_info_timer #topmenu_timer.running { + color: black; +} +#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_timer #quick_add_selectbox, +#egw_fw_topmenu_info_items #topmenu_info_quick_add #timer_selectbox, +#egw_fw_topmenu_info_items #topmenu_info_timer #timer_selectbox { height: 0px; float: left; display: inline-block; + /* do NOT show empty label */ } -#egw_fw_topmenu_info_items #topmenu_info_quick_add #quick_add_selectbox::part(form-control-input) { +#egw_fw_topmenu_info_items #topmenu_info_quick_add #quick_add_selectbox sl-menu-item[value=""], +#egw_fw_topmenu_info_items #topmenu_info_timer #quick_add_selectbox sl-menu-item[value=""], +#egw_fw_topmenu_info_items #topmenu_info_quick_add #timer_selectbox sl-menu-item[value=""], +#egw_fw_topmenu_info_items #topmenu_info_timer #timer_selectbox sl-menu-item[value=""] { + display: none; +} +#egw_fw_topmenu_info_items #topmenu_info_quick_add #quick_add_selectbox::part(form-control-input), +#egw_fw_topmenu_info_items #topmenu_info_timer #quick_add_selectbox::part(form-control-input), +#egw_fw_topmenu_info_items #topmenu_info_quick_add #timer_selectbox::part(form-control-input), +#egw_fw_topmenu_info_items #topmenu_info_timer #timer_selectbox::part(form-control-input) { border: none !important; } -#egw_fw_topmenu_info_items #topmenu_info_quick_add #quick_add_selectbox::part(form-control) { +#egw_fw_topmenu_info_items #topmenu_info_quick_add #quick_add_selectbox::part(form-control), +#egw_fw_topmenu_info_items #topmenu_info_timer #quick_add_selectbox::part(form-control), +#egw_fw_topmenu_info_items #topmenu_info_quick_add #timer_selectbox::part(form-control), +#egw_fw_topmenu_info_items #topmenu_info_timer #timer_selectbox::part(form-control) { margin-left: -3em; } -#egw_fw_topmenu_info_items #topmenu_info_quick_add #quick_add_selectbox::part(menu) { +#egw_fw_topmenu_info_items #topmenu_info_quick_add #quick_add_selectbox::part(menu), +#egw_fw_topmenu_info_items #topmenu_info_timer #quick_add_selectbox::part(menu), +#egw_fw_topmenu_info_items #topmenu_info_quick_add #timer_selectbox::part(menu), +#egw_fw_topmenu_info_items #topmenu_info_timer #timer_selectbox::part(menu) { max-height: 60vh; } -#egw_fw_topmenu_info_items #topmenu_info_quick_add et2-select#quick_add_selectbox sl-menu-item[value=""] { - display: none; -} #egw_fw_topmenu_info_items img#topmenu_info_error { width: 16px; height: 16px; diff --git a/pixelegg/css/monochrome.css b/pixelegg/css/monochrome.css index 079ca13d70..1ca92a153e 100644 --- a/pixelegg/css/monochrome.css +++ b/pixelegg/css/monochrome.css @@ -5248,7 +5248,8 @@ span.overlayContainer img.overlay { Author : stefanreinhardt */ #egw_fw_topmenu_info_items { - display: inline-block; + display: flex !important; + flex-direction: row-reverse; height: 45px; position: absolute; padding-right: 2px; @@ -5436,7 +5437,6 @@ span.overlayContainer img.overlay { } #egw_fw_topmenu_info_items #topmenu_info_quick_add { position: relative; - /* do NOT show empty label */ } #egw_fw_topmenu_info_items #topmenu_info_quick_add span#quick_add { float: right; @@ -5455,23 +5455,71 @@ span.overlayContainer img.overlay { line-height: 0.6em; background-color: white; } -#egw_fw_topmenu_info_items #topmenu_info_quick_add #quick_add_selectbox { +#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; +} +#egw_fw_topmenu_info_items #topmenu_info_timer #topmenu_timer.running { + color: black; +} +#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_timer #quick_add_selectbox, +#egw_fw_topmenu_info_items #topmenu_info_quick_add #timer_selectbox, +#egw_fw_topmenu_info_items #topmenu_info_timer #timer_selectbox { height: 0px; float: left; display: inline-block; + /* do NOT show empty label */ } -#egw_fw_topmenu_info_items #topmenu_info_quick_add #quick_add_selectbox::part(form-control-input) { +#egw_fw_topmenu_info_items #topmenu_info_quick_add #quick_add_selectbox sl-menu-item[value=""], +#egw_fw_topmenu_info_items #topmenu_info_timer #quick_add_selectbox sl-menu-item[value=""], +#egw_fw_topmenu_info_items #topmenu_info_quick_add #timer_selectbox sl-menu-item[value=""], +#egw_fw_topmenu_info_items #topmenu_info_timer #timer_selectbox sl-menu-item[value=""] { + display: none; +} +#egw_fw_topmenu_info_items #topmenu_info_quick_add #quick_add_selectbox::part(form-control-input), +#egw_fw_topmenu_info_items #topmenu_info_timer #quick_add_selectbox::part(form-control-input), +#egw_fw_topmenu_info_items #topmenu_info_quick_add #timer_selectbox::part(form-control-input), +#egw_fw_topmenu_info_items #topmenu_info_timer #timer_selectbox::part(form-control-input) { border: none !important; } -#egw_fw_topmenu_info_items #topmenu_info_quick_add #quick_add_selectbox::part(form-control) { +#egw_fw_topmenu_info_items #topmenu_info_quick_add #quick_add_selectbox::part(form-control), +#egw_fw_topmenu_info_items #topmenu_info_timer #quick_add_selectbox::part(form-control), +#egw_fw_topmenu_info_items #topmenu_info_quick_add #timer_selectbox::part(form-control), +#egw_fw_topmenu_info_items #topmenu_info_timer #timer_selectbox::part(form-control) { margin-left: -3em; } -#egw_fw_topmenu_info_items #topmenu_info_quick_add #quick_add_selectbox::part(menu) { +#egw_fw_topmenu_info_items #topmenu_info_quick_add #quick_add_selectbox::part(menu), +#egw_fw_topmenu_info_items #topmenu_info_timer #quick_add_selectbox::part(menu), +#egw_fw_topmenu_info_items #topmenu_info_quick_add #timer_selectbox::part(menu), +#egw_fw_topmenu_info_items #topmenu_info_timer #timer_selectbox::part(menu) { max-height: 60vh; } -#egw_fw_topmenu_info_items #topmenu_info_quick_add et2-select#quick_add_selectbox sl-menu-item[value=""] { - display: none; -} #egw_fw_topmenu_info_items img#topmenu_info_error { width: 16px; height: 16px; diff --git a/pixelegg/css/pixelegg.css b/pixelegg/css/pixelegg.css index a45eaa7864..70e97eec22 100644 --- a/pixelegg/css/pixelegg.css +++ b/pixelegg/css/pixelegg.css @@ -5258,7 +5258,8 @@ span.overlayContainer img.overlay { Author : stefanreinhardt */ #egw_fw_topmenu_info_items { - display: inline-block; + display: flex !important; + flex-direction: row-reverse; height: 45px; position: absolute; padding-right: 2px; @@ -5446,7 +5447,6 @@ span.overlayContainer img.overlay { } #egw_fw_topmenu_info_items #topmenu_info_quick_add { position: relative; - /* do NOT show empty label */ } #egw_fw_topmenu_info_items #topmenu_info_quick_add span#quick_add { float: right; @@ -5465,23 +5465,71 @@ span.overlayContainer img.overlay { line-height: 0.6em; background-color: white; } -#egw_fw_topmenu_info_items #topmenu_info_quick_add #quick_add_selectbox { +#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; +} +#egw_fw_topmenu_info_items #topmenu_info_timer #topmenu_timer.running { + color: black; +} +#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_timer #quick_add_selectbox, +#egw_fw_topmenu_info_items #topmenu_info_quick_add #timer_selectbox, +#egw_fw_topmenu_info_items #topmenu_info_timer #timer_selectbox { height: 0px; float: left; display: inline-block; + /* do NOT show empty label */ } -#egw_fw_topmenu_info_items #topmenu_info_quick_add #quick_add_selectbox::part(form-control-input) { +#egw_fw_topmenu_info_items #topmenu_info_quick_add #quick_add_selectbox sl-menu-item[value=""], +#egw_fw_topmenu_info_items #topmenu_info_timer #quick_add_selectbox sl-menu-item[value=""], +#egw_fw_topmenu_info_items #topmenu_info_quick_add #timer_selectbox sl-menu-item[value=""], +#egw_fw_topmenu_info_items #topmenu_info_timer #timer_selectbox sl-menu-item[value=""] { + display: none; +} +#egw_fw_topmenu_info_items #topmenu_info_quick_add #quick_add_selectbox::part(form-control-input), +#egw_fw_topmenu_info_items #topmenu_info_timer #quick_add_selectbox::part(form-control-input), +#egw_fw_topmenu_info_items #topmenu_info_quick_add #timer_selectbox::part(form-control-input), +#egw_fw_topmenu_info_items #topmenu_info_timer #timer_selectbox::part(form-control-input) { border: none !important; } -#egw_fw_topmenu_info_items #topmenu_info_quick_add #quick_add_selectbox::part(form-control) { +#egw_fw_topmenu_info_items #topmenu_info_quick_add #quick_add_selectbox::part(form-control), +#egw_fw_topmenu_info_items #topmenu_info_timer #quick_add_selectbox::part(form-control), +#egw_fw_topmenu_info_items #topmenu_info_quick_add #timer_selectbox::part(form-control), +#egw_fw_topmenu_info_items #topmenu_info_timer #timer_selectbox::part(form-control) { margin-left: -3em; } -#egw_fw_topmenu_info_items #topmenu_info_quick_add #quick_add_selectbox::part(menu) { +#egw_fw_topmenu_info_items #topmenu_info_quick_add #quick_add_selectbox::part(menu), +#egw_fw_topmenu_info_items #topmenu_info_timer #quick_add_selectbox::part(menu), +#egw_fw_topmenu_info_items #topmenu_info_quick_add #timer_selectbox::part(menu), +#egw_fw_topmenu_info_items #topmenu_info_timer #timer_selectbox::part(menu) { max-height: 60vh; } -#egw_fw_topmenu_info_items #topmenu_info_quick_add et2-select#quick_add_selectbox sl-menu-item[value=""] { - display: none; -} #egw_fw_topmenu_info_items img#topmenu_info_error { width: 16px; height: 16px; diff --git a/pixelegg/js/fw_pixelegg.js b/pixelegg/js/fw_pixelegg.js index eab70077be..ff5b5872f9 100644 --- a/pixelegg/js/fw_pixelegg.js +++ b/pixelegg/js/fw_pixelegg.js @@ -138,6 +138,7 @@ import './slider.js'; .on('change', function() { framework.tzSelection(this.value); return false; }) .on('click', function(e) { e.stopPropagation(); }); window.egw.link_quick_add('topmenu_info_quick_add'); + window.egw.add_timer('topmenu_info_timer'); // allowing javascript urls in topmenu and sidebox only under CSP by binding click handlers to them var href_regexp = /^javascript:([^\(]+)\((.*)?\);?$/; diff --git a/pixelegg/less/layout_raster_buttons.less b/pixelegg/less/layout_raster_buttons.less index 10214bf6de..ddf2e71cae 100644 --- a/pixelegg/less/layout_raster_buttons.less +++ b/pixelegg/less/layout_raster_buttons.less @@ -19,7 +19,8 @@ @import (reference) "definitions.less"; #egw_fw_topmenu_info_items { - display: inline-block; + display: flex !important; + flex-direction: row-reverse; height: 45px; position: absolute; padding-right: 2px; @@ -42,7 +43,6 @@ } } #topmenu_info_user_avatar { - span.fw_avatar_stat { position: absolute; } @@ -231,31 +231,61 @@ background-color: white; } } + } - // ############################################################################## - // quick_add selectbox - // ADD different APPs + #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; + } + #topmenu_timer.running { + color: black; + } + &: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_selectbox { + // quick_add and timer selectbox / menu + #topmenu_info_quick_add, #topmenu_info_timer { + #quick_add_selectbox, #timer_selectbox { height: 0px; float: left; display: inline-block; - } - #quick_add_selectbox::part(form-control-input) { - border: none !important; - } - #quick_add_selectbox::part(form-control) { - margin-left: -3em; - } - #quick_add_selectbox::part(menu) { - max-height: 60vh; - } - /* do NOT show empty label */ - et2-select#quick_add_selectbox { + /* do NOT show empty label */ sl-menu-item[value=""] { display: none; } } + #quick_add_selectbox::part(form-control-input), #timer_selectbox::part(form-control-input) { + border: none !important; + } + #quick_add_selectbox::part(form-control), #timer_selectbox::part(form-control) { + margin-left: -3em; + } + #quick_add_selectbox::part(menu), #timer_selectbox::part(menu) { + max-height: 60vh; + } } // ############################################################################## diff --git a/pixelegg/mobile/fw_mobile.css b/pixelegg/mobile/fw_mobile.css index 4269262cfb..dd8e28d0db 100644 --- a/pixelegg/mobile/fw_mobile.css +++ b/pixelegg/mobile/fw_mobile.css @@ -5279,7 +5279,8 @@ span.overlayContainer img.overlay { Author : stefanreinhardt */ #egw_fw_topmenu_info_items { - display: inline-block; + display: flex !important; + flex-direction: row-reverse; height: 45px; position: absolute; padding-right: 2px; @@ -5467,7 +5468,6 @@ span.overlayContainer img.overlay { } #egw_fw_topmenu_info_items #topmenu_info_quick_add { position: relative; - /* do NOT show empty label */ } #egw_fw_topmenu_info_items #topmenu_info_quick_add span#quick_add { float: right; @@ -5486,23 +5486,71 @@ span.overlayContainer img.overlay { line-height: 0.6em; background-color: white; } -#egw_fw_topmenu_info_items #topmenu_info_quick_add #quick_add_selectbox { +#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; +} +#egw_fw_topmenu_info_items #topmenu_info_timer #topmenu_timer.running { + color: black; +} +#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_timer #quick_add_selectbox, +#egw_fw_topmenu_info_items #topmenu_info_quick_add #timer_selectbox, +#egw_fw_topmenu_info_items #topmenu_info_timer #timer_selectbox { height: 0px; float: left; display: inline-block; + /* do NOT show empty label */ } -#egw_fw_topmenu_info_items #topmenu_info_quick_add #quick_add_selectbox::part(form-control-input) { +#egw_fw_topmenu_info_items #topmenu_info_quick_add #quick_add_selectbox sl-menu-item[value=""], +#egw_fw_topmenu_info_items #topmenu_info_timer #quick_add_selectbox sl-menu-item[value=""], +#egw_fw_topmenu_info_items #topmenu_info_quick_add #timer_selectbox sl-menu-item[value=""], +#egw_fw_topmenu_info_items #topmenu_info_timer #timer_selectbox sl-menu-item[value=""] { + display: none; +} +#egw_fw_topmenu_info_items #topmenu_info_quick_add #quick_add_selectbox::part(form-control-input), +#egw_fw_topmenu_info_items #topmenu_info_timer #quick_add_selectbox::part(form-control-input), +#egw_fw_topmenu_info_items #topmenu_info_quick_add #timer_selectbox::part(form-control-input), +#egw_fw_topmenu_info_items #topmenu_info_timer #timer_selectbox::part(form-control-input) { border: none !important; } -#egw_fw_topmenu_info_items #topmenu_info_quick_add #quick_add_selectbox::part(form-control) { +#egw_fw_topmenu_info_items #topmenu_info_quick_add #quick_add_selectbox::part(form-control), +#egw_fw_topmenu_info_items #topmenu_info_timer #quick_add_selectbox::part(form-control), +#egw_fw_topmenu_info_items #topmenu_info_quick_add #timer_selectbox::part(form-control), +#egw_fw_topmenu_info_items #topmenu_info_timer #timer_selectbox::part(form-control) { margin-left: -3em; } -#egw_fw_topmenu_info_items #topmenu_info_quick_add #quick_add_selectbox::part(menu) { +#egw_fw_topmenu_info_items #topmenu_info_quick_add #quick_add_selectbox::part(menu), +#egw_fw_topmenu_info_items #topmenu_info_timer #quick_add_selectbox::part(menu), +#egw_fw_topmenu_info_items #topmenu_info_quick_add #timer_selectbox::part(menu), +#egw_fw_topmenu_info_items #topmenu_info_timer #timer_selectbox::part(menu) { max-height: 60vh; } -#egw_fw_topmenu_info_items #topmenu_info_quick_add et2-select#quick_add_selectbox sl-menu-item[value=""] { - display: none; -} #egw_fw_topmenu_info_items img#topmenu_info_error { width: 16px; height: 16px; diff --git a/timesheet/inc/class.timesheet_bo.inc.php b/timesheet/inc/class.timesheet_bo.inc.php index f6897e8700..6cd2e71fde 100644 --- a/timesheet/inc/class.timesheet_bo.inc.php +++ b/timesheet/inc/class.timesheet_bo.inc.php @@ -1041,4 +1041,14 @@ class timesheet_bo extends Api\Storage } return parent::data2db($intern ? null : $data); // important to use null, if $intern! } -} + + public function ajax_event(array $state) + { + Api\Cache::setSession(__CLASS__, 'timer', $state); + } + + public static function timerState() + { + return Api\Cache::getSession(__CLASS__, 'timer'); + } +} \ No newline at end of file diff --git a/timesheet/inc/class.timesheet_hooks.inc.php b/timesheet/inc/class.timesheet_hooks.inc.php index e254685313..c65a2e4b57 100644 --- a/timesheet/inc/class.timesheet_hooks.inc.php +++ b/timesheet/inc/class.timesheet_hooks.inc.php @@ -213,4 +213,12 @@ class timesheet_hooks return true; } -} + + public static function add_timer($data) + { + $state = timesheet_bo::timerState(); + $GLOBALS['egw']->framework->_add_topmenu_info_item('
0:00
', 'timer'); + } +} \ No newline at end of file diff --git a/timesheet/setup/setup.inc.php b/timesheet/setup/setup.inc.php index 74765f4b53..15eda50f7c 100644 --- a/timesheet/setup/setup.inc.php +++ b/timesheet/setup/setup.inc.php @@ -16,9 +16,9 @@ if (!defined('TIMESHEET_APP')) } $setup_info[TIMESHEET_APP]['name'] = TIMESHEET_APP; -$setup_info[TIMESHEET_APP]['version'] = '21.1'; +$setup_info[TIMESHEET_APP]['version'] = '22.1'; $setup_info[TIMESHEET_APP]['app_order'] = 5; -$setup_info[TIMESHEET_APP]['tables'] = array('egw_timesheet','egw_timesheet_extra'); +$setup_info[TIMESHEET_APP]['tables'] = array('egw_timesheet','egw_timesheet_extra','egw_timesheet_events'); $setup_info[TIMESHEET_APP]['enable'] = 1; $setup_info[TIMESHEET_APP]['index'] = 'timesheet.timesheet_ui.index&ajax=true'; @@ -45,9 +45,10 @@ $setup_info[TIMESHEET_APP]['hooks']['search_link'] = 'timesheet_hooks::search_li $setup_info[TIMESHEET_APP]['hooks']['pm_cumulate'] = 'timesheet_hooks::cumulate'; $setup_info[TIMESHEET_APP]['hooks']['deleteaccount'] = 'timesheet.timesheet_bo.deleteaccount'; $setup_info[TIMESHEET_APP]['hooks']['acl_rights'] = 'timesheet_hooks::acl_rights'; +$setup_info[TIMESHEET_APP]['hooks']['topmenu_info'] = 'timesheet_hooks::add_timer'; /* Dependencies for this app to work */ $setup_info[TIMESHEET_APP]['depends'][] = array( 'appname' => 'api', 'versions' => Array('21.1') -); +); \ No newline at end of file diff --git a/timesheet/setup/tables_current.inc.php b/timesheet/setup/tables_current.inc.php index 6fc1f50c4f..1e588df2e9 100644 --- a/timesheet/setup/tables_current.inc.php +++ b/timesheet/setup/tables_current.inc.php @@ -45,5 +45,23 @@ $phpgw_baseline = array( 'fk' => array(), 'ix' => array(), 'uc' => array() + ), + 'egw_timesheet_events' => array( + 'fd' => array( + 'tse_id' => array('type' => 'auto','nullable' => False), + 'ts_id' => array('type' => 'int','precision' => '4','comment' => 'or NULL for not yet created'), + 'tse_timestamp' => array('type' => 'timestamp','nullable' => False,'comment' => 'original time'), + 'tse_time' => array('type' => 'timestamp','comment' => 'edited time'), + 'account_id' => array('type' => 'int','meta' => 'user','precision' => '4','nullable' => False,'comment' => 'user timesheet is for'), + 'tse_modified' => array('type' => 'timestamp','nullable' => False,'default' => 'current_timestamp','comment' => 'automatic modification TS'), + 'tse_modifier' => array('type' => 'int','meta' => 'user','precision' => '4','comment' => 'modifier'), + 'tse_app' => array('type' => 'ascii','precision' => '24','comment' => 'app, if set on creation'), + 'tse_app_id' => array('type' => 'ascii','precision' => '64','comment' => 'app-id, if set on creation'), + 'tse_type' => array('type' => 'int','precision' => '16','nullable' => False,'comment' => '&1=start,&2=stop/pause,&16=overal-working-time') + ), + 'pk' => array('tse_id'), + 'fk' => array(), + 'ix' => array('ts_id'), + 'uc' => array('tse_id') ) ); diff --git a/timesheet/setup/tables_update.inc.php b/timesheet/setup/tables_update.inc.php index 88c1e64a3e..bb91e9deef 100644 --- a/timesheet/setup/tables_update.inc.php +++ b/timesheet/setup/tables_update.inc.php @@ -200,3 +200,28 @@ function timesheet_upgrade20_1() { return $GLOBALS['setup_info']['timesheet']['currentver'] = '21.1'; } + +function timesheet_upgrade21_1() +{ + $GLOBALS['egw_setup']->oProc->CreateTable('egw_timesheet_events',array( + 'fd' => array( + 'tse_id' => array('type' => 'auto','nullable' => False), + 'ts_id' => array('type' => 'int','precision' => '4','comment' => 'or NULL for not yet created'), + 'tse_timestamp' => array('type' => 'timestamp','nullable' => False,'comment' => 'original time'), + 'tse_time' => array('type' => 'timestamp','comment' => 'edited time'), + 'account_id' => array('type' => 'int','meta' => 'user','precision' => '4','nullable' => False,'comment' => 'user timesheet is for'), + 'tse_modified' => array('type' => 'timestamp','nullable' => False,'default' => 'current_timestamp','comment' => 'automatic modification TS'), + 'tse_modifier' => array('type' => 'int','meta' => 'user','precision' => '4','comment' => 'modifier'), + 'tse_app' => array('type' => 'ascii','precision' => '24','comment' => 'app, if set on creation'), + 'tse_app_id' => array('type' => 'ascii','precision' => '64','comment' => 'app-id, if set on creation'), + 'tse_type' => array('type' => 'int','precision' => '16','nullable' => False,'comment' => '&1=start,&2=stop/pause,&16=overal-working-time') + ), + 'pk' => array('tse_id'), + 'fk' => array(), + 'ix' => array('ts_id'), + 'uc' => array('tse_id') + )); + + return $GLOBALS['setup_info']['timesheet']['currentver'] = '22.1'; +} +