[add] user_settings lesend angebunden und umgesetzt

This commit is contained in:
fenris 2026-03-27 11:23:41 +01:00
parent a5c09d11f0
commit 9fdafe3536
10 changed files with 466 additions and 73 deletions

View file

@ -1,11 +1,11 @@
/**
* @author fenris
*/
declare type int = number;
type int = number;
/**
* @author fenris
*/
declare type float = number;
type float = number;
declare class Buffer {
constructor(x: string, modifier?: string);
toString(modifier?: string): string;
@ -19,7 +19,7 @@ declare namespace lib_plankton.base {
/**
* @author fenris
*/
declare type type_pseudopointer<type_value> = {
type type_pseudopointer<type_value> = {
value: type_value;
};
/**
@ -1444,8 +1444,8 @@ declare namespace lib_plankton.list {
/**
* retrieves the element and its index of the list, which has the maximum value
*/
function max<type_element, type_value>(list: Array<type_element>, target_function: ((element: type_element) => type_value), options: {
compare_value: ((value1: type_value, value2: type_value) => boolean);
function max<type_element, type_value>(list: Array<type_element>, target_function: ((element: type_element) => type_value), { "compare_value": compare_value, }?: {
compare_value?: ((value1: type_value, value2: type_value) => boolean);
}): type_result_max<type_element, type_value>;
/**
* retrieves the element and its index of the list, which has the mininum value
@ -2002,7 +2002,7 @@ declare namespace lib_plankton.storage.memory {
clear(): Promise<void>;
write(key: any, value: any): Promise<boolean>;
delete(key: any): Promise<void>;
read(key: any): Promise<type_item>;
read(key: any): Promise<Awaited<type_item>>;
search(term: any): Promise<{
key: string;
preview: string;
@ -3793,6 +3793,9 @@ declare namespace lib_plankton.pit {
/**
*/
function to_date_object(pit: type_pit): Date;
/**
*/
function from_date_object(date_object: Date): type_pit;
/**
* @todo test
*/
@ -3814,6 +3817,12 @@ declare namespace lib_plankton.pit {
/**
*/
function is_between(pit: type_pit, reference_left: type_pit, reference_right: type_pit): boolean;
/**
*/
function shift_second(pit: type_pit, increment: int): type_pit;
/**
*/
function shift_minute(pit: type_pit, increment: int): type_pit;
/**
*/
function shift_hour(pit: type_pit, increment: int): type_pit;
@ -3895,14 +3904,15 @@ declare namespace lib_plankton.pit {
function timezone_shift_format(timezone_shift: int): string;
/**
*/
function date_format(date: type_date): string;
function date_format(date: type_date, { "short": short, }?: {
short?: boolean;
}): string;
/**
*/
function time_format(time: type_time, { "show_seconds": option_show_seconds, }?: {
show_seconds?: boolean;
}): string;
/**
* @todo show timezone
*/
function datetime_format(datetime: (null | type_datetime), { "timezone_indicator": option_timezone_indicator, "show_timezone": option_show_timezone, "adjust_to_ce": option_adjust_to_ce, "omit_date": option_omit_date, }?: {
timezone_indicator?: string;
@ -3912,11 +3922,15 @@ declare namespace lib_plankton.pit {
}): string;
/**
*/
function timespan_format(from: type_datetime, to: (null | type_datetime), { "timezone_indicator": option_timezone_indicator, "show_timezone": option_show_timezone, "adjust_to_ce": option_adjust_to_ce, "omit_date": option_omit_date, }?: {
function timespan_format(from: (null | type_datetime), to: (null | type_datetime), { "timezone_indicator": timezone_indicator, "show_timezone": show_timezone, "adjust_to_ce": adjust_to_ce, "omit_date": omit_date, "indicator_open_both": indicator_open_both, "indicator_open_right": indicator_open_right, "indicator_open_left": indicator_open_left, "indicator_closed": indicator_closed, }?: {
timezone_indicator?: string;
show_timezone?: boolean;
adjust_to_ce?: boolean;
omit_date?: boolean;
indicator_open_both?: string;
indicator_open_right?: string;
indicator_open_left?: string;
indicator_closed?: string;
}): string;
}
declare namespace lib_plankton.translate {
@ -4509,8 +4523,9 @@ declare namespace lib_plankton.zoo_input {
class class_input_text extends class_input_simple<string> implements interface_input<string> {
/**
*/
constructor({ "pattern": pattern, }?: {
constructor({ "pattern": pattern, "placeholder": placeholder, }?: {
pattern?: (null | string);
placeholder?: (null | string);
});
}
}
@ -5148,6 +5163,56 @@ declare namespace lib_plankton.zoo_input {
constructor();
}
}
declare namespace lib_plankton.zoo_input {
/**
* @author fenris
*/
class class_input_file implements interface_input<(null | string | ArrayBuffer)> {
/**
*/
private required;
/**
*/
private mime_type;
/**
*/
private capture;
/**
*/
private dom_input;
/**
*/
constructor({ "required": required, "mime_type": mime_type, "capture": capture, }?: {
required?: boolean;
mime_type?: (null | string);
capture?: boolean;
});
/**
* [implementation]
*/
setup(parent: HTMLElement): Promise<void>;
/**
* [implementation]
*/
read(): Promise<(null | string | ArrayBuffer)>;
/**
* [implementation]
*/
write(value: (null | string | ArrayBuffer)): Promise<void>;
/**
* [implementation]
*/
lock(mode: boolean): Promise<void>;
/**
* [implementation]
*/
hook_change(action: (() => void)): Promise<void>;
/**
* [implementation]
*/
focus(): void;
}
}
declare namespace lib_plankton.zoo_form {
/**
*/

View file

@ -2241,7 +2241,7 @@ var __generator = (this && this.__generator) || function (thisArg, body) {
function verb(n) { return function (v) { return step([n, v]); }; }
function step(op) {
if (f) throw new TypeError("Generator is already executing.");
while (_) try {
while (g && (g = 0, op[0] && (_ = 0)), _) try {
if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
if (y = 0, t) op = [op[0] & 2, t.value];
switch (op[0]) {
@ -3849,10 +3849,8 @@ var lib_plankton;
/**
* retrieves the element and its index of the list, which has the maximum value
*/
function max(list, target_function, options) {
options = Object.assign({
"compare_value": instance_compare
}, options);
function max(list, target_function, _a) {
var _b = _a === void 0 ? {} : _a, _c = _b["compare_value"], compare_value = _c === void 0 ? (function (x, y) { return (x <= y); }) : _c;
/*if (is_empty<type_element>(list)) {
throw (new Error("the max-arg of an empty list is not defined"));
}
@ -3862,7 +3860,7 @@ var lib_plankton;
var value = target_function(element);
if ((result == null)
||
(!options.compare_value(value, result.value))) {
(!compare_value(value, result.value))) {
return { "index": index, "element": element, "value": value };
}
else {
@ -9970,6 +9968,12 @@ var lib_plankton;
* @author fenris
*/
class class_relation {
/**
* @author fenris
*/
check(value, reference) {
return this.predicate(value, reference);
}
/**
* @author fenris
*/
@ -9979,12 +9983,6 @@ var lib_plankton;
this.name = name;
this.predicate = predicate;
}
/**
* @author fenris
*/
check(value, reference) {
return this.predicate(value, reference);
}
/**
* @author fenris
*/
@ -11390,6 +11388,7 @@ var lib_plankton;
function from_date_object(date_object) {
return Math.round(date_object.getTime() / 1000);
}
pit_1.from_date_object = from_date_object;
/**
* @todo test
*/
@ -11460,6 +11459,18 @@ var lib_plankton;
is_before(pit, reference_right));
}
pit_1.is_between = is_between;
/**
*/
function shift_second(pit, increment) {
return (pit + (increment));
}
pit_1.shift_second = shift_second;
/**
*/
function shift_minute(pit, increment) {
return (pit + (60 * increment));
}
pit_1.shift_minute = shift_minute;
/**
*/
function shift_hour(pit, increment) {
@ -11783,8 +11794,9 @@ var lib_plankton;
pit_1.timezone_shift_format = timezone_shift_format;
/**
*/
function date_format(date) {
return lib_plankton.string.coin("{{year}}-{{month}}-{{day}}", {
function date_format(date, { "short": short = false, } = {}) {
return lib_plankton.string.coin("{{year}}{{separator}}{{month}}{{separator}}{{day}}", {
"separator": (short ? "" : "-"),
"year": date.year.toFixed(0).padStart(4, "0"),
"month": date.month.toFixed(0).padStart(2, "0"),
"day": date.day.toFixed(0).padStart(2, "0"),
@ -11806,7 +11818,6 @@ var lib_plankton;
}
pit_1.time_format = time_format;
/**
* @todo show timezone
*/
function datetime_format(datetime, { "timezone_indicator": option_timezone_indicator = "", "show_timezone": option_show_timezone = false, "adjust_to_ce": option_adjust_to_ce = false, "omit_date": option_omit_date = false, } = {}) {
if (datetime === null) {
@ -11849,49 +11860,77 @@ var lib_plankton;
pit_1.datetime_format = datetime_format;
/**
*/
function timespan_format(from, to, { "timezone_indicator": option_timezone_indicator = "", "show_timezone": option_show_timezone = false, "adjust_to_ce": option_adjust_to_ce = false, "omit_date": option_omit_date = false, } = {}) {
const from_adjusted = (option_adjust_to_ce
function timespan_format(from, to, { "timezone_indicator": timezone_indicator = "", "show_timezone": show_timezone = false, "adjust_to_ce": adjust_to_ce = false, "omit_date": omit_date = false, "indicator_open_both": indicator_open_both = "?", "indicator_open_right": indicator_open_right = "> ", "indicator_open_left": indicator_open_left = "< ", "indicator_closed": indicator_closed = " — ", } = {}) {
const from_adjusted = ((from === null)
?
datetime_translate_ce(from)
null
:
from);
(adjust_to_ce
?
datetime_translate_ce(from)
:
from));
const to_adjusted = ((to === null)
?
null
:
(option_adjust_to_ce
(adjust_to_ce
?
datetime_translate_ce(to)
:
to));
return lib_plankton.string.coin("{{from}}{{to_macro}}{{macro_timezone}}", {
"from": datetime_format(from_adjusted, {
"show_timezone": false,
"adjust_to_ce": false,
"omit_date": option_omit_date,
}),
"to_macro": ((to_adjusted === null)
?
""
:
lib_plankton.string.coin(" - {{to}}", {
"to": datetime_format(to_adjusted, {
"omit_date": ((from_adjusted.date.year === to_adjusted.date.year)
&&
(from_adjusted.date.month === to_adjusted.date.month)
&&
(from_adjusted.date.day === to_adjusted.date.day))
}),
})),
"macro_timezone": (option_show_timezone
?
lib_plankton.string.coin(" [{{timezone_indicator}}{{timezone_value}}]", {
"timezone_indicator": option_timezone_indicator,
"timezone_value": timezone_shift_format(from_adjusted.timezone_shift),
})
:
""),
});
return (((to_adjusted === null)
&&
(from_adjusted === null))
?
indicator_open_both
:
lib_plankton.string.coin("{{prefix}}{{from_macro}}{{interfix}}{{to_macro}}{{macro_timezone}}", {
"prefix": ((to_adjusted === null)
?
indicator_open_right
:
""),
"from_macro": ((from_adjusted === null)
?
""
:
datetime_format(from_adjusted, {
"show_timezone": false,
"adjust_to_ce": false,
"omit_date": omit_date,
})),
"interfix": ((from_adjusted === null)
?
indicator_open_left
:
((to_adjusted === null)
?
""
:
indicator_closed)),
"to_macro": ((to_adjusted === null)
?
""
:
datetime_format(to_adjusted, {
"omit_date": ((from_adjusted !== null)
&&
((from_adjusted.date.year === to_adjusted.date.year)
&&
(from_adjusted.date.month === to_adjusted.date.month)
&&
(from_adjusted.date.day === to_adjusted.date.day)))
})),
"macro_timezone": (show_timezone
?
lib_plankton.string.coin(" [{{timezone_indicator}}{{timezone_value}}]", {
"timezone_indicator": timezone_indicator,
"timezone_value": timezone_shift_format(from_adjusted.timezone_shift),
})
:
""),
}));
}
pit_1.timespan_format = timespan_format;
})(pit = lib_plankton.pit || (lib_plankton.pit = {}));
@ -13625,12 +13664,13 @@ var lib_plankton;
class class_input_text extends zoo_input.class_input_simple {
/**
*/
constructor({ "pattern": pattern = null,
constructor({ "pattern": pattern = null, "placeholder": placeholder = null,
// "autocompletion_list": autocompletion_list = null,
} = {}) {
super("text", representation => representation, value => value, {
"additional_attributes": {
"pattern": pattern,
"placeholder": placeholder,
}
});
}
@ -15305,6 +15345,138 @@ 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-2025 'kcf' <fenris@folksprak.org>
»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 <http://www.gnu.org/licenses/>.
*/
var lib_plankton;
(function (lib_plankton) {
var zoo_input;
(function (zoo_input) {
/**
* @author fenris
*/
class class_input_file {
/**
*/
constructor({ "required": required = false, "mime_type": mime_type = null, "capture": capture = false, } = {}) {
this.required = required;
this.mime_type = mime_type;
this.capture = capture;
this.dom_input = null;
}
/**
* [implementation]
*/
setup(parent) {
this.dom_input = document.createElement("input");
this.dom_input.setAttribute("type", "file");
if (this.mime_type === null) {
// do nothing
}
else {
this.dom_input.setAttribute("accept", this.mime_type);
}
if (!this.capture) {
// do nothing
}
else {
this.dom_input.setAttribute("capture", "capture");
}
if (!this.required) {
// do nothing
}
else {
this.dom_input.setAttribute("required", "required");
}
parent.appendChild(this.dom_input);
return Promise.resolve(undefined);
}
/**
* [implementation]
*/
read() {
if (this.required && (!this.dom_input.reportValidity())) {
return Promise.reject("required");
}
else {
return (new Promise((resolve, reject) => {
if (this.dom_input.files.length <= 0) {
resolve(null);
}
else {
const file = this.dom_input.files[0];
const reader = new FileReader();
reader.onerror = () => {
reader.abort();
reject(new Error());
};
reader.onload = (event) => {
resolve(reader.result);
};
// reader.readAsDataURL(file);
reader.readAsArrayBuffer(file);
}
}));
}
}
/**
* [implementation]
*/
write(value) {
if (value === null) {
this.dom_input.value = null;
return Promise.resolve(undefined);
}
else {
return Promise.reject(new Error("not implemented (might even be impossible)"));
}
}
/**
* [implementation]
*/
lock(mode) {
if (mode) {
this.dom_input.setAttribute("disabled", "disabled");
}
else {
this.dom_input.removeAttribute("disabled");
}
return Promise.resolve(undefined);
}
/**
* [implementation]
*/
hook_change(action) {
this.dom_input.addEventListener("change", () => {
action();
});
return Promise.resolve(undefined);
}
/**
* [implementation]
*/
focus() {
this.dom_input.focus();
}
}
zoo_input.class_input_file = class_input_file;
})(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-2025 'kcf' <fenris@folksprak.org>

View file

@ -304,25 +304,110 @@ namespace _dali.helpers
/**
*/
export function datetime_input(
use_fallback : boolean
)
: lib_plankton.zoo_input.interface_input<lib_plankton.pit.type_datetime>
{
return (
_dali.conf.get().misc.use_central_europe_specific_datetime_inputs
use_fallback
?
new lib_plankton.zoo_input.class_input_datetime_central_europe(
new lib_plankton.zoo_input.class_input_wrapped<
{
"label_date": lib_plankton.translate.get("common.date"),
"label_time": lib_plankton.translate.get("common.time"),
date : string;
time : string;
},
lib_plankton.pit.type_datetime
>(
new lib_plankton.zoo_input.class_input_group(
[
{
"name": "date",
"input": new lib_plankton.zoo_input.class_input_text(
{
"pattern": "[0-9]{4}-[0-9]{2}-[0-9]{2}",
"placeholder": "YYYY-MM-DD",
}
),
"label": lib_plankton.translate.get("common.date"),
},
{
"name": "time",
"input": new lib_plankton.zoo_input.class_input_text(
{
"pattern": "[0-9]{2}:[0-9]{2}",
"placeholder": "HH:MM",
}
),
"label": lib_plankton.translate.get("common.time"),
},
]
),
(inner) => {
const date_parts : Array<string> = inner.date.split("-");
const time_parts : Array<string> = inner.time.split(":");
const datetime_raw : lib_plankton.pit.type_datetime = {
"timezone_shift": 0,
"date": {
"year": parseInt(date_parts[0]),
"month": parseInt(date_parts[1]),
"day": parseInt(date_parts[2]),
},
"time": {
"hour": parseInt(time_parts[0]),
"minute": parseInt(time_parts[1]),
"second": 0,
},
};
return {
"timezone_shift": (
_dali.conf.get().misc.use_central_europe_specific_datetime_inputs
?
lib_plankton.pit.timezone_shift_ce(lib_plankton.pit.from_datetime(datetime_raw))
:
0
),
"date": datetime_raw.date,
"time": datetime_raw.time,
};
},
(outer) => {
return {
"date": lib_plankton.string.coin(
"{{year}}-{{month}}-{{day}}",
{
"year": outer.date.year.toFixed(0).padStart(4, "0"),
"month": outer.date.month.toFixed(0).padStart(2, "0"),
"day": outer.date.day.toFixed(0).padStart(2, "0"),
}
),
"time": lib_plankton.string.coin(
"{{hour}}:{{minute}}",
{
"hour": outer.time.hour.toFixed(0).padStart(2, "0"),
"minute": outer.time.minute.toFixed(0).padStart(2, "0"),
}
),
}
}
)
:
new lib_plankton.zoo_input.class_input_datetime(
{
"label_timezone_shift": lib_plankton.translate.get("common.timezone_shift"),
"label_date": lib_plankton.translate.get("common.date"),
"label_time": lib_plankton.translate.get("common.time"),
}
(
_dali.conf.get().misc.use_central_europe_specific_datetime_inputs
?
new lib_plankton.zoo_input.class_input_datetime_central_europe(
{
"label_date": lib_plankton.translate.get("common.date"),
"label_time": lib_plankton.translate.get("common.time"),
}
)
:
new lib_plankton.zoo_input.class_input_datetime(
{
"label_timezone_shift": lib_plankton.translate.get("common.timezone_shift"),
"label_date": lib_plankton.translate.get("common.date"),
"label_time": lib_plankton.translate.get("common.time"),
}
)
)
);
}

View file

@ -198,11 +198,11 @@ namespace _dali
);
if (status.logged_in)
{
_dali.notify_login(status.name);
await _dali.notify_login(status.name);
}
else
{
_dali.notify_logout();
await _dali.notify_logout();
}
}

View file

@ -36,6 +36,10 @@ namespace _dali.model
name : string;
}
>;
settings : {
use_fallback_for_date_and_time_inputs : boolean;
weekview_vertical_default : boolean;
};
calendars : (
null
|
@ -170,6 +174,18 @@ namespace _dali.model
}
/**
*/
export async function settings(
)
: Promise<
_dali.type_user_settings
>
{
return Promise.resolve(_state.settings);
}
/**
*/
async function sync_calendars(
@ -637,6 +653,10 @@ namespace _dali.model
_state = {
"groups": [],
"users": [],
"settings": {
"use_fallback_for_date_and_time_inputs": false,
"weekview_vertical_default": false,
},
"calendars": lib_plankton.map.hashmap.implementation_map(
lib_plankton.map.hashmap.make(
calendar_id => calendar_id.toFixed(0)
@ -668,6 +688,7 @@ namespace _dali.model
)
);
_state.users = await _dali.backend.user_list();
_state.settings = (await _dali.backend.user_get()).settings;
await sync_calendars();
lib_plankton.map.clear(_state.events);
lib_plankton.set.clear(_state.covered_dates);

View file

@ -421,6 +421,41 @@ namespace _dali.backend
}
/**
*/
export function user_get(
)
: Promise<
{
name : string;
groups : Array<
int
>;
email_address : (
null
|
string
);
dav_token : (
null
|
string
);
settings : {
use_fallback_for_date_and_time_inputs : boolean;
weekview_vertical_default : boolean;
};
}
>
{
return call(
lib_plankton.http.enum_method.get,
"/user",
null
);
}
/**
*/
export function user_dav_conf(

View file

@ -52,6 +52,14 @@ namespace _dali
export type type_user_id = int;
/**
*/
export type type_user_settings = {
use_fallback_for_date_and_time_inputs : boolean;
weekview_vertical_default : boolean;
};
/**
*/
export type type_user_object = {
@ -62,6 +70,7 @@ namespace _dali
|
string
);
settings : type_user_settings;
};

View file

@ -212,6 +212,7 @@ namespace _dali.widgets
{
"name": "event_begin",
"input": _dali.helpers.datetime_input(
(await _dali.model.settings()).use_fallback_for_date_and_time_inputs
),
"label": lib_plankton.translate.get("event.begin")
},
@ -219,6 +220,7 @@ namespace _dali.widgets
"name": "event_end",
"input": new lib_plankton.zoo_input.class_input_soft<lib_plankton.pit.type_datetime>(
_dali.helpers.datetime_input(
(await _dali.model.settings()).use_fallback_for_date_and_time_inputs
)
),
"label": lib_plankton.translate.get("event.end")

View file

@ -569,7 +569,11 @@ namespace _dali.widgets
this.get_entries,
{
"initial_view_mode": view_mode,
"weekview_initial_vertical": (view_kind === _dali.enum_view_kind.touch),
"weekview_initial_vertical": (
(await _dali.model.settings()).weekview_vertical_default
||
(view_kind === _dali.enum_view_kind.touch)
),
"action_create_event": this.action_create_event,
"action_edit_event": this.action_edit_event,
}

View file

@ -2,7 +2,7 @@
dir_lib := lib
dir_source := source
dir_temp := /tmp/zeitbild-frontend-web-temp
dir_temp := /tmp/dali-temp
dir_build := build
dir_tools := tools