diff --git a/calendar/js/View.js b/calendar/js/View.js index fbe4583b30..bb9b227c76 100644 --- a/calendar/js/View.js +++ b/calendar/js/View.js @@ -234,9 +234,9 @@ var weekN = /** @class */ (function (_super_1) { }; weekN.end_date = function (state) { state.days = '' + (state.days >= 5 ? state.days : egw.preference('days_in_weekview', 'calendar') || 7); - var d = app.calendar.date.start_of_week(app.calendar.View.start_date.call(this, state)); + var d = app.calendar.date.start_of_week(_super_1.start_date.call(this, state)); // Always 7 days, we just turn weekends on or off - d.setUTCHours(24 * 7 * (parseInt(this.egw.preference('multiple_weeks', 'calendar')) || 3) - 1); + d.setUTCHours(24 * 7 * (parseInt(app.calendar.egw.preference('multiple_weeks', 'calendar')) || 3) - 1); return d; }; return weekN; diff --git a/calendar/js/View.ts b/calendar/js/View.ts index 6502defdbe..4fc7a5ad34 100644 --- a/calendar/js/View.ts +++ b/calendar/js/View.ts @@ -257,9 +257,9 @@ export class weekN extends View { state.days = '' + (state.days >= 5 ? state.days : egw.preference('days_in_weekview', 'calendar') || 7); - var d = app.calendar.date.start_of_week(app.calendar.View.start_date.call(this, state)); + var d = app.calendar.date.start_of_week(super.start_date(state)); // Always 7 days, we just turn weekends on or off - d.setUTCHours(24 * 7 * (parseInt(this.egw.preference('multiple_weeks', 'calendar')) || 3) - 1); + d.setUTCHours(24 * 7 * (parseInt(app.calendar.egw.preference('multiple_weeks', 'calendar')) || 3) - 1); return d; } } diff --git a/calendar/js/et2_widget_planner.js b/calendar/js/et2_widget_planner.js index 5473623a2d..c6236bec56 100644 --- a/calendar/js/et2_widget_planner.js +++ b/calendar/js/et2_widget_planner.js @@ -668,6 +668,7 @@ var et2_calendar_planner = /** @class */ (function (_super) { } this.widget.update_timer = null; this.widget.doInvalidate = true; + this.widget._updateNow(); window.setTimeout(jQuery.proxy(function () { if (this.loader) this.loader.hide(); }, this.widget), 500); }, { widget: this, "trigger": trigger }), et2_dataview_grid.ET2_GRID_INVALIDATE_TIMEOUT); @@ -819,6 +820,31 @@ var et2_calendar_planner = /** @class */ (function (_super) { content += "\n"; return content; }; + /** + * Update the 'now' line + * @private + */ + et2_calendar_planner.prototype._updateNow = function () { + var now = _super.prototype._updateNow.call(this); + if (now === false || this.grouper == this.groupers.month) { + this.now_div.hide(); + return false; + } + // Planner uses the dates, not just the times so need things right + now = new Date(now.valueOf() - now.getTimezoneOffset() * 60000); + var row = null; + for (var i = 0; i < this._children.length && row == null; i++) { + if (this._children[i].instanceOf(et2_widget_planner_row_1.et2_calendar_planner_row)) { + row = this._children[i]; + } + } + if (!row) { + this.now_div.hide(); + return false; + } + this.now_div.appendTo(this.grid) + .css('left', row._time_to_position(now) + '%'); + }; /** * Make a header showing the months * @param {Date} start diff --git a/calendar/js/et2_widget_planner.ts b/calendar/js/et2_widget_planner.ts index bdfac4a1ae..8e934ae62a 100644 --- a/calendar/js/et2_widget_planner.ts +++ b/calendar/js/et2_widget_planner.ts @@ -855,6 +855,7 @@ export class et2_calendar_planner extends et2_calendar_view implements et2_IDeta this.widget.update_timer = null; this.widget.doInvalidate = true; + this.widget._updateNow(); window.setTimeout(jQuery.proxy(function() {if(this.loader) this.loader.hide();},this.widget),500); },{widget:this,"trigger":trigger}),et2_dataview_grid.ET2_GRID_INVALIDATE_TIMEOUT); } @@ -1054,6 +1055,37 @@ export class et2_calendar_planner extends et2_calendar_view implements et2_IDeta return content; } + /** + * Update the 'now' line + * @private + */ + public _updateNow() + { + let now = super._updateNow(); + if(now === false || this.grouper == this.groupers.month) + { + this.now_div.hide(); + return false; + } + + // Planner uses the dates, not just the times so need things right + now = new Date(now.valueOf() - now.getTimezoneOffset()*60000); + let row = null; + for(let i = 0; i < this._children.length && row == null; i++) + { + if(this._children[i].instanceOf(et2_calendar_planner_row)) + { + row = this._children[i]; + } + } + if(!row) + { + this.now_div.hide(); + return false; + } + this.now_div.appendTo(this.grid) + .css('left', row._time_to_position(now) + '%'); + } /** * Make a header showing the months diff --git a/calendar/js/et2_widget_timegrid.js b/calendar/js/et2_widget_timegrid.js index 889126f976..e0f4557f78 100644 --- a/calendar/js/et2_widget_timegrid.js +++ b/calendar/js/et2_widget_timegrid.js @@ -30,6 +30,7 @@ var et2_core_inheritance_1 = require("../../api/js/etemplate/et2_core_inheritanc var et2_widget_view_1 = require("./et2_widget_view"); var et2_core_DOMWidget_1 = require("../../api/js/etemplate/et2_core_DOMWidget"); var et2_dataview_view_grid_1 = require("../../api/js/etemplate/et2_dataview_view_grid"); +var et2_widget_daycol_1 = require("./et2_widget_daycol"); /** * Class which implements the "calendar-timegrid" XET-Tag for displaying a span of days * @@ -450,6 +451,7 @@ var et2_calendar_timegrid = /** @class */ (function (_super) { if (this.trigger) { this.widget.change(); } + this.widget._updateNow(); // Hide loader window.setTimeout(jQuery.proxy(function () { this.loader.hide(); }, this.widget), 200); }, { widget: this, "trigger": trigger }), et2_dataview_view_grid_1.et2_dataview_grid.ET2_GRID_INVALIDATE_TIMEOUT); @@ -484,7 +486,7 @@ var et2_calendar_timegrid = /** @class */ (function (_super) { if (_sender === this || !_sender) { return this.div ? this.div[0] : null; } - else if (_sender.instanceOf(et2_calendar_daycol)) { + else if (_sender.instanceOf(et2_widget_daycol_1.et2_calendar_daycol)) { return this.days ? this.days[0] : null; } else if (_sender) { @@ -504,6 +506,29 @@ var et2_calendar_timegrid = /** @class */ (function (_super) { this.scrolling.scrollTop(this._top_time + 2); } }; + /** + * Update the 'now' line + * @private + */ + et2_calendar_timegrid.prototype._updateNow = function () { + var now = _super.prototype._updateNow.call(this); + if (now === false || this.options.granularity == 0) { + this.now_div.hide(); + return false; + } + for (var i = 0; i < this.day_widgets.length; i++) { + var day = this.day_widgets[i]; + if (day.getDate() >= now) { + day = this.day_widgets[i - 1]; + this.now_div.appendTo(day.getDOMNode()).show(); + var pos = day._time_to_position(now.getHours() * 60 + now.getMinutes()); + //this.now_div.position({my: 'left', at: 'left', of: day.getDOMNode()}); + this.now_div.css('top', pos + '%'); + break; + } + } + return true; + }; /** * Clear everything, and redraw the whole grid */ @@ -541,7 +566,7 @@ var et2_calendar_timegrid = /** @class */ (function (_super) { this.days.css('height', '100%'); this.iterateOver(function (day) { day.resize(); - }, this, et2_calendar_daycol); + }, this, et2_widget_daycol_1.et2_calendar_daycol); return; } var wd_start = 60 * this.options.day_start; @@ -768,6 +793,8 @@ var et2_calendar_timegrid = /** @class */ (function (_super) { } // Handle not fully visible elements this._scroll(); + // Set 'now' line + this._updateNow(); // TODO: Figure out how to do this with detached nodes /* var nodes = this.day_col.getDetachedNodes(); @@ -893,7 +920,7 @@ var et2_calendar_timegrid = /** @class */ (function (_super) { owner_match = owner_match || col.options.owner.indexOf(id) !== -1; own_timegrid = (col === event.getParent()); } - }, this, et2_calendar_daycol); + }, this, et2_widget_daycol_1.et2_calendar_daycol); } } var enabled = !owner_match && @@ -1112,7 +1139,7 @@ var et2_calendar_timegrid = /** @class */ (function (_super) { if (col.div.has(timegrid.gridHover).length || col.header.has(timegrid.gridHover).length) { add_owner = col.options.owner; } - }, this, et2_calendar_daycol); + }, this, et2_widget_daycol_1.et2_calendar_daycol); } egw().json('calendar.calendar_uiforms.ajax_invite', [ button_id === 'series' ? event_data.id : event_data.app_id, diff --git a/calendar/js/et2_widget_timegrid.ts b/calendar/js/et2_widget_timegrid.ts index de5bb08933..5a8b588ac0 100644 --- a/calendar/js/et2_widget_timegrid.ts +++ b/calendar/js/et2_widget_timegrid.ts @@ -18,6 +18,7 @@ import {ClassWithAttributes} from "../../api/js/etemplate/et2_core_inheritance"; import {et2_calendar_view} from "./et2_widget_view"; import {et2_action_object_impl} from "../../api/js/etemplate/et2_core_DOMWidget"; import {et2_dataview_grid} from "../../api/js/etemplate/et2_dataview_view_grid"; +import {et2_calendar_daycol} from "./et2_widget_daycol"; /** * Class which implements the "calendar-timegrid" XET-Tag for displaying a span of days @@ -618,6 +619,8 @@ export class et2_calendar_timegrid extends et2_calendar_view implements et2_IDet { this.widget.change(); } + this.widget._updateNow(); + // Hide loader window.setTimeout(jQuery.proxy(function() {this.loader.hide();},this.widget),200); },{widget:this,"trigger":trigger}),et2_dataview_grid.ET2_GRID_INVALIDATE_TIMEOUT); @@ -692,6 +695,34 @@ export class et2_calendar_timegrid extends et2_calendar_view implements et2_IDet } + /** + * Update the 'now' line + * @private + */ + public _updateNow() + { + let now = super._updateNow(); + if(now === false || this.options.granularity == 0) + { + this.now_div.hide(); + return false; + } + for(var i = 0; i < this.day_widgets.length; i++) + { + let day = this.day_widgets[i]; + if(day.getDate() >= now) + { + day = this.day_widgets[i-1]; + this.now_div.appendTo(day.getDOMNode()).show(); + let pos = day._time_to_position(now.getHours() * 60 + now.getMinutes()); + //this.now_div.position({my: 'left', at: 'left', of: day.getDOMNode()}); + this.now_div.css('top', pos + '%'); + break; + } + } + return true; + } + /** * Clear everything, and redraw the whole grid */ @@ -1032,6 +1063,9 @@ export class et2_calendar_timegrid extends et2_calendar_view implements et2_IDet // Handle not fully visible elements this._scroll(); + // Set 'now' line + this._updateNow(); + // TODO: Figure out how to do this with detached nodes /* var nodes = this.day_col.getDetachedNodes(); diff --git a/calendar/js/et2_widget_view.js b/calendar/js/et2_widget_view.js index f199c6635d..8b3d32f0f5 100644 --- a/calendar/js/et2_widget_view.js +++ b/calendar/js/et2_widget_view.js @@ -45,11 +45,14 @@ var et2_calendar_view = /** @class */ (function (_super) { _super.call(this, _parent, _attrs, et2_core_inheritance_1.ClassWithAttributes.extendAttributes(et2_calendar_view._attributes, _child || {})) || this; _this.dataStorePrefix = 'calendar'; _this.update_timer = null; + _this.now_timer = null; // Used for its date calculations _this._date_helper = et2_createWidget('date-time', {}, null); _this._date_helper.loadingFinished(); _this.loader = jQuery('
'); + _this.now_div = jQuery('
'); _this.update_timer = null; + _this.now_timer = null; // Used to support dragging on empty space to create an event _this.drag_create = { start: null, @@ -68,12 +71,19 @@ var et2_calendar_view = /** @class */ (function (_super) { if (this.update_timer) { window.clearTimeout(this.update_timer); } + // Stop the 'now' line + if (this.now_timer) { + window.clearInterval(this.now_timer); + } }; et2_calendar_view.prototype.doLoadingFinished = function () { _super.prototype.doLoadingFinished.call(this); this.loader.hide(0).prependTo(this.div); + this.div.append(this.now_div); if (this.options.owner) this.set_owner(this.options.owner); + // Start moving 'now' line + this.now_timer = window.setInterval(this._updateNow.bind(this), 60000); return true; }; /** @@ -274,6 +284,25 @@ var et2_calendar_view = /** @class */ (function (_super) { et2_calendar_view.prototype._createNamespace = function () { return true; }; + /** + * Update the 'now' line + * + * Here we just do some limit checks and return the current date/time. + * Extending widgets should handle position. + * + * @private + */ + et2_calendar_view.prototype._updateNow = function () { + var now = new Date(); + // Use date widget's existing functions to deal + this._date_helper.set_value(now); + now = new Date(this._date_helper.getValue()); + if (this.get_start_date() <= now && this.get_end_date() >= now) { + return now; + } + this.now_div.hide(); + return false; + }; /** * Calendar supports many different owner types, including users & resources. * This translates an ID to a user-friendly name. diff --git a/calendar/js/et2_widget_view.ts b/calendar/js/et2_widget_view.ts index edb31ea42d..9162d71fab 100644 --- a/calendar/js/et2_widget_view.ts +++ b/calendar/js/et2_widget_view.ts @@ -16,6 +16,7 @@ import {et2_widget, WidgetConfig} from "../../api/js/etemplate/et2_core_widget"; import {et2_valueWidget} from "../../api/js/etemplate/et2_core_valueWidget"; import {ClassWithAttributes} from "../../api/js/etemplate/et2_core_inheritance"; import {et2_date} from "../../api/js/etemplate/et2_widget_date"; +import {et2_calendar_event} from "./et2_widget_event"; /** * Parent class for the various calendar views to reduce copied code @@ -48,8 +49,10 @@ export class et2_calendar_view extends et2_valueWidget protected _date_helper: et2_date; protected loader: JQuery; protected div: JQuery; + protected now_div: JQuery; protected update_timer: number = null; + protected now_timer: number = null; protected drag_create: { parent: et2_widget; start: any; end: any; event: et2_calendar_event }; protected value: any; @@ -70,7 +73,9 @@ export class et2_calendar_view extends et2_valueWidget this._date_helper.loadingFinished(); this.loader = jQuery('
'); + this.now_div = jQuery('
'); this.update_timer = null; + this.now_timer = null; // Used to support dragging on empty space to create an event this.drag_create = { @@ -93,14 +98,23 @@ export class et2_calendar_view extends et2_valueWidget { window.clearTimeout(this.update_timer); } + + // Stop the 'now' line + if(this.now_timer) + { + window.clearInterval(this.now_timer); + } } doLoadingFinished( ) { super.doLoadingFinished(); this.loader.hide(0).prependTo(this.div); + this.div.append(this.now_div); if(this.options.owner) this.set_owner(this.options.owner); + // Start moving 'now' line + this.now_timer = window.setInterval(this._updateNow.bind(this), 60000); return true; } @@ -341,6 +355,30 @@ export class et2_calendar_view extends et2_valueWidget return true; } + /** + * Update the 'now' line + * + * Here we just do some limit checks and return the current date/time. + * Extending widgets should handle position. + * + * @private + */ + public _updateNow() + { + let now = new Date(); + // Use date widget's existing functions to deal + this._date_helper.set_value(now); + + now = new Date(this._date_helper.getValue()); + if(this.get_start_date() <= now && this.get_end_date() >= now) + { + return now; + } + + this.now_div.hide(); + return false; + } + /** * Calendar supports many different owner types, including users & resources. * This translates an ID to a user-friendly name. diff --git a/calendar/templates/default/app.css b/calendar/templates/default/app.css index 62a9dbaf1a..c1fac3e30a 100644 --- a/calendar/templates/default/app.css +++ b/calendar/templates/default/app.css @@ -241,6 +241,26 @@ e.g. the div with class calendar_calTimeGrid is generated by the timeGridWidget box-shadow: 0 0 5px; } +/* Current time indicator */ +.calendar_now { + position: absolute; + background: red; +} +.calendar_calTimeGrid .calendar_now { + height: 2px; + width: 100%; + left: 0px +} +.calendar_calTimeGridList .calendar_now { + display: none; +} +.calendar_plannerWidget .calendar_now { + height: 100%; + width: 2px; + top: 0px; +} + + .calendar_size120b { font-size: 120%; font-weight: bold; } /* marks a day in the colum-header as today diff --git a/calendar/templates/pixelegg/app.css b/calendar/templates/pixelegg/app.css index 621b342383..a1ca527efd 100755 --- a/calendar/templates/pixelegg/app.css +++ b/calendar/templates/pixelegg/app.css @@ -245,6 +245,24 @@ e.g. the div with class calendar_calTimeGrid is generated by the timeGridWidget -moz-box-shadow: 0 0 5px; box-shadow: 0 0 5px; } +/* Current time indicator */ +.calendar_now { + position: absolute; + background: red; +} +.calendar_calTimeGrid .calendar_now { + height: 2px; + width: 100%; + left: 0px; +} +.calendar_calTimeGridList .calendar_now { + display: none; +} +.calendar_plannerWidget .calendar_now { + height: 100%; + width: 2px; + top: 0px; +} .calendar_size120b { font-size: 120%; font-weight: bold;