From 1f91b8f9c8b1ddd188482aa2121b93c4a4f4b1b7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christian=20Fra=C3=9F?= Date: Wed, 2 Jul 2025 18:33:14 +0200 Subject: [PATCH] [task-193] --- source/data/localization/deu.loc.json | 103 ++++--- source/data/localization/eng.loc.json | 107 ++++--- source/logic/backend.ts | 68 +++++ source/logic/main.ts | 15 +- source/pages/invite_create/logic.ts | 263 +++++++++++++++++ .../{list => invite_create}/structure.html | 6 +- source/pages/invite_create/style.css | 31 ++ source/pages/invite_handle/logic.ts | 269 ++++++++++-------- source/pages/invite_handle/structure.html | 10 +- source/pages/invite_handle/style.css | 27 ++ source/pages/invite_list/logic.ts | 45 ++- source/pages/invite_list/structure.html | 6 +- source/pages/{list => invite_list}/style.css | 4 + source/pages/invite_view/logic.ts | 249 ++++++++++++++++ .../{create => invite_view}/structure.html | 6 +- .../pages/{register => invite_view}/style.css | 16 +- source/pages/login/logic.ts | 2 +- .../pages/{create => member_create}/logic.ts | 31 +- .../{view => member_create}/structure.html | 9 +- .../pages/{create => member_create}/style.css | 0 source/pages/{list => member_list}/logic.ts | 28 +- source/pages/member_list/structure.html | 22 ++ source/pages/member_list/style.css | 19 ++ .../{register => member_register}/logic.ts | 45 +-- .../structure.html | 18 +- source/pages/member_register/style.css | 27 ++ source/pages/{view => member_view}/logic.ts | 42 +-- source/pages/member_view/structure.html | 22 ++ source/pages/{view => member_view}/style.css | 8 +- source/style/style.css | 4 +- tools/makefile | 34 ++- 31 files changed, 1193 insertions(+), 343 deletions(-) create mode 100644 source/pages/invite_create/logic.ts rename source/pages/{list => invite_create}/structure.html (87%) create mode 100644 source/pages/invite_create/style.css create mode 100644 source/pages/invite_handle/style.css rename source/pages/{list => invite_list}/style.css (94%) create mode 100644 source/pages/invite_view/logic.ts rename source/pages/{create => invite_view}/structure.html (87%) rename source/pages/{register => invite_view}/style.css (62%) rename source/pages/{create => member_create}/logic.ts (75%) rename source/pages/{view => member_create}/structure.html (85%) rename source/pages/{create => member_create}/style.css (100%) rename source/pages/{list => member_list}/logic.ts (75%) create mode 100644 source/pages/member_list/structure.html create mode 100644 source/pages/member_list/style.css rename source/pages/{register => member_register}/logic.ts (71%) rename source/pages/{register => member_register}/structure.html (68%) create mode 100644 source/pages/member_register/style.css rename source/pages/{view => member_view}/logic.ts (76%) create mode 100644 source/pages/member_view/structure.html rename source/pages/{view => member_view}/style.css (83%) diff --git a/source/data/localization/deu.loc.json b/source/data/localization/deu.loc.json index 4e05eb9..2ea4083 100644 --- a/source/data/localization/deu.loc.json +++ b/source/data/localization/deu.loc.json @@ -4,52 +4,62 @@ }, "tree": { "common.not_used": "nicht verwendet", + "common.changeable": "änderbar", + "common.initial_value": "Vorausfüllung", + "common.timezone_shift": "Zeitzonen-Verschiebung", + "common.date": "Datum", + "common.time": "Uhzeit", + "domain.member.member": "Mitglied", + "domain.member.membership_number.label": "Mitgliedsnummer", + "domain.member.name_real_value.label": "Echter Name", + "domain.member.name_real_index.label": "Namens-Index", + "domain.member.groups.label": "Gruppen", + "domain.member.registered.label": "registriert", + "domain.member.enabled.label": "aktiviert", + "domain.member.email_address_private.label": "private E-Mail-Adresse", + "domain.member.email_address_veiled.label": "pseudonymisierte E-Mail-Adresse", + "domain.member.email_address_nominal.label": "namentliche E-Mail-Adresse", + "domain.member.email_redirect_to_private_address.label": "eingehende E-Mails zu privater Adresse umleiten", + "domain.member.email_allow_sending.label": "Versenden von E-Mails erlauben", + "domain.member.name_login.label": "Anmeldename", + "domain.member.password_set.label": "Passwort gesetzt", + "domain.invite.key.label": "Schlüssel", + "domain.invite.expiry.label": "Ablaufzeitpunkt", + "domain.invite.url.label": "URL", "page.login.title": "Anmelden", "page.login.name": "Name", "page.login.password": "Passwort", "page.login.submit": "Anmelden", - "page.create.title": "Mitglied anlegen", - "page.list.title": "Mitglieder-Liste", - "page.view.title": "Mitglied", - "page.view.form.field.membership_number.label": "Mitgliedsnummer", - "page.view.form.field.name_real_value.label": "Echter Name", - "page.view.form.field.name_real_index.label": "Namens-Index", - "page.view.form.field.groups.label": "Gruppen", - "page.view.form.field.registered.label": "registriert", - "page.view.form.field.enabled.label": "aktiviert", - "page.view.form.field.email_address_private.label": "private E-Mail-Adresse", - "page.view.form.field.email_address_veiled.label": "pseudonymisierte E-Mail-Adresse", - "page.view.form.field.email_address_nominal.label": "namentliche E-Mail-Adresse", - "page.view.form.field.email_redirect_to_private_address.label": "eingehende E-Mails zu privater Adresse umleiten", - "page.view.form.field.email_allow_sending.label": "Versenden von E-Mails erlauben", - "page.view.form.field.name_login.label": "Anmeldename", - "page.view.form.field.password_set.label": "Passwort gesetzt", - "page.view.form.action.save": "Änderungen speichern", - "page.view.form.action.summon": "Zur Registrierung auffordern", - "page.view.misc.summoned": "Benachrichtigung verschickt", - "page.view.misc.test_info": "Im Produktiv-Szenario würde an dieser Stelle eine E-Mail an die hinterlegte private E-Mail-Adresse des Mitglieds versendet werden mit einem Willkommens-Gruß und dem Aufruf folgenden Link zu öffnen:\n\n{{url}}", - "page.register.title": "Registrieren", - "page.register.form.field.email_address.label": "Partei-E-Mail-Adresse einrichten", - "page.register.form.field.email_address.help": "Für Partei-Angelegenheiten möchten wir dir anbieten gesonderte E-Mail-Adressen zu verwenden.\n\nDeine namentliche E-Mail-Adresse würde lauten »{{email_address_nominal}}« und die pseudonymisierte »{{email_address_veiled}}«\n\nDie Partei-E-Mail-Adressen können zum Empfangen von E-Mails verwendet werden. Falls es nötig werden sollte, dass du auch E-Mails mit über die Partei-Adresse verschicken kannst, wende dich bitte an den/die Mitgliederbeauftragte:n!", - "page.register.form.field.email_address.option.none": "keine", - "page.register.form.field.email_address.option.only_veiled": "nur pseudonymisiert", - "page.register.form.field.email_address.option.both": "pseudonymisiert und namentlich", - "page.register.form.field.email_redirect.label": "eingehende E-Mails an private Adresse leiten", - "page.register.form.field.email_redirect.help": "", - "page.register.form.field.password_value.label": "Passwort für Netz-Dienste", - "page.register.form.field.password_value.help": "das Passwort für die Anmeldung bei den Netz-Diensten.\n\nDu solltest dir merken oder geeignet abspeichern, was du hier einträgst.\n\nSolltest du dieses Passwort mal vergessen oder verlieren, hast du die Möglichkeit ein neues zu setzen.", - "page.register.form.field.password_confirmation.label": "Passwort wiederholen", - "page.register.form.field.password_confirmation.help": "", - "page.register.form.submit": "Abschicken", - "page.register.flaw.already_registered": "bereits registriert", - "page.register.flaw.password_mismatch": "die Passwörter stimmen nicht überein", - "page.register.flaw.password_too_short": "das Passwort muss mindestens {{minimum_length}} Zeichen haben", - "page.register.flaw.password_too_long": "das Passwort darf höchstens {{maximum_length}} Zeichen haben", - "page.register.flaw.password_lacks_letter": "das Passwort muss einen Buchstaben beinhalten", - "page.register.flaw.password_lacks_number": "das Passwort muss eine Zahl beinhalten", - "page.register.flaw.password_lacks_special_character": "das Passwort muss ein Sonderzeichen beinhalten", - "page.register.flaw.unhandled_error": "da ist etwas schief gelaufen :/", - "page.register.success": "Danke!", + "page.logout.title": "Abmelden", + "page.member_create.title": "Mitglied anlegen", + "page.member_list.title": "Mitglieder", + "page.member_view.title": "Mitglied", + "page.member_view.form.action.save": "Änderungen speichern", + "page.member_view.form.action.summon": "Zur Registrierung auffordern", + "page.member_view.misc.summoned": "Benachrichtigung verschickt", + "page.member_view.misc.test_info": "Im Produktiv-Szenario würde an dieser Stelle eine E-Mail an die hinterlegte private E-Mail-Adresse des Mitglieds versendet werden mit einem Willkommens-Gruß und dem Aufruf folgenden Link zu öffnen:\n\n{{url}}", + "page.member_register.title": "Registrieren", + "page.member_register.form.field.email_address.label": "Partei-E-Mail-Adresse einrichten", + "page.member_register.form.field.email_address.help": "Für Partei-Angelegenheiten möchten wir dir anbieten gesonderte E-Mail-Adressen zu verwenden.\n\nDeine namentliche E-Mail-Adresse würde lauten »{{email_address_nominal}}« und die pseudonymisierte »{{email_address_veiled}}«\n\nDie Partei-E-Mail-Adressen können zum Empfangen von E-Mails verwendet werden. Falls es nötig werden sollte, dass du auch E-Mails mit über die Partei-Adresse verschicken kannst, wende dich bitte an den/die Mitgliederbeauftragte:n!", + "page.member_register.form.field.email_address.option.none": "keine", + "page.member_register.form.field.email_address.option.only_veiled": "nur pseudonymisiert", + "page.member_register.form.field.email_address.option.both": "pseudonymisiert und namentlich", + "page.member_register.form.field.email_redirect.label": "eingehende E-Mails an private Adresse leiten", + "page.member_register.form.field.email_redirect.help": "", + "page.member_register.form.field.password_value.label": "Passwort für Netz-Dienste", + "page.member_register.form.field.password_value.help": "das Passwort für die Anmeldung bei den Netz-Diensten.\n\nDu solltest dir merken oder geeignet abspeichern, was du hier einträgst.\n\nSolltest du dieses Passwort mal vergessen oder verlieren, hast du die Möglichkeit ein neues zu setzen.", + "page.member_register.form.field.password_confirmation.label": "Passwort wiederholen", + "page.member_register.form.field.password_confirmation.help": "", + "page.member_register.form.submit": "Abschicken", + "page.member_register.flaw.already_registered": "bereits registriert", + "page.member_register.flaw.password_mismatch": "die Passwörter stimmen nicht überein", + "page.member_register.flaw.password_too_short": "das Passwort muss mindestens {{minimum_length}} Zeichen haben", + "page.member_register.flaw.password_too_long": "das Passwort darf höchstens {{maximum_length}} Zeichen haben", + "page.member_register.flaw.password_lacks_letter": "das Passwort muss einen Buchstaben beinhalten", + "page.member_register.flaw.password_lacks_number": "das Passwort muss eine Zahl beinhalten", + "page.member_register.flaw.password_lacks_special_character": "das Passwort muss ein Sonderzeichen beinhalten", + "page.member_register.flaw.unhandled_error": "da ist etwas schief gelaufen :/", + "page.member_register.success": "Danke!", "page.password_change_init.title": "Passwort ändern", "page.password_change_init.info": "Falls dein Mitglieds-Konto zugeordnet werden kann, wird eine E-Mail mit weiteren Anweisungen an deine private Adresse geschickt.", "page.password_change_init.identifier": "Anmelde-Name oder private E-Mail-Adresse", @@ -71,6 +81,13 @@ "page.password_change_exec.flaw.unhandled_error": "da ist etwas schief gelaufen :/", "page.password_change_exec.status.success": "erledigt", "page.invite_list.title": "Einladungen", - "page.invite_handle.title": "Einladung" + "page.invite_create.title": "Einladung anlegen", + "page.invite_create.form.field.send_immediatly.label": "Link sofort versenden", + "page.invite_create.form.action.submit": "anlegen", + "page.invite_view.title": "Einladung", + "page.invite_handle.title": "Einladung", + "page.invite_handle.message.invalid": "ungültig", + "page.invite_handle.message.successfull": "erfolgreich", + "page.invite_handle.form.action.submit": "annehmen" } } diff --git a/source/data/localization/eng.loc.json b/source/data/localization/eng.loc.json index 333b68c..33217f8 100644 --- a/source/data/localization/eng.loc.json +++ b/source/data/localization/eng.loc.json @@ -4,52 +4,62 @@ }, "tree": { "common.not_used": "not used", - "page.login.title": "Login", + "common.changeable": "changeable", + "common.initial_value": "initial value", + "common.timezone_shift": "timezone shift", + "common.date": "date", + "common.time": "time", + "domain.member.member": "member", + "domain.member.membership_number.label": "membership number", + "domain.member.name_real_value.label": "real name", + "domain.member.name_real_index.label": "name index", + "domain.member.groups.label": "groups", + "domain.member.registered.label": "registered", + "domain.member.enabled.label": "enabled", + "domain.member.email_address_private.label": "private e-mail address", + "domain.member.email_address_veiled.label": "veiled e-mail address", + "domain.member.email_address_nominal.label": "nominal e-mail address", + "domain.member.email_redirect_to_private_address.label": "redirect incoming e-mails to private address", + "domain.member.email_allow_sending.label": "allow sending e-mails", + "domain.member.name_login.label": "login name", + "domain.member.password_set.label": "password set", + "domain.invite.key.label": "key", + "domain.invite.expiry.label": "expiration", + "domain.invite.url.url": "URL", + "page.login.title": "login", "page.login.name": "name", "page.login.password": "password", "page.login.submit": "login", - "page.create.title": "Create member", - "page.list.title": "Member list", - "page.view.title": "Member", - "page.view.form.field.membership_number.label": "membership number", - "page.view.form.field.name_real_value.label": "real name", - "page.view.form.field.name_real_index.label": "name index", - "page.view.form.field.groups.label": "groups", - "page.view.form.field.registered.label": "registered", - "page.view.form.field.enabled.label": "enabled", - "page.view.form.field.email_address_private.label": "private e-mail address", - "page.view.form.field.email_address_veiled.label": "veiled e-mail address", - "page.view.form.field.email_address_nominal.label": "nominal e-mail address", - "page.view.form.field.email_redirect_to_private_address.label": "redirect incoming e-mails to private address", - "page.view.form.field.email_allow_sending.label": "allow sending e-mails", - "page.view.form.field.name_login.label": "login name", - "page.view.form.field.password_set.label": "password set", - "page.view.form.action.save": "save changes", - "page.view.form.action.summon": "urge for registration", - "page.view.misc.summoned": "notification sent", - "page.view.misc.test_info": "in a productive environment the system would now send an e-mail to the member's private address with a welcome note and a call to open the following link:\n\n{{url}}", - "page.register.title": "Register", - "page.register.form.field.email_address.label": "Set up party e-mail address", - "page.register.form.field.email_address.help": "We offer you to use a special e-mail address for any party concerns.\n\nYour namely e-mail address would be »{{email_address_nominal}}« and the veiled one »{{email_address_veiled}}«\n\nThe party e-mail address may be used for the reception of e-mails. In case it becomes necessary for you to submit e-mails via a party address, please get in contact with your membership authority!", - "page.register.form.field.email_address.option.none": "none", - "page.register.form.field.email_address.option.only_veiled": "only veiled", - "page.register.form.field.email_address.option.both": "both, veiled and namely", - "page.register.form.field.email_redirect.label": "redirect incoming e-mails to private address", - "page.register.form.field.email_redirect.help": "", - "page.register.form.field.password_value.label": "password for online services", - "page.register.form.field.password_value.help": "the password for logging in to the online services\n\nYou should remember, denote or save properly, what you enter here.\n\nIn case you forget or lose the password some day, you can reset it.", - "page.register.form.field.password_confirmation.label": "confirm password", - "page.register.form.field.password_confirmation.help": "", - "page.register.form.submit": "submit", - "page.register.flaw.already_registered": "already registered", - "page.register.flaw.password_mismatch": "passwords do not match", - "page.register.flaw.password_too_short": "the password must have at least {{minimum_length}} characters", - "page.register.flaw.password_too_long": "the password must not have more than {{maximum_length}} characters", - "page.register.flaw.password_lacks_letter": "the password must contain a letter", - "page.register.flaw.password_lacks_number": "the password must contain a number", - "page.register.flaw.password_lacks_special_character": "the password must contain a special character", - "page.register.flaw.unhandled_error": "something went wrong :/", - "page.register.success": "Thanks!", + "page.logout.title": "logout", + "page.member_create.title": "Create member", + "page.member_list.title": "Members", + "page.member_view.title": "Member", + "page.member_view.form.action.save": "save changes", + "page.member_view.form.action.summon": "urge for registration", + "page.member_view.misc.summoned": "notification sent", + "page.member_view.misc.test_info": "in a productive environment the system would now send an e-mail to the member's private address with a welcome note and a call to open the following link:\n\n{{url}}", + "page.member_register.title": "Register", + "page.member_register.form.field.email_address.label": "Set up party e-mail address", + "page.member_register.form.field.email_address.help": "We offer you to use a special e-mail address for any party concerns.\n\nYour namely e-mail address would be »{{email_address_nominal}}« and the veiled one »{{email_address_veiled}}«\n\nThe party e-mail address may be used for the reception of e-mails. In case it becomes necessary for you to submit e-mails via a party address, please get in contact with your membership authority!", + "page.member_register.form.field.email_address.option.none": "none", + "page.member_register.form.field.email_address.option.only_veiled": "only veiled", + "page.member_register.form.field.email_address.option.both": "both, veiled and namely", + "page.member_register.form.field.email_redirect.label": "redirect incoming e-mails to private address", + "page.member_register.form.field.email_redirect.help": "", + "page.member_register.form.field.password_value.label": "password for online services", + "page.member_register.form.field.password_value.help": "the password for logging in to the online services\n\nYou should remember, denote or save properly, what you enter here.\n\nIn case you forget or lose the password some day, you can reset it.", + "page.member_register.form.field.password_confirmation.label": "confirm password", + "page.member_register.form.field.password_confirmation.help": "", + "page.member_register.form.submit": "submit", + "page.member_register.flaw.already_registered": "already registered", + "page.member_register.flaw.password_mismatch": "passwords do not match", + "page.member_register.flaw.password_too_short": "the password must have at least {{minimum_length}} characters", + "page.member_register.flaw.password_too_long": "the password must not have more than {{maximum_length}} characters", + "page.member_register.flaw.password_lacks_letter": "the password must contain a letter", + "page.member_register.flaw.password_lacks_number": "the password must contain a number", + "page.member_register.flaw.password_lacks_special_character": "the password must contain a special character", + "page.member_register.flaw.unhandled_error": "something went wrong :/", + "page.member_register.success": "Thanks!", "page.password_change_init.title": "Change Password", "page.password_change_init.info": "In case your member account can be found, an e-mail with further instructions will be sent to your private e-mail address.", "page.password_change_init.identifier": "Login name or private e-mail address", @@ -70,7 +80,14 @@ "page.password_change_exec.flaw.password_lacks_special_character": "das Passwort muss ein Sonderzeichen beinhalten", "page.password_change_exec.flaw.unhandled_error": "da ist etwas schief gelaufen :/", "page.password_change_exec.status.success": "done", - "page.invite_list.title": "Invites", - "page.invite_handle.title": "Invite" + "page.invite_list.title": "invites", + "page.invite_create.title": "create invite", + "page.invite_create.form.field.send_immediatly.label": "send link immediatly", + "page.invite_create.form.action.submit": "create", + "page.invite_view.title": "invitation", + "page.invite_handle.title": "invitation", + "page.invite_handle.message.invalid": "invalid", + "page.invite_handle.message.successfull": "successful", + "page.invite_handle.form.action.submit": "accept" } } diff --git a/source/logic/backend.ts b/source/logic/backend.ts index e9ca607..3e0417c 100644 --- a/source/logic/backend.ts +++ b/source/logic/backend.ts @@ -511,6 +511,74 @@ namespace _espe.backend } + /** + */ + export async function invite_read( + id : int + ) : Promise< + { + key : string; + expiry : (null | int); + membership_number_changeable : boolean; + membership_number_value : (null | string); + name_changeable : boolean; + name_value : string; + email_address_changeable : boolean; + email_address_value : (null | string); + groups_changeable : boolean; + groups_value : Array; + } + > + { + return abstract_call( + "GET", + lib_plankton.string.coin( + "/invite/read?id={{id}}", + { + "id": id.toFixed(0), + } + ) + ); + } + + + /** + */ + export async function invite_create( + data : { + membership_number_changeable : boolean; + membership_number_value : (null | string); + name_changeable : boolean; + name_value : string; + email_address_changeable : boolean; + email_address_value : (null | string); + groups_changeable : boolean; + groups_value : Array; + expiry : (null | int); + }, + send_immediatly : boolean, + notification_target_url_template : (null | string) + ) : Promise< + { + id : int; + key : string; + } + > + { + return abstract_call( + "POST", + "/invite/create", + { + "data": { + "data": data, + "notification_target_url_template": notification_target_url_template, + "send_immediatly": send_immediatly, + } + } + ); + } + + /** */ export async function invite_examine( diff --git a/source/logic/main.ts b/source/logic/main.ts index b53ada6..94e0fee 100644 --- a/source/logic/main.ts +++ b/source/logic/main.ts @@ -56,27 +56,22 @@ function setup_nav( > = [ { "location": {"name": "login", "parameters": {}}, - "label": "Anmelden", + "label": lib_plankton.translate.get("page.login.title"), "classes": ["logged_out"], }, { - "location": {"name": "list", "parameters": {}}, - "label": "Liste", - "classes": ["logged_in"], - }, - { - "location": {"name": "create", "parameters": {}}, - "label": "Anlegen", + "location": {"name": "member_list", "parameters": {}}, + "label": lib_plankton.translate.get("page.member_list.title"), "classes": ["logged_in"], }, { "location": {"name": "invite_list", "parameters": {}}, - "label": "Einladungen", + "label": lib_plankton.translate.get("page.invite_list.title"), "classes": ["logged_in"], }, { "location": {"name": "logout", "parameters": {}}, - "label": "Abmelden", + "label": lib_plankton.translate.get("page.logout.title"), "classes": ["logged_in"], }, ]; diff --git a/source/pages/invite_create/logic.ts b/source/pages/invite_create/logic.ts new file mode 100644 index 0000000..c551656 --- /dev/null +++ b/source/pages/invite_create/logic.ts @@ -0,0 +1,263 @@ +/* +Espe | Ein schlichtes Werkzeug zur Mitglieder-Verwaltung | Frontend +Copyright (C) 2024 Christian Fraß + +This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public +License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later +version. + +This program 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 General Public License for more details. + +You should have received a copy of the GNU General Public License along with this program. If not, see +. + */ + +lib_plankton.zoo_page.register( + "invite_create", + async (parameters, target_element) => { + target_element.appendChild(template_request("invite_create")); + + target_element.querySelector(".invite_create-title").textContent = lib_plankton.translate.get("page.invite_create.title"); + + const indent = str => (/*"... " + */str); + + /** + * @todo outsource + */ + const null_when_empty = (str) => (((str === null) || (str === "")) ? null : str); + + const form = new lib_plankton.zoo_form.class_form< + { + data : { + membership_number_changeable : boolean; + membership_number_value : (null | string); + name_changeable : boolean; + name_value : string; + email_address_changeable : boolean; + email_address_value : (null | string); + groups_changeable : boolean; + groups_value : Array; + expiry : (null | int); + }; + send_immediatly : boolean; + }, + { + membership_number : { + changeable : boolean; + value : string; + }; + name : { + changeable : boolean; + value : string; + }; + email_address : { + changeable : boolean; + value : string; + }; + groups : { + changeable : boolean; + value : Array; + }; + expiry : (null | lib_plankton.pit.type_datetime); + send_immediatly : boolean; + } + >( + value => ({ + "membership_number": { + "changeable": value.data.membership_number_changeable, + "value": (value.data.membership_number_value ?? ""), + }, + "name": { + "changeable": value.data.name_changeable, + "value": value.data.name_value, + }, + "email_address": { + "changeable": value.data.email_address_changeable, + "value": (value.data.email_address_value ?? ""), + }, + "groups": { + "changeable": value.data.groups_changeable, + "value": value.data.groups_value, + }, + "expiry": ( + (value.data.expiry === null) + ? + null + : + lib_plankton.pit.to_datetime(lib_plankton.pit.from_unix_timestamp(value.data.expiry)) + ), + "send_immediatly": value.send_immediatly, + }), + representation => ({ + "data": { + "membership_number_changeable": representation.membership_number.changeable, + "membership_number_value": null_when_empty(representation.membership_number.value), + "name_changeable": representation.name.changeable, + "name_value": representation.name.value, + "email_address_changeable": representation.email_address.changeable, + "email_address_value": null_when_empty(representation.email_address.value), + "groups_changeable": representation.groups.changeable, + "groups_value": representation.groups.value, + "expiry": ( + (representation.expiry === null) + ? + null + : + lib_plankton.pit.to_unix_timestamp(lib_plankton.pit.from_datetime(representation.expiry)) + ), + }, + "send_immediatly": representation.send_immediatly, + }), + new lib_plankton.zoo_input.class_input_group( + [ + { + "name": "membership_number", + "input": new lib_plankton.zoo_input.class_input_group( + [ + { + "name": "value", + "input": new lib_plankton.zoo_input.class_input_text(), + "label": indent(lib_plankton.translate.get("common.initial_value")), + }, + { + "name": "changeable", + "input": new lib_plankton.zoo_input.class_input_checkbox(), + "label": indent(lib_plankton.translate.get("common.changeable")), + }, + ] + ), + "label": lib_plankton.translate.get("domain.member.membership_number.label"), + }, + { + "name": "groups", + "input": new lib_plankton.zoo_input.class_input_group( + [ + { + "name": "value", + "input": new lib_plankton.zoo_input.class_input_list( + () => new lib_plankton.zoo_input.class_input_text() + ), + "label": indent(lib_plankton.translate.get("common.initial_value")), + }, + { + "name": "changeable", + "input": new lib_plankton.zoo_input.class_input_checkbox(), + "label": indent(lib_plankton.translate.get("common.changeable")), + }, + ] + ), + "label": lib_plankton.translate.get("domain.member.groups.label"), + }, + { + "name": "name", + "input": new lib_plankton.zoo_input.class_input_group( + [ + { + "name": "value", + "input": new lib_plankton.zoo_input.class_input_text(), + "label": indent(lib_plankton.translate.get("common.initial_value")), + }, + { + "name": "changeable", + "input": new lib_plankton.zoo_input.class_input_checkbox(), + "label": indent(lib_plankton.translate.get("common.changeable")), + }, + ] + ), + "label": lib_plankton.translate.get("domain.member.name_real_value.label"), + }, + { + "name": "email_address", + "input": new lib_plankton.zoo_input.class_input_group( + [ + { + "name": "value", + "input": new lib_plankton.zoo_input.class_input_text(), + "label": indent(lib_plankton.translate.get("common.initial_value")), + }, + { + "name": "changeable", + "input": new lib_plankton.zoo_input.class_input_checkbox(), + "label": indent(lib_plankton.translate.get("common.changeable")), + }, + ] + ), + "label": lib_plankton.translate.get("domain.member.email_address_private.label"), + }, + { + "name": "expiry", + "input": new lib_plankton.zoo_input.class_input_soft( + new lib_plankton.zoo_input.class_input_datetime_central_europe( + { + // "label_timezone_shift": indent(lib_plankton.translate.get("common.timezone_shift")), + "label_date": indent(lib_plankton.translate.get("common.date")), + "label_time": indent(lib_plankton.translate.get("common.time")), + } + ) + ), + "label": lib_plankton.translate.get("domain.invite.expiry.label"), + }, + { + "name": "send_immediatly", + "input": new lib_plankton.zoo_input.class_input_checkbox(), + "label": indent(lib_plankton.translate.get("page.invite_create.form.field.send_immediatly.label")), + }, + ] + ), + [ + { + "label": lib_plankton.translate.get("page.invite_create.form.action.submit"), + "procedure": async (get_value, get_representation) => { + const value = await get_value(); + const result : {id : int; key : string;} = await _espe.backend.invite_create( + value.data, + value.send_immediatly, + lib_plankton.zoo_page.encode( + { + "name": "invite_handle", + "parameters": { + "key": "{{key}}", + } + } + ) + ); + lib_plankton.zoo_page.set( + true + ? + { + "name": "invite_view", + "parameters": {"id": result.id.toFixed(0)} + } + : + { + "name": "invite_list", + "parameters": {} + } + ); + }, + } + ] + ); + await form.setup(target_element.querySelector(".invite_create-form") as HTMLElement); + form.input_write( + { + "data": { + "membership_number_changeable": false, + "membership_number_value": null, + "name_changeable": false, + "name_value": "", + "email_address_changeable": true, + "email_address_value": null, + "groups_changeable": false, + "groups_value": [], + /** + * @todo conf + */ + "expiry": lib_plankton.pit.shift_week(lib_plankton.pit.now(), 2), + }, + "send_immediatly": true, + } + ); + } +); diff --git a/source/pages/list/structure.html b/source/pages/invite_create/structure.html similarity index 87% rename from source/pages/list/structure.html rename to source/pages/invite_create/structure.html index 674709e..8961bd7 100644 --- a/source/pages/list/structure.html +++ b/source/pages/invite_create/structure.html @@ -13,7 +13,7 @@ You should have received a copy of the GNU General Public License along with thi . --> -