From fc0ee9209456e7968f1bbada158364236e9069cd Mon Sep 17 00:00:00 2001 From: Fenris Wolf Date: Thu, 26 Sep 2024 16:47:01 +0200 Subject: [PATCH] [mod] pages --- lib/plankton/plankton.d.ts | 148 +++++- lib/plankton/plankton.js | 418 +++++++++++++++ source/logic/backend.ts | 4 +- source/logic/helpers.ts | 467 ---------------- source/logic/main.ts | 532 ------------------- source/logic/types.ts | 4 +- source/logic/view.ts | 84 +-- source/pages/calendar_add/logic.ts | 180 +++++++ source/pages/calendar_add/structure.html.tpl | 1 + source/pages/event_add/logic.ts | 163 ++++++ source/pages/event_add/structure.html.tpl | 0 source/pages/events/logic.ts | 30 ++ source/pages/events/structure.html.tpl | 0 source/pages/login/logic.ts | 106 ++++ source/pages/login/structure.html.tpl | 0 source/pages/logout/logic.ts | 22 + source/pages/oidc_finish/logic.ts | 20 + tools/makefile | 6 + tools/update-plankton | 1 + 19 files changed, 1112 insertions(+), 1074 deletions(-) create mode 100644 source/pages/calendar_add/logic.ts create mode 100644 source/pages/calendar_add/structure.html.tpl create mode 100644 source/pages/event_add/logic.ts create mode 100644 source/pages/event_add/structure.html.tpl create mode 100644 source/pages/events/logic.ts create mode 100644 source/pages/events/structure.html.tpl create mode 100644 source/pages/login/logic.ts create mode 100644 source/pages/login/structure.html.tpl create mode 100644 source/pages/logout/logic.ts create mode 100644 source/pages/oidc_finish/logic.ts diff --git a/lib/plankton/plankton.d.ts b/lib/plankton/plankton.d.ts index 99d85a1..805e1c7 100644 --- a/lib/plankton/plankton.d.ts +++ b/lib/plankton/plankton.d.ts @@ -6,29 +6,6 @@ type int = number; * @author fenris */ type float = number; -/** - * @author fenris - */ -type type_date = { - year: int; - month: int; - day: int; -}; -/** - * @author fenris - */ -type type_time = { - hour: int; - minute: int; - second: int; -}; -/** - * @author fenris - */ -type type_datetimeobject = { - date: type_date; - time: type_time; -}; declare class Buffer { constructor(x: string, modifier?: string); toString(modifier?: string): string; @@ -3141,6 +3118,94 @@ declare namespace lib_plankton.zoo_page { export function start(): void; export {}; } +declare namespace lib_plankton.pit { + /** + */ + type type_date = { + year: int; + month: int; + day: int; + }; + /** + */ + type type_ywd = { + year: int; + week: int; + day: int; + }; + /** + */ + type type_time = { + hour: int; + minute: int; + second: int; + }; + /** + */ + type type_datetime = { + timezone_shift: int; + date: type_date; + time: (null | type_time); + }; + /** + */ + type type_pit = int; +} +declare namespace lib_plankton.pit { + /** + */ + function date_object_get_week_of_year(date: Date): int; + /** + */ + function to_unix_timestamp(pit: type_pit): int; + /** + */ + function from_unix_timestamp(unix_timestamp: int): type_pit; + /** + */ + function to_date_object(pit: type_pit): Date; + /** + * @todo timezone + */ + function to_datetime(pit: type_pit, options?: { + timezone_shift?: int; + }): type_datetime; + /** + */ + function from_datetime(datetime: type_datetime): type_pit; + /** + */ + function is_before(pit: type_pit, reference: type_pit): boolean; + /** + */ + function is_between(pit: type_pit, reference_left: type_pit, reference_right: type_pit): boolean; + /** + */ + function shift_day(pit: type_pit, increment: int): type_pit; + /** + */ + function shift_week(pit: type_pit, increment: int): type_pit; + /** + */ + function trunc_week(pit: type_pit): type_pit; + /** + */ + function now(): type_pit; + /** + * @param year year according to specified timezone shift + * @param week week according to specified timezone shift + * @return the begin of the week (monday, 00:00) + */ + function from_ywd(ywd: type_ywd, options?: { + timezone_shift?: int; + }): type_pit; + /** + * @todo timezone + */ + function to_ywd(pit: type_pit, options?: { + timezone_shift?: int; + }): type_ywd; +} declare namespace lib_plankton.zoo_input { /** * @author fenris @@ -3343,7 +3408,7 @@ declare namespace lib_plankton.zoo_input { /** * @author fenris */ - class class_input_date implements interface_input<(null | type_date)> { + class class_input_date implements interface_input<(null | lib_plankton.pit.type_date)> { /** */ private required; @@ -3362,11 +3427,11 @@ declare namespace lib_plankton.zoo_input { /** * [implementation] */ - read(): Promise<(null | type_date)>; + read(): Promise<(null | lib_plankton.pit.type_date)>; /** * [implementation] */ - write(value: (null | type_date)): Promise; + write(value: (null | lib_plankton.pit.type_date)): Promise; } } declare namespace lib_plankton.zoo_input { @@ -3607,7 +3672,7 @@ declare namespace lib_plankton.zoo_input { /** * @author fenris */ - class class_input_time implements interface_input<(null | type_time)> { + class class_input_time implements interface_input<(null | lib_plankton.pit.type_time)> { /** */ private dom_input; @@ -3621,11 +3686,11 @@ declare namespace lib_plankton.zoo_input { /** * [implementation] */ - read(): Promise<(null | type_time)>; + read(): Promise<(null | lib_plankton.pit.type_time)>; /** * [implementation] */ - write(value: (null | type_time)): Promise; + write(value: (null | lib_plankton.pit.type_time)): Promise; } } declare namespace lib_plankton.zoo_input { @@ -3658,6 +3723,31 @@ declare namespace lib_plankton.zoo_input { write(value: type_record): Promise; } } +declare namespace lib_plankton.zoo_input { + /** + */ + class class_input_datetime implements interface_input { + /** + */ + private core; + /** + */ + constructor(options?: { + label_timezone_shift?: string; + label_date?: string; + label_time?: string; + }); + /** + */ + setup(parent: HTMLElement): Promise; + /** + */ + read(): Promise; + /** + */ + write(value: lib_plankton.pit.type_datetime): Promise; + } +} declare namespace lib_plankton.zoo_form { /** */ diff --git a/lib/plankton/plankton.js b/lib/plankton/plankton.js index e7d913f..be209ef 100644 --- a/lib/plankton/plankton.js +++ b/lib/plankton/plankton.js @@ -8931,6 +8931,353 @@ var lib_plankton; })(zoo_page = lib_plankton.zoo_page || (lib_plankton.zoo_page = {})); })(lib_plankton || (lib_plankton = {})); /* +This file is part of »bacterio-plankton:pit«. + +Copyright 2016-2024 'Christian Fraß, Christian Neubauer, Martin Springwald GbR' + + +»bacterio-plankton:pit« 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:pit« 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:pit«. If not, see . + */ +/* +This file is part of »bacterio-plankton:pit«. + +Copyright 2016-2024 'Christian Fraß, Christian Neubauer, Martin Springwald GbR' + + +»bacterio-plankton:pit« 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:pit« 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:pit«. If not, see . + */ +var lib_plankton; +(function (lib_plankton) { + var pit; + (function (pit_1) { + /** + */ + function date_object_get_week_of_year(date) { + let date_ = new Date(date.getTime()); + date_.setHours(0, 0, 0, 0); + // Thursday in current week decides the year. + date_.setDate(date_.getDate() + 3 - (date_.getDay() + 6) % 7); + // January 4 is always in week 1. + let week1 = new Date(date_.getFullYear(), 0, 4); + // Adjust to Thursday in week 1 and count number of weeks from date to week1. + return (1 + + + Math.round((((date_.getTime() - week1.getTime()) / 86400000) + - + 3 + + + (week1.getDay() + 6) % 7) + / + 7)); + } + pit_1.date_object_get_week_of_year = date_object_get_week_of_year; + /** + */ + function to_unix_timestamp(pit) { + return pit; + } + pit_1.to_unix_timestamp = to_unix_timestamp; + /** + */ + function from_unix_timestamp(unix_timestamp) { + return unix_timestamp; + } + pit_1.from_unix_timestamp = from_unix_timestamp; + /** + */ + function to_date_object(pit) { + return (new Date(pit * 1000)); + } + pit_1.to_date_object = to_date_object; + /** + */ + function from_date_object(date_object) { + return Math.round(date_object.getTime() / 1000); + } + /** + * @todo timezone + */ + function to_datetime(pit, options = {}) { + options = Object.assign({ + "timezone_shift": 0, + }, options); + return lib_plankton.call.convey(pit, [ + to_date_object, + (x) => x.getTime(), + (x) => (x + ((options.timezone_shift * (60 * 60)) * 1000)), + (x) => new Date(x), + x => x.toISOString(), + x => ({ + "timezone_shift": options.timezone_shift, + "date": { + "year": parseInt(x.slice(0, 4)), + "month": parseInt(x.slice(5, 7)), + "day": parseInt(x.slice(8, 10)), + }, + "time": { + "hour": parseInt(x.slice(11, 13)), + "minute": parseInt(x.slice(14, 16)), + "second": parseInt(x.slice(17, 19)), + }, + }) + ]); + } + pit_1.to_datetime = to_datetime; + /** + */ + function from_datetime(datetime) { + return lib_plankton.call.convey(datetime, [ + (x) => lib_plankton.string.coin("{{year}}-{{month}}-{{day}}T{{hour}}:{{minute}}:{{second}}.000+{{shift}}", { + "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"), + "hour": ((x.time !== null) ? x.time.hour : 0).toFixed(0).padStart(2, "0"), + "minute": ((x.time !== null) ? x.time.minute : 0).toFixed(0).padStart(2, "0"), + "second": ((x.time !== null) ? x.time.second : 0).toFixed(0).padStart(2, "0"), + "shift": (x.timezone_shift.toFixed(0).padStart(2, "0") + ":00"), + }), + x => (new Date(x)), + from_date_object, + ]); + } + pit_1.from_datetime = from_datetime; + /** + */ + function is_before(pit, reference) { + return (pit < reference); + } + pit_1.is_before = is_before; + /** + */ + function is_after(pit, reference) { + return (pit > reference); + } + /** + */ + function is_between(pit, reference_left, reference_right) { + return (is_after(pit, reference_left) + && + is_before(pit, reference_right)); + } + pit_1.is_between = is_between; + /** + */ + function shift_hour(pit, increment) { + return (pit + (60 * 60 * increment)); + } + /** + */ + function shift_day(pit, increment) { + return (pit + (60 * 60 * 24 * increment)); + } + pit_1.shift_day = shift_day; + /** + */ + function shift_week(pit, increment) { + return (pit + (60 * 60 * 24 * 7 * increment)); + } + pit_1.shift_week = shift_week; + /** + */ + function shift_year(pit, increment) { + return (pit + (60 * 60 * 24 * 365 * increment)); + } + /** + */ + function trunc_minute(pit) { + const datetime_input = to_datetime(pit); + const datetime_output = { + "timezone_shift": 0, + "date": { + "year": datetime_input.date.year, + "month": datetime_input.date.month, + "day": datetime_input.date.day, + }, + "time": { + "hour": ((datetime_input.time === null) + ? + 0 + : + datetime_input.time.hour), + "minute": ((datetime_input.time === null) + ? + 0 + : + datetime_input.time.minute), + "second": 0, + }, + }; + return from_datetime(datetime_output); + } + /** + */ + function trunc_hour(pit) { + const datetime_input = to_datetime(pit); + const datetime_output = { + "timezone_shift": 0, + "date": { + "year": datetime_input.date.year, + "month": datetime_input.date.month, + "day": datetime_input.date.day, + }, + "time": { + "hour": ((datetime_input.time === null) + ? + 0 + : + datetime_input.time.hour), + "minute": 0, + "second": 0, + }, + }; + return from_datetime(datetime_output); + } + /** + */ + function trunc_day(pit) { + const datetime_input = to_datetime(pit); + const datetime_output = { + "timezone_shift": 0, + "date": { + "year": datetime_input.date.year, + "month": datetime_input.date.month, + "day": datetime_input.date.day, + }, + "time": { + "hour": 0, + "minute": 0, + "second": 0, + }, + }; + return from_datetime(datetime_output); + } + /** + */ + function trunc_week(pit) { + const date_object = to_date_object(pit); + return lib_plankton.call.convey(date_object.getDay(), [ + (x) => ((x === 0) ? 7 : x), + (x) => (x - 1), + (x) => shift_day(pit, (-x)), + trunc_day + ]); + } + pit_1.trunc_week = trunc_week; + /** + */ + function trunc_month(pit) { + const datetime_input = to_datetime(pit); + const datetime_output = { + "timezone_shift": 0, + "date": { + "year": datetime_input.date.year, + "month": datetime_input.date.month, + "day": 1, + }, + "time": { + "hour": 0, + "minute": 0, + "second": 0, + }, + }; + return from_datetime(datetime_output); + } + /** + */ + function trunc_year(pit) { + const datetime_input = to_datetime(pit); + const datetime_output = { + "timezone_shift": 0, + "date": { + "year": datetime_input.date.year, + "month": 1, + "day": 1, + }, + "time": { + "hour": 0, + "minute": 0, + "second": 0, + }, + }; + return from_datetime(datetime_output); + } + /** + */ + function now() { + return from_date_object(new Date(Date.now())); + } + pit_1.now = now; + /** + * @param year year according to specified timezone shift + * @param week week according to specified timezone shift + * @return the begin of the week (monday, 00:00) + */ + function from_ywd(ywd, options = {}) { + options = Object.assign({ + "timezone_shift": 0, + }, options); + return lib_plankton.call.convey({ + "timezone_shift": options.timezone_shift, + "date": { + "year": ywd.year, + "month": 1, + "day": 1, + }, + "time": { + "hour": 0, + "minute": 0, + "second": 0 + } + }, [ + from_datetime, + (x) => shift_week(x, (ywd.week - 1)), + trunc_week, + (x) => shift_day(x, (ywd.day - 1)), + ]); + } + pit_1.from_ywd = from_ywd; + /** + * @todo timezone + */ + function to_ywd(pit, options = {}) { + options = Object.assign({ + "timezone_shift": 0, + }, options); + return lib_plankton.call.convey(pit, [ + to_date_object, + x => ({ + "year": x.getFullYear(), + "week": date_object_get_week_of_year(x), + "day": ((day => (day <= 0) ? 7 : day)(x.getDay())), + }) + ]); + } + pit_1.to_ywd = to_ywd; + })(pit = lib_plankton.pit || (lib_plankton.pit = {})); +})(lib_plankton || (lib_plankton = {})); +/* This file is part of »bacterio-plankton:zoo-input«. Copyright 2016-2024 'Christian Fraß, Christian Neubauer, Martin Springwald GbR' @@ -10252,6 +10599,77 @@ var lib_plankton; })(zoo_input = lib_plankton.zoo_input || (lib_plankton.zoo_input = {})); })(lib_plankton || (lib_plankton = {})); /* +This file is part of »bacterio-plankton:zoo-input«. + +Copyright 2016-2024 'Christian Fraß, Christian Neubauer, Martin Springwald GbR' + + +»bacterio-plankton:zoo-input« 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-input« 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-input«. If not, see . + */ +var lib_plankton; +(function (lib_plankton) { + var zoo_input; + (function (zoo_input) { + /** + */ + class class_input_datetime { + /** + */ + constructor(options = {}) { + options = Object.assign({ + "label_timezone_shift": "", + "label_date": "", + "label_time": "", + }, options); + this.core = new zoo_input.class_input_group([ + { + "name": "timezone_shift", + "input": new zoo_input.class_input_number(), + "label": options.label_timezone_shift, + }, + { + "name": "date", + "input": new zoo_input.class_input_date(), + "label": options.label_date, + }, + { + "name": "time", + "input": new zoo_input.class_input_soft(new zoo_input.class_input_time()), + "label": options.label_time, + }, + ]); + } + /** + */ + async setup(parent) { + return this.core.setup(parent); + } + /** + */ + async read() { + return this.core.read(); + } + /** + */ + async write(value) { + return this.core.write(value); + } + } + zoo_input.class_input_datetime = class_input_datetime; + })(zoo_input = lib_plankton.zoo_input || (lib_plankton.zoo_input = {})); +})(lib_plankton || (lib_plankton = {})); +/* This file is part of »bacterio-plankton:zoo-form«. Copyright 2016-2024 'Christian Fraß, Christian Neubauer, Martin Springwald GbR' diff --git a/source/logic/backend.ts b/source/logic/backend.ts index d275432..6ae5b70 100644 --- a/source/logic/backend.ts +++ b/source/logic/backend.ts @@ -327,8 +327,8 @@ namespace _zeitbild.frontend_web.backend * @todo prevent loops */ export async function events( - from_pit : _zeitbild.frontend_web.helpers.type_pit, - to_pit : _zeitbild.frontend_web.helpers.type_pit, + from_pit : lib_plankton.pit.type_pit, + to_pit : lib_plankton.pit.type_pit, options : { calendar_ids ?: (null | Array<_zeitbild.frontend_web.type.calendar_id>); } = {} diff --git a/source/logic/helpers.ts b/source/logic/helpers.ts index 15d5c4c..36856b8 100644 --- a/source/logic/helpers.ts +++ b/source/logic/helpers.ts @@ -65,472 +65,5 @@ namespace _zeitbild.frontend_web.helpers } return Promise.resolve>(results); } - - - /** - */ - export function date_object_get_week_of_year( - date : Date - ) : int - { - let date_ : Date = new Date(date.getTime()); - date_.setHours(0, 0, 0, 0); - // Thursday in current week decides the year. - date_.setDate(date_.getDate() + 3 - (date_.getDay() + 6) % 7); - // January 4 is always in week 1. - let week1 : Date = new Date(date_.getFullYear(), 0, 4); - // Adjust to Thursday in week 1 and count number of weeks from date to week1. - return ( - 1 - + - Math.round( - ( - ((date_.getTime() - week1.getTime()) / 86400000) - - - 3 - + - (week1.getDay() + 6) % 7 - ) - / - 7 - ) - ); - } - - - /** - * @todo unite with type_datetimeobject? - */ - export type type_datetime = { - timezone_shift : int; - date : type_date; - time : ( - null - | - type_time - ); - }; - - - /** - * @todo timezone_shift - */ - function datetime_from_date_object( - date : Date, - options : { - timezone_shift ?: int; - } = {} - ) : type_datetime - { - options = Object.assign( - { - "timezone_shift": 0, - }, - options - ); - const date_ : Date = lib_plankton.call.convey( - date, - [ - (x : Date) => x.getTime(), - (x : int) => (x + (((options.timezone_shift as int) * (60 * 60)) * 1000)), - (x : int) => new Date(x), - ] - ); - const iso_string : string = date_.toISOString(); - return { - "timezone_shift": (options.timezone_shift as int), - "date": { - "year": parseInt(iso_string.slice(0, 4)), - "month": parseInt(iso_string.slice(5, 7)), - "day": parseInt(iso_string.slice(8, 10)), - }, - "time": { - "hour": parseInt(iso_string.slice(11, 13)), - "minute": parseInt(iso_string.slice(14, 16)), - "second": parseInt(iso_string.slice(17, 19)), - }, - }; - } - - - - /** - * @todo negative shift? - */ - function datetime_to_date_object( - datetime : type_datetime - ) : Date - { - const iso_string : string = lib_plankton.string.coin( - "{{year}}-{{month}}-{{day}}T{{hour}}:{{minute}}:{{second}}.000+{{shift}}", - { - "year": datetime.date.year.toFixed(0).padStart(4, "0"), - "month": datetime.date.month.toFixed(0).padStart(2, "0"), - "day": datetime.date.day.toFixed(0).padStart(2, "0"), - "hour": ((datetime.time !== null) ? datetime.time.hour : 0).toFixed(0).padStart(2, "0"), - "minute": ((datetime.time !== null) ? datetime.time.minute : 0).toFixed(0).padStart(2, "0"), - "second": ((datetime.time !== null) ? datetime.time.second : 0).toFixed(0).padStart(2, "0"), - "shift": (datetime.timezone_shift.toFixed(0).padStart(2, "0") + ":00"), - } - ); - return (new Date(iso_string)); - } - - - /** - */ - export type type_pit = int; - - - /** - */ - export function pit_to_date_object( - pit : type_pit - ) : Date - { - return (new Date(pit * 1000)); - } - - - /** - */ - function pit_from_date_object( - date_object : Date - ) : type_pit - { - return Math.round(date_object.getTime() / 1000); - } - - - /** - */ - export function pit_now( - ) : type_pit - { - return pit_from_date_object(new Date(Date.now())); - } - - - /** - * @todo timezone - */ - export function pit_to_datetime( - pit : type_pit, - options : { - timezone_shift ?: int - } = {} - ) : type_datetime - { - options = Object.assign( - { - "timezone_shift": 0, - }, - options - ); - const date_object : Date = pit_to_date_object(pit); - return datetime_from_date_object( - date_object, - { - "timezone_shift": (options.timezone_shift as int), - } - ); - } - - - /** - */ - export function pit_from_datetime( - datetime : type_datetime - ) : type_pit - { - return lib_plankton.call.convey( - datetime, - [ - datetime_to_date_object, - pit_from_date_object, - ] - ); - } - - - /** - */ - export function pit_is_before( - pit : type_pit, - reference : type_pit - ) : boolean - { - return (pit < reference); - } - - - /** - */ - function pit_is_after( - pit : type_pit, - reference : type_pit - ) : boolean - { - return (pit > reference); - } - - - /** - */ - export function pit_is_between( - pit : type_pit, - reference_left : type_pit, - reference_right : type_pit - ) : boolean - { - return ( - pit_is_after(pit, reference_left) - && - pit_is_before(pit, reference_right) - ); - } - - - /** - */ - function pit_shift_hour( - pit : type_pit, - increment : int - ) : type_pit - { - return (pit + (60 * 60 * increment)); - } - - - /** - */ - export function pit_shift_day( - pit : type_pit, - increment : int - ) : type_pit - { - return (pit + (60 * 60 * 24 * increment)); - } - - - /** - */ - export function pit_shift_week( - pit : type_pit, - increment : int - ) : type_pit - { - return (pit + (60 * 60 * 24 * 7 * increment)); - } - - - /** - */ - function pit_shift_year( - pit : type_pit, - increment : int - ) : type_pit - { - return (pit + (60 * 60 * 24 * 365 * increment)); - } - - - /** - */ - function pit_trunc_minute( - pit : type_pit - ) : type_pit - { - const datetime_input : type_datetime = pit_to_datetime(pit); - const datetime_output : type_datetime = { - "timezone_shift": 0, - "date": { - "year": datetime_input.date.year, - "month": datetime_input.date.month, - "day": datetime_input.date.day, - }, - "time": { - "hour": ( - (datetime_input.time === null) - ? - 0 - : - datetime_input.time.hour - ), - "minute": ( - (datetime_input.time === null) - ? - 0 - : - datetime_input.time.minute - ), - "second": 0, - }, - }; - return pit_from_datetime(datetime_output); - } - - - /** - */ - function pit_trunc_hour( - pit : type_pit - ) : type_pit - { - const datetime_input : type_datetime = pit_to_datetime(pit); - const datetime_output : type_datetime = { - "timezone_shift": 0, - "date": { - "year": datetime_input.date.year, - "month": datetime_input.date.month, - "day": datetime_input.date.day, - }, - "time": { - "hour": ( - (datetime_input.time === null) - ? - 0 - : - datetime_input.time.hour - ), - "minute": 0, - "second": 0, - }, - }; - return pit_from_datetime(datetime_output); - } - - - /** - */ - function pit_trunc_day( - pit : type_pit - ) : type_pit - { - const datetime_input : type_datetime = pit_to_datetime(pit); - const datetime_output : type_datetime = { - "timezone_shift": 0, - "date": { - "year": datetime_input.date.year, - "month": datetime_input.date.month, - "day": datetime_input.date.day, - }, - "time": { - "hour": 0, - "minute": 0, - "second": 0, - }, - }; - return pit_from_datetime(datetime_output); - } - - - /** - */ - export function pit_trunc_week( - pit : type_pit - ) : type_pit - { - const date_object : Date = pit_to_date_object(pit); - return lib_plankton.call.convey( - date_object.getDay(), - [ - (x : int) => ((x === 0) ? 7 : x), - (x : int) => (x - 1), - (x : int) => pit_shift_day(pit, (-x)), - pit_trunc_day - ] - ); - } - - - /** - */ - function pit_trunc_month( - pit : type_pit - ) : type_pit - { - const datetime_input : type_datetime = pit_to_datetime(pit); - const datetime_output : type_datetime = { - "timezone_shift": 0, - "date": { - "year": datetime_input.date.year, - "month": datetime_input.date.month, - "day": 1, - }, - "time": { - "hour": 0, - "minute": 0, - "second": 0, - }, - }; - return pit_from_datetime(datetime_output); - } - - - /** - */ - function pit_trunc_year( - pit : type_pit - ) : type_pit - { - const datetime_input : type_datetime = pit_to_datetime(pit); - const datetime_output : type_datetime = { - "timezone_shift": 0, - "date": { - "year": datetime_input.date.year, - "month": 1, - "day": 1, - }, - "time": { - "hour": 0, - "minute": 0, - "second": 0, - }, - }; - return pit_from_datetime(datetime_output); - } - - - /** - * @param year year according to specified timezone shift - * @param week week according to specified timezone shift - * @return the begin of the week (monday, 00:00) - */ - export function pit_from_year_and_week( - year : int, - week : int, - options : { - timezone_shift ?: int; - } = {} - ) : type_pit - { - options = Object.assign( - { - "timezone_shift": 0, - }, - options - ); - return lib_plankton.call.convey( - { - "timezone_shift": (options.timezone_shift as int), - "date": { - "year": year, - "month": 1, - "day": 1, - }, - "time": { - "hour": 0, - "minute": 0, - "second": 0 - } - }, - [ - pit_from_datetime, - (x : type_pit) => pit_shift_week(x, (week - 1)), - pit_trunc_week, - ] - ); - } } diff --git a/source/logic/main.ts b/source/logic/main.ts index f293354..ad822ea 100644 --- a/source/logic/main.ts +++ b/source/logic/main.ts @@ -1,78 +1,4 @@ -/** - */ -class class_input_datetime implements lib_plankton.zoo_input.interface_input<_zeitbild.frontend_web.helpers.type_datetime> -{ - - /** - */ - private core : lib_plankton.zoo_input.class_input_group<_zeitbild.frontend_web.helpers.type_datetime>; - - - /** - */ - public constructor( - prefix : string - ) - { - this.core = new lib_plankton.zoo_input.class_input_group<_zeitbild.frontend_web.helpers.type_datetime>( - [ - { - "name": "timezone_shift", - "input": new lib_plankton.zoo_input.class_input_number( - ), - "label": (prefix + lib_plankton.translate.get("common.timezone_shift")), - }, - { - "name": "date", - "input": new lib_plankton.zoo_input.class_input_date( - ), - "label": (prefix + lib_plankton.translate.get("common.date")), - }, - { - "name": "time", - "input": new lib_plankton.zoo_input.class_input_soft( - new lib_plankton.zoo_input.class_input_time( - ) - ), - "label": (prefix + lib_plankton.translate.get("common.time")), - }, - ] - ); - } - - - /** - */ - public async setup( - parent : HTMLElement - ) : Promise - { - return this.core.setup(parent); - } - - - /** - */ - public async read( - ) : Promise<_zeitbild.frontend_web.helpers.type_datetime> - { - return this.core.read(); - } - - - /** - */ - public async write( - value : _zeitbild.frontend_web.helpers.type_datetime - ) : Promise - { - return this.core.write(value); - } - -} - - /** */ namespace _zeitbild.frontend_web @@ -103,464 +29,6 @@ namespace _zeitbild.frontend_web lib_plankton.zoo_page.init( document.querySelector("main"), { - "pool": { - "login": async (parameters, target_element) => { - const preparation : {kind : string; data : any;} = await _zeitbild.frontend_web.backend.session_prepare( - ); - switch (preparation.kind) { - case "internal": { - target_element.innerHTML = await _zeitbild.frontend_web.helpers.template_coin( - "login", - { - } - ); - 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("page.login.internal.name"), - }, - { - "name": "password", - "input": new lib_plankton.zoo_input.class_input_password(), - "label": lib_plankton.translate.get("page.login.internal.password"), - }, - ] - ), - [ - { - "label": lib_plankton.translate.get("page.login.internal.do"), - "target": "submit", - "procedure": async (get_value, get_representation) => { - const value : any = await get_value(); - try { - await _zeitbild.frontend_web.backend.session_begin( - value.name, - value.password - ); - lib_plankton.zoo_page.set( - { - "name": "events", - "parameters": {} - } - ); - } - catch (error) { - lib_plankton.zoo_page.set( - { - "name": "login", - "parameters": { - "name": value.name, - } - } - ); - } - } - }, - ] - ); - await form.setup(document.querySelector("#login")); - await form.input_write( - { - "name": (parameters.name ?? ""), - "password": "", - } - ); - break; - } - case "oidc": { - let element_a : HTMLElement = document.createElement("a");; - element_a.textContent = lib_plankton.string.coin( - lib_plankton.translate.get("page.login.oidc.via"), - { - "title": preparation.data.label, - } - ); - element_a.setAttribute("href", preparation.data.url); - target_element.innerHTML = ""; - target_element.appendChild(element_a); - break; - } - default: { - break; - } - } - }, - "oidc_finish": async (parameters, target_element) => { - await _zeitbild.frontend_web.backend.set_session_key(parameters["session_key"]); - lib_plankton.zoo_page.set( - { - "name": "events", - "parameters": {} - } - ); - }, - "logout": async (parameters, target_element) => { - await _zeitbild.frontend_web.backend.session_end( - ); - lib_plankton.zoo_page.set( - { - "name": "login", - "parameters": { - } - } - ); - }, - "calendar_add": async (parameters, target_element) => { - target_element.innerHTML = await _zeitbild.frontend_web.helpers.template_coin( - "calendar_add", - { - "label": lib_plankton.translate.get("page.calendar_add.title") - } - ); - const form : lib_plankton.zoo_form.class_form< - _zeitbild.frontend_web.type.calendar_object, - { - name : string; - access_default_level : string; - resource_kind : string; - } - > = new lib_plankton.zoo_form.class_form< - _zeitbild.frontend_web.type.calendar_object, - { - name : string; - access_default_level : string; - resource_kind : string; - } - >( - (calendar_object) => ({ - "name": calendar_object.name, - "access_default_level": (() => { - switch (calendar_object.access.default_level) { - case _zeitbild.frontend_web.type.enum_access_level.none: return "none"; - case _zeitbild.frontend_web.type.enum_access_level.view: return "view"; - case _zeitbild.frontend_web.type.enum_access_level.edit: return "edit"; - case _zeitbild.frontend_web.type.enum_access_level.admin: return "admin"; - } - }) (), - "resource_kind": calendar_object.resource.kind, - }), - (raw) => ({ - "name": raw.name, - "access": { - "default_level": (() => { - switch (raw.access_default_level) { - case "none": return _zeitbild.frontend_web.type.enum_access_level.none; - case "view": return _zeitbild.frontend_web.type.enum_access_level.view; - case "edit": return _zeitbild.frontend_web.type.enum_access_level.edit; - case "admin": return _zeitbild.frontend_web.type.enum_access_level.admin; - } - }) (), - "attributed": lib_plankton.map.hashmap.implementation_map( - lib_plankton.map.hashmap.make( - x => x.toFixed(0) - ) - ), - }, - "resource": (() => { - switch (raw.resource_kind) { - case "local": { - return { - "kind": "local", - "data": { - "events": [], - } - }; - break; - } - case "caldav": { - return { - "kind": "caldav", - "data": { - "url": "", // TODO - "read_only": true, // TODO - } - }; - break; - } - default: { - throw (new Error("invalid resource kind: " + raw.resource_kind)); - break; - } - } - }) (), - }), - new lib_plankton.zoo_input.class_input_group( - [ - { - "name": "name", - "input": new lib_plankton.zoo_input.class_input_text(), - "label": lib_plankton.translate.get("calendar.name") - }, - { - "name": "access_default_level", - "input": new lib_plankton.zoo_input.class_input_selection( - [ - { - "value": "none", - "label": lib_plankton.translate.get("access_level.none"), - }, - { - "value": "view", - "label": lib_plankton.translate.get("access_level.view") - }, - { - "value": "edit", - "label": lib_plankton.translate.get("access_level.edit") - }, - { - "value": "admin", - "label": lib_plankton.translate.get("access_level.admin") - }, - ] - ), - "label": lib_plankton.string.coin( - "{{default_level}}", - { - "head": lib_plankton.translate.get("calendar.access.access"), - "default_level": lib_plankton.translate.get("calendar.access.default_level"), - } - ) - }, - { - "name": "resource_kind", - "input": new lib_plankton.zoo_input.class_input_selection( - [ - { - "value": "local", - "label": lib_plankton.translate.get("resource.kinds.local.title") - }, - { - "value": "caldav", - "label": lib_plankton.translate.get("resource.kinds.caldav.title") - }, - ] - ), - "label": lib_plankton.translate.get("resource.kind") - }, - ] - ), - [ - { - "label": lib_plankton.translate.get("page.calendar_add.actions.do"), - "target": "submit", - "procedure": async (get_value, get_representation) => { - const value : any = await get_value(); - try { - await _zeitbild.frontend_web.backend.calendar_add( - value - ); - lib_plankton.zoo_page.set( - { - "name": "events", - "parameters": {} - } - ); - } - catch (error) { - // do nothing - /* - lib_plankton.zoo_page.set( - { - "name": "event_add", - "parameters": { - } - } - ); - */ - } - } - }, - ] - ); - await form.setup(document.querySelector("#calendar_add_form")); - }, - "event_add": async (parameters, target_element) => { - const calendar_id : int = parseInt(parameters["calendar_id"]); - target_element.innerHTML = await _zeitbild.frontend_web.helpers.template_coin( - "event_add", - { - "label": lib_plankton.translate.get("page.event_add.title") - } - ); - const form : lib_plankton.zoo_form.class_form< - { - calendar_id : _zeitbild.frontend_web.type.calendar_id; - event_object : _zeitbild.frontend_web.type.event_object; - }, - { - calendar_id : string; - name : string; - begin : _zeitbild.frontend_web.helpers.type_datetime; - end : (null | _zeitbild.frontend_web.helpers.type_datetime); - location : (null | string); - description : (null | string); - } - > = new lib_plankton.zoo_form.class_form< - { - calendar_id : _zeitbild.frontend_web.type.calendar_id; - event_object : _zeitbild.frontend_web.type.event_object; - }, - { - calendar_id : string; - name : string; - begin : _zeitbild.frontend_web.helpers.type_datetime; - end : (null | _zeitbild.frontend_web.helpers.type_datetime); - location : (null | string); - description : (null | string); - } - >( - (value) => ({ - "calendar_id": value.calendar_id.toFixed(0), - "name": value.event_object.name, - "begin": value.event_object.begin, - "end": value.event_object.end, - "location": value.event_object.location, - "description": value.event_object.description, - }), - (representation) => ({ - "calendar_id": parseInt(representation.calendar_id), - "event_object": { - "name": representation.name, - "begin": representation.begin, - "end": representation.end, - "location": representation.location, - "description": representation.description, - } - }), - new lib_plankton.zoo_input.class_input_group( - [ - { - "name": "calendar_id", - "input": new lib_plankton.zoo_input.class_input_selection( - (await _zeitbild.frontend_web.backend.calendar_list()) - .filter( - (entry) => (["edit","admin"].includes(entry.access_level)) - ) - .map( - (entry) => ({ - "value": entry.id.toFixed(0), - "label": entry.name, - }) - ) - ), - "label": lib_plankton.translate.get("calendar.calendar") - }, - { - "name": "name", - "input": new lib_plankton.zoo_input.class_input_text( - ), - "label": lib_plankton.translate.get("event.name") - }, - { - "name": "begin", - "input": new class_input_datetime( - "" - ), - "label": lib_plankton.translate.get("event.begin") - }, - { - "name": "end", - "input": new lib_plankton.zoo_input.class_input_soft<_zeitbild.frontend_web.helpers.type_datetime>( - new class_input_datetime( - "" - ) - ), - "label": lib_plankton.translate.get("event.end") - }, - { - "name": "location", - "input": new lib_plankton.zoo_input.class_input_soft( - new lib_plankton.zoo_input.class_input_text( - ) - ), - "label": lib_plankton.translate.get("event.location") - }, - { - "name": "description", - "input": new lib_plankton.zoo_input.class_input_soft( - new lib_plankton.zoo_input.class_input_text( - ) - ), - "label": lib_plankton.translate.get("event.description") - }, - ] - ), - [ - { - "label": lib_plankton.translate.get("page.event_add.actions.do"), - "target": "submit", - "procedure": async (get_value, get_representation) => { - const value : any = await get_value(); - try { - await _zeitbild.frontend_web.backend.calendar_event_add( - value.calendar_id, - value.event_object - ); - lib_plankton.zoo_page.set( - { - "name": "events", - "parameters": {} - } - ); - } - catch (error) { - // do nothing - /* - lib_plankton.zoo_page.set( - { - "name": "event_add", - "parameters": { - } - } - ); - */ - } - } - }, - ] - ); - /* - await form.write( - { - "calendar_id": parameters["calendar_id"], - } - ); - */ - await form.setup(document.querySelector("#event_add_form")); - }, - "events": async (parameters, target_element) => { - const content = await _zeitbild.frontend_web.view.calendar_view_table_html( - { - "calendar_ids": null, - // TODO - "from": { - "year": 2024, - "week": 37 - }, - // TODO - "to": { - "year": 2024, - "week": 43 - }, - "timezone_shift": /*conf.timezone_shift*/0, - } - ); - target_element.innerHTML = content; - }, - }, "fallback": { "name": "login", "parameters": {} diff --git a/source/logic/types.ts b/source/logic/types.ts index fcebbc4..cccdfae 100644 --- a/source/logic/types.ts +++ b/source/logic/types.ts @@ -35,11 +35,11 @@ namespace _zeitbild.frontend_web.type */ export type event_object = { name : string; - begin : _zeitbild.frontend_web.helpers.type_datetime; + begin : lib_plankton.pit.type_datetime; end : ( null | - _zeitbild.frontend_web.helpers.type_datetime + lib_plankton.pit.type_datetime ); location : ( null diff --git a/source/logic/view.ts b/source/logic/view.ts index 26f48fa..755e546 100644 --- a/source/logic/view.ts +++ b/source/logic/view.ts @@ -161,7 +161,7 @@ namespace _zeitbild.frontend_web.view week : int; data : Array< { - pit : _zeitbild.frontend_web.helpers.type_pit; + pit : lib_plankton.pit.type_pit; entries : Array< { calendar_id : _zeitbild.frontend_web.type.calendar_id; @@ -176,17 +176,23 @@ namespace _zeitbild.frontend_web.view } > { - const now_pit : _zeitbild.frontend_web.helpers.type_pit = _zeitbild.frontend_web.helpers.pit_now(); - const from_pit : _zeitbild.frontend_web.helpers.type_pit = _zeitbild.frontend_web.helpers.pit_from_year_and_week( - (from as {year : int; week : int}).year, - (from as {year : int; week : int}).week, + const now_pit : lib_plankton.pit.type_pit = lib_plankton.pit.now(); + const from_pit : lib_plankton.pit.type_pit = lib_plankton.pit.from_ywd( + { + "year": (from as {year : int; week : int}).year, + "week": (from as {year : int; week : int}).week, + "day": 1, + }, { "timezone_shift": (timezone_shift as int), } ); - const to_pit : _zeitbild.frontend_web.helpers.type_pit = _zeitbild.frontend_web.helpers.pit_from_year_and_week( - (to as {year : int; week : int}).year, - (to as {year : int; week : int}).week, + const to_pit : lib_plankton.pit.type_pit = lib_plankton.pit.from_ywd( + { + "year": (to as {year : int; week : int}).year, + "week": (to as {year : int; week : int}).week, + "day": 1, + }, { "timezone_shift": (timezone_shift as int), } @@ -218,7 +224,7 @@ namespace _zeitbild.frontend_web.view week : int; data : Array< { - pit : _zeitbild.frontend_web.helpers.type_pit; + pit : lib_plankton.pit.type_pit; entries : Array< { calendar_id : _zeitbild.frontend_web.type.calendar_id; @@ -255,7 +261,7 @@ namespace _zeitbild.frontend_web.view }; let row : Array< { - pit : _zeitbild.frontend_web.helpers.type_pit; + pit : lib_plankton.pit.type_pit; entries : Array< { calendar_id : _zeitbild.frontend_web.type.calendar_id; @@ -267,12 +273,12 @@ namespace _zeitbild.frontend_web.view > = []; let day : int = 0; while (true) { - const pit_current : _zeitbild.frontend_web.helpers.type_pit = _zeitbild.frontend_web.helpers.pit_shift_day( + const pit_current : lib_plankton.pit.type_pit = lib_plankton.pit.shift_day( from_pit, day ); if ( - _zeitbild.frontend_web.helpers.pit_is_before( + lib_plankton.pit.is_before( pit_current, to_pit ) @@ -317,7 +323,7 @@ namespace _zeitbild.frontend_web.view .forEach( (entry) => { const distance_seconds : int = ( - _zeitbild.frontend_web.helpers.pit_from_datetime(entry.event.begin) + lib_plankton.pit.from_datetime(entry.event.begin) - from_pit ); @@ -381,30 +387,24 @@ namespace _zeitbild.frontend_web.view } = {} ) : Promise { - const now_pit : _zeitbild.frontend_web.helpers.type_pit = _zeitbild.frontend_web.helpers.pit_now(); + const now_pit : lib_plankton.pit.type_pit = lib_plankton.pit.now(); options = Object.assign( { "calendar_ids": null, "from": lib_plankton.call.convey( now_pit, [ - (x : _zeitbild.frontend_web.helpers.type_pit) => _zeitbild.frontend_web.helpers.pit_shift_week(x, -1), - _zeitbild.frontend_web.helpers.pit_to_date_object, - (x : Date) => ({ - "year": x.getFullYear(), - "week": _zeitbild.frontend_web.helpers.date_object_get_week_of_year(x), - }) + (x : lib_plankton.pit.type_pit) => lib_plankton.pit.shift_week(x, -1), + lib_plankton.pit.to_ywd, + x => ({"year": x.year, "week": x.week}), ] ), "to": lib_plankton.call.convey( now_pit, [ - (x : _zeitbild.frontend_web.helpers.type_pit) => _zeitbild.frontend_web.helpers.pit_shift_week(x, +4), - _zeitbild.frontend_web.helpers.pit_to_date_object, - (x : Date) => ({ - "year": x.getFullYear(), - "week": _zeitbild.frontend_web.helpers.date_object_get_week_of_year(x), - }) + (x : lib_plankton.pit.type_pit) => lib_plankton.pit.shift_week(x, +4), + lib_plankton.pit.to_ywd, + x => ({"year": x.year, "week": x.week}), ] ), "timezone_shift": 0, @@ -423,7 +423,7 @@ namespace _zeitbild.frontend_web.view week : int; data : Array< { - pit : _zeitbild.frontend_web.helpers.type_pit; + pit : lib_plankton.pit.type_pit; entries : Array< { calendar_id : _zeitbild.frontend_web.type.calendar_id; @@ -515,8 +515,8 @@ namespace _zeitbild.frontend_web.view "title": lib_plankton.call.convey( cell.pit, [ - _zeitbild.frontend_web.helpers.pit_to_datetime, - (x : _zeitbild.frontend_web.helpers.type_datetime) => lib_plankton.string.coin( + lib_plankton.pit.to_datetime, + (x : lib_plankton.pit.type_datetime) => lib_plankton.string.coin( "{{year}}-{{month}}-{{day}}", { "year": x.date.year.toFixed(0).padStart(4, "0"), @@ -529,8 +529,8 @@ namespace _zeitbild.frontend_web.view "day": lib_plankton.call.convey( cell.pit, [ - _zeitbild.frontend_web.helpers.pit_to_datetime, - (x : _zeitbild.frontend_web.helpers.type_datetime) => lib_plankton.string.coin( + lib_plankton.pit.to_datetime, + (x : lib_plankton.pit.type_datetime) => lib_plankton.string.coin( "{{day}}", { "year": x.date.year.toFixed(0).padStart(4, "0"), @@ -584,8 +584,8 @@ namespace _zeitbild.frontend_web.view async function calendar_view_list_data( calendar_ids : Array<_zeitbild.frontend_web.type.calendar_id>, options : { - from ?: _zeitbild.frontend_web.helpers.type_pit; - to ?: _zeitbild.frontend_web.helpers.type_pit; + from ?: lib_plankton.pit.type_pit; + to ?: lib_plankton.pit.type_pit; timezone_shift ?: int; } = {} ) : Promise< @@ -597,19 +597,19 @@ namespace _zeitbild.frontend_web.view > > { - const now_pit : _zeitbild.frontend_web.helpers.type_pit = _zeitbild.frontend_web.helpers.pit_now(); + const now_pit : lib_plankton.pit.type_pit = lib_plankton.pit.now(); options = Object.assign( { "from": lib_plankton.call.convey( now_pit, [ - (x : _zeitbild.frontend_web.helpers.type_pit) => _zeitbild.frontend_web.helpers.pit_shift_day(x, -1), + (x : lib_plankton.pit.type_pit) => lib_plankton.pit.shift_day(x, -1), ] ), "to": lib_plankton.call.convey( now_pit, [ - (x : _zeitbild.frontend_web.helpers.type_pit) => _zeitbild.frontend_web.helpers.pit_shift_week(x, +4), + (x : lib_plankton.pit.type_pit) => lib_plankton.pit.shift_week(x, +4), ] ), "timezone_shift": 0, @@ -623,8 +623,8 @@ namespace _zeitbild.frontend_web.view event : _zeitbild.frontend_web.type.event_object; } > = await _zeitbild.frontend_web.backend.events( - (options.from as _zeitbild.frontend_web.helpers.type_pit), - (options.to as _zeitbild.frontend_web.helpers.type_pit), + (options.from as lib_plankton.pit.type_pit), + (options.to as lib_plankton.pit.type_pit), { "calendar_ids": calendar_ids, } @@ -632,9 +632,9 @@ namespace _zeitbild.frontend_web.view // TODO: optimize entries.sort( (entry_1, entry_2) => ( - _zeitbild.frontend_web.helpers.pit_from_datetime(entry_1.event.begin) + lib_plankton.pit.from_datetime(entry_1.event.begin) - - _zeitbild.frontend_web.helpers.pit_from_datetime(entry_2.event.begin) + lib_plankton.pit.from_datetime(entry_2.event.begin) ) ); @@ -647,8 +647,8 @@ namespace _zeitbild.frontend_web.view export async function calendar_view_list_html( calendar_ids : Array<_zeitbild.frontend_web.type.calendar_id>, options : { - from ?: _zeitbild.frontend_web.helpers.type_pit; - to ?: _zeitbild.frontend_web.helpers.type_pit; + from ?: lib_plankton.pit.type_pit; + to ?: lib_plankton.pit.type_pit; timezone_shift ?: int; } = {} ) : Promise diff --git a/source/pages/calendar_add/logic.ts b/source/pages/calendar_add/logic.ts new file mode 100644 index 0000000..7cbd980 --- /dev/null +++ b/source/pages/calendar_add/logic.ts @@ -0,0 +1,180 @@ +namespace _zeitbild.frontend_web.pages +{ + + /** + */ + lib_plankton.zoo_page.register( + "calendar_add", + async (parameters, target_element) => { + target_element.innerHTML = await _zeitbild.frontend_web.helpers.template_coin( + "calendar_add", + { + "label": lib_plankton.translate.get("page.calendar_add.title") + } + ); + const form : lib_plankton.zoo_form.class_form< + _zeitbild.frontend_web.type.calendar_object, + { + name : string; + access_default_level : string; + resource_kind : string; + } + > = new lib_plankton.zoo_form.class_form< + _zeitbild.frontend_web.type.calendar_object, + { + name : string; + access_default_level : string; + resource_kind : string; + } + >( + (calendar_object) => ({ + "name": calendar_object.name, + "access_default_level": (() => { + switch (calendar_object.access.default_level) { + case _zeitbild.frontend_web.type.enum_access_level.none: return "none"; + case _zeitbild.frontend_web.type.enum_access_level.view: return "view"; + case _zeitbild.frontend_web.type.enum_access_level.edit: return "edit"; + case _zeitbild.frontend_web.type.enum_access_level.admin: return "admin"; + } + }) (), + "resource_kind": calendar_object.resource.kind, + }), + (raw) => ({ + "name": raw.name, + "access": { + "default_level": (() => { + switch (raw.access_default_level) { + case "none": return _zeitbild.frontend_web.type.enum_access_level.none; + case "view": return _zeitbild.frontend_web.type.enum_access_level.view; + case "edit": return _zeitbild.frontend_web.type.enum_access_level.edit; + case "admin": return _zeitbild.frontend_web.type.enum_access_level.admin; + } + }) (), + "attributed": lib_plankton.map.hashmap.implementation_map( + lib_plankton.map.hashmap.make( + x => x.toFixed(0) + ) + ), + }, + "resource": (() => { + switch (raw.resource_kind) { + case "local": { + return { + "kind": "local", + "data": { + "events": [], + } + }; + break; + } + case "caldav": { + return { + "kind": "caldav", + "data": { + "url": "", // TODO + "read_only": true, // TODO + } + }; + break; + } + default: { + throw (new Error("invalid resource kind: " + raw.resource_kind)); + break; + } + } + }) (), + }), + new lib_plankton.zoo_input.class_input_group( + [ + { + "name": "name", + "input": new lib_plankton.zoo_input.class_input_text(), + "label": lib_plankton.translate.get("calendar.name") + }, + { + "name": "access_default_level", + "input": new lib_plankton.zoo_input.class_input_selection( + [ + { + "value": "none", + "label": lib_plankton.translate.get("access_level.none"), + }, + { + "value": "view", + "label": lib_plankton.translate.get("access_level.view") + }, + { + "value": "edit", + "label": lib_plankton.translate.get("access_level.edit") + }, + { + "value": "admin", + "label": lib_plankton.translate.get("access_level.admin") + }, + ] + ), + "label": lib_plankton.string.coin( + "{{default_level}}", + { + "head": lib_plankton.translate.get("calendar.access.access"), + "default_level": lib_plankton.translate.get("calendar.access.default_level"), + } + ) + }, + { + "name": "resource_kind", + "input": new lib_plankton.zoo_input.class_input_selection( + [ + { + "value": "local", + "label": lib_plankton.translate.get("resource.kinds.local.title") + }, + { + "value": "caldav", + "label": lib_plankton.translate.get("resource.kinds.caldav.title") + }, + ] + ), + "label": lib_plankton.translate.get("resource.kind") + }, + ] + ), + [ + { + "label": lib_plankton.translate.get("page.calendar_add.actions.do"), + "target": "submit", + "procedure": async (get_value, get_representation) => { + const value : any = await get_value(); + try { + await _zeitbild.frontend_web.backend.calendar_add( + value + ); + lib_plankton.zoo_page.set( + { + "name": "events", + "parameters": {} + } + ); + } + catch (error) { + // do nothing + /* + lib_plankton.zoo_page.set( + { + "name": "event_add", + "parameters": { + } + } + ); + */ + } + } + }, + ] + ); + await form.setup(document.querySelector("#calendar_add_form")); + return Promise.resolve(undefined); + } + ); + +} diff --git a/source/pages/calendar_add/structure.html.tpl b/source/pages/calendar_add/structure.html.tpl new file mode 100644 index 0000000..8b13789 --- /dev/null +++ b/source/pages/calendar_add/structure.html.tpl @@ -0,0 +1 @@ + diff --git a/source/pages/event_add/logic.ts b/source/pages/event_add/logic.ts new file mode 100644 index 0000000..f09961b --- /dev/null +++ b/source/pages/event_add/logic.ts @@ -0,0 +1,163 @@ +namespace _zeitbild.frontend_web.pages +{ + + /** + */ + lib_plankton.zoo_page.register( + "event_add", + async (parameters, target_element) => { + const calendar_id : int = parseInt(parameters["calendar_id"]); + target_element.innerHTML = await _zeitbild.frontend_web.helpers.template_coin( + "event_add", + { + "label": lib_plankton.translate.get("page.event_add.title") + } + ); + const form : lib_plankton.zoo_form.class_form< + { + calendar_id : _zeitbild.frontend_web.type.calendar_id; + event_object : _zeitbild.frontend_web.type.event_object; + }, + { + calendar_id : string; + name : string; + begin : lib_plankton.pit.type_datetime; + end : (null | lib_plankton.pit.type_datetime); + location : (null | string); + description : (null | string); + } + > = new lib_plankton.zoo_form.class_form< + { + calendar_id : _zeitbild.frontend_web.type.calendar_id; + event_object : _zeitbild.frontend_web.type.event_object; + }, + { + calendar_id : string; + name : string; + begin : lib_plankton.pit.type_datetime; + end : (null | lib_plankton.pit.type_datetime); + location : (null | string); + description : (null | string); + } + >( + (value) => ({ + "calendar_id": value.calendar_id.toFixed(0), + "name": value.event_object.name, + "begin": value.event_object.begin, + "end": value.event_object.end, + "location": value.event_object.location, + "description": value.event_object.description, + }), + (representation) => ({ + "calendar_id": parseInt(representation.calendar_id), + "event_object": { + "name": representation.name, + "begin": representation.begin, + "end": representation.end, + "location": representation.location, + "description": representation.description, + } + }), + new lib_plankton.zoo_input.class_input_group( + [ + { + "name": "calendar_id", + "input": new lib_plankton.zoo_input.class_input_selection( + (await _zeitbild.frontend_web.backend.calendar_list()) + .filter( + (entry) => (["edit","admin"].includes(entry.access_level)) + ) + .map( + (entry) => ({ + "value": entry.id.toFixed(0), + "label": entry.name, + }) + ) + ), + "label": lib_plankton.translate.get("calendar.calendar") + }, + { + "name": "name", + "input": new lib_plankton.zoo_input.class_input_text( + ), + "label": lib_plankton.translate.get("event.name") + }, + { + "name": "begin", + "input": new lib_plankton.zoo_input.class_input_datetime( + ), + "label": lib_plankton.translate.get("event.begin") + }, + { + "name": "end", + "input": new lib_plankton.zoo_input.class_input_soft( + new lib_plankton.zoo_input.class_input_datetime( + ) + ), + "label": lib_plankton.translate.get("event.end") + }, + { + "name": "location", + "input": new lib_plankton.zoo_input.class_input_soft( + new lib_plankton.zoo_input.class_input_text( + ) + ), + "label": lib_plankton.translate.get("event.location") + }, + { + "name": "description", + "input": new lib_plankton.zoo_input.class_input_soft( + new lib_plankton.zoo_input.class_input_text( + ) + ), + "label": lib_plankton.translate.get("event.description") + }, + ] + ), + [ + { + "label": lib_plankton.translate.get("page.event_add.actions.do"), + "target": "submit", + "procedure": async (get_value, get_representation) => { + const value : any = await get_value(); + try { + await _zeitbild.frontend_web.backend.calendar_event_add( + value.calendar_id, + value.event_object + ); + lib_plankton.zoo_page.set( + { + "name": "events", + "parameters": {} + } + ); + } + catch (error) { + // do nothing + /* + lib_plankton.zoo_page.set( + { + "name": "event_add", + "parameters": { + } + } + ); + */ + } + } + }, + ] + ); + /* + await form.write( + { + "calendar_id": parameters["calendar_id"], + } + ); + */ + await form.setup(document.querySelector("#event_add_form")); + return Promise.resolve(undefined); + } + ); + +} diff --git a/source/pages/event_add/structure.html.tpl b/source/pages/event_add/structure.html.tpl new file mode 100644 index 0000000..e69de29 diff --git a/source/pages/events/logic.ts b/source/pages/events/logic.ts new file mode 100644 index 0000000..7502912 --- /dev/null +++ b/source/pages/events/logic.ts @@ -0,0 +1,30 @@ +namespace _zeitbild.frontend_web.pages +{ + + /** + */ + lib_plankton.zoo_page.register( + "events", + async (parameters, target_element) => { + const content = await _zeitbild.frontend_web.view.calendar_view_table_html( + { + "calendar_ids": null, + // TODO + "from": { + "year": 2024, + "week": 37 + }, + // TODO + "to": { + "year": 2024, + "week": 43 + }, + "timezone_shift": /*conf.timezone_shift*/0, + } + ); + target_element.innerHTML = content; + return Promise.resolve(undefined); + }, + ); + +} diff --git a/source/pages/events/structure.html.tpl b/source/pages/events/structure.html.tpl new file mode 100644 index 0000000..e69de29 diff --git a/source/pages/login/logic.ts b/source/pages/login/logic.ts new file mode 100644 index 0000000..e1af974 --- /dev/null +++ b/source/pages/login/logic.ts @@ -0,0 +1,106 @@ +namespace _zeitbild.frontend_web.pages +{ + + /** + */ + lib_plankton.zoo_page.register( + "login", + async (parameters, target_element) => { + const preparation : {kind : string; data : any;} = await _zeitbild.frontend_web.backend.session_prepare( + ); + switch (preparation.kind) { + case "internal": { + target_element.innerHTML = await _zeitbild.frontend_web.helpers.template_coin( + "login", + { + } + ); + 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("page.login.internal.name"), + }, + { + "name": "password", + "input": new lib_plankton.zoo_input.class_input_password(), + "label": lib_plankton.translate.get("page.login.internal.password"), + }, + ] + ), + [ + { + "label": lib_plankton.translate.get("page.login.internal.do"), + "target": "submit", + "procedure": async (get_value, get_representation) => { + const value : any = await get_value(); + try { + await _zeitbild.frontend_web.backend.session_begin( + value.name, + value.password + ); + lib_plankton.zoo_page.set( + { + "name": "events", + "parameters": {} + } + ); + } + catch (error) { + lib_plankton.zoo_page.set( + { + "name": "login", + "parameters": { + "name": value.name, + } + } + ); + } + } + }, + ] + ); + await form.setup(document.querySelector("#login")); + await form.input_write( + { + "name": (parameters.name ?? ""), + "password": "", + } + ); + break; + } + case "oidc": { + let element_a : HTMLElement = document.createElement("a");; + element_a.textContent = lib_plankton.string.coin( + lib_plankton.translate.get("page.login.oidc.via"), + { + "title": preparation.data.label, + } + ); + element_a.setAttribute("href", preparation.data.url); + target_element.innerHTML = ""; + target_element.appendChild(element_a); + break; + } + default: { + break; + } + } + return Promise.resolve(undefined); + } + ); + +} + diff --git a/source/pages/login/structure.html.tpl b/source/pages/login/structure.html.tpl new file mode 100644 index 0000000..e69de29 diff --git a/source/pages/logout/logic.ts b/source/pages/logout/logic.ts new file mode 100644 index 0000000..bddb58f --- /dev/null +++ b/source/pages/logout/logic.ts @@ -0,0 +1,22 @@ +namespace _zeitbild.frontend_web.pages +{ + + /** + */ + lib_plankton.zoo_page.register( + "logout", + async (parameters, target_element) => { + await _zeitbild.frontend_web.backend.session_end( + ); + lib_plankton.zoo_page.set( + { + "name": "login", + "parameters": { + } + } + ); + return Promise.resolve(undefined); + } + ); + +} diff --git a/source/pages/oidc_finish/logic.ts b/source/pages/oidc_finish/logic.ts new file mode 100644 index 0000000..30615ca --- /dev/null +++ b/source/pages/oidc_finish/logic.ts @@ -0,0 +1,20 @@ +namespace _zeitbild.frontend_web.pages +{ + + /** + */ + lib_plankton.zoo_page.register( + "oidc_finish", + async (parameters, target_element) => { + await _zeitbild.frontend_web.backend.set_session_key(parameters["session_key"]); + lib_plankton.zoo_page.set( + { + "name": "events", + "parameters": {} + } + ); + return Promise.resolve(undefined); + } + ); + +} diff --git a/tools/makefile b/tools/makefile index 579ee80..b0255b1 100644 --- a/tools/makefile +++ b/tools/makefile @@ -52,6 +52,12 @@ ${dir_temp}/logic-unlinked.js: \ ${dir_source}/logic/types.ts \ ${dir_source}/logic/backend.ts \ ${dir_source}/logic/view.ts \ + ${dir_source}/pages/login/logic.ts \ + ${dir_source}/pages/logout/logic.ts \ + ${dir_source}/pages/oidc_finish/logic.ts \ + ${dir_source}/pages/calendar_add/logic.ts \ + ${dir_source}/pages/event_add/logic.ts \ + ${dir_source}/pages/events/logic.ts \ ${dir_source}/logic/main.ts @ ${cmd_log} "logic | compile …" @ ${cmd_mkdir} $(dir $@) diff --git a/tools/update-plankton b/tools/update-plankton index 0f2a6d6..c1c150b 100755 --- a/tools/update-plankton +++ b/tools/update-plankton @@ -19,6 +19,7 @@ modules="${modules} map" modules="${modules} http" modules="${modules} log" modules="${modules} url" +modules="${modules} pit" modules="${modules} www_form" modules="${modules} translate" modules="${modules} zoo-page"