From 63504f4e706207931f39a7ab78813f724cd064cc Mon Sep 17 00:00:00 2001 From: Fenris Wolf Date: Sun, 26 Oct 2025 21:46:58 +0100 Subject: [PATCH 1/6] [mod] Tages-Beschriftung in Wochenansichts-Zellen --- source/data/localization/deu.loc.json | 12 ++++ source/data/localization/eng.loc.json | 12 ++++ source/helpers.ts | 25 +++++++ source/main.ts | 24 ------- source/resources/conf.ts | 36 +++++++--- source/widgets/menu/logic.ts | 6 +- source/widgets/menu/style.css | 28 +++++--- source/widgets/weekview/logic.ts | 72 ++++++------------- source/widgets/weekview/style.css | 1 - .../templates/tableview-cell-entry.html.tpl | 2 +- .../templates/tableview-cell.html.tpl | 2 +- 11 files changed, 122 insertions(+), 98 deletions(-) diff --git a/source/data/localization/deu.loc.json b/source/data/localization/deu.loc.json index f5ec083..abaf730 100644 --- a/source/data/localization/deu.loc.json +++ b/source/data/localization/deu.loc.json @@ -14,6 +14,18 @@ "common.weekday.friday": "Fr", "common.weekday.saturday": "Sa", "common.weekday.sunday": "So", + "common.monthname.january": "Jan", + "common.monthname.february": "Feb", + "common.monthname.march": "Mär", + "common.monthname.april": "Apr", + "common.monthname.may": "Mai", + "common.monthname.june": "Jun", + "common.monthname.july": "Jul", + "common.monthname.august": "Aug", + "common.monthname.september": "Sep", + "common.monthname.october": "Okt", + "common.monthname.november": "Nov", + "common.monthname.december": "Dez", "common.open": "öffnen", "common.edit": "bearbeiten", "common.show": "zeigen", diff --git a/source/data/localization/eng.loc.json b/source/data/localization/eng.loc.json index 47785ec..1436b7d 100644 --- a/source/data/localization/eng.loc.json +++ b/source/data/localization/eng.loc.json @@ -14,6 +14,18 @@ "common.weekday.friday": "Fri", "common.weekday.saturday": "Sat", "common.weekday.sunday": "Sun", + "common.monthname.january": "jan", + "common.monthname.february": "feb", + "common.monthname.march": "mar", + "common.monthname.april": "apr", + "common.monthname.may": "may", + "common.monthname.june": "jun", + "common.monthname.july": "jul", + "common.monthname.august": "aug", + "common.monthname.september": "sep", + "common.monthname.october": "oct", + "common.monthname.november": "nov", + "common.monthname.december": "dec", "common.open": "open", "common.edit": "edit", "common.show": "show", diff --git a/source/helpers.ts b/source/helpers.ts index df17da7..48b1a3f 100644 --- a/source/helpers.ts +++ b/source/helpers.ts @@ -283,4 +283,29 @@ namespace _dali.helpers ); } + + /** + */ + export function month_name( + month : int + ) + : string + { + const keys : Array = [ + "common.monthname.january", + "common.monthname.february", + "common.monthname.march", + "common.monthname.april", + "common.monthname.may", + "common.monthname.june", + "common.monthname.july", + "common.monthname.august", + "common.monthname.september", + "common.monthname.october", + "common.monthname.november", + "common.monthname.december", + ]; + return lib_plankton.translate.get(keys[month-1]); + } + } diff --git a/source/main.ts b/source/main.ts index 83ef871..97cb9d8 100644 --- a/source/main.ts +++ b/source/main.ts @@ -40,21 +40,6 @@ namespace _dali } - /** - * @todo reload page when switching to "logged_out" - */ - async function update( - ) - : Promise - { - lib_plankton.log.debug( - "dali.update" - ); - const logged_in : boolean = _dali.is_logged_in(); - lib_plankton.zoo_page.nav_set_groups(nav_groups(logged_in)); - // lib_plankton.zoo_page.reload(); - } - /** */ @@ -196,16 +181,7 @@ namespace _dali } ); } - await update(); await _dali.overlay.initialize(); - /* - lib_plankton.call.loop( - () => { - update(); - }, - _dali.conf.get().misc.update_interval - ); - */ // check if logged_in { diff --git a/source/resources/conf.ts b/source/resources/conf.ts index 68968ca..915504b 100644 --- a/source/resources/conf.ts +++ b/source/resources/conf.ts @@ -73,14 +73,15 @@ namespace _dali.conf "default": "http://localhost:8888/#oidc_finish,session_key={{session_key}}" }, "use_central_europe_specific_datetime_inputs": { - "nullable": true, + "nullable": false, "type": "boolean", "default": false }, - "update_interval": { + "weekview_cell_day_format": { "nullable": false, - "type": "integer", - "default": 60 + "type": "string", + "default": "d.b", + "description": "available placeholders: Y,m,b,d,W,w (as in UNIX command 'date')" }, }, "required": [ @@ -98,7 +99,25 @@ namespace _dali.conf /** */ - var _data : (null | any) = null; + type type_data = { + version : string; + backend : { + scheme : string; + host : string; + port : int; + path : string; + }; + misc : { + oidc_redirect_uri_template : string; + use_central_europe_specific_datetime_inputs : string; + weekview_cell_day_format : string; + }; + }; + + + /** + */ + var _data : (null | type_data) = null; /** @@ -113,7 +132,7 @@ namespace _dali.conf /** */ export function get( - ) : any + ) : type_data { if (_data === null) { @@ -131,10 +150,7 @@ namespace _dali.conf path : string ) : Promise { - _data = await lib_plankton.conf.load( - _schema, - path - ); + _data = ((await lib_plankton.conf.load(_schema, path)) as type_data); return Promise.resolve(undefined); } diff --git a/source/widgets/menu/logic.ts b/source/widgets/menu/logic.ts index 195be71..fd9d540 100644 --- a/source/widgets/menu/logic.ts +++ b/source/widgets/menu/logic.ts @@ -66,7 +66,7 @@ namespace _dali.widgets.menu entry_data_list : Array, { "initial_groups": initial_groups = [], - "initial_label": initial_label = "=", + "initial_label": initial_label = "", } : { @@ -115,10 +115,10 @@ namespace _dali.widgets.menu : void { this.label = label; - this.container.querySelector(".widget-menu-button").textContent = ( + this.container.querySelector(".widget-menu-button").innerHTML = ( (this.label === null) ? - "[=]" + ("[" + "=" + "]") : ("[" + this.label + "]") ); diff --git a/source/widgets/menu/style.css b/source/widgets/menu/style.css index ab45279..8451302 100644 --- a/source/widgets/menu/style.css +++ b/source/widgets/menu/style.css @@ -47,6 +47,24 @@ list-style-type: none; } +.widget-menu-entry +{ + margin: 12px 8px; + text-transform: capitalize; + background-color: hsl(var(--hue), 0%, 25%); + color: hsl(var(--hue), 0%, 100%); + border-bottom: 2px solid hsl(0, 0%, 25%); +} + +.widget-menu-entry:hover +{ + color: hsl(var(--hue), 0%, 100%); + border-bottom: 2px solid hsl(0, 0%, 100%); + + transition: 1s ease color; +} + +/* .widget-menu-entry { margin: 8px; @@ -58,15 +76,7 @@ background-color: hsl(var(--hue), 0%, 25%); color: hsl(var(--hue), 0%, 100%); } - -.widget-menu-entry:hover::before -{ - content: "» "; - /* - background-color: hsl(var(--hue), 0%, 50%); - color: hsl(var(--hue), 0%, 100%); - */ -} + */ .widget-menu-entry.widget-menu-entry-hidden { diff --git a/source/widgets/weekview/logic.ts b/source/widgets/weekview/logic.ts index 8ed405f..fec5824 100644 --- a/source/widgets/weekview/logic.ts +++ b/source/widgets/weekview/logic.ts @@ -121,7 +121,7 @@ namespace _dali.widgets.weekview "vertical": vertical = false, "initial_year": initial_year = null, "initial_week": initial_week = null, - "initial_count": initial_count = 4, + "initial_count": initial_count = 5, } : { @@ -386,13 +386,6 @@ namespace _dali.widgets.weekview "tableview-cell-entry", { "color": _dali.helpers.event_color(entry.hue), - /* - "title": class_widget_weekview.event_generate_tooltip( - entry.calendar_name, - entry.event_object - ), - */ - "title": "", "name": entry.event_object.name, "rel": entry.key, "additional_classes": lib_plankton.string.coin( @@ -763,6 +756,8 @@ namespace _dali.widgets.weekview today_begin_pit, today_end_pit ); + const day_as_date : lib_plankton.pit.type_date = lib_plankton.pit.to_datetime_ce(day_pit).date; + const day_as_ywd : lib_plankton.pit.type_ywd = lib_plankton.pit.to_ywd(day_pit); return _dali.helpers.template_coin( "widget-weekview", "tableview-cell", @@ -772,47 +767,22 @@ namespace _dali.widgets.weekview .concat(is_today ? ["weekview-cell-today"] : []) .join(" ") ), - "title": lib_plankton.call.convey( - day_pit, - [ - lib_plankton.pit.to_datetime_ce, - (x : lib_plankton.pit.type_datetime) => lib_plankton.string.coin( - "{{year}}-{{month}}-{{day}}", - { - "year": x.date.year.toFixed(0).padStart(4, "0"), - "month": x.date.month.toFixed(0).padStart(2, "0"), - "day": x.date.day.toFixed(0).padStart(2, "0"), - } - ), - ] + "day": ( + _dali.conf.get().misc.weekview_cell_day_format + .replace(new RegExp("Y", "g"), day_as_date.year.toFixed(0).padStart(4, "0")) + .replace(new RegExp("m", "g"), day_as_date.month.toFixed(0).padStart(2, "0")) + .replace(new RegExp("b", "g"), _dali.helpers.month_name(day_as_date.month)) + .replace(new RegExp("d", "g"), day_as_date.day.toFixed(0).padStart(2, "0")) + .replace(new RegExp("W", "g"), day_as_ywd.week.toFixed(0).padStart(2, "0")) + .replace(new RegExp("w", "g"), day_as_ywd.day.toFixed(0).padStart(1, "0")) ), - "day": lib_plankton.call.convey( - day_pit, - [ - lib_plankton.pit.to_datetime_ce, - (x : lib_plankton.pit.type_datetime) => lib_plankton.string.coin( - "{{year}}-{{month}}-{{day}}", - { - "year": x.date.year.toFixed(0).padStart(4, "0"), - "month": x.date.month.toFixed(0).padStart(2, "0"), - "day": x.date.day.toFixed(0).padStart(2, "0"), - } - ), - ] - ), - "rel": lib_plankton.call.convey( - day_pit, - [ - lib_plankton.pit.to_datetime_ce, - (x : lib_plankton.pit.type_datetime) => lib_plankton.string.coin( - "{{year}}-{{month}}-{{day}}", - { - "year": x.date.year.toFixed(0).padStart(4, "0"), - "month": x.date.month.toFixed(0).padStart(2, "0"), - "day": x.date.day.toFixed(0).padStart(2, "0"), - } - ) - ] + "rel": lib_plankton.string.coin( + "{{year}}-{{month}}-{{day}}", + { + "year": day_as_date.year.toFixed(0).padStart(4, "0"), + "month": day_as_date.month.toFixed(0).padStart(2, "0"), + "day": day_as_date.day.toFixed(0).padStart(2, "0"), + } ), "entries": "" } @@ -835,7 +805,11 @@ namespace _dali.widgets.weekview element.addEventListener( "click", (event) => { - if (! (element === event.target)) + if ( + (! (element === event.target)) + && + (! (event.target as HTMLElement).classList.contains("weekview-day")) + ) { // do nothing } diff --git a/source/widgets/weekview/style.css b/source/widgets/weekview/style.css index f9c98fd..93b07bc 100644 --- a/source/widgets/weekview/style.css +++ b/source/widgets/weekview/style.css @@ -87,7 +87,6 @@ .weekview-day { font-size: 0.75em; - cursor: help; } .weekview-events diff --git a/source/widgets/weekview/templates/tableview-cell-entry.html.tpl b/source/widgets/weekview/templates/tableview-cell-entry.html.tpl index 3b578f9..e4240e7 100644 --- a/source/widgets/weekview/templates/tableview-cell-entry.html.tpl +++ b/source/widgets/weekview/templates/tableview-cell-entry.html.tpl @@ -1,3 +1,3 @@ -
  • +
  • {{name}}
  • diff --git a/source/widgets/weekview/templates/tableview-cell.html.tpl b/source/widgets/weekview/templates/tableview-cell.html.tpl index 7c2d76a..5fb9651 100644 --- a/source/widgets/weekview/templates/tableview-cell.html.tpl +++ b/source/widgets/weekview/templates/tableview-cell.html.tpl @@ -1,5 +1,5 @@ - + {{day}}
      -- 2.47.3 From bb33ff66b32b207a376df2a570deaa3e525e10b8 Mon Sep 17 00:00:00 2001 From: Fenris Wolf Date: Mon, 27 Oct 2025 17:22:13 +0100 Subject: [PATCH 2/6] [task-419] [int] --- lib/plankton/plankton.d.ts | 43 +++ lib/plankton/plankton.js | 224 +++++++++++++++ source/helpers.ts | 46 ++- source/pages/overview/logic.ts | 171 +++++------ source/pages/overview/style.css | 10 - .../overview/templates/body-regular.html.tpl | 4 + .../overview/templates/body-touch.html.tpl | 1 + .../pages/overview/templates/default.html.tpl | 18 -- source/pages/overview/templates/main.html.tpl | 8 + source/types.ts | 80 +++++- source/widgets/multiview/logic.ts | 269 ++++++++++++++++++ source/widgets/multiview/style.css | 10 + 12 files changed, 739 insertions(+), 145 deletions(-) create mode 100644 source/pages/overview/templates/body-regular.html.tpl create mode 100644 source/pages/overview/templates/body-touch.html.tpl delete mode 100644 source/pages/overview/templates/default.html.tpl create mode 100644 source/pages/overview/templates/main.html.tpl create mode 100644 source/widgets/multiview/logic.ts create mode 100644 source/widgets/multiview/style.css diff --git a/lib/plankton/plankton.d.ts b/lib/plankton/plankton.d.ts index 2b7018d..c6ea0f0 100644 --- a/lib/plankton/plankton.d.ts +++ b/lib/plankton/plankton.d.ts @@ -4194,6 +4194,49 @@ declare namespace lib_plankton.zoo_widget { load(target_element: HTMLElement): Promise; } } +declare namespace lib_plankton.zoo_widget { + /** + */ + class class_slider implements interface_widget { + /** + */ + private conf; + /** + */ + private state; + /** + */ + constructor(content: Array, { "threshold": threshold, "acceleration_function": acceleration_function, "initial_index": initial_index, }?: { + threshold?: float; + acceleration_function?: ((float: any) => float); + initial_index?: int; + }); + /** + */ + private static cap; + /** + */ + private static position_subtract; + /** + */ + private static touch_event_position; + /** + */ + private set_translation; + /** + */ + private start; + /** + */ + private update; + /** + */ + private finish; + /** + */ + load(target_element: HTMLElement): Promise; + } +} declare namespace lib_plankton.zoo_page { /** */ diff --git a/lib/plankton/plankton.js b/lib/plankton/plankton.js index f94ef73..a0e736f 100644 --- a/lib/plankton/plankton.js +++ b/lib/plankton/plankton.js @@ -12754,6 +12754,230 @@ var lib_plankton; })(zoo_widget = lib_plankton.zoo_widget || (lib_plankton.zoo_widget = {})); })(lib_plankton || (lib_plankton = {})); /* +This file is part of »bacterio-plankton:zoo-widget«. + +Copyright 2016-2025 'kcf' + +»bacterio-plankton:zoo-widget« is free software: you can redistribute it and/or modify +it under the terms of the GNU Lesser General Public License as published by +the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. + +»bacterio-plankton:zoo-widget« is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU Lesser General Public License for more details. + +You should have received a copy of the GNU Lesser General Public License +along with »bacterio-plankton:zoo-widget«. If not, see . + */ +var lib_plankton; +(function (lib_plankton) { + var zoo_widget; + (function (zoo_widget) { + /** + */ + class class_slider { + /** + */ + constructor(content, { "threshold": threshold = 200, "acceleration_function": acceleration_function = (x => (x * 3)), "initial_index": initial_index = 1, } = {}) { + this.conf = { + "content": content, + "threshold": threshold, + "acceleration_function": acceleration_function, + }; + this.state = { + "dom_context": null, + "index": initial_index, + "touch_start_position": null, + }; + } + /** + */ + static cap(minimum, maximum, value) { + let result = value; + if (minimum !== null) { + result = Math.max(minimum, result); + } + if (maximum !== null) { + result = Math.min(maximum, result); + } + return result; + } + /** + */ + static position_subtract(position1, position2) { + return { + "x": (position1.x - position2.x), + "y": (position1.y - position2.y), + }; + } + /** + */ + static touch_event_position(touch_event) { + return ((touch_event.changedTouches.length <= 0) + ? + null + : + { + "x": touch_event.changedTouches[0].pageX, + "y": touch_event.changedTouches[0].pageY, + }); + } + /** + */ + set_translation(position) { + const difference = (((this.state.touch_start_position === null) || (position === null)) + ? + null + : + class_slider.position_subtract(position, this.state.touch_start_position)); + this.state.dom_context.querySelector(".slides").style.transform = (([ + lib_plankton.string.coin("translateX({{value}}%)", { + "value": ((this.state.index - 1) * (-100)).toFixed(0) + }) + ] + .concat((difference === null) + ? + [] + : + [ + // + lib_plankton.string.coin("translateX({{value}}px)", { + "value": class_slider.cap(((this.state.index >= this.conf.content.length) + ? + (-this.conf.threshold) + : + null), ((this.state.index <= 1) + ? + this.conf.threshold + : + null), this.conf.acceleration_function(difference.x)).toFixed(0), + }) + ])) + .join(" ")); + } + /** + */ + start(position) { + if (position === null) { + // do nothing + } + else { + if (this.state.touch_start_position === null) { + this.state.touch_start_position = position; + } + else { + // do nothing + } + } + } + /** + */ + update(position) { + if (position === null) { + // do nothing + } + else { + if (this.state.touch_start_position === null) { + // do nothing + } + else { + this.set_translation(position); + } + } + } + /** + */ + finish(position) { + if (position === null) { + this.state.touch_start_position = null; + // do nothing + } + else { + if (this.state.touch_start_position === null) { + // do nothing + } + else { + const difference = class_slider.position_subtract(position, this.state.touch_start_position); + const offset = this.conf.acceleration_function(difference.x); + const index_increment = (() => { + if (offset <= -this.conf.threshold) { + return ((this.state.index >= this.conf.content.length) ? 0 : (+1)); + } + else if ((offset > -this.conf.threshold) && (offset < this.conf.threshold)) { + return 0; + } + else if (offset >= this.conf.threshold) { + return ((this.state.index <= 1) ? 0 : (-1)); + } + else { + // not possible + } + })(); + this.state.index += index_increment; + this.set_translation(null); + this.state.touch_start_position = null; + } + } + } + /** + */ + async load(target_element) { + this.state.dom_context = target_element; + // structure + { + const dom_container = document.createElement("div"); + { + dom_container.style.overflow = "hidden"; + dom_container.style.whiteSpace = "nowrap"; + } + { + const dom_content = document.createElement("div"); + { + dom_content.style.height = "100%"; + dom_content.style.width = "100%"; + dom_content.style.transition = "transform 0.25s ease-in-out"; + } + dom_content.classList.add("slides"); + for (const slide of this.conf.content) { + const dom_slide = document.createElement("div"); + dom_slide.classList.add("slide"); + { + dom_slide.style.display = "inline-block"; + dom_slide.style.height = "100%"; + dom_slide.style.width = "100%"; + dom_slide.style.transition = "width 0.25s ease-in-out"; + } + await slide.load(dom_slide); + dom_content.appendChild(dom_slide); + } + dom_container.appendChild(dom_content); + } + this.state.dom_context.appendChild(dom_container); + } + // listeners + { + this.state.dom_context.addEventListener("touchstart", (event) => { + this.start(class_slider.touch_event_position(event)); + }); + this.state.dom_context.addEventListener("touchmove", (event) => { + this.update(class_slider.touch_event_position(event)); + }); + this.state.dom_context.addEventListener("touchend", (event) => { + this.finish(class_slider.touch_event_position(event)); + }); + this.state.dom_context.addEventListener("touchcancel", (event) => { + this.finish(null); + }); + } + this.set_translation(null); + } + } + zoo_widget.class_slider = class_slider; + })(zoo_widget = lib_plankton.zoo_widget || (lib_plankton.zoo_widget = {})); +})(lib_plankton || (lib_plankton = {})); +/* This file is part of »bacterio-plankton:zoo-page«. Copyright 2016-2025 'kcf' diff --git a/source/helpers.ts b/source/helpers.ts index 48b1a3f..b1c5995 100644 --- a/source/helpers.ts +++ b/source/helpers.ts @@ -23,6 +23,23 @@ along with »dali«. If not, see . namespace _dali.helpers { + /** + * @todo outsource + */ + function is_touch_device( + ) + : boolean + { + return ( + ("ontouchstart" in window) + || + (navigator.maxTouchPoints > 0) + || + (navigator["msMaxTouchPoints"] > 0) + ); + } + + /** */ var _template_cache : Record = {}; @@ -32,12 +49,13 @@ namespace _dali.helpers */ export function view_mode_determine( mode_descriptor : string - ) : _dali.enum_view_mode + ) + : _dali.enum_view_mode { if (mode_descriptor === "auto") { return ( - (window.innerWidth >= 800) + (window.innerWidth >= 1000) ? _dali.enum_view_mode.week : @@ -51,6 +69,30 @@ namespace _dali.helpers } + /** + */ + export function view_kind_determine( + mode_descriptor : string + ) + : _dali.enum_view_kind + { + if (mode_descriptor === "auto") + { + return ( + is_touch_device() + ? + _dali.enum_view_kind.touch + : + _dali.enum_view_kind.regular + ); + } + else + { + return view_kind_decode(mode_descriptor); + } + } + + /** */ export async function template_coin( diff --git a/source/pages/overview/logic.ts b/source/pages/overview/logic.ts index 2266acc..27f229c 100644 --- a/source/pages/overview/logic.ts +++ b/source/pages/overview/logic.ts @@ -28,33 +28,9 @@ namespace _dali.pages.overview async (parameters, target_element) => { // params const view_mode : _dali.enum_view_mode = _dali.helpers.view_mode_determine(parameters["mode"] ?? "auto"); + const view_kind : _dali.enum_view_kind = _dali.helpers.view_kind_determine(parameters["kind"] ?? "auto"); // exec - target_element.innerHTML = await _dali.helpers.template_coin( - "overview", - "default", - { - } - ); - - let widget_mode_switcher : lib_plankton.zoo_widget.interface_widget; - let widget_sources : _dali.widgets.sources.class_widget_sources; - let widget_weekview : _dali.widgets.weekview.class_widget_weekview; - let widget_listview : _dali.widgets.listview.class_widget_listview; - - /** - * @todo ordentlich machen (nicht nur week und list) - */ - function set_view_mode - ( - view_mode : _dali.enum_view_mode - ) - : void - { - const compact : boolean = (view_mode !== _dali.enum_view_mode.week); - target_element.querySelector("#overview").classList.toggle("overview-compact", compact); - } - /** */ async function get_available_calendars( @@ -125,7 +101,7 @@ namespace _dali.pages.overview : Promise { await widget_sources.update({"priviliged": priviliged}); - await widget_weekview.update_entries(); + await widget_multiview.update_entries(); } /** @@ -146,7 +122,7 @@ namespace _dali.pages.overview ) : Promise { - await widget_weekview.update_entries(); + await widget_multiview.update_entries(); } /** @@ -500,7 +476,71 @@ namespace _dali.pages.overview _dali.overlay.toggle({"mode": true}); await widget.load(_dali.overlay.get_content_element()); } - + + const widget_sources : _dali.widgets.sources.class_widget_sources = ( + new _dali.widgets.sources.class_widget_sources( + _dali.model.calendar_list, + { + "initial_priviliged": _dali.is_logged_in(), + "action_add": action_create_calendar, + "action_select": (entry) => action_edit_calendar(entry), + "action_toggle": (entry, mode) => { + widget_multiview.toggle_calendar_visibilty(entry.id, {"mode": mode}); + }, + } + ) + ); + const widget_multiview : _dali.widgets.multiview.class_widget_multiview = ( + new _dali.widgets.multiview.class_widget_multiview( + get_entries, + { + "initial_view_mode": view_mode, + "action_create_event": action_create_event, + "action_edit_event": action_edit_event, + } + ) + ); + + target_element.innerHTML = await _dali.helpers.template_coin( + "overview", + "main", + { + } + ); + + switch (view_kind) + { + case _dali.enum_view_kind.regular: + { + target_element.querySelector("#overview-body").innerHTML = await _dali.helpers.template_coin( + "overview", + "body-regular", + { + } + ); + + await widget_sources.load(target_element.querySelector("#overview-pane-left")); + await widget_multiview.load(target_element.querySelector("#overview-pane-right")); + + break; + } + case _dali.enum_view_kind.touch: + { + const widget_slider = new lib_plankton.zoo_widget.class_slider( + [ + widget_sources, + widget_multiview, + ], + { + "threshold": 100, + "initial_index": 2, + } + ) + await widget_slider.load(target_element.querySelector("#overview-body")); + break; + } + } + // hint { const dom_hint = target_element.querySelector("#overview-hint"); @@ -510,79 +550,8 @@ namespace _dali.pages.overview // mode switcher { - widget_mode_switcher = new _dali.widgets.mode_switcher.class_widget_mode_switcher( - [ - { - "mode": _dali.enum_view_mode.week, - "label": lib_plankton.translate.get("page.overview.mode.week"), - }, - { - "mode": _dali.enum_view_mode.list, - "label": lib_plankton.translate.get("page.overview.mode.list"), - }, - ], - { - "initial_selection": view_mode, - "action_change": (view_mode) => { - lib_plankton.zoo_page.set( - { - "name": "overview", - "parameters": { - "mode": _dali.view_mode_encode(view_mode), - } - } - ); - set_view_mode(view_mode); - } - } - ); - set_view_mode(view_mode); - await widget_mode_switcher.load(target_element.querySelector("#overview-mode")); - } - - // sources - { - widget_sources = new _dali.widgets.sources.class_widget_sources( - _dali.model.calendar_list, - { - "initial_priviliged": _dali.is_logged_in(), - "action_add": action_create_calendar, - "action_select": (entry) => action_edit_calendar(entry), - "action_toggle": (entry, mode) => { - widget_weekview.toggle_visibility(entry.id, {"mode": mode}); - widget_listview.toggle_visibility(entry.id, {"mode": mode}); - }, - } - ); - await widget_sources.load(target_element.querySelector("#overview-pane-left")); - } - - // weekview - { - widget_weekview = ( - new _dali.widgets.weekview.class_widget_weekview( - get_entries, - { - "action_select_event": (event_key) => action_edit_event(event_key), - "action_select_day": (date) => action_create_event({"date": date}), - } - ) - ); - await widget_weekview.load(target_element.querySelector("#overview-pane-right-weekview")); - } - - // listview - { - widget_listview = ( - new _dali.widgets.listview.class_widget_listview( - get_entries, - { - "action_select": (event_key) => action_edit_event(event_key), - "action_add": () => action_create_event(), - } - ) - ); - await widget_listview.load(target_element.querySelector("#overview-pane-right-listview")); + // set_view_mode(view_mode); + // await widget_mode_switcher.load(target_element.querySelector("#overview-mode")); } _dali.model.listen_reset( diff --git a/source/pages/overview/style.css b/source/pages/overview/style.css index f60b623..9e2a028 100644 --- a/source/pages/overview/style.css +++ b/source/pages/overview/style.css @@ -34,13 +34,3 @@ flex-grow: 1; flex-shrink: 1; } - -#overview.overview-compact #overview-pane-left {/*flex-basis: 25%;*/display: none;} -#overview.overview-compact #overview-pane-right {flex-basis: 75%;} -#overview.overview-compact #overview-pane-right-listview {} -#overview.overview-compact #overview-pane-right-weekview {display: none;} - -#overview:not(.overview-compact) #overview-pane-left {flex-basis: 12.5%;} -#overview:not(.overview-compact) #overview-pane-right {flex-basis: 87.5%;} -#overview:not(.overview-compact) #overview-pane-right-listview {display: none;} -#overview:not(.overview-compact) #overview-pane-right-weekview {} diff --git a/source/pages/overview/templates/body-regular.html.tpl b/source/pages/overview/templates/body-regular.html.tpl new file mode 100644 index 0000000..1cf6257 --- /dev/null +++ b/source/pages/overview/templates/body-regular.html.tpl @@ -0,0 +1,4 @@ +
      +
      +
      +
      diff --git a/source/pages/overview/templates/body-touch.html.tpl b/source/pages/overview/templates/body-touch.html.tpl new file mode 100644 index 0000000..8b13789 --- /dev/null +++ b/source/pages/overview/templates/body-touch.html.tpl @@ -0,0 +1 @@ + diff --git a/source/pages/overview/templates/default.html.tpl b/source/pages/overview/templates/default.html.tpl deleted file mode 100644 index aeb85a8..0000000 --- a/source/pages/overview/templates/default.html.tpl +++ /dev/null @@ -1,18 +0,0 @@ -
      -
      -
      -
      -
      -
      -
      -
      -
      -
      -
      -
      -
      -
      -
      -
      -
      -
      diff --git a/source/pages/overview/templates/main.html.tpl b/source/pages/overview/templates/main.html.tpl new file mode 100644 index 0000000..57a0928 --- /dev/null +++ b/source/pages/overview/templates/main.html.tpl @@ -0,0 +1,8 @@ +
      +
      +
      +
      +
      +
      +
      +
      diff --git a/source/types.ts b/source/types.ts index 925bdb4..5767175 100644 --- a/source/types.ts +++ b/source/types.ts @@ -25,7 +25,8 @@ namespace _dali /** */ - export enum enum_access_level { + export enum enum_access_level + { none, view, edit, @@ -202,20 +203,12 @@ namespace _dali }; - /** - */ - export enum enum_view_mode - { - week, - list, - } - - /** */ export function access_level_encode( access_level : _dali.enum_access_level - ) : ("none" | "view" | "edit" | "admin") + ) + : ("none" | "view" | "edit" | "admin") { switch (access_level) { @@ -231,7 +224,8 @@ namespace _dali */ export function access_level_decode( representation : /*("none" | "view" | "edit" | "admin")*/string - ) : _dali.enum_access_level + ) + : _dali.enum_access_level { switch (representation) { @@ -244,11 +238,21 @@ namespace _dali } + /** + */ + export enum enum_view_mode + { + week, + list, + } + + /** */ export function view_mode_encode( mode : _dali.enum_view_mode - ) : string + ) + : string { switch (mode) { @@ -263,7 +267,8 @@ namespace _dali */ export function view_mode_decode( view_mode_encoded : string - ) : _dali.enum_view_mode + ) + : _dali.enum_view_mode { const map : Record = { "week": _dali.enum_view_mode.week, @@ -279,4 +284,51 @@ namespace _dali } } + + /** + */ + export enum enum_view_kind + { + regular, + touch, + } + + + /** + */ + export function view_kind_encode( + kind : _dali.enum_view_kind + ) + : string + { + switch (kind) + { + case _dali.enum_view_kind.regular: {return "regular"; break;} + case _dali.enum_view_kind.touch: {return "touch"; break;} + default: {throw (new Error("invalid kind"));} + } + } + + + /** + */ + export function view_kind_decode( + view_kind_encoded : string + ) + : _dali.enum_view_kind + { + const map : Record = { + "regular": _dali.enum_view_kind.regular, + "touch": _dali.enum_view_kind.touch, + }; + if (! (view_kind_encoded in map)) + { + throw (new Error("invalid kind: " + view_kind_encoded)); + } + else + { + return map[view_kind_encoded]; + } + } + } diff --git a/source/widgets/multiview/logic.ts b/source/widgets/multiview/logic.ts new file mode 100644 index 0000000..b34d7b5 --- /dev/null +++ b/source/widgets/multiview/logic.ts @@ -0,0 +1,269 @@ +/* +This file is part of »dali«. + +Copyright 2025 'kcf' + +»dali« is free software: you can redistribute it and/or modify +it under the terms of the GNU Lesser General Public License as published by +the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. + +»dali« is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU Lesser General Public License for more details. + +You should have received a copy of the GNU Lesser General Public License +along with »dali«. If not, see . + */ + + +namespace _dali.widgets.multiview +{ + + /** + */ + type type_get_entries = ( + ( + from_pit : lib_plankton.pit.type_pit, + to_pit : lib_plankton.pit.type_pit, + calendar_ids : Array<_dali.type_calendar_id> + ) + => + Promise> + ); + + + /** + */ + type type_create_event = ( + ( + stuff ?: { + date ?: lib_plankton.pit.type_date; + } + ) + => + Promise + ); + + + /** + */ + type type_edit_event = ( + ( + event_key : _dali.type_event_key + ) + => + Promise + ); + + + /** + */ + export class class_widget_multiview + implements lib_plankton.zoo_widget.interface_widget + { + + /** + */ + private initial_view_mode : _dali.enum_view_mode; + + + /** + */ + private get_entries : type_get_entries; + + + /** + */ + private action_create_event : type_create_event; + + + /** + */ + private action_edit_event : type_edit_event; + + + /** + */ + private dom_context : (null | HTMLElement); + + + /** + */ + private widget_mode_switcher : _dali.widgets.mode_switcher.class_widget_mode_switcher; + + + /** + */ + private widget_weekview : _dali.widgets.weekview.class_widget_weekview; + + + /** + */ + private widget_listview : _dali.widgets.listview.class_widget_listview; + + + /** + */ + public constructor( + get_entries : type_get_entries, + { + "initial_view_mode": initial_view_mode = _dali.enum_view_mode.week, + "action_create_event": action_create_event = ((stuff) => Promise.resolve(undefined)), + "action_edit_event": action_edit_event = ((event_key) => Promise.resolve(undefined)), + } + : + { + initial_view_mode ?: _dali.enum_view_mode; + action_create_event ?: type_create_event; + action_edit_event ?: type_edit_event; + } + = + { + } + ) + { + this.get_entries = get_entries; + this.initial_view_mode = initial_view_mode; + this.action_create_event = action_create_event; + this.action_edit_event = action_edit_event; + this.dom_context = null; + } + + + /** + */ + public toggle_calendar_visibilty( + calendar_id : _dali.type_calendar_id, + { + "mode": mode = null, + } + : + { + mode ?: (null | boolean); + } + = + { + } + ) + : void + { + this.widget_weekview.toggle_visibility(calendar_id, {"mode": mode}); + this.widget_listview.toggle_visibility(calendar_id, {"mode": mode}); + } + + + /** + */ + private set_view_mode + ( + view_mode : _dali.enum_view_mode + ) + : void + { + this.dom_context.setAttribute("rel", _dali.view_mode_encode(view_mode)); + } + + + /** + */ + public update_entries( + ) + : + Promise + { + return this.widget_weekview.update_entries(); + } + + + /** + * [implementation] + */ + public async load( + target_element : Element + ) + : Promise + { + this.dom_context = (target_element as HTMLElement); + + this.dom_context.classList.add("widget-multiview"); + + // mode switcher + { + this.widget_mode_switcher = ( + new _dali.widgets.mode_switcher.class_widget_mode_switcher( + [ + { + "mode": _dali.enum_view_mode.week, + "label": lib_plankton.translate.get("page.overview.mode.week"), + }, + { + "mode": _dali.enum_view_mode.list, + "label": lib_plankton.translate.get("page.overview.mode.list"), + }, + ], + { + "initial_selection": this.initial_view_mode, + "action_change": (view_mode) => { + console.warn("todo"); + /* + lib_plankton.zoo_page.set( + { + "name": "overview", + "parameters": { + "mode": _dali.view_mode_encode(view_mode), + } + } + ); + */ + this.set_view_mode(view_mode); + } + } + ) + ); + let dom_wrapper = document.createElement("div"); + dom_wrapper.classList.add("widget-multiview-mode_switcher"); + await this.widget_mode_switcher.load(dom_wrapper); + this.dom_context.appendChild(dom_wrapper); + } + // weekview + { + this.widget_weekview = ( + new _dali.widgets.weekview.class_widget_weekview( + this.get_entries, + { + "action_select_event": (event_key) => this.action_edit_event(event_key), + "action_select_day": (date) => this.action_create_event({"date": date}), + } + ) + ); + let dom_wrapper = document.createElement("div"); + dom_wrapper.classList.add("widget-multiview-weekview"); + await this.widget_weekview.load(dom_wrapper); + this.dom_context.appendChild(dom_wrapper); + } + // listview + { + this.widget_listview = ( + new _dali.widgets.listview.class_widget_listview( + this.get_entries, + { + "action_select": (event_key) => this.action_edit_event(event_key), + "action_add": () => this.action_create_event(), + } + ) + ); + let dom_wrapper = document.createElement("div"); + dom_wrapper.classList.add("widget-multiview-listview"); + await this.widget_listview.load(dom_wrapper); + this.dom_context.appendChild(dom_wrapper); + } + this.set_view_mode(this.initial_view_mode); + + return Promise.resolve(undefined); + } + + } + +} diff --git a/source/widgets/multiview/style.css b/source/widgets/multiview/style.css new file mode 100644 index 0000000..a9fbf06 --- /dev/null +++ b/source/widgets/multiview/style.css @@ -0,0 +1,10 @@ +.widget-multiview-mode_switcher +{ + margin-bottom: 12px; +} + +.widget-multiview[rel="week"] > .widget-multiview-weekview {} +.widget-multiview[rel="week"] > .widget-multiview-listview {display: none;} + +.widget-multiview[rel="list"] > .widget-multiview-weekview {display: none;} +.widget-multiview[rel="list"] > .widget-multiview-listview {} -- 2.47.3 From 7a5aeb3ff33fd7b49417279a0d06f0bd800a3999 Mon Sep 17 00:00:00 2001 From: Fenris Wolf Date: Mon, 27 Oct 2025 23:11:28 +0100 Subject: [PATCH 3/6] [task-419] [int] --- lib/plankton/plankton.js | 74 +++-- source/pages/overview/logic.ts | 30 +- source/pages/overview/style.css | 27 +- .../overview/templates/body-regular.html.tpl | 4 - .../overview/templates/body-touch.html.tpl | 1 - source/widgets/listview/logic.ts | 278 ++++++++++-------- source/widgets/mode_switcher/style.css | 4 + source/widgets/multiview/logic.ts | 29 +- source/widgets/weekview/logic.ts | 3 +- 9 files changed, 262 insertions(+), 188 deletions(-) delete mode 100644 source/pages/overview/templates/body-regular.html.tpl delete mode 100644 source/pages/overview/templates/body-touch.html.tpl create mode 100644 source/widgets/mode_switcher/style.css diff --git a/lib/plankton/plankton.js b/lib/plankton/plankton.js index a0e736f..dfa0424 100644 --- a/lib/plankton/plankton.js +++ b/lib/plankton/plankton.js @@ -12743,9 +12743,10 @@ var lib_plankton; const dom_container = document.createElement("div"); dom_container.classList.add("widget-bunch"); for (const element of this.elements) { - const dom_li = document.createElement("li"); - await element.load(dom_li); - dom_container.appendChild(dom_li); + const dom_element = document.createElement("div"); + dom_element.classList.add("widget-bunch-element"); + await element.load(dom_element); + dom_container.appendChild(dom_element); } target_element.appendChild(dom_container); } @@ -12832,7 +12833,7 @@ var lib_plankton; null : class_slider.position_subtract(position, this.state.touch_start_position)); - this.state.dom_context.querySelector(".slides").style.transform = (([ + this.state.dom_context.querySelector(".widget-slider-slides").style.transform = (([ lib_plankton.string.coin("translateX({{value}}%)", { "value": ((this.state.index - 1) * (-100)).toFixed(0) }) @@ -12842,7 +12843,6 @@ var lib_plankton; [] : [ - // lib_plankton.string.coin("translateX({{value}}px)", { "value": class_slider.cap(((this.state.index >= this.conf.content.length) ? @@ -12925,30 +12925,60 @@ var lib_plankton; */ async load(target_element) { this.state.dom_context = target_element; + // style + { + const dom_style = document.createElement("style"); + dom_style.textContent = ([ + { + "selector": ".widget-slider", + "settings": { + "overflow": "hidden", + "white-space": "nowrap", + "width": "100%", + }, + }, + { + "selector": ".widget-slider-slides", + "settings": { + "width": "100%", + "height": "100%", + "transition": "transform 0.25s ease-in-out", + } + }, + { + "selector": ".widget-slider-slide", + "settings": { + "display": "inline-block", + "height": "100%", + "width": "100%;", + "vertical-align": "top", + "white-space": "normal", + "transition": "width 0.25s ease-in-out", + } + } + ] + .map(rule => lib_plankton.string.coin("{{selector}} {{{settings}}}", { + "selector": rule.selector, + "settings": (Object.entries(rule.settings) + .map(([key, value]) => lib_plankton.string.coin("{{key}}: {{value}};", { + "key": key, + "value": value, + })) + .join(" ")) + })) + .join("\n")); + this.state.dom_context.appendChild(dom_style); + } // structure { const dom_container = document.createElement("div"); - { - dom_container.style.overflow = "hidden"; - dom_container.style.whiteSpace = "nowrap"; - } + dom_container.classList.add("widget-slider"); { const dom_content = document.createElement("div"); - { - dom_content.style.height = "100%"; - dom_content.style.width = "100%"; - dom_content.style.transition = "transform 0.25s ease-in-out"; - } - dom_content.classList.add("slides"); + dom_content.classList.add("widget-slider-slides"); for (const slide of this.conf.content) { const dom_slide = document.createElement("div"); - dom_slide.classList.add("slide"); - { - dom_slide.style.display = "inline-block"; - dom_slide.style.height = "100%"; - dom_slide.style.width = "100%"; - dom_slide.style.transition = "width 0.25s ease-in-out"; - } + dom_slide.classList.add("widget-slider-slide"); await slide.load(dom_slide); dom_content.appendChild(dom_slide); } diff --git a/source/pages/overview/logic.ts b/source/pages/overview/logic.ts index 27f229c..873374c 100644 --- a/source/pages/overview/logic.ts +++ b/source/pages/overview/logic.ts @@ -495,6 +495,7 @@ namespace _dali.pages.overview get_entries, { "initial_view_mode": view_mode, + "weekview_initial_vertical": (view_kind === _dali.enum_view_kind.touch), "action_create_event": action_create_event, "action_edit_event": action_edit_event, } @@ -512,16 +513,21 @@ namespace _dali.pages.overview { case _dali.enum_view_kind.regular: { - target_element.querySelector("#overview-body").innerHTML = await _dali.helpers.template_coin( - "overview", - "body-regular", + const widget_slider = new lib_plankton.zoo_widget.class_slider( + [ + new lib_plankton.zoo_widget.class_bunch( + [ + widget_sources, + widget_multiview, + ] + ), + ], { - } + "threshold": 100, + "initial_index": 1, + } ); - - await widget_sources.load(target_element.querySelector("#overview-pane-left")); - await widget_multiview.load(target_element.querySelector("#overview-pane-right")); - + await widget_slider.load(target_element.querySelector("#overview-body")); break; } case _dali.enum_view_kind.touch: @@ -535,7 +541,7 @@ namespace _dali.pages.overview "threshold": 100, "initial_index": 2, } - ) + ); await widget_slider.load(target_element.querySelector("#overview-body")); break; } @@ -548,12 +554,6 @@ namespace _dali.pages.overview dom_hint.classList.toggle("overview-hint-hidden", _dali.is_logged_in()); } - // mode switcher - { - // set_view_mode(view_mode); - // await widget_mode_switcher.load(target_element.querySelector("#overview-mode")); - } - _dali.model.listen_reset( async (priviliged) => { update_sources_and_entries({"priviliged": priviliged}); diff --git a/source/pages/overview/style.css b/source/pages/overview/style.css index 9e2a028..1d7c2dc 100644 --- a/source/pages/overview/style.css +++ b/source/pages/overview/style.css @@ -23,14 +23,37 @@ flex-wrap: nowrap; } -#overview-body #overview-pane-left +#overview-pane-left { + flex-basis: 12.5%; flex-grow: 0; flex-shrink: 1; } -#overview-body #overview-pane-right +#overview-pane-right { + flex-basis: 87.5%; flex-grow: 1; flex-shrink: 1; } + +#overview-body .widget-slider-slide .widget-bunch +{ + display: flex; + flex-direction: row; + flex-wrap: nowrap; +} + +#overview-body .widget-slider-slide .widget-bunch-element:nth-child(1) +{ + flex-grow: 0; + flex-shrink: 1; + flex-basis: 12.5%; +} + +#overview-body .widget-slider-slide .widget-bunch-element:nth-child(2) +{ + flex-grow: 1; + flex-shrink: 1; + flex-basis: 87.5%; +} diff --git a/source/pages/overview/templates/body-regular.html.tpl b/source/pages/overview/templates/body-regular.html.tpl deleted file mode 100644 index 1cf6257..0000000 --- a/source/pages/overview/templates/body-regular.html.tpl +++ /dev/null @@ -1,4 +0,0 @@ -
      -
      -
      -
      diff --git a/source/pages/overview/templates/body-touch.html.tpl b/source/pages/overview/templates/body-touch.html.tpl deleted file mode 100644 index 8b13789..0000000 --- a/source/pages/overview/templates/body-touch.html.tpl +++ /dev/null @@ -1 +0,0 @@ - diff --git a/source/widgets/listview/logic.ts b/source/widgets/listview/logic.ts index 34c68e6..98d3340 100644 --- a/source/widgets/listview/logic.ts +++ b/source/widgets/listview/logic.ts @@ -162,146 +162,121 @@ namespace _dali.widgets.listview /** - * [implementation] */ - public async load( - target_element : Element + public async update_entries( ) : Promise { - const now_pit : lib_plankton.pit.type_pit = lib_plankton.pit.now(); - const from_pit : lib_plankton.pit.type_pit = now_pit; - const to_pit : lib_plankton.pit.type_pit = lib_plankton.pit.shift_week(now_pit, +4); - const entries : Array<_dali.type_event_object_extended> = await this.get_entries( - from_pit, - to_pit, - null - ); - entries.sort( - (x, y) => ( - lib_plankton.pit.from_datetime(x.event_object.begin) - - - lib_plankton.pit.from_datetime(y.event_object.begin) - ) - ); - - // view + // structure { - target_element.innerHTML = await _dali.helpers.template_coin( - "widget-listview", - "main", - { - "add_href": "", - "add_label": lib_plankton.translate.get("widget.listview.add"), - "add_extra_classes": ( - (! await _dali.is_logged_in()) - ? - " listview-add-hidden" - : - "" - ), - "entries": ( - ( - await _dali.helpers.promise_row( - entries - .filter( - (entry) => ( - this.include_passed - ? - true - : - lib_plankton.pit.is_after( - lib_plankton.pit.from_datetime(entry.event_object.begin), - now_pit - ) - ) - ) - .map( - (entry) => () => _dali.helpers.template_coin( - "widget-listview", - "entry", - { - "name_value": entry.event_object.name, - "calendar_value": entry.calendar_name, - "when_value": lib_plankton.pit.timespan_format( - entry.event_object.begin, - entry.event_object.end, - { - "timezone_indicator": lib_plankton.translate.get("common.timezone_indicator"), - "adjust_to_ce": true, - "show_timezone": false, - } - ), - "location_label": lib_plankton.translate.get("event.location"), - "location_extra_classes": ( - (entry.event_object.location === null) - ? - " listview-entry-field-empty" - : - "" - ), - "location_value": ( - (entry.event_object.location === null) - ? - "?" - : - entry.event_object.location - ), - "link_label": lib_plankton.translate.get("event.link"), - "link_extra_classes": ( - (entry.event_object.link === null) - ? - " listview-entry-field-empty" - : - "" - ), - "link_value": ( - (entry.event_object.link === null) - ? - "?" - : - entry.event_object.link - ), - "link_action": lib_plankton.translate.get("common.open"), - "description_label": lib_plankton.translate.get("event.description"), - "description_extra_classes": ( - (entry.event_object.description === null) - ? - " listview-entry-field-empty" - : - "" - ), - "description_value": ( - (entry.event_object.description === null) - ? - "?" - : - entry.event_object.description - ), - "raw": JSON.stringify(entry), - "color": _dali.helpers.event_color(entry.hue), - "rel": entry.key, - }, - ) + const now_pit : lib_plankton.pit.type_pit = lib_plankton.pit.now(); + const from_pit : lib_plankton.pit.type_pit = now_pit; + const to_pit : lib_plankton.pit.type_pit = lib_plankton.pit.shift_week(now_pit, +4); + const entries : Array<_dali.type_event_object_extended> = await this.get_entries( + from_pit, + to_pit, + null + ); + entries.sort( + (x, y) => ( + lib_plankton.pit.from_datetime(x.event_object.begin) + - + lib_plankton.pit.from_datetime(y.event_object.begin) + ) + ); + const dom_list : HTMLElement = this.container.querySelector(".listview-entries"); + dom_list.innerHTML = ( + ( + await _dali.helpers.promise_row( + entries + .filter( + (entry) => ( + this.include_passed + ? + true + : + lib_plankton.pit.is_after( + lib_plankton.pit.from_datetime(entry.event_object.begin), + now_pit ) ) ) - .join("") - ), - } + .map( + (entry) => () => _dali.helpers.template_coin( + "widget-listview", + "entry", + { + "name_value": entry.event_object.name, + "calendar_value": entry.calendar_name, + "when_value": lib_plankton.pit.timespan_format( + entry.event_object.begin, + entry.event_object.end, + { + "timezone_indicator": lib_plankton.translate.get("common.timezone_indicator"), + "adjust_to_ce": true, + "show_timezone": false, + } + ), + "location_label": lib_plankton.translate.get("event.location"), + "location_extra_classes": ( + (entry.event_object.location === null) + ? + " listview-entry-field-empty" + : + "" + ), + "location_value": ( + (entry.event_object.location === null) + ? + "?" + : + entry.event_object.location + ), + "link_label": lib_plankton.translate.get("event.link"), + "link_extra_classes": ( + (entry.event_object.link === null) + ? + " listview-entry-field-empty" + : + "" + ), + "link_value": ( + (entry.event_object.link === null) + ? + "?" + : + entry.event_object.link + ), + "link_action": lib_plankton.translate.get("common.open"), + "description_label": lib_plankton.translate.get("event.description"), + "description_extra_classes": ( + (entry.event_object.description === null) + ? + " listview-entry-field-empty" + : + "" + ), + "description_value": ( + (entry.event_object.description === null) + ? + "?" + : + entry.event_object.description + ), + "raw": JSON.stringify(entry), + "color": _dali.helpers.event_color(entry.hue), + "rel": entry.key, + }, + ) + ) + ) + ) + .join("") ); } - - // control + // listeners { - target_element.querySelector(".listview-add").addEventListener( - "click", - (event) => { - event.preventDefault(); - this.action_add(); - } - ); - target_element.querySelectorAll(".listview-entry").forEach( + this.container.querySelectorAll(".listview-entry").forEach( (element) => { element.addEventListener( "click", @@ -320,8 +295,51 @@ namespace _dali.widgets.listview } ); } + } + + + /** + * [implementation] + */ + public async load( + target_element : Element + ) + : Promise + { + this.container = target_element; - this.container = target_element.querySelector(".listview"); + // view + { + target_element.innerHTML = await _dali.helpers.template_coin( + "widget-listview", + "main", + { + "add_href": "", + "add_label": lib_plankton.translate.get("widget.listview.add"), + "add_extra_classes": ( + (! await _dali.is_logged_in()) + ? + " listview-add-hidden" + : + "" + ), + "entries": "", + } + ); + } + + // control + { + target_element.querySelector(".listview-add").addEventListener( + "click", + (event) => { + event.preventDefault(); + this.action_add(); + } + ); + } + + await this.update_entries(); return Promise.resolve(undefined); } diff --git a/source/widgets/mode_switcher/style.css b/source/widgets/mode_switcher/style.css new file mode 100644 index 0000000..4261776 --- /dev/null +++ b/source/widgets/mode_switcher/style.css @@ -0,0 +1,4 @@ +.widget-mode_switcher-option +{ + margin-left: 16px; +} diff --git a/source/widgets/multiview/logic.ts b/source/widgets/multiview/logic.ts index b34d7b5..87929aa 100644 --- a/source/widgets/multiview/logic.ts +++ b/source/widgets/multiview/logic.ts @@ -69,6 +69,11 @@ namespace _dali.widgets.multiview private initial_view_mode : _dali.enum_view_mode; + /** + */ + private weekview_initial_vertical : boolean; + + /** */ private get_entries : type_get_entries; @@ -110,12 +115,14 @@ namespace _dali.widgets.multiview get_entries : type_get_entries, { "initial_view_mode": initial_view_mode = _dali.enum_view_mode.week, + "weekview_initial_vertical": weekview_initial_vertical = false, "action_create_event": action_create_event = ((stuff) => Promise.resolve(undefined)), "action_edit_event": action_edit_event = ((event_key) => Promise.resolve(undefined)), } : { initial_view_mode ?: _dali.enum_view_mode; + weekview_initial_vertical ?: boolean; action_create_event ?: type_create_event; action_edit_event ?: type_edit_event; } @@ -126,6 +133,7 @@ namespace _dali.widgets.multiview { this.get_entries = get_entries; this.initial_view_mode = initial_view_mode; + this.weekview_initial_vertical = weekview_initial_vertical; this.action_create_event = action_create_event; this.action_edit_event = action_edit_event; this.dom_context = null; @@ -168,12 +176,17 @@ namespace _dali.widgets.multiview /** */ - public update_entries( + public async update_entries( ) : Promise { - return this.widget_weekview.update_entries(); + await Promise.all( + [ + this.widget_weekview.update_entries(), + this.widget_listview.update_entries(), + ] + ); } @@ -206,17 +219,6 @@ namespace _dali.widgets.multiview { "initial_selection": this.initial_view_mode, "action_change": (view_mode) => { - console.warn("todo"); - /* - lib_plankton.zoo_page.set( - { - "name": "overview", - "parameters": { - "mode": _dali.view_mode_encode(view_mode), - } - } - ); - */ this.set_view_mode(view_mode); } } @@ -235,6 +237,7 @@ namespace _dali.widgets.multiview { "action_select_event": (event_key) => this.action_edit_event(event_key), "action_select_day": (date) => this.action_create_event({"date": date}), + "vertical": this.weekview_initial_vertical, } ) ); diff --git a/source/widgets/weekview/logic.ts b/source/widgets/weekview/logic.ts index fec5824..16f8cd5 100644 --- a/source/widgets/weekview/logic.ts +++ b/source/widgets/weekview/logic.ts @@ -36,7 +36,8 @@ namespace _dali.widgets.weekview /** */ - export class class_widget_weekview implements lib_plankton.zoo_widget.interface_widget + export class class_widget_weekview + implements lib_plankton.zoo_widget.interface_widget { /** -- 2.47.3 From 1c8d3d0725fabdc6d6f9c29677ccd944c7af72b4 Mon Sep 17 00:00:00 2001 From: Fenris Wolf Date: Tue, 28 Oct 2025 00:25:20 +0100 Subject: [PATCH 4/6] [task-419] [int] --- source/style/main.css | 2 +- source/widgets/special_number_input/logic.ts | 164 ++++++++++++ .../templates/main.html.tpl | 8 + source/widgets/weekview/logic.ts | 249 ++++++------------ source/widgets/weekview/style.css | 18 +- .../templates/control-vertical.html.tpl | 6 + .../widgets/weekview/templates/main.html.tpl | 30 --- tools/makefile | 8 + 8 files changed, 281 insertions(+), 204 deletions(-) create mode 100644 source/widgets/special_number_input/logic.ts create mode 100644 source/widgets/special_number_input/templates/main.html.tpl create mode 100644 source/widgets/weekview/templates/control-vertical.html.tpl diff --git a/source/style/main.css b/source/style/main.css index 6feb245..dc06abf 100644 --- a/source/style/main.css +++ b/source/style/main.css @@ -101,7 +101,7 @@ a:hover button { - padding: 8px; + padding: 4px 8px; text-transform: uppercase; cursor: pointer; diff --git a/source/widgets/special_number_input/logic.ts b/source/widgets/special_number_input/logic.ts new file mode 100644 index 0000000..c7199b4 --- /dev/null +++ b/source/widgets/special_number_input/logic.ts @@ -0,0 +1,164 @@ +/* +This file is part of »dali«. + +Copyright 2025 'kcf' + +»dali« is free software: you can redistribute it and/or modify +it under the terms of the GNU Lesser General Public License as published by +the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. + +»dali« is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU Lesser General Public License for more details. + +You should have received a copy of the GNU Lesser General Public License +along with »dali«. If not, see . + */ + + +namespace _dali.widgets +{ + + /** + */ + export class class_widget_special_number_input + implements lib_plankton.zoo_widget.interface_widget + { + + /** + */ + private action_change : ((int) => Promise); + + + /** + */ + private label : (null | string); + + + /** + */ + private minimum : (null | int); + + + /** + */ + private maximum : (null | int); + + + /** + */ + private value : int; + + + /** + */ + public constructor( + { + "label": label = null, + "minimum": minimum = null, + "maximum": maximum = null, + "initial_value": initial_value = 0, + "action_change": action_change = ((value) => Promise.resolve(undefined)), + } + : + { + label ?: (null | string); + minimum ?: (null | int); + maximum ?: (null | int); + initial_value ?: int; + action_change ?: ((int) => Promise); + } + = + { + } + ) + { + this.label = label; + this.minimum = minimum; + this.maximum = maximum; + this.value = initial_value; + this.action_change = action_change; + } + + + /** + * [implementation] + */ + public async load( + target_element : HTMLElement + ) + : Promise + { + const dom_dummy = document.createElement("div"); + dom_dummy.innerHTML = await _dali.helpers.template_coin( + "widget-special_number_input", + "main", + { + "label": this.label, + } + ); + + const dom_input : HTMLInputElement = (dom_dummy.querySelector(".widget-special_number_input-input > input") as HTMLInputElement); + + // listeners + { + dom_input.addEventListener( + "change", + () => { + this.value = parseInt(dom_input.value); + if ( + ((this.minimum === null) || (this.value >= this.minimum)) + && + ((this.maximum === null) || (this.value <= this.maximum)) + ) + { + this.action_change(this.value); + } + else + { + // do nothing + } + } + ); + dom_dummy.querySelector(".widget-special_number_input-prev").addEventListener( + "click", + () => { + if ((this.minimum === null) || (this.value > this.minimum)) + { + this.value -= 1; + dom_input.value = this.value.toFixed(0); + this.action_change(this.value); + } + else + { + // do nothing + } + } + ); + dom_dummy.querySelector(".widget-special_number_input-next").addEventListener( + "click", + () => { + if ((this.maximum === null) || (this.value < this.maximum)) + { + this.value += 1; + dom_input.value = this.value.toFixed(0); + this.action_change(this.value); + } + else + { + // do nothing + } + } + ); + } + + dom_input.value = this.value.toFixed(0); + + target_element.appendChild(dom_dummy.querySelector(".widget-special_number_input")); + } + + } + +} diff --git a/source/widgets/special_number_input/templates/main.html.tpl b/source/widgets/special_number_input/templates/main.html.tpl new file mode 100644 index 0000000..e16ce21 --- /dev/null +++ b/source/widgets/special_number_input/templates/main.html.tpl @@ -0,0 +1,8 @@ +
      + +
      + + + +
      +
      diff --git a/source/widgets/weekview/logic.ts b/source/widgets/weekview/logic.ts index 16f8cd5..b2bcd1a 100644 --- a/source/widgets/weekview/logic.ts +++ b/source/widgets/weekview/logic.ts @@ -571,19 +571,6 @@ namespace _dali.widgets.weekview } - /** - */ - private async update_controls( - ) : Promise - { - const context : Element = this.container; - (context.querySelector(".weekview-control-year input") as HTMLInputElement).value = this.year.toFixed(0); - (context.querySelector(".weekview-control-week input") as HTMLInputElement).value = this.week.toFixed(0); - (context.querySelector(".weekview-control-count input") as HTMLInputElement).value = this.count.toFixed(0); - (context.querySelector(".weekview-control-vertical input") as HTMLInputElement).checked = this.vertical; - } - - /** */ private async update_table( @@ -881,169 +868,91 @@ namespace _dali.widgets.weekview "widget-weekview", "main", { - "label_control_year": lib_plankton.translate.get("widget.weekview.controls.year"), - "label_control_week": lib_plankton.translate.get("widget.weekview.controls.week"), - "label_control_count": lib_plankton.translate.get("widget.weekview.controls.count"), - "label_control_vertical": lib_plankton.translate.get("widget.weekview.controls.vertical"), - "label_control_apply": lib_plankton.translate.get("widget.weekview.controls.apply"), } ); - this.container = target_element.querySelector(".weekview"); - // controls + // control:year { - // direct inputs - { - [ - { - "name": "year", - "selector": ".weekview-control-year input", - "retrieve": element => parseInt(element.value), - "write": x => {this.year = x;} - }, - { - "name": "week", - "selector": ".weekview-control-week input", - "retrieve": element => parseInt(element.value), - "write": x => {this.week = x;} - }, - { - "name": "count", - "selector": ".weekview-control-count input", - "retrieve": element => parseInt(element.value), - "write": x => {this.count = x;} - }, - { - "name": "vertical", - "selector": ".weekview-control-vertical input", - "retrieve": element => element.checked, - "write": x => {this.vertical = x;} - }, - ].forEach( - (entry) => { - const element : HTMLInputElement = (target_element.querySelector(entry.selector) as HTMLInputElement); - element.addEventListener( - "change", - async (event) => { - event.preventDefault(); - const value : unknown = entry.retrieve(element); - entry.write(value); - await this.update_table(); - await this.update_entries(); - } - ); - } - ); - } - // buttons - { - // year + const widget : lib_plankton.zoo_widget.interface_widget = new _dali.widgets.class_widget_special_number_input( { - /** - * @todo limit - */ - target_element.querySelector(".weekview-control-year-prev").addEventListener( - "click", - async () => { - this.year -= 1; - await this.update_controls(); - await this.update_table(); - await this.update_entries(); - } - ); - /** - * @todo limit - */ - target_element.querySelector(".weekview-control-year-next").addEventListener( - "click", - async () => { - this.year += 1; - await this.update_controls(); - await this.update_table(); - await this.update_entries(); - } - ); + "label": lib_plankton.translate.get("widget.weekview.controls.year"), + "minimum": 1900, + "maximum": 2500, + "initial_value": this.year, + "action_change": async (value) => { + this.year = value; + await this.update_table(); + await this.update_entries(); + }, } - // week - { - target_element.querySelector(".weekview-control-week-prev").addEventListener( - "click", - async () => { - if (this.week >= 1) - { - this.week -= 1; - } - else - { - this.year -= 1; - /** - * @todo get correct week - */ - this.week = 51; - } - await this.update_controls(); - await this.update_table(); - await this.update_entries(); - } - ); - target_element.querySelector(".weekview-control-week-next").addEventListener( - "click", - async () => { - /** - * @todo correct limit - */ - if (this.week <= 51) - { - this.week += 1; - } - else - { - this.year += 1; - this.week = 1; - } - await this.update_controls(); - await this.update_table(); - await this.update_entries(); - } - ); - } - // count - { - target_element.querySelector(".weekview-control-count-prev").addEventListener( - "click", - async () => { - if (this.count >= 2) - { - this.count -= 1; - await this.update_controls(); - await this.update_table(); - await this.update_entries(); - } - else - { - // do nothing - } - } - ); - target_element.querySelector(".weekview-control-count-next").addEventListener( - "click", - async () => { - if (this.count <= 6) - { - this.count += 1; - await this.update_controls(); - await this.update_table(); - await this.update_entries(); - } - else - { - // do nothing - } - } - ); - } - } + ); + await widget.load(target_element.querySelector(".weekview-controls")); } - await this.update_controls(); + // control:week + { + const widget : lib_plankton.zoo_widget.interface_widget = new _dali.widgets.class_widget_special_number_input( + { + "label": lib_plankton.translate.get("widget.weekview.controls.week"), + "minimum": 1, + /** + * @todo correct + */ + "maximum": 53, + "initial_value": this.week, + "action_change": async (value) => { + this.week = value; + await this.update_table(); + await this.update_entries(); + }, + } + ); + await widget.load(target_element.querySelector(".weekview-controls")); + } + // control:count + /* + { + const widget : lib_plankton.zoo_widget.interface_widget = new _dali.widgets.class_widget_special_number_input( + { + "label": lib_plankton.translate.get("widget.weekview.controls.count"), + "minimum": 2, + "maximum": 6, + "initial_value": this.count, + "action_change": async (value) => { + this.count = value; + await this.update_table(); + await this.update_entries(); + }, + } + ); + await widget.load(target_element.querySelector(".weekview-controls")); + } + */ + // control:vertical + { + const dom_dummy : HTMLElement = document.createElement("div"); + dom_dummy.innerHTML = await _dali.helpers.template_coin( + "widget-weekview", + "control-vertical", + { + "label": lib_plankton.translate.get("widget.weekview.controls.vertical"), + } + ); + const dom_input : HTMLInputElement = (dom_dummy.querySelector("input") as HTMLInputElement); + dom_input.addEventListener( + "change", + async () => { + event.preventDefault(); + const value : boolean = dom_input.checked; + this.vertical = value; + await this.update_table(); + await this.update_entries(); + } + ); + dom_input.checked = this.vertical; + target_element.querySelector(".weekview-controls").appendChild(dom_dummy.querySelector(".weekview-control-vertical")); + } + + this.container = target_element.querySelector(".weekview"); + await this.update_table(); await this.update_entries(); diff --git a/source/widgets/weekview/style.css b/source/widgets/weekview/style.css index 93b07bc..542660d 100644 --- a/source/widgets/weekview/style.css +++ b/source/widgets/weekview/style.css @@ -2,7 +2,7 @@ { display: flex; flex-direction: row; - flex-wrap: wrap; + flex-wrap: nowrap; justify-content: right; margin-bottom: 12px; @@ -16,11 +16,23 @@ flex-grow: 0; flex-shrink: 1; + min-width: 80px; + margin: 0 0 0 8px; +} + +.weekview-controls .widget-special_number_input +{ + flex-basis: 0; + flex-grow: 0; + flex-shrink: 1; + min-width: 140px; - margin: 0 12px; + margin: 0 0 0 8px; } .weekview-control-label +, +.weekview-controls .widget-special_number_input-label { display: block; @@ -35,7 +47,7 @@ display: inline-block; } -.weekview-control input +.weekview-controls .widget-special_number_input input { max-width: 40px; } diff --git a/source/widgets/weekview/templates/control-vertical.html.tpl b/source/widgets/weekview/templates/control-vertical.html.tpl new file mode 100644 index 0000000..b19eb83 --- /dev/null +++ b/source/widgets/weekview/templates/control-vertical.html.tpl @@ -0,0 +1,6 @@ +
      + +
      + +
      +
      diff --git a/source/widgets/weekview/templates/main.html.tpl b/source/widgets/weekview/templates/main.html.tpl index 7d4be90..0bf066d 100644 --- a/source/widgets/weekview/templates/main.html.tpl +++ b/source/widgets/weekview/templates/main.html.tpl @@ -1,35 +1,5 @@
      -
      - -
      - - - -
      -
      -
      - -
      - - - -
      -
      -
      - -
      - - - -
      -
      -
      - -
      - -
      -
      diff --git a/tools/makefile b/tools/makefile index 42319cc..885210b 100644 --- a/tools/makefile +++ b/tools/makefile @@ -31,6 +31,7 @@ ${dir_build}/index.html: \ .PHONY: templates templates: \ templates-widgets-login \ + templates-widgets-special_number_input \ templates-widgets-sources \ templates-widgets-listview \ templates-widgets-weekview \ @@ -45,6 +46,13 @@ templates-widgets-login: \ @ ${cmd_mkdir} ${dir_build}/templates/widget-login @ ${cmd_cp} -r -u -v ${dir_source}/widgets/login/templates/* ${dir_build}/templates/widget-login/ +.PHONY: templates-widgets-special_number_input +templates-widgets-special_number_input: \ + $(wildcard ${dir_source}/widgets/special_number_input/templates/*) + @ ${cmd_log} "templates:widget:special_number_input …" + @ ${cmd_mkdir} ${dir_build}/templates/widget-special_number_input + @ ${cmd_cp} -r -u -v ${dir_source}/widgets/special_number_input/templates/* ${dir_build}/templates/widget-special_number_input/ + .PHONY: templates-widgets-sources templates-widgets-sources: \ $(wildcard ${dir_source}/widgets/sources/templates/*) -- 2.47.3 From 0c7dbbaa573858314aecc3bd2c0cbb28e5838e67 Mon Sep 17 00:00:00 2001 From: Fenris Wolf Date: Tue, 28 Oct 2025 09:08:05 +0100 Subject: [PATCH 5/6] [task-419] [int] --- source/widgets/special_number_input/logic.ts | 2 +- source/widgets/special_number_input/style.css | 34 +++++++++++++++++++ .../templates/main.html.tpl | 8 ++--- source/widgets/weekview/logic.ts | 30 ++++++++++------ source/widgets/weekview/style.css | 27 ++------------- 5 files changed, 61 insertions(+), 40 deletions(-) create mode 100644 source/widgets/special_number_input/style.css diff --git a/source/widgets/special_number_input/logic.ts b/source/widgets/special_number_input/logic.ts index c7199b4..d593f89 100644 --- a/source/widgets/special_number_input/logic.ts +++ b/source/widgets/special_number_input/logic.ts @@ -100,7 +100,7 @@ namespace _dali.widgets } ); - const dom_input : HTMLInputElement = (dom_dummy.querySelector(".widget-special_number_input-input > input") as HTMLInputElement); + const dom_input : HTMLInputElement = (dom_dummy.querySelector(".widget-special_number_input-input") as HTMLInputElement); // listeners { diff --git a/source/widgets/special_number_input/style.css b/source/widgets/special_number_input/style.css new file mode 100644 index 0000000..a76ee8d --- /dev/null +++ b/source/widgets/special_number_input/style.css @@ -0,0 +1,34 @@ +.widget-special_number_input-controls +{ + white-space: nowrap; +} + +.widget-special_number_input-controls > * +{ + display: inline-block; +} + +.widget-special_number_input-button +{ + padding: 4px 4px; + margin: 0; + + cursor: pointer; +} + +.widget-special_number_input-label +{ + display: block; + + font-size: 0.75em; + /* + text-transform: uppercase; + */ +} + +.widget-special_number_input-input +{ + max-width: 40px; + margin: 0; + text-align: center; +} diff --git a/source/widgets/special_number_input/templates/main.html.tpl b/source/widgets/special_number_input/templates/main.html.tpl index e16ce21..f8590b6 100644 --- a/source/widgets/special_number_input/templates/main.html.tpl +++ b/source/widgets/special_number_input/templates/main.html.tpl @@ -1,8 +1,8 @@
      -
      - - - +
      +
      + +
      diff --git a/source/widgets/weekview/logic.ts b/source/widgets/weekview/logic.ts index b2bcd1a..2d26075 100644 --- a/source/widgets/weekview/logic.ts +++ b/source/widgets/weekview/logic.ts @@ -192,7 +192,8 @@ namespace _dali.widgets.weekview */ private static entry_hash( entry : _dali.type_event_object_extended - ) : string + ) + : string { return lib_plankton.call.convey( { @@ -214,7 +215,8 @@ namespace _dali.widgets.weekview private static event_generate_tooltip( calendar_name : string, event_object : _dali.type_event_object - ) : string + ) + : string { return ( lib_plankton.string.coin( @@ -360,7 +362,8 @@ namespace _dali.widgets.weekview */ private async entry_insert( entry : _dali.type_event_object_extended - ) : Promise<(null | HTMLElement)> + ) + : Promise<(null | HTMLElement)> { const selector : string = lib_plankton.string.coin( ".weekview-cell[rel=\"{{rel}}\"] > .weekview-events", @@ -423,7 +426,8 @@ namespace _dali.widgets.weekview */ private async entry_add( entry : _dali.type_event_object_extended - ) : Promise + ) + : Promise { const dom_entry : (null | HTMLElement) = await this.entry_insert(entry); if (dom_entry === null) @@ -448,7 +452,8 @@ namespace _dali.widgets.weekview private async entry_update( key : _dali.type_event_key, entry : _dali.type_event_object_extended - ) : Promise + ) + : Promise { if (! this.event_map.has(key)) { @@ -504,7 +509,8 @@ namespace _dali.widgets.weekview */ private async entry_remove( key : _dali.type_event_key - ) : Promise + ) + : Promise { if (! this.event_map.has(key)) { @@ -533,7 +539,8 @@ namespace _dali.widgets.weekview /** */ public async update_entries( - ) : Promise + ) + : Promise { const entries : Array<_dali.type_event_object_extended> = await this.get_entries_wrapped( ); @@ -574,7 +581,8 @@ namespace _dali.widgets.weekview /** */ private async update_table( - ) : Promise + ) + : Promise { /** * @todo avoid? @@ -834,7 +842,8 @@ namespace _dali.widgets.weekview = { } - ) : void + ) + : void { this.container.querySelectorAll(".weekview-event_entry").forEach( (element) => { @@ -862,7 +871,8 @@ namespace _dali.widgets.weekview */ public async load( target_element : Element - ) : Promise + ) + : Promise { target_element.innerHTML = await _dali.helpers.template_coin( "widget-weekview", diff --git a/source/widgets/weekview/style.css b/source/widgets/weekview/style.css index 542660d..a5b88d2 100644 --- a/source/widgets/weekview/style.css +++ b/source/widgets/weekview/style.css @@ -10,29 +10,16 @@ text-align: center; } -.weekview-control +.weekview-controls > * { flex-basis: 0; flex-grow: 0; flex-shrink: 1; - min-width: 80px; - margin: 0 0 0 8px; -} - -.weekview-controls .widget-special_number_input -{ - flex-basis: 0; - flex-grow: 0; - flex-shrink: 1; - - min-width: 140px; - margin: 0 0 0 8px; + margin: 0 0 0 16px; } .weekview-control-label -, -.weekview-controls .widget-special_number_input-label { display: block; @@ -42,16 +29,6 @@ */ } -.weekview-control-input > * -{ - display: inline-block; -} - -.weekview-controls .widget-special_number_input input -{ - max-width: 40px; -} - .weekview-table table { width: 100%; -- 2.47.3 From 57ce184761e55fc64b7dec4766313c72629a5988 Mon Sep 17 00:00:00 2001 From: Fenris Wolf Date: Tue, 28 Oct 2025 11:38:58 +0100 Subject: [PATCH 6/6] [task-419] [int] --- misc/conf-example.json | 2 +- source/base.ts | 15 +- source/data/localization/deu.loc.json | 38 +- source/data/localization/eng.loc.json | 38 +- source/helpers.ts | 19 + source/main.ts | 134 ++--- source/overlay.ts | 15 +- .../caldav/templates/conf-token_set.html.tpl | 18 - .../templates/conf-token_unset.html.tpl | 4 - source/pages/caldav/templates/main.html.tpl | 6 - .../caldav/templates/unavailable.html.tpl | 3 - source/pages/oidc_finish/logic.ts | 41 -- source/pages/overview/templates/main.html.tpl | 8 - source/{pages => widgets}/caldav/logic.ts | 96 ++-- source/{pages => widgets}/caldav/style.css | 8 +- .../caldav/templates/available.html.tpl | 4 +- .../templates/conf-setup_hint_entry.html.tpl | 2 +- .../caldav/templates/conf-token_set.html.tpl | 18 + .../templates/conf-token_unset.html.tpl | 4 + source/widgets/caldav/templates/main.html.tpl | 8 + .../caldav/templates/unavailable.html.tpl | 3 + source/widgets/calendar_edit/logic.ts | 2 +- source/widgets/event_edit/logic.ts | 2 +- source/widgets/listview/logic.ts | 2 +- source/widgets/login/logic.ts | 129 +---- .../widgets/login/templates/default.html.tpl | 2 - source/widgets/login_internal/logic.ts | 164 ++++++ source/widgets/login_oidc/logic.ts | 110 ++++ source/widgets/login_oidc/style.css | 5 + .../login_oidc/templates/main.html.tpl | 4 + source/widgets/menu/logic.ts | 2 +- source/widgets/mode_switcher/logic.ts | 2 +- source/widgets/multiview/logic.ts | 24 +- source/{pages => widgets}/overview/logic.ts | 474 ++++++++++-------- source/{pages => widgets}/overview/style.css | 18 +- .../widgets/overview/templates/main.html.tpl | 8 + source/widgets/sources/logic.ts | 2 +- source/widgets/weekview/logic.ts | 2 +- tools/makefile | 56 +-- 39 files changed, 897 insertions(+), 595 deletions(-) delete mode 100644 source/pages/caldav/templates/conf-token_set.html.tpl delete mode 100644 source/pages/caldav/templates/conf-token_unset.html.tpl delete mode 100644 source/pages/caldav/templates/main.html.tpl delete mode 100644 source/pages/caldav/templates/unavailable.html.tpl delete mode 100644 source/pages/oidc_finish/logic.ts delete mode 100644 source/pages/overview/templates/main.html.tpl rename source/{pages => widgets}/caldav/logic.ts (58%) rename source/{pages => widgets}/caldav/style.css (55%) rename source/{pages => widgets}/caldav/templates/available.html.tpl (64%) rename source/{pages => widgets}/caldav/templates/conf-setup_hint_entry.html.tpl (56%) create mode 100644 source/widgets/caldav/templates/conf-token_set.html.tpl create mode 100644 source/widgets/caldav/templates/conf-token_unset.html.tpl create mode 100644 source/widgets/caldav/templates/main.html.tpl create mode 100644 source/widgets/caldav/templates/unavailable.html.tpl delete mode 100644 source/widgets/login/templates/default.html.tpl create mode 100644 source/widgets/login_internal/logic.ts create mode 100644 source/widgets/login_oidc/logic.ts create mode 100644 source/widgets/login_oidc/style.css create mode 100644 source/widgets/login_oidc/templates/main.html.tpl rename source/{pages => widgets}/overview/logic.ts (63%) rename source/{pages => widgets}/overview/style.css (56%) create mode 100644 source/widgets/overview/templates/main.html.tpl diff --git a/misc/conf-example.json b/misc/conf-example.json index cf5b37e..330b798 100644 --- a/misc/conf-example.json +++ b/misc/conf-example.json @@ -7,7 +7,7 @@ "path": "" }, "misc": { - "oidc_redirect_uri_template": "http://localhost:8888/#oidc_finish,session_key={{session_key}}", + "oidc_redirect_uri_template": "http://localhost:8888/?action=oidc_finish&session_key={{session_key}}", "use_central_europe_specific_datetime_inputs": true } } diff --git a/source/base.ts b/source/base.ts index e4de274..dab47b3 100644 --- a/source/base.ts +++ b/source/base.ts @@ -106,8 +106,19 @@ namespace _dali { await _dali.backend.set_session_key(session_key); const status = await _dali.backend.status(); - await _dali.notify_login(status.name); - return Promise.resolve(undefined); + if (! status.logged_in) + { + lib_plankton.log.error( + "dali.oidc_login_failed" + ); + await _dali.notify_logout(); + return Promise.reject(new Error("oidc login failed")); + } + else + { + await _dali.notify_login(status.name); + return Promise.resolve(undefined); + } } diff --git a/source/data/localization/deu.loc.json b/source/data/localization/deu.loc.json index abaf730..af4a35a 100644 --- a/source/data/localization/deu.loc.json +++ b/source/data/localization/deu.loc.json @@ -27,6 +27,7 @@ "common.monthname.november": "Nov", "common.monthname.december": "Dez", "common.open": "öffnen", + "common.close": "schließen", "common.edit": "bearbeiten", "common.show": "zeigen", "common.hide": "ausblenden", @@ -78,27 +79,20 @@ "widget.login.internal.password": "Kennwort", "widget.login.internal.do": "Anmelden", "widget.login.oidc.via": "via {{title}}", - "page.caldav.title": "CalDAV", - "page.caldav.unavailable": "CalDAV nicht verfügbar", - "page.caldav.conf.title": "Zugangsdaten", - "page.caldav.conf.address": "Adresse (URL)", - "page.caldav.conf.username": "Nutzername", - "page.caldav.conf.password": "Kennwort", - "page.caldav.conf.setup_hints": "Einrichtungs-Hinweise", - "page.caldav.conf.token_unset": "es muss zunächst ein Token gesetzt werden", - "page.caldav.set_token.title": "Token setzen", - "page.caldav.set_token.action.set": "setzen", - "page.caldav.set_token.action.overwrite": "überschreiben", - "page.calendar_add.title": "Kalendar anlegen", - "page.calendar_add.actions.do": "anlegen", - "page.calendar_edit.title.regular": "Kalendar bearbeiten", - "page.calendar_edit.title.read_only": "Kalendar-Details", - "page.event_add.title": "Termin anlegen", - "page.event_edit.title.regular": "Termin bearbeiten", - "page.event_edit.title.read_only": "Termin-Details", - "page.overview.title": "Übersicht", - "page.overview.login_hint": "anmelden um nicht-öffentliche Termine zu sehen", - "page.overview.mode.week": "Wochen-Ansicht", - "page.overview.mode.list": "Listen-Ansicht" + "widget.caldav.title": "CalDAV", + "widget.caldav.unavailable": "CalDAV nicht verfügbar", + "widget.caldav.conf.title": "Zugangsdaten", + "widget.caldav.conf.address": "Adresse (URL)", + "widget.caldav.conf.username": "Nutzername", + "widget.caldav.conf.password": "Kennwort", + "widget.caldav.conf.setup_hints": "Einrichtungs-Hinweise", + "widget.caldav.conf.token_unset": "es muss zunächst ein Token gesetzt werden", + "widget.caldav.set_token.title": "Token setzen", + "widget.caldav.set_token.action.set": "setzen", + "widget.caldav.set_token.action.overwrite": "überschreiben", + "widget.overview.title": "Übersicht", + "widget.overview.login_hint": "anmelden um nicht-öffentliche Termine zu sehen", + "widget.overview.mode.week": "Wochen-Ansicht", + "widget.overview.mode.list": "Listen-Ansicht" } } diff --git a/source/data/localization/eng.loc.json b/source/data/localization/eng.loc.json index 1436b7d..c63e674 100644 --- a/source/data/localization/eng.loc.json +++ b/source/data/localization/eng.loc.json @@ -27,6 +27,7 @@ "common.monthname.november": "nov", "common.monthname.december": "dec", "common.open": "open", + "common.close": "close", "common.edit": "edit", "common.show": "show", "common.hide": "hide", @@ -78,27 +79,20 @@ "widget.login.internal.password": "password", "widget.login.internal.do": "login", "widget.login.oidc.via": "via {{title}}", - "page.caldav.title": "CalDAV", - "page.caldav.unavailable": "CalDAV not available", - "page.caldav.conf.title": "credentials", - "page.caldav.conf.address": "address (URL)", - "page.caldav.conf.username": "username", - "page.caldav.conf.password": "password", - "page.caldav.conf.setup_hints": "setup hints", - "page.caldav.conf.token_unset": "a token has to be set", - "page.caldav.set_token.title": "set token", - "page.caldav.set_token.action.set": "set", - "page.caldav.set_token.action.overwrite": "overwrite", - "page.calendar_add.title": "Add calendar", - "page.calendar_add.actions.do": "anlegen", - "page.event_add.title": "Add event", - "page.calendar_edit.title.regular": "Edit calendar", - "page.calendar_edit.title.read_only": "Calendar details", - "page.event_edit.title.regular": "Edit event", - "page.event_edit.title.read_only": "Event details", - "page.overview.title": "Overview", - "page.overview.login_hint": "log in to view non-public events", - "page.overview.mode.week": "week view", - "page.overview.mode.list": "list view" + "widget.caldav.title": "CalDAV", + "widget.caldav.unavailable": "CalDAV not available", + "widget.caldav.conf.title": "credentials", + "widget.caldav.conf.address": "address (URL)", + "widget.caldav.conf.username": "username", + "widget.caldav.conf.password": "password", + "widget.caldav.conf.setup_hints": "setup hints", + "widget.caldav.conf.token_unset": "a token has to be set", + "widget.caldav.set_token.title": "set token", + "widget.caldav.set_token.action.set": "set", + "widget.caldav.set_token.action.overwrite": "overwrite", + "widget.overview.title": "Overview", + "widget.overview.login_hint": "log in to view non-public events", + "widget.overview.mode.week": "week view", + "widget.overview.mode.list": "list view" } } diff --git a/source/helpers.ts b/source/helpers.ts index b1c5995..e955bae 100644 --- a/source/helpers.ts +++ b/source/helpers.ts @@ -350,4 +350,23 @@ namespace _dali.helpers return lib_plankton.translate.get(keys[month-1]); } + + /** + */ + export function loading( + mode : boolean + ) + : void + { + if (! mode) + { + _dali.overlay.toggle({"mode": false}); + } + else + { + _dali.overlay.get_content_element().innerHTML = "[...]"; + _dali.overlay.toggle({"mode": true}); + } + } + } diff --git a/source/main.ts b/source/main.ts index 97cb9d8..af55d02 100644 --- a/source/main.ts +++ b/source/main.ts @@ -23,24 +23,6 @@ along with »dali«. If not, see . namespace _dali { - /** - */ - function nav_groups( - logged_in : boolean - ) - : Array - { - return ( - logged_in - ? - ["logged_in"] - : - ["logged_out"] - ); - } - - - /** */ export async function main( @@ -52,7 +34,7 @@ namespace _dali "conf.json" ); - // init + // init:logger lib_plankton.log.set_main_logger( [ { @@ -68,6 +50,11 @@ namespace _dali }, ] ); + // init:overlay + { + await _dali.overlay.initialize(); + _dali.helpers.loading(true); + } // init:localization { const order : Array = ["deu", "eng"]; @@ -76,10 +63,11 @@ namespace _dali "verbosity": 1, "packages": await Promise.all( order.map( - async (code) => JSON.parse( - await lib_plankton.file.read( - "data/localization/" + code + ".loc.json" - ) + code => ( + Promise.resolve(code) + .then(code => Promise.resolve(lib_plankton.string.coin("data/localization/{{code}}.loc.json", {"code": code}))) + .then(lib_plankton.file.read) + .then(content => Promise.resolve(JSON.parse(content))) ) ) ), @@ -88,11 +76,14 @@ namespace _dali } ); } + // init:backend await _dali.backend.initialize( _dali.conf.get()["backend"] ); + // init:model await _dali.model.initialize( ); + // init:page lib_plankton.zoo_page.init( document.querySelector("main"), { @@ -100,69 +91,55 @@ namespace _dali "name": "overview", "parameters": {} }, - /* - "nav_entries": [ - ], - */ - "nav_initial_groups": [], } ); - // menu widget + // init:menu { - const widget_menu : _dali.widgets.menu.class_widget_menu = new _dali.widgets.menu.class_widget_menu( + const widget_menu : _dali.widgets.class_widget_menu = new _dali.widgets.class_widget_menu( [ { "label": lib_plankton.translate.get("common.login"), "groups": ["logged_out"], - "action": () => { - const widget_login = new _dali.widgets.login.class_widget_login( + "action": async () => { + _dali.helpers.loading(true); + const widget : lib_plankton.zoo_widget.interface_widget = new _dali.widgets.class_widget_login( { "action_cancel": () => { _dali.overlay.clear(); _dali.overlay.toggle({"mode": false}); }, "action_success": async () => { + _dali.helpers.loading(true); const status = await _dali.backend.status(); _dali.notify_login(status.name); - _dali.overlay.clear(); - _dali.overlay.toggle({"mode": false}); + // _dali.overlay.clear(); + _dali.helpers.loading(false); }, } ); - _dali.overlay.clear(); + await widget.load(_dali.overlay.get_content_element()); + // _dali.helpers.loading(false); _dali.overlay.toggle({"mode": true}); - widget_login.load(_dali.overlay.get_content_element()); }, }, { - "label": lib_plankton.translate.get("page.overview.title"), - "groups": ["logged_out", "logged_in"], - "action": () => { - lib_plankton.zoo_page.set( - { - "name": "overview", - "parameters": {} - } - ); - }, - }, - { - "label": lib_plankton.translate.get("page.caldav.title"), + "label": lib_plankton.translate.get("widget.caldav.title"), "groups": ["logged_in"], - "action": () => { - lib_plankton.zoo_page.set( - { - "name": "caldav", - "parameters": {} - } - ); + "action": async () => { + _dali.helpers.loading(true); + const widget : lib_plankton.zoo_widget.interface_widget = new _dali.widgets.class_widget_caldav(); + await widget.load(_dali.overlay.get_content_element()); + // _dali.helpers.loading(false); + _dali.overlay.toggle({"mode": true}); }, }, { "label": lib_plankton.translate.get("common.logout"), "groups": ["logged_in"], - "action": () => { - _dali.logout(); + "action": async () => { + _dali.helpers.loading(true); + await _dali.logout(); + _dali.helpers.loading(false); }, }, ] @@ -181,9 +158,36 @@ namespace _dali } ); } - await _dali.overlay.initialize(); - // check if logged_in + // process actions + { + let url_search_params : URLSearchParams = new URLSearchParams(window.location.search); + const action : (null | string) = url_search_params.get("action"); + switch (action) + { + case "oidc_finish": + { + try + { + await _dali.oidc_finish(url_search_params.get("session_key")); + } + catch (error_) + { + // do nothing + } + document.location = "/"; + break; + } + default: + case null: + { + // do nothing + break; + } + } + } + + // process status { const status = await _dali.backend.status(); lib_plankton.log.info( @@ -200,7 +204,15 @@ namespace _dali } } - lib_plankton.zoo_page.start(); + // load overview + { + const widget : lib_plankton.zoo_widget.interface_widget = ( + new _dali.widgets.class_widget_overview( + ) + ); + await widget.load(document.querySelector("main")); + } + _dali.helpers.loading(false); return Promise.resolve(undefined); } diff --git a/source/overlay.ts b/source/overlay.ts index 8db482b..890a42d 100644 --- a/source/overlay.ts +++ b/source/overlay.ts @@ -24,7 +24,8 @@ namespace _dali.overlay /** */ function get_container_element( - ) : HTMLElement + ) + : HTMLElement { return document.querySelector("#overlay"); } @@ -33,7 +34,8 @@ namespace _dali.overlay /** */ export function get_content_element( - ) : HTMLElement + ) + : HTMLElement { return document.querySelector("#overlay_content"); } @@ -42,7 +44,8 @@ namespace _dali.overlay /** */ export function clear( - ) : void + ) + : void { get_content_element().innerHTML = ""; } @@ -61,7 +64,8 @@ namespace _dali.overlay = { } - ) : void + ) + : void { get_container_element().classList.toggle("overlay_active", mode ?? undefined); } @@ -70,7 +74,8 @@ namespace _dali.overlay /** */ export function initialize( - ) : Promise + ) + : Promise { clear(); const container_element : HTMLElement = get_container_element(); diff --git a/source/pages/caldav/templates/conf-token_set.html.tpl b/source/pages/caldav/templates/conf-token_set.html.tpl deleted file mode 100644 index 0a8b003..0000000 --- a/source/pages/caldav/templates/conf-token_set.html.tpl +++ /dev/null @@ -1,18 +0,0 @@ -
      - - {{address_value}} -
      -
      - - {{username_value}} -
      -
      - - {{password_value}} -
      -
      - -
        -{{setup_hint_entries}} -
      -
      diff --git a/source/pages/caldav/templates/conf-token_unset.html.tpl b/source/pages/caldav/templates/conf-token_unset.html.tpl deleted file mode 100644 index 1d78bf3..0000000 --- a/source/pages/caldav/templates/conf-token_unset.html.tpl +++ /dev/null @@ -1,4 +0,0 @@ -
      - ({{text}}) -
      - diff --git a/source/pages/caldav/templates/main.html.tpl b/source/pages/caldav/templates/main.html.tpl deleted file mode 100644 index da98a2b..0000000 --- a/source/pages/caldav/templates/main.html.tpl +++ /dev/null @@ -1,6 +0,0 @@ -
      -

      {{label}}

      -
      -{{content}} -
      -
      diff --git a/source/pages/caldav/templates/unavailable.html.tpl b/source/pages/caldav/templates/unavailable.html.tpl deleted file mode 100644 index d6d75fb..0000000 --- a/source/pages/caldav/templates/unavailable.html.tpl +++ /dev/null @@ -1,3 +0,0 @@ -
      - {{text}} -
      diff --git a/source/pages/oidc_finish/logic.ts b/source/pages/oidc_finish/logic.ts deleted file mode 100644 index 925f93e..0000000 --- a/source/pages/oidc_finish/logic.ts +++ /dev/null @@ -1,41 +0,0 @@ -/* -This file is part of »dali«. - -Copyright 2025 'kcf' - -»dali« is free software: you can redistribute it and/or modify -it under the terms of the GNU Lesser General Public License as published by -the Free Software Foundation, either version 3 of the License, or -(at your option) any later version. - -»dali« is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU Lesser General Public License for more details. - -You should have received a copy of the GNU Lesser General Public License -along with »dali«. If not, see . - */ - - -namespace _dali.pages -{ - - /** - */ - lib_plankton.zoo_page.register( - "oidc_finish", - async (parameters, target_element) => { - target_element.innerHTML = ""; - await _dali.oidc_finish(parameters["session_key"]); - lib_plankton.zoo_page.set( - { - "name": "overview", - "parameters": {} - } - ); - return Promise.resolve(undefined); - } - ); - -} diff --git a/source/pages/overview/templates/main.html.tpl b/source/pages/overview/templates/main.html.tpl deleted file mode 100644 index 57a0928..0000000 --- a/source/pages/overview/templates/main.html.tpl +++ /dev/null @@ -1,8 +0,0 @@ -
      -
      -
      -
      -
      -
      -
      -
      diff --git a/source/pages/caldav/logic.ts b/source/widgets/caldav/logic.ts similarity index 58% rename from source/pages/caldav/logic.ts rename to source/widgets/caldav/logic.ts index 028108b..d382238 100644 --- a/source/pages/caldav/logic.ts +++ b/source/widgets/caldav/logic.ts @@ -18,65 +18,80 @@ along with »dali«. If not, see . */ -namespace _dali.pages +namespace _dali.widgets { /** */ - lib_plankton.zoo_page.register( - "caldav", - async (parameters, target_element) => { + export class class_widget_caldav + { + + /** + */ + public constructor( + ) + { + } + + + /** + */ + public async load( + target_element : HTMLElement + ) + : Promise + { target_element.innerHTML = ""; const conf = await _dali.backend.user_dav_conf(); target_element.innerHTML = await _dali.helpers.template_coin( - "caldav", + "widget-caldav", "main", { - "label": lib_plankton.translate.get("page.caldav.title"), + "title": lib_plankton.translate.get("widget.caldav.title"), "content": ( (conf === null) ? await _dali.helpers.template_coin( - "caldav", + "widget-caldav", "unavailable", { - "text": lib_plankton.translate.get("page.caldav.unavailable"), + "text": lib_plankton.translate.get("widget.caldav.unavailable"), } ) : await _dali.helpers.template_coin( - "caldav", + "widget-caldav", "available", { - "conf_title": lib_plankton.translate.get("page.caldav.conf.title"), + "conf_title": lib_plankton.translate.get("widget.caldav.conf.title"), "conf_content": ( (conf.password === null) ? await _dali.helpers.template_coin( - "caldav", + "widget-caldav", "conf-token_unset", { - "text": lib_plankton.translate.get("page.caldav.conf.token_unset") + "text": lib_plankton.translate.get("widget.caldav.conf.token_unset") } ) : await _dali.helpers.template_coin( - "caldav", + "widget-caldav", "conf-token_set", { - "address_label": lib_plankton.translate.get("page.caldav.conf.address"), + "address_label": lib_plankton.translate.get("widget.caldav.conf.address"), "address_value": conf.address, - "username_label": lib_plankton.translate.get("page.caldav.conf.username"), + "username_label": lib_plankton.translate.get("widget.caldav.conf.username"), "username_value": conf.username, - "password_label": lib_plankton.translate.get("page.caldav.conf.password"), + "password_label": lib_plankton.translate.get("widget.caldav.conf.password"), "password_value": conf.password, - "setup_hints_label": lib_plankton.translate.get("page.caldav.conf.setup_hints"), + "setup_hints_label": lib_plankton.translate.get("widget.caldav.conf.setup_hints"), "setup_hint_entries": ( await lib_plankton.call.promise_condense( conf.setup_hints .map( entry => () => _dali.helpers.template_coin( - "caldav", + "widget-caldav", "conf-setup_hint_entry", { "text": entry.label, @@ -101,31 +116,45 @@ namespace _dali.pages } ) ), - "set_token_title": lib_plankton.translate.get("page.caldav.set_token.title"), + "set_token_title": lib_plankton.translate.get("widget.caldav.set_token.title"), "set_token_action": ( (conf.password === null) ? - lib_plankton.translate.get("page.caldav.set_token.action.set") + lib_plankton.translate.get("widget.caldav.set_token.action.set") : - lib_plankton.translate.get("page.caldav.set_token.action.overwrite") + lib_plankton.translate.get("widget.caldav.set_token.action.overwrite") ), } ) - ) + ), + "close": lib_plankton.translate.get("common.close"), } ); - - /** - * logic: set token - */ + // logic { - if (conf !== null) + // set token { - document.querySelector("#caldav-set_token > button").addEventListener( + if (conf === null) + { + // do nothing + } + else + { + target_element.querySelector(".widget-caldav-set_token > button").addEventListener( + "click", + async () => { + await _dali.backend.user_dav_token(); + await this.load(target_element); + } + ); + } + } + // close + { + target_element.querySelector(".widget-caldav-close").addEventListener( "click", - async () => { - await _dali.backend.user_dav_token(); - lib_plankton.zoo_page.reload(); + () => { + _dali.overlay.toggle({"mode": false}); } ); } @@ -133,7 +162,8 @@ namespace _dali.pages return Promise.resolve(undefined); } - ); - + + } + } diff --git a/source/pages/caldav/style.css b/source/widgets/caldav/style.css similarity index 55% rename from source/pages/caldav/style.css rename to source/widgets/caldav/style.css index 47e293b..e053072 100644 --- a/source/pages/caldav/style.css +++ b/source/widgets/caldav/style.css @@ -1,9 +1,9 @@ -.caldav-conf-section +.widget-caldav-conf-section { margin-bottom: 16px; } -.caldav-conf-section-label +.widget-caldav-conf-section-label { margin-left: 16px; display: block; @@ -11,12 +11,12 @@ text-transform: capitalize; } -.caldav-conf-section-value +.widget-caldav-conf-section-value { margin-left: 32px; } -.caldav-conf-section-value-regular +.widget-caldav-conf-section-value-regular { font-family: monospace; } diff --git a/source/pages/caldav/templates/available.html.tpl b/source/widgets/caldav/templates/available.html.tpl similarity index 64% rename from source/pages/caldav/templates/available.html.tpl rename to source/widgets/caldav/templates/available.html.tpl index c8bb50b..56b3cde 100644 --- a/source/pages/caldav/templates/available.html.tpl +++ b/source/widgets/caldav/templates/available.html.tpl @@ -1,8 +1,8 @@ -
      +

      {{conf_title}}

      {{conf_content}}
      -
      +

      {{set_token_title}}

      diff --git a/source/pages/caldav/templates/conf-setup_hint_entry.html.tpl b/source/widgets/caldav/templates/conf-setup_hint_entry.html.tpl similarity index 56% rename from source/pages/caldav/templates/conf-setup_hint_entry.html.tpl rename to source/widgets/caldav/templates/conf-setup_hint_entry.html.tpl index d4338e6..737f0e8 100644 --- a/source/pages/caldav/templates/conf-setup_hint_entry.html.tpl +++ b/source/widgets/caldav/templates/conf-setup_hint_entry.html.tpl @@ -1,3 +1,3 @@ -
    • +
    • {{text}}{{remark}}
    • diff --git a/source/widgets/caldav/templates/conf-token_set.html.tpl b/source/widgets/caldav/templates/conf-token_set.html.tpl new file mode 100644 index 0000000..5b5441a --- /dev/null +++ b/source/widgets/caldav/templates/conf-token_set.html.tpl @@ -0,0 +1,18 @@ +
      + + {{address_value}} +
      +
      + + {{username_value}} +
      +
      + + {{password_value}} +
      +
      + +
        +{{setup_hint_entries}} +
      +
      diff --git a/source/widgets/caldav/templates/conf-token_unset.html.tpl b/source/widgets/caldav/templates/conf-token_unset.html.tpl new file mode 100644 index 0000000..beb63a5 --- /dev/null +++ b/source/widgets/caldav/templates/conf-token_unset.html.tpl @@ -0,0 +1,4 @@ +
      + ({{text}}) +
      + diff --git a/source/widgets/caldav/templates/main.html.tpl b/source/widgets/caldav/templates/main.html.tpl new file mode 100644 index 0000000..c4dfd7d --- /dev/null +++ b/source/widgets/caldav/templates/main.html.tpl @@ -0,0 +1,8 @@ +
      +

      {{title}}

      +
      +{{content}} +
      +
      + +
      diff --git a/source/widgets/caldav/templates/unavailable.html.tpl b/source/widgets/caldav/templates/unavailable.html.tpl new file mode 100644 index 0000000..28f7bf8 --- /dev/null +++ b/source/widgets/caldav/templates/unavailable.html.tpl @@ -0,0 +1,3 @@ +
      + {{text}} +
      diff --git a/source/widgets/calendar_edit/logic.ts b/source/widgets/calendar_edit/logic.ts index 4c30a1d..a3464ba 100644 --- a/source/widgets/calendar_edit/logic.ts +++ b/source/widgets/calendar_edit/logic.ts @@ -18,7 +18,7 @@ along with »dali«. If not, see . */ -namespace _dali.widgets.calendar_edit +namespace _dali.widgets { /** diff --git a/source/widgets/event_edit/logic.ts b/source/widgets/event_edit/logic.ts index d2f76cc..4eecdb7 100644 --- a/source/widgets/event_edit/logic.ts +++ b/source/widgets/event_edit/logic.ts @@ -18,7 +18,7 @@ along with »dali«. If not, see . */ -namespace _dali.widgets.event_edit +namespace _dali.widgets { /** diff --git a/source/widgets/listview/logic.ts b/source/widgets/listview/logic.ts index 98d3340..53fbba0 100644 --- a/source/widgets/listview/logic.ts +++ b/source/widgets/listview/logic.ts @@ -18,7 +18,7 @@ along with »dali«. If not, see . */ -namespace _dali.widgets.listview +namespace _dali.widgets { /** diff --git a/source/widgets/login/logic.ts b/source/widgets/login/logic.ts index 4838588..ba90d34 100644 --- a/source/widgets/login/logic.ts +++ b/source/widgets/login/logic.ts @@ -18,7 +18,7 @@ along with »dali«. If not, see . */ -namespace _dali.widgets.login +namespace _dali.widgets { /** @@ -73,7 +73,7 @@ namespace _dali.widgets.login * [implementation] */ public async load( - target_element : Element + target_element : HTMLElement ) : Promise { @@ -86,125 +86,36 @@ namespace _dali.widgets.login { case "internal": { - target_element.innerHTML = await _dali.helpers.template_coin( - "widget-login", - "default", - { - } - ); - const form : lib_plankton.zoo_form.class_form< - {name : string; password : string;}, - {name : string; password : string;} - > = new lib_plankton.zoo_form.class_form< - {name : string; password : string;}, - {name : string; password : string;} - >( - x => x, - x => x, - new lib_plankton.zoo_input.class_input_group< - {name : string; password : string;} - >( - [ - { - "name": "name", - "input": new lib_plankton.zoo_input.class_input_text(), - "label": lib_plankton.translate.get("widget.login.internal.name"), - }, - { - "name": "password", - "input": new lib_plankton.zoo_input.class_input_password(), - "label": lib_plankton.translate.get("widget.login.internal.password"), - }, - ] - ), - ( - [] - .concat( - [ - { - "label": lib_plankton.translate.get("widget.login.internal.do"), - "procedure": async (get_value, get_representation) => { - const value : any = await get_value(); - try - { - await _dali.backend.session_begin( - value.name, - value.password - ); - if (this.action_success !== null) this.action_success(); - } - catch (error) - { - // todo - } - } - } - ] - ) - .concat( - (this.action_cancel === null) - ? - [] - : - [ - { - "label": lib_plankton.translate.get("common.cancel"), - "procedure": () => { - this.action_cancel(); - } - } - ] - ) + const sub_widget : lib_plankton.zoo_widget.interface_widget = ( + new class_widget_login_internal( + preparation.data, + { + "initial_name": this.initial_name, + "action_cancel": this.action_cancel, + "action_success": this.action_success, + } ) ); - await form.setup(document.querySelector(".widget-login")); - await form.input_write( - { - "name": this.initial_name, - "password": "", - } - ); + await sub_widget.load(target_element); break; } case "oidc": { - // link - { - let element_a : HTMLElement = document.createElement("a");; - element_a.textContent = lib_plankton.string.coin( - lib_plankton.translate.get("widget.login.oidc.via"), + const sub_widget : lib_plankton.zoo_widget.interface_widget = ( + new class_widget_login_oidc( + preparation.data, { - "title": preparation.data.label, + "action_cancel": this.action_cancel, + "action_success": this.action_success, } - ); - element_a.setAttribute("href", preparation.data.url); - target_element.appendChild(element_a); - } - { - let dom_br : HTMLElement = document.createElement("br"); - target_element.appendChild(dom_br); - } - { - let dom_br : HTMLElement = document.createElement("br"); - target_element.appendChild(dom_br); - } - // cancel - { - let dom_cancel : HTMLElement = document.createElement("button"); - dom_cancel.textContent = lib_plankton.translate.get("common.cancel"); - dom_cancel.addEventListener( - "click", - () => { - this.action_cancel(); - } - ); - target_element.appendChild(dom_cancel); - } + ) + ); + await sub_widget.load(target_element); break; } default: { - // todo + throw (new Error("unhandled login kind: " + preparation.kind)); break; } } diff --git a/source/widgets/login/templates/default.html.tpl b/source/widgets/login/templates/default.html.tpl deleted file mode 100644 index 9ac6980..0000000 --- a/source/widgets/login/templates/default.html.tpl +++ /dev/null @@ -1,2 +0,0 @@ - diff --git a/source/widgets/login_internal/logic.ts b/source/widgets/login_internal/logic.ts new file mode 100644 index 0000000..5e85b46 --- /dev/null +++ b/source/widgets/login_internal/logic.ts @@ -0,0 +1,164 @@ +/* +This file is part of »dali«. + +Copyright 2025 'kcf' + +»dali« is free software: you can redistribute it and/or modify +it under the terms of the GNU Lesser General Public License as published by +the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. + +»dali« is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU Lesser General Public License for more details. + +You should have received a copy of the GNU Lesser General Public License +along with »dali«. If not, see . + */ + + +namespace _dali.widgets +{ + + /** + */ + export class class_widget_login_internal + implements lib_plankton.zoo_widget.interface_widget + { + + /** + */ + private preparation_data : any; + + + /** + */ + private initial_name : (null | string); + + + /** + * [hook] + */ + private action_cancel : (null | (() => void)); + + + /** + * [hook] + */ + private action_success : (null | (() => void)); + + + /** + */ + public constructor( + preparation_data : any, + { + "initial_name": initial_name = null, + "action_cancel": action_cancel = null, + "action_success": action_success = null, + } + : + { + initial_name ?: (null | string); + action_cancel ?: (null | (() => void)); + action_success ?: (null | (() => void)); + } + = + { + } + ) + { + this.preparation_data = preparation_data; + this.initial_name = initial_name; + this.action_cancel = action_cancel; + this.action_success = action_success; + } + + + /** + * [implementation] + */ + public async load( + target_element : HTMLElement + ) + : Promise + { + const form : lib_plankton.zoo_form.class_form< + {name : string; password : string;}, + {name : string; password : string;} + > = new lib_plankton.zoo_form.class_form< + {name : string; password : string;}, + {name : string; password : string;} + >( + x => x, + x => x, + new lib_plankton.zoo_input.class_input_group< + {name : string; password : string;} + >( + [ + { + "name": "name", + "input": new lib_plankton.zoo_input.class_input_text(), + "label": lib_plankton.translate.get("widget.login.internal.name"), + }, + { + "name": "password", + "input": new lib_plankton.zoo_input.class_input_password(), + "label": lib_plankton.translate.get("widget.login.internal.password"), + }, + ] + ), + ( + [] + .concat( + [ + { + "label": lib_plankton.translate.get("widget.login.internal.do"), + "procedure": async (get_value, get_representation) => { + const value : any = await get_value(); + try + { + await _dali.backend.session_begin( + value.name, + value.password + ); + if (this.action_success !== null) this.action_success(); + } + catch (error) + { + // todo + } + } + } + ] + ) + .concat( + (this.action_cancel === null) + ? + [] + : + [ + { + "label": lib_plankton.translate.get("common.cancel"), + "procedure": () => { + this.action_cancel(); + } + } + ] + ) + ) + ); + target_element.innerHTML = ""; + await form.setup(target_element); + await form.input_write( + { + "name": this.initial_name, + "password": "", + } + ); + } + + } + +} diff --git a/source/widgets/login_oidc/logic.ts b/source/widgets/login_oidc/logic.ts new file mode 100644 index 0000000..b5a4500 --- /dev/null +++ b/source/widgets/login_oidc/logic.ts @@ -0,0 +1,110 @@ +/* +This file is part of »dali«. + +Copyright 2025 'kcf' + +»dali« is free software: you can redistribute it and/or modify +it under the terms of the GNU Lesser General Public License as published by +the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. + +»dali« is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU Lesser General Public License for more details. + +You should have received a copy of the GNU Lesser General Public License +along with »dali«. If not, see . + */ + + +namespace _dali.widgets +{ + + /** + */ + export class class_widget_login_oidc + implements lib_plankton.zoo_widget.interface_widget + { + + /** + */ + private preparation_data : any; + + + /** + * [hook] + */ + private action_cancel : (null | (() => void)); + + + /** + * [hook] + */ + private action_success : (null | (() => void)); + + + /** + */ + public constructor( + preparation_data : any, + { + "action_cancel": action_cancel = null, + "action_success": action_success = null, + } + : + { + action_cancel ?: (null | (() => void)); + action_success ?: (null | (() => void)); + } + = + { + } + ) + { + this.preparation_data = preparation_data; + this.action_cancel = action_cancel; + this.action_success = action_success; + } + + + /** + * [implementation] + */ + public async load( + target_element : HTMLElement + ) + : Promise + { + // structure + { + target_element.innerHTML = await _dali.helpers.template_coin( + "widget-login_oidc", + "main", + { + "label": lib_plankton.string.coin( + lib_plankton.translate.get("widget.login.oidc.via"), + { + "title": this.preparation_data.label, + } + ), + "href": this.preparation_data.url, + "cancel": lib_plankton.translate.get("common.cancel"), + } + ); + } + + // controls + { + target_element.querySelector(".widget-login_oidc-cancel").addEventListener( + "click", + () => { + this.action_cancel(); + } + ); + } + } + + } + +} diff --git a/source/widgets/login_oidc/style.css b/source/widgets/login_oidc/style.css new file mode 100644 index 0000000..ab5f060 --- /dev/null +++ b/source/widgets/login_oidc/style.css @@ -0,0 +1,5 @@ +.widget-login_oidc-cancel +{ + display: block; + margin-top: 32px; +} diff --git a/source/widgets/login_oidc/templates/main.html.tpl b/source/widgets/login_oidc/templates/main.html.tpl new file mode 100644 index 0000000..57cdffb --- /dev/null +++ b/source/widgets/login_oidc/templates/main.html.tpl @@ -0,0 +1,4 @@ + diff --git a/source/widgets/menu/logic.ts b/source/widgets/menu/logic.ts index fd9d540..617a2f0 100644 --- a/source/widgets/menu/logic.ts +++ b/source/widgets/menu/logic.ts @@ -18,7 +18,7 @@ along with »dali«. If not, see . */ -namespace _dali.widgets.menu +namespace _dali.widgets { /** diff --git a/source/widgets/mode_switcher/logic.ts b/source/widgets/mode_switcher/logic.ts index 691782b..6a40a29 100644 --- a/source/widgets/mode_switcher/logic.ts +++ b/source/widgets/mode_switcher/logic.ts @@ -18,7 +18,7 @@ along with »dali«. If not, see . */ -namespace _dali.widgets.mode_switcher +namespace _dali.widgets { /** diff --git a/source/widgets/multiview/logic.ts b/source/widgets/multiview/logic.ts index 87929aa..414c8d6 100644 --- a/source/widgets/multiview/logic.ts +++ b/source/widgets/multiview/logic.ts @@ -18,7 +18,7 @@ along with »dali«. If not, see . */ -namespace _dali.widgets.multiview +namespace _dali.widgets { /** @@ -96,17 +96,17 @@ namespace _dali.widgets.multiview /** */ - private widget_mode_switcher : _dali.widgets.mode_switcher.class_widget_mode_switcher; + private widget_mode_switcher : _dali.widgets.class_widget_mode_switcher; /** */ - private widget_weekview : _dali.widgets.weekview.class_widget_weekview; + private widget_weekview : _dali.widgets.class_widget_weekview; /** */ - private widget_listview : _dali.widgets.listview.class_widget_listview; + private widget_listview : _dali.widgets.class_widget_listview; /** @@ -205,15 +205,21 @@ namespace _dali.widgets.multiview // mode switcher { this.widget_mode_switcher = ( - new _dali.widgets.mode_switcher.class_widget_mode_switcher( + new _dali.widgets.class_widget_mode_switcher( [ { "mode": _dali.enum_view_mode.week, - "label": lib_plankton.translate.get("page.overview.mode.week"), + /** + * @todo as dependency + */ + "label": lib_plankton.translate.get("widget.overview.mode.week"), }, { "mode": _dali.enum_view_mode.list, - "label": lib_plankton.translate.get("page.overview.mode.list"), + /** + * @todo as dependency + */ + "label": lib_plankton.translate.get("widget.overview.mode.list"), }, ], { @@ -232,7 +238,7 @@ namespace _dali.widgets.multiview // weekview { this.widget_weekview = ( - new _dali.widgets.weekview.class_widget_weekview( + new _dali.widgets.class_widget_weekview( this.get_entries, { "action_select_event": (event_key) => this.action_edit_event(event_key), @@ -249,7 +255,7 @@ namespace _dali.widgets.multiview // listview { this.widget_listview = ( - new _dali.widgets.listview.class_widget_listview( + new _dali.widgets.class_widget_listview( this.get_entries, { "action_select": (event_key) => this.action_edit_event(event_key), diff --git a/source/pages/overview/logic.ts b/source/widgets/overview/logic.ts similarity index 63% rename from source/pages/overview/logic.ts rename to source/widgets/overview/logic.ts index 873374c..5a25153 100644 --- a/source/pages/overview/logic.ts +++ b/source/widgets/overview/logic.ts @@ -18,120 +18,98 @@ along with »dali«. If not, see . */ -namespace _dali.pages.overview +namespace _dali.widgets { /** */ - lib_plankton.zoo_page.register( - "overview", - async (parameters, target_element) => { - // params - const view_mode : _dali.enum_view_mode = _dali.helpers.view_mode_determine(parameters["mode"] ?? "auto"); - const view_kind : _dali.enum_view_kind = _dali.helpers.view_kind_determine(parameters["kind"] ?? "auto"); - - // exec - /** - */ - async function get_available_calendars( - ) - : Promise< - Array< - _dali.type_calendar_object_reduced_with_id - > - > - { - return ( - (await _dali.model.calendar_list()) - /* - .filter( - (entry) => ( - (entry.access_level === _dali.enum_access_level.edit) - || - (entry.access_level === _dali.enum_access_level.admin) - ) - ) - */ - ); + type type_action_create_calendar = ( + ( + ) + => + Promise + ); + + + /** + */ + type type_action_edit_calendar = ( + ( + type_calendar_object_reduced_with_id + ) + => + Promise + ); + + + /** + */ + type type_action_create_event = ( + ( + stuff ?: { + date ?: lib_plankton.pit.type_date; } - - /** - * @todo add return type - */ - async function get_entries( - from_pit : lib_plankton.pit.type_pit, - to_pit : lib_plankton.pit.type_pit, - calendar_ids : Array<_dali.type_calendar_id> - ) - : Promise> - { - /** - * @todo do NOT wait? - */ - await _dali.model.sync_events( - { - "from": from_pit, - "to": to_pit, - }, - { - "calendar_ids": calendar_ids, - } - ); - /** - * @todo filter - */ - return _dali.model.event_list(); - } - - /** - * @todo update listview - */ - async function update_sources_and_entries( - { - "priviliged": priviliged = null, - } - : - { - priviliged ?: (null | boolean); - } - = - { - } - ) - : Promise - { - await widget_sources.update({"priviliged": priviliged}); - await widget_multiview.update_entries(); - } - - /** - * @todo use priviliged? - * @todo update listview - */ - async function update_entries( - { - "priviliged": priviliged = null, - } - : - { - priviliged ?: (null | boolean); - } - = - { - } - ) - : Promise - { - await widget_multiview.update_entries(); - } - - /** - */ - async function action_create_calendar( - ) - : Promise - { - const widget = new _dali.widgets.calendar_edit.class_widget_calendar_edit( + ) + => + Promise + ); + + + /** + */ + type type_action_edit_event = ( + ( + event_key : _dali.type_event_key + ) + => + Promise + ); + + + /** + */ + export class class_widget_overview + implements lib_plankton.zoo_widget.interface_widget + { + + /** + */ + private widget_sources : _dali.widgets.class_widget_sources; + + + /** + */ + private widget_multiview : _dali.widgets.class_widget_multiview; + + + /** + */ + private action_create_calendar : type_action_create_calendar; + + + /** + */ + private action_edit_calendar : type_action_edit_calendar; + + + /** + */ + private action_create_event : type_action_create_event; + + + /** + */ + private action_edit_event : type_action_edit_event; + + + /** + */ + public constructor( + ) + { + this.action_create_calendar = async ( + ) => { + const widget = new _dali.widgets.class_widget_calendar_edit( await _dali.model.group_list(), await _dali.model.user_list(), { @@ -179,7 +157,7 @@ namespace _dali.pages.overview ) .then( () => { - update_sources_and_entries(); + this.update_sources_and_entries(); _dali.overlay.toggle({"mode": false}); } ) @@ -197,15 +175,10 @@ namespace _dali.pages.overview _dali.overlay.clear(); _dali.overlay.toggle({"mode": true}); await widget.load(_dali.overlay.get_content_element()); - } - - /** - */ - async function action_edit_calendar( - calendar_object_reduced_with_id : type_calendar_object_reduced_with_id - ) - : Promise - { + }; + this.action_edit_calendar = async ( + calendar_object_reduced_with_id + ) => { const read_only : boolean = (() => { switch (calendar_object_reduced_with_id.access_level) { @@ -242,7 +215,7 @@ namespace _dali.pages.overview const calendar_object : _dali.type_calendar_object = await _dali.model.calendar_get( calendar_id ); - const widget = new _dali.widgets.calendar_edit.class_widget_calendar_edit( + const widget = new _dali.widgets.class_widget_calendar_edit( await _dali.model.group_list(), await _dali.model.user_list(), calendar_object, @@ -258,7 +231,7 @@ namespace _dali.pages.overview ) .then( () => { - update_sources_and_entries(); + this.update_sources_and_entries(); _dali.overlay.toggle({"mode": false}); } ); @@ -269,7 +242,7 @@ namespace _dali.pages.overview ) .then( () => { - update_sources_and_entries(); + this.update_sources_and_entries(); _dali.overlay.toggle({"mode": false}); } ); @@ -281,11 +254,10 @@ namespace _dali.pages.overview await widget.load(_dali.overlay.get_content_element()); } } - /** * @todo unterschiedliches Verhalten bei Anmeldung? */ - async function action_create_event( + this.action_create_event = async ( { "date": date = lib_plankton.pit.to_datetime(lib_plankton.pit.now()).date, } @@ -296,17 +268,15 @@ namespace _dali.pages.overview = { } - ) - : Promise - { + ) => { if (! _dali.is_logged_in()) { // do nothing } else { - const widget = new _dali.widgets.event_edit.class_widget_event_edit( - (await get_available_calendars()), + const widget = new _dali.widgets.class_widget_event_edit( + (await this.get_available_calendars()), { "calendar_id": null, "event_name": "", @@ -359,7 +329,7 @@ namespace _dali.pages.overview ) .then( () => { - update_entries(); + this.update_entries(); _dali.overlay.toggle({"mode": false}); } ) @@ -376,15 +346,11 @@ namespace _dali.pages.overview await widget.load(_dali.overlay.get_content_element()); } } - /** */ - async function action_edit_event - ( - event_key : _dali.type_event_key - ) - : Promise - { + this.action_edit_event = async ( + event_key + ) => { const event_object_extended : _dali.type_event_object_extended = await _dali.model.event_get(event_key); const read_only : boolean = (() => { switch (event_object_extended.access_level) @@ -407,8 +373,8 @@ namespace _dali.pages.overview } } }) (); - const widget = new _dali.widgets.event_edit.class_widget_event_edit( - (await get_available_calendars()), + const widget = new _dali.widgets.class_widget_event_edit( + (await this.get_available_calendars()), { "calendar_id": event_object_extended.calendar_id, "event_name": event_object_extended.event_object.name, @@ -437,7 +403,7 @@ namespace _dali.pages.overview ) .then( () => { - update_entries(); + this.update_entries(); _dali.overlay.toggle({"mode": false}); } ) @@ -456,7 +422,7 @@ namespace _dali.pages.overview ) .then( () => { - update_entries(); + this.update_entries(); _dali.overlay.toggle({"mode": false}); } ) @@ -471,98 +437,212 @@ namespace _dali.pages.overview }, } ); - _dali.overlay.clear(); _dali.overlay.toggle({"mode": true}); await widget.load(_dali.overlay.get_content_element()); } + } + + + /** + */ + private async get_available_calendars( + ) + : Promise< + Array< + _dali.type_calendar_object_reduced_with_id + > + > + { + return ( + (await _dali.model.calendar_list()) + /* + .filter( + (entry) => ( + (entry.access_level === _dali.enum_access_level.edit) + || + (entry.access_level === _dali.enum_access_level.admin) + ) + ) + */ + ); + } + + + /** + */ + private async get_entries( + from_pit : lib_plankton.pit.type_pit, + to_pit : lib_plankton.pit.type_pit, + calendar_ids : Array<_dali.type_calendar_id> + ) + : Promise> + { + /** + * @todo do NOT wait? + */ + await _dali.model.sync_events( + { + "from": from_pit, + "to": to_pit, + }, + { + "calendar_ids": calendar_ids, + } + ); + /** + * @todo filter + */ + return _dali.model.event_list(); + } + + + /** + */ + private async update_sources_and_entries( + { + "priviliged": priviliged = null, + } + : + { + priviliged ?: (null | boolean); + } + = + { + } + ) + : Promise + { + await this.widget_sources.update({"priviliged": priviliged}); + await this.widget_multiview.update_entries(); + } + + + /** + * @todo use priviliged? + */ + private async update_entries( + { + "priviliged": priviliged = null, + } + : + { + priviliged ?: (null | boolean); + } + = + { + } + ) + : Promise + { + await this.widget_multiview.update_entries(); + } + + + + /** + * [implementation] + */ + public async load( + target_element : HTMLElement + ) + : Promise + { + const view_mode : _dali.enum_view_mode = _dali.helpers.view_mode_determine("auto"); + const view_kind : _dali.enum_view_kind = _dali.helpers.view_kind_determine("auto"); - const widget_sources : _dali.widgets.sources.class_widget_sources = ( - new _dali.widgets.sources.class_widget_sources( + this.widget_sources = ( + new _dali.widgets.class_widget_sources( _dali.model.calendar_list, { "initial_priviliged": _dali.is_logged_in(), - "action_add": action_create_calendar, - "action_select": (entry) => action_edit_calendar(entry), + "action_add": this.action_create_calendar, + "action_select": this.action_edit_calendar, "action_toggle": (entry, mode) => { - widget_multiview.toggle_calendar_visibilty(entry.id, {"mode": mode}); + this.widget_multiview.toggle_calendar_visibilty(entry.id, {"mode": mode}); }, } ) ); - const widget_multiview : _dali.widgets.multiview.class_widget_multiview = ( - new _dali.widgets.multiview.class_widget_multiview( - get_entries, + this.widget_multiview = ( + new _dali.widgets.class_widget_multiview( + this.get_entries, { "initial_view_mode": view_mode, "weekview_initial_vertical": (view_kind === _dali.enum_view_kind.touch), - "action_create_event": action_create_event, - "action_edit_event": action_edit_event, + "action_create_event": this.action_create_event, + "action_edit_event": this.action_edit_event, } ) ); target_element.innerHTML = await _dali.helpers.template_coin( - "overview", + "widget-overview", "main", { } ); - - switch (view_kind) + + // head { - case _dali.enum_view_kind.regular: + // hint { - const widget_slider = new lib_plankton.zoo_widget.class_slider( - [ - new lib_plankton.zoo_widget.class_bunch( - [ - widget_sources, - widget_multiview, - ] - ), - ], - { - "threshold": 100, - "initial_index": 1, - } - ); - await widget_slider.load(target_element.querySelector("#overview-body")); - break; - } - case _dali.enum_view_kind.touch: - { - const widget_slider = new lib_plankton.zoo_widget.class_slider( - [ - widget_sources, - widget_multiview, - ], - { - "threshold": 100, - "initial_index": 2, - } - ); - await widget_slider.load(target_element.querySelector("#overview-body")); - break; + const dom_hint = target_element.querySelector(".widget-overview-hint"); + dom_hint.textContent = lib_plankton.translate.get("widget.overview.login_hint"); + dom_hint.classList.toggle("widget-overview-hint-hidden", _dali.is_logged_in()); } } - - // hint + // body { - const dom_hint = target_element.querySelector("#overview-hint"); - dom_hint.textContent = lib_plankton.translate.get("page.overview.login_hint"); - dom_hint.classList.toggle("overview-hint-hidden", _dali.is_logged_in()); + let widget_slider : lib_plankton.zoo_widget.interface_widget; + switch (view_kind) + { + case _dali.enum_view_kind.regular: + { + widget_slider = new lib_plankton.zoo_widget.class_slider( + [ + new lib_plankton.zoo_widget.class_bunch( + [ + this.widget_sources, + this.widget_multiview, + ] + ), + ], + { + "threshold": 100, + "initial_index": 1, + } + ); + break; + } + case _dali.enum_view_kind.touch: + { + widget_slider = new lib_plankton.zoo_widget.class_slider( + [ + this.widget_sources, + this.widget_multiview, + ], + { + "threshold": 100, + "initial_index": 2, + } + ); + break; + } + } + await widget_slider.load(target_element.querySelector(".widget-overview-body")); } _dali.model.listen_reset( async (priviliged) => { - update_sources_and_entries({"priviliged": priviliged}); - target_element.querySelector("#overview-hint").classList.toggle("overview-hint-hidden", priviliged); + this.update_sources_and_entries({"priviliged": priviliged}); + target_element.querySelector(".widget-overview-hint").classList.toggle("widget-overview-hint-hidden", priviliged); } ); return Promise.resolve(undefined); - }, - ); - + } + + } + } diff --git a/source/pages/overview/style.css b/source/widgets/overview/style.css similarity index 56% rename from source/pages/overview/style.css rename to source/widgets/overview/style.css index 1d7c2dc..813ec16 100644 --- a/source/pages/overview/style.css +++ b/source/widgets/overview/style.css @@ -1,57 +1,57 @@ -#overview-head +.widget-overview-head { padding-bottom: 12px; margin-bottom: 12px; border-bottom: 1px solid; } -#overview-hint +.widget-overview-hint { text-align: center; font-weight: bold; } -#overview-hint.overview-hint-hidden +.widget-overview-hint.widget-overview-hint-hidden { display: none; } -#overview-body +.widget-overview-body { display: flex; flex-direction: row; flex-wrap: nowrap; } -#overview-pane-left +.widget-overview-pane-left { flex-basis: 12.5%; flex-grow: 0; flex-shrink: 1; } -#overview-pane-right +.widget-overview-pane-right { flex-basis: 87.5%; flex-grow: 1; flex-shrink: 1; } -#overview-body .widget-slider-slide .widget-bunch +.widget-overview-body .widget-slider-slide .widget-bunch { display: flex; flex-direction: row; flex-wrap: nowrap; } -#overview-body .widget-slider-slide .widget-bunch-element:nth-child(1) +.widget-overview-body .widget-slider-slide .widget-bunch-element:nth-child(1) { flex-grow: 0; flex-shrink: 1; flex-basis: 12.5%; } -#overview-body .widget-slider-slide .widget-bunch-element:nth-child(2) +.widget-overview-body .widget-slider-slide .widget-bunch-element:nth-child(2) { flex-grow: 1; flex-shrink: 1; diff --git a/source/widgets/overview/templates/main.html.tpl b/source/widgets/overview/templates/main.html.tpl new file mode 100644 index 0000000..d4d3054 --- /dev/null +++ b/source/widgets/overview/templates/main.html.tpl @@ -0,0 +1,8 @@ +
      +
      +
      +
      +
      +
      +
      +
      diff --git a/source/widgets/sources/logic.ts b/source/widgets/sources/logic.ts index 04bbc3b..355927a 100644 --- a/source/widgets/sources/logic.ts +++ b/source/widgets/sources/logic.ts @@ -18,7 +18,7 @@ along with »dali«. If not, see . */ -namespace _dali.widgets.sources +namespace _dali.widgets { /** diff --git a/source/widgets/weekview/logic.ts b/source/widgets/weekview/logic.ts index 2d26075..ac939de 100644 --- a/source/widgets/weekview/logic.ts +++ b/source/widgets/weekview/logic.ts @@ -18,7 +18,7 @@ along with »dali«. If not, see . */ -namespace _dali.widgets.weekview +namespace _dali.widgets { /** diff --git a/tools/makefile b/tools/makefile index 885210b..c2b20c8 100644 --- a/tools/makefile +++ b/tools/makefile @@ -30,21 +30,14 @@ ${dir_build}/index.html: \ .PHONY: templates templates: \ - templates-widgets-login \ templates-widgets-special_number_input \ + templates-widgets-login_oidc \ templates-widgets-sources \ + templates-widgets-caldav \ templates-widgets-listview \ templates-widgets-weekview \ - templates-widgets-mode_switcher \ - templates-pages-caldav \ - templates-pages-overview - -.PHONY: templates-widgets-login -templates-widgets-login: \ - $(wildcard ${dir_source}/widgets/login/templates/*) - @ ${cmd_log} "templates:widget:login …" - @ ${cmd_mkdir} ${dir_build}/templates/widget-login - @ ${cmd_cp} -r -u -v ${dir_source}/widgets/login/templates/* ${dir_build}/templates/widget-login/ + templates-widgets-overview \ + templates-widgets-mode_switcher .PHONY: templates-widgets-special_number_input templates-widgets-special_number_input: \ @@ -53,6 +46,13 @@ templates-widgets-special_number_input: \ @ ${cmd_mkdir} ${dir_build}/templates/widget-special_number_input @ ${cmd_cp} -r -u -v ${dir_source}/widgets/special_number_input/templates/* ${dir_build}/templates/widget-special_number_input/ +.PHONY: templates-widgets-login_oidc +templates-widgets-login_oidc: \ + $(wildcard ${dir_source}/widgets/login_oidc/templates/*) + @ ${cmd_log} "templates:widget:login_oidc …" + @ ${cmd_mkdir} ${dir_build}/templates/widget-login_oidc + @ ${cmd_cp} -r -u -v ${dir_source}/widgets/login_oidc/templates/* ${dir_build}/templates/widget-login_oidc/ + .PHONY: templates-widgets-sources templates-widgets-sources: \ $(wildcard ${dir_source}/widgets/sources/templates/*) @@ -60,6 +60,13 @@ templates-widgets-sources: \ @ ${cmd_mkdir} ${dir_build}/templates/widget-sources @ ${cmd_cp} -r -u -v ${dir_source}/widgets/sources/templates/* ${dir_build}/templates/widget-sources/ +.PHONY: templates-widgets-caldav +templates-widgets-caldav: \ + $(wildcard ${dir_source}/widgets/caldav/templates/*) + @ ${cmd_log} "templates:widget:caldav …" + @ ${cmd_mkdir} ${dir_build}/templates/widget-caldav + @ ${cmd_cp} -r -u -v ${dir_source}/widgets/caldav/templates/* ${dir_build}/templates/widget-caldav/ + .PHONY: templates-widgets-listview templates-widgets-listview: \ $(wildcard ${dir_source}/widgets/listview/templates/*) @@ -74,6 +81,13 @@ templates-widgets-weekview: \ @ ${cmd_mkdir} ${dir_build}/templates/widget-weekview @ ${cmd_cp} -r -u -v ${dir_source}/widgets/weekview/templates/* ${dir_build}/templates/widget-weekview/ +.PHONY: templates-widgets-overview +templates-widgets-overview: \ + $(wildcard ${dir_source}/widgets/overview/templates/*) + @ ${cmd_log} "templates:widget:overview …" + @ ${cmd_mkdir} ${dir_build}/templates/widget-overview + @ ${cmd_cp} -r -u -v ${dir_source}/widgets/overview/templates/* ${dir_build}/templates/widget-overview/ + .PHONY: templates-widgets-mode_switcher templates-widgets-mode_switcher: \ $(wildcard ${dir_source}/widgets/mode_switcher/templates/*) @@ -81,27 +95,12 @@ templates-widgets-mode_switcher: \ @ ${cmd_mkdir} ${dir_build}/templates/widget-mode_switcher @ ${cmd_cp} -r -u -v ${dir_source}/widgets/mode_switcher/templates/* ${dir_build}/templates/widget-mode_switcher/ -.PHONY: templates-pages-caldav -templates-pages-caldav: \ - $(wildcard ${dir_source}/pages/caldav/templates/*) - @ ${cmd_log} "templates:page:caldav …" - @ ${cmd_mkdir} ${dir_build}/templates/caldav - @ ${cmd_cp} -r -u -v ${dir_source}/pages/caldav/templates/* ${dir_build}/templates/caldav/ - -.PHONY: templates-pages-overview -templates-pages-overview: \ - $(wildcard ${dir_source}/pages/overview/templates/*) - @ ${cmd_log} "templates:page:overview …" - @ ${cmd_mkdir} ${dir_build}/templates/overview - @ ${cmd_cp} -r -u -v ${dir_source}/pages/overview/templates/* ${dir_build}/templates/overview/ - .PHONY: style style: ${dir_build}/style.css ${dir_build}/style.css: \ $(wildcard ${dir_source}/style/*.css) \ - $(wildcard ${dir_source}/widgets/*/style.css) \ - $(wildcard ${dir_source}/pages/*/style.css) + $(wildcard ${dir_source}/widgets/*/style.css) @ ${cmd_log} "style …" @ ${cmd_mkdir} ${dir_build} @ ${cmd_cat} $^ > $@ @@ -116,10 +115,9 @@ ${dir_temp}/logic-unlinked.js: \ ${dir_source}/base.ts \ ${dir_source}/types.ts \ ${dir_source}/model.ts \ - ${dir_source}/helpers.ts \ ${dir_source}/overlay.ts \ + ${dir_source}/helpers.ts \ $(wildcard ${dir_source}/widgets/*/logic.ts) \ - $(wildcard ${dir_source}/pages/*/logic.ts) \ ${dir_source}/main.ts @ ${cmd_log} "logic | compile …" @ ${cmd_mkdir} $(dir $@) -- 2.47.3