This commit is contained in:
Fenris Wolf 2024-09-11 20:19:13 +02:00
parent 12697e2a7a
commit 762f3ba3d6
9 changed files with 267 additions and 231 deletions

View file

@ -1,5 +1,4 @@
{ {
"view_mode": "table", "view_mode": "table",
"calendar_id": 6,
"timezone_shift": 0 "timezone_shift": 0
} }

View file

@ -63,7 +63,7 @@
], ],
"calendars": [ "calendars": [
{ {
"id": 5, "id": 1,
"object": { "object": {
"kind": "concrete", "kind": "concrete",
"data": { "data": {
@ -123,7 +123,7 @@
} }
}, },
{ {
"id": 3, "id": 2,
"object": { "object": {
"kind": "concrete", "kind": "concrete",
"data": { "data": {
@ -198,7 +198,7 @@
} }
}, },
{ {
"id": 4, "id": 3,
"object": { "object": {
"kind": "concrete", "kind": "concrete",
"data": { "data": {
@ -226,7 +226,7 @@
} }
}, },
{ {
"id": 1, "id": 4,
"object": { "object": {
"kind": "concrete", "kind": "concrete",
"data": { "data": {
@ -283,7 +283,7 @@
} }
}, },
{ {
"id": 2, "id": 5,
"object": { "object": {
"kind": "concrete", "kind": "concrete",
"data": { "data": {
@ -333,27 +333,11 @@
}, },
{ {
"id": 6, "id": 6,
"object": {
"kind": "collection",
"data": {
"name": "Überblick",
"sources": [
1,
2,
3,
4,
5
]
}
}
},
{
"id": 7,
"object": { "object": {
"kind": "caldav", "kind": "caldav",
"data": { "data": {
"name": "Lixer", "name": "Lixer",
"private": false, "private": true,
"read_only": true, "read_only": true,
"source_url": "https://export.kalender.digital/ics/0/3e10dae66950379d4cc8/gesamterkalender.ics?past_months=3&future_months=36" "source_url": "https://export.kalender.digital/ics/0/3e10dae66950379d4cc8/gesamterkalender.ics?past_months=3&future_months=36"
} }

View file

@ -1,5 +1,6 @@
- Kalender sollen unabhängig von Nutzern bestehen können - Kalender sollen unabhängig von Nutzern bestehen können
- einem Kalender können beliebig viele Nutzer zugeordnet werden, die jeweils bestimmte Berechtigungen haben (z.B. als Rollen "admin", "editor", "viewer", …) - einem Kalender können beliebig viele Nutzer zugeordnet werden, die jeweils bestimmte Berechtigungen haben (z.B. als Rollen "admin", "editor", "viewer", …)
- Events bilden keine Domäne
- Berechtigungen: - Berechtigungen:
- Kalender anlegen - Kalender anlegen
- Kalender-Stammdaten ändern - Kalender-Stammdaten ändern
@ -11,11 +12,10 @@
- es gibt verschiedene Arten von Kalendern: - es gibt verschiedene Arten von Kalendern:
- konkret - konkret
- enthält Veranstaltungen - enthält Veranstaltungen
- Sammlung
- enthält selbst keine Veranstaltungen
- verweist auf beliebig viele andere Kalender (Kreise vermeiden)
- extern - extern
- über CalDAV - über CalDAV
- sollte read-only- und read/write-Modus haben - sollte read-only- und read/write-Modus haben
- nach dem Anmelden sieht man eine Liste mit öffentlichen Kalendern, gruppiert nach jewiliger Rolle - nach dem Anmelden sieht man eine Kalender-Ansicht mit folgenden Kalendern kombiniert angezeigt:
- öffentliche Kalender
- nicht öffentliche Kalendar, bei welchen man Lese-Berechtigung hat
- Entwurfsname: "zeitbild" - Entwurfsname: "zeitbild"

View file

@ -130,14 +130,6 @@ namespace _zeitbild.frontend.resources.backend
}; };
break; break;
} }
case "collection": {
return {
"key": calendar_entry.id,
"preview": {
"name": calendar_entry.object.data.name,
}
};
}
case "caldav": { case "caldav": {
return { return {
"key": calendar_entry.id, "key": calendar_entry.id,
@ -179,7 +171,7 @@ namespace _zeitbild.frontend.resources.backend
* @todo prevent loops * @todo prevent loops
*/ */
export async function calendar_gather_events( export async function calendar_gather_events(
calendar_id : type_calendar_id, calendar_ids : Array<type_calendar_id>,
from_pit : _zeitbild.frontend.helpers.type_pit, from_pit : _zeitbild.frontend.helpers.type_pit,
to_pit : _zeitbild.frontend.helpers.type_pit to_pit : _zeitbild.frontend.helpers.type_pit
) : Promise< ) : Promise<
@ -192,19 +184,38 @@ namespace _zeitbild.frontend.resources.backend
> >
> >
{ {
lib_plankton.log.info(
"calendar_gather_events",
{
"calendar_ids": calendar_ids,
}
);
await init(); await init();
let result : Array<
{
calendar_id : type_calendar_id;
calendar_name : string;
event : type_event;
}
> = [];
for await (const calendar_id of calendar_ids) {
const calendar_object : type_calendar_object = await calendar_read( const calendar_object : type_calendar_object = await calendar_read(
calendar_id calendar_id
); );
if (calendar_object.data.private) {
lib_plankton.log.info( lib_plankton.log.info(
"calendar_gather_events", "calendar_gather_events_private_calendar_blocked",
{ {
"calendar_id": calendar_id, "calendar_id": calendar_id,
} }
); );
}
else {
switch (calendar_object.kind) { switch (calendar_object.kind) {
case "concrete": { case "concrete": {
return Promise.resolve( result = (
result
.concat(
calendar_object.data.events calendar_object.data.events
.filter( .filter(
(event) => _zeitbild.frontend.helpers.pit_is_between( (event) => _zeitbild.frontend.helpers.pit_is_between(
@ -220,29 +231,6 @@ namespace _zeitbild.frontend.resources.backend
"event": event "event": event
}) })
) )
);
break;
}
case "collection": {
return (
Promise.all(
calendar_object.data.sources
.map(
(source_calendar_id) => calendar_gather_events(
source_calendar_id,
from_pit,
to_pit
)
)
)
.then(
(entries) => Promise.resolve(
entries
.reduce(
(x, y) => x.concat(y),
[]
)
)
) )
); );
break; break;
@ -272,7 +260,9 @@ namespace _zeitbild.frontend.resources.backend
{ {
} }
); );
return Promise.resolve( result = (
result
.concat(
vcalendar.vevents vcalendar.vevents
.map( .map(
(vevent : lib_plankton.ical.type_vevent) => ( (vevent : lib_plankton.ical.type_vevent) => (
@ -330,10 +320,14 @@ namespace _zeitbild.frontend.resources.backend
"event": event, "event": event,
}) })
) )
)
); );
break; break;
} }
} }
} }
}
return Promise.resolve(result);
}
} }

View file

@ -7,11 +7,87 @@ namespace _zeitbild.frontend
*/ */
type type_conf = { type type_conf = {
view_mode : string; view_mode : string;
calendar_id : int; calendar_ids : Array<int>;
timezone_shift : int; timezone_shift : int;
}; };
/**
*/
async function render(
conf : type_conf,
calendar_ids : Array<type_calendar_id>
) : Promise<void>
{
calendar_ids.sort();
const target : HTMLElement = (document.querySelector("body") as HTMLBodyElement);
switch (conf.view_mode) {
default: {
throw (new Error("invalid view mode"));
break;
}
case "table": {
const content : string = await _zeitbild.frontend.view.calendar_view_table_html(
calendar_ids,
{
"from": {
"year": 2024,
"week": 35
},
"to": {
"year": 2024,
"week": 43
},
"timezone_shift": conf.timezone_shift,
}
);
target.innerHTML = content;
/*
document.querySelectorAll(".tableview-sources-entry").forEach(
(element) => {
element.addEventListener(
"click",
(event) => {
const element_ : HTMLElement = (event.target as HTMLElement);
const calendar_id : type_calendar_id = parseInt(element_.getAttribute("rel") as string);
const active : boolean = element_.classList.toggle("tableview-sources-entry-active");
render(
conf,
lib_plankton.call.convey(
calendar_ids,
[
(x : Array<int>) => (
active
?
calendar_ids.concat([calendar_id])
:
calendar_ids.filter(y => (y !== calendar_id))
),
]
)
);
}
);
}
);
*/
break;
}
case "list": {
const content : string = await _zeitbild.frontend.view.calendar_view_list_html(
calendar_ids,
{
"timezone_shift": conf.timezone_shift,
}
);
target.innerHTML = content;
break;
}
}
return Promise.resolve<void>(undefined);
}
/** /**
*/ */
export async function main( export async function main(
@ -27,42 +103,29 @@ namespace _zeitbild.frontend
// conf // conf
const conf : type_conf = lib_plankton.json.decode(await lib_plankton.file.read("conf.json")); const conf : type_conf = lib_plankton.json.decode(await lib_plankton.file.read("conf.json"));
// args
const url : URL = new URL(window.location.toString());
const calendar_ids : Array<type_calendar_id> = (
(url.searchParams.get("ids") !== null)
?
lib_plankton.call.convey(
url.searchParams.get("ids"),
[
(x : string) => lib_plankton.string.split(x, ","),
(x : Array<string>) => x.map(y => parseInt(y)),
]
)
:
(await _zeitbild.frontend.resources.backend.calendar_list()).map(x => x.key)
);
// exec // exec
let content : string; await render(
switch (conf.view_mode) { conf,
default: { calendar_ids
content = "";
throw (new Error("invalid view mode"));
break;
}
case "table": {
content = await _zeitbild.frontend.view.calendar_view_table_html(
conf.calendar_id,
{
"from": {
"year": 2024,
"week": 35
},
"to": {
"year": 2024,
"week": 43
},
"timezone_shift": conf.timezone_shift,
}
); );
break;
}
case "list": {
content = await _zeitbild.frontend.view.calendar_view_list_html(
conf.calendar_id,
{
"timezone_shift": conf.timezone_shift,
}
);
break;
}
}
(document.querySelector("body") as HTMLBodyElement).innerHTML = content;
return Promise.resolve<void>(undefined); return Promise.resolve<void>(undefined);
} }

View file

@ -72,17 +72,6 @@ namespace _zeitbild.frontend
}; };
} }
| |
{
kind : "collection";
data : {
name : string;
private : boolean;
sources : Array<
type_calendar_id
>;
}
}
|
{ {
kind : "caldav"; kind : "caldav";
data : { data : {

View file

@ -65,7 +65,7 @@ namespace _zeitbild.frontend.view
{ {
"year": event.end.date.year.toFixed(0).padStart(4, "0"), "year": event.end.date.year.toFixed(0).padStart(4, "0"),
"month": event.end.date.month.toFixed(0).padStart(2, "0"), "month": event.end.date.month.toFixed(0).padStart(2, "0"),
"day": event.end.date.month.toFixed(0).padStart(2, "0"), "day": event.end.date.day.toFixed(0).padStart(2, "0"),
} }
) )
: :
@ -134,7 +134,7 @@ namespace _zeitbild.frontend.view
* @todo kein "while" * @todo kein "while"
*/ */
async function calendar_view_table_data( async function calendar_view_table_data(
calendar_id : type_calendar_id, calendar_ids : Array<type_calendar_id>,
options : { options : {
from ?: { from ?: {
year : int; year : int;
@ -232,7 +232,7 @@ namespace _zeitbild.frontend.view
event : type_event; event : type_event;
} }
> = await _zeitbild.frontend.resources.backend.calendar_gather_events( > = await _zeitbild.frontend.resources.backend.calendar_gather_events(
calendar_id, calendar_ids,
from_pit, from_pit,
to_pit to_pit
); );
@ -389,7 +389,7 @@ namespace _zeitbild.frontend.view
/** /**
*/ */
export async function calendar_view_table_html( export async function calendar_view_table_html(
calendar_id : type_calendar_id, calendar_ids : Array<type_calendar_id>,
options : { options : {
from ?: { from ?: {
year : int; year : int;
@ -428,7 +428,7 @@ namespace _zeitbild.frontend.view
} }
>; >;
} = await calendar_view_table_data( } = await calendar_view_table_data(
calendar_id, calendar_ids,
options options
); );
const sources : lib_plankton.structures.type_hashmap< const sources : lib_plankton.structures.type_hashmap<
@ -448,7 +448,7 @@ namespace _zeitbild.frontend.view
"value": { "value": {
"name": pair.value.name, "name": pair.value.name,
"color": lib_plankton.color.give_generic( "color": lib_plankton.color.give_generic(
(pair.key + 0.2), (pair.key - 1),
{ {
"saturation": 0.375, "saturation": 0.375,
"value": 0.375, "value": 0.375,
@ -470,6 +470,7 @@ namespace _zeitbild.frontend.view
{ {
"name": data.name, "name": data.name,
"color": lib_plankton.color.output_hex(data.color), "color": lib_plankton.color.output_hex(data.color),
"rel": calendar_id.toFixed(0),
} }
) )
) )
@ -567,7 +568,7 @@ namespace _zeitbild.frontend.view
/** /**
*/ */
async function calendar_view_list_data( async function calendar_view_list_data(
calendar_id : type_calendar_id, calendar_ids : Array<type_calendar_id>,
options : { options : {
from ?: _zeitbild.frontend.helpers.type_pit; from ?: _zeitbild.frontend.helpers.type_pit;
to ?: _zeitbild.frontend.helpers.type_pit; to ?: _zeitbild.frontend.helpers.type_pit;
@ -608,7 +609,7 @@ namespace _zeitbild.frontend.view
event : type_event; event : type_event;
} }
> = await _zeitbild.frontend.resources.backend.calendar_gather_events( > = await _zeitbild.frontend.resources.backend.calendar_gather_events(
calendar_id, calendar_ids,
(options.from as _zeitbild.frontend.helpers.type_pit), (options.from as _zeitbild.frontend.helpers.type_pit),
(options.to as _zeitbild.frontend.helpers.type_pit) (options.to as _zeitbild.frontend.helpers.type_pit)
); );
@ -628,7 +629,7 @@ namespace _zeitbild.frontend.view
/** /**
*/ */
export async function calendar_view_list_html( export async function calendar_view_list_html(
calendar_id : type_calendar_id, calendar_ids : Array<type_calendar_id>,
options : { options : {
from ?: _zeitbild.frontend.helpers.type_pit; from ?: _zeitbild.frontend.helpers.type_pit;
to ?: _zeitbild.frontend.helpers.type_pit; to ?: _zeitbild.frontend.helpers.type_pit;
@ -642,7 +643,7 @@ namespace _zeitbild.frontend.view
event : type_event; event : type_event;
} }
> = await calendar_view_list_data( > = await calendar_view_list_data(
calendar_id, calendar_ids,
options options
); );
return Promise.resolve<string>( return Promise.resolve<string>(

View file

@ -22,11 +22,17 @@ html {
margin: 0; margin: 0;
padding: 0; padding: 0;
list-style-type: none; list-style-type: none;
font-size: 0.75em;
} }
.tableview-sources-entry { .tableview-sources-entry {
margin: 8px; margin: 8px;
padding: 4px; padding: 4px;
cursor: pointer;
}
.tableview-sources-entry:not(.tableview-sources-entry-active) {
filter: saturate(0);
} }
.calendar table { .calendar table {

View file

@ -1 +1 @@
<li class="tableview-sources-entry" style="background-color: {{color}}">{{name}}</li> <li class="tableview-sources-entry tableview-sources-entry-active" style="background-color: {{color}}" rel="{{rel}}">{{name}}</li>