backend/source/logic/view.ts
Fenris Wolf 762f3ba3d6 [mod]
2024-09-11 20:19:13 +02:00

696 lines
15 KiB
TypeScript

/**
*/
namespace _zeitbild.frontend.view
{
/**
*/
function event_generate_tooltip(
calendar_name : string,
event : type_event
) : string
{
return (
lib_plankton.string.coin(
"[{{calendar_name}}] {{event_name}}\n",
{
"calendar_name": calendar_name,
"event_name": event.name,
}
)
+
"--\n"
+
(
(event.begin.time !== null)
?
lib_plankton.string.coin(
"{{label}}: {{value}}\n",
{
"label": "Anfang", // TODO: translate
"value": lib_plankton.string.coin(
"{{hour}}:{{minute}}",
{
"hour": event.begin.time.hour.toFixed(0).padStart(2, "0"),
"minute": event.begin.time.minute.toFixed(0).padStart(2, "0"),
}
), // TODO: outsource
}
)
:
""
)
+
(
(event.end !== null)
?
lib_plankton.string.coin(
"{{label}}: {{value}}\n",
{
"label": "Ende", // TODO: translate
"value": (
[
(
(
(event.end.date.year !== event.begin.date.year)
||
(event.end.date.month !== event.begin.date.month)
||
(event.end.date.day !== event.begin.date.day)
)
?
lib_plankton.string.coin(
"{{year}}-{{month}}-{{day}}",
{
"year": event.end.date.year.toFixed(0).padStart(4, "0"),
"month": event.end.date.month.toFixed(0).padStart(2, "0"),
"day": event.end.date.day.toFixed(0).padStart(2, "0"),
}
)
:
null
),
(
(event.end.time !== null)
?
lib_plankton.string.coin(
"{{hour}}:{{minute}}",
{
"hour": event.end.time.hour.toFixed(0).padStart(2, "0"),
"minute": event.end.time.minute.toFixed(0).padStart(2, "0"),
}
)
:
null
),
]
.filter(x => (x !== null))
.join(",")
),
}
)
:
""
)
+
(
(event.location !== null)
?
(
lib_plankton.string.coin(
"{{label}}: {{value}}\n",
{
"label": "Ort", // TODO
"value": event.location,
}
)
)
:
""
)
+
(
(event.description !== null)
?
(
"--\n"
+
lib_plankton.string.coin(
"{{description}}\n",
{
"description": event.description,
}
)
)
:
""
)
);
}
/**
* @todo kein "while"
*/
async function calendar_view_table_data(
calendar_ids : Array<type_calendar_id>,
options : {
from ?: {
year : int;
week : int;
},
to ?: {
year : int;
week : int;
},
timezone_shift ?: int;
} = {}
) : Promise<
{
sources : lib_plankton.structures.type_hashmap<
type_calendar_id,
{
name : string;
}
>;
rows : Array<
{
week : int;
data : Array<
{
pit : _zeitbild.frontend.helpers.type_pit;
entries : Array<
{
calendar_id : type_calendar_id;
event : type_event;
}
>;
today : boolean;
}
>;
}
>
}
>
{
const now_pit : _zeitbild.frontend.helpers.type_pit = _zeitbild.frontend.helpers.pit_now();
options = Object.assign(
{
"from": lib_plankton.call.convey(
now_pit,
[
(x : _zeitbild.frontend.helpers.type_pit) => _zeitbild.frontend.helpers.pit_shift_week(x, -1),
_zeitbild.frontend.helpers.pit_to_date_object,
(x : Date) => ({
"year": x.getFullYear(),
"week": _zeitbild.frontend.helpers.date_object_get_week_of_year(x),
})
]
),
"to": lib_plankton.call.convey(
now_pit,
[
(x : _zeitbild.frontend.helpers.type_pit) => _zeitbild.frontend.helpers.pit_shift_week(x, +4),
_zeitbild.frontend.helpers.pit_to_date_object,
(x : Date) => ({
"year": x.getFullYear(),
"week": _zeitbild.frontend.helpers.date_object_get_week_of_year(x),
})
]
),
"timezone_shift": 0,
},
options
);
/*
const calendar_object : type_calendar_object = calendar_read(
data,
calendar_id
);
*/
const from_pit : _zeitbild.frontend.helpers.type_pit = _zeitbild.frontend.helpers.pit_from_year_and_week(
(options.from as {year : int; week : int}).year,
(options.from as {year : int; week : int}).week,
{
"timezone_shift": (options.timezone_shift as int),
}
);
const to_pit : _zeitbild.frontend.helpers.type_pit = _zeitbild.frontend.helpers.pit_from_year_and_week(
(options.to as {year : int; week : int}).year,
(options.to as {year : int; week : int}).week,
{
"timezone_shift": (options.timezone_shift as int),
}
);
// prepare
const entries : Array<
{
calendar_id : type_calendar_id;
calendar_name : string;
event : type_event;
}
> = await _zeitbild.frontend.resources.backend.calendar_gather_events(
calendar_ids,
from_pit,
to_pit
);
let result : {
sources : lib_plankton.structures.type_hashmap<
type_calendar_id,
{
name : string;
}
>;
rows : Array<
{
week : int;
data : Array<
{
pit : _zeitbild.frontend.helpers.type_pit;
entries : Array<
{
calendar_id : type_calendar_id;
event : type_event;
}
>;
today : boolean;
}
>;
}
>;
} = {
"sources": lib_plankton.structures.hashmap_construct(
x => x.toFixed(0),
(
entries
.map(
(entry) => (
{
"key": entry.calendar_id,
"value": {
"name": entry.calendar_name,
}
}
)
)
)
),
"rows": [],
};
let row : Array<
{
pit : _zeitbild.frontend.helpers.type_pit;
entries : Array<
{
calendar_id : type_calendar_id;
event : type_event;
}
>;
today : boolean;
}
> = [];
let day : int = 0;
while (true) {
const pit_current : _zeitbild.frontend.helpers.type_pit = _zeitbild.frontend.helpers.pit_shift_day(
from_pit,
day
);
if (
_zeitbild.frontend.helpers.pit_is_before(
pit_current,
to_pit
)
) {
day += 1;
row.push(
{
"pit": pit_current,
"entries": [],
"today": false, // TODO
}
);
if (day % 7 === 0) {
result.rows.push(
{
"week": (
(options.from as {year : int; week : int}).week
+
Math.floor(day / 7)
-
1 // TODO
),
"data": row
}
);
row = [];
}
else {
// do nothing
}
}
else {
break;
}
}
// fill
{
// events
(
entries
.forEach(
(entry) => {
const distance_seconds : int = (
_zeitbild.frontend.helpers.pit_from_datetime(entry.event.begin)
-
from_pit
);
const distance_days : int = (distance_seconds / (60 * 60 * 24));
const week : int = Math.floor(Math.floor(distance_days) / 7);
const day : int = (Math.floor(distance_days) % 7);
if ((week >= 0) && (week < result.rows.length)) {
result.rows[week].data[day].entries.push(entry);
}
else {
// do nothing
}
}
)
);
// today
{
const distance_seconds : int = (
now_pit
-
from_pit
);
const distance_days : int = (distance_seconds / (60 * 60 * 24));
const week : int = Math.floor(Math.floor(distance_days) / 7);
const day : int = (Math.floor(distance_days) % 7);
if ((week >= 0) && (week < result.rows.length)) {
result.rows[week].data[day].today = true;
}
else {
// do nothing
}
}
}
return Promise.resolve(result);
}
/**
*/
export async function calendar_view_table_html(
calendar_ids : Array<type_calendar_id>,
options : {
from ?: {
year : int;
week : int;
};
to ?: {
year : int;
week : int;
};
timezone_shift ?: int;
} = {}
) : Promise<string>
{
const stuff : {
sources : lib_plankton.structures.type_hashmap<
type_calendar_id,
{
name : string;
}
>;
rows : Array<
{
week : int;
data : Array<
{
pit : _zeitbild.frontend.helpers.type_pit;
entries : Array<
{
calendar_id : type_calendar_id;
event : type_event;
}
>;
today : boolean;
}
>;
}
>;
} = await calendar_view_table_data(
calendar_ids,
options
);
const sources : lib_plankton.structures.type_hashmap<
type_calendar_id,
{
name : string;
color : lib_plankton.color.type_color;
}
> = lib_plankton.structures.hashmap_construct(
(x => x.toFixed(0)),
lib_plankton.structures.hashmap_dump(
stuff.sources
)
.map(
(pair) => ({
"key": pair.key,
"value": {
"name": pair.value.name,
"color": lib_plankton.color.give_generic(
(pair.key - 1),
{
"saturation": 0.375,
"value": 0.375,
}
),
}
})
)
);
return _zeitbild.frontend.helpers.template_coin(
"tableview",
{
"sources": (
await _zeitbild.frontend.helpers.promise_row<string>(
lib_plankton.structures.hashmap_dump(sources)
.map(
({"key": calendar_id, "value": data}) => async () => _zeitbild.frontend.helpers.template_coin(
"tableview-sources-entry",
{
"name": data.name,
"color": lib_plankton.color.output_hex(data.color),
"rel": calendar_id.toFixed(0),
}
)
)
)
).join(""),
"rows": (
await _zeitbild.frontend.helpers.promise_row<string>(
stuff.rows
.map(
(row) => async () => _zeitbild.frontend.helpers.template_coin(
"tableview-row",
{
"week": row.week.toFixed(0).padStart(2, "0"),
"cells": (
await _zeitbild.frontend.helpers.promise_row<string>(
row.data
.map(
(cell) => async () => _zeitbild.frontend.helpers.template_coin(
"tableview-cell",
{
"extra_classes": (
[""]
.concat(cell.today ? ["calendar-cell-today"] : [])
.join(" ")
),
"title": lib_plankton.call.convey(
cell.pit,
[
_zeitbild.frontend.helpers.pit_to_datetime,
(x : _zeitbild.frontend.helpers.type_datetime) => lib_plankton.string.coin(
"{{year}}-{{month}}-{{day}}",
{
"year": x.date.year.toFixed(0).padStart(4, "0"),
"month": x.date.month.toFixed(0).padStart(2, "0"),
"day": x.date.day.toFixed(0).padStart(2, "0"),
}
),
]
),
"day": lib_plankton.call.convey(
cell.pit,
[
_zeitbild.frontend.helpers.pit_to_datetime,
(x : _zeitbild.frontend.helpers.type_datetime) => lib_plankton.string.coin(
"{{day}}",
{
"year": x.date.year.toFixed(0).padStart(4, "0"),
"month": x.date.month.toFixed(0).padStart(2, "0"),
"day": x.date.day.toFixed(0).padStart(2, "0"),
}
),
]
),
"entries": (
await _zeitbild.frontend.helpers.promise_row<string>(
cell.entries
.map(
(entry) => () => _zeitbild.frontend.helpers.template_coin(
"tableview-cell-entry",
{
"color": lib_plankton.color.output_hex(
lib_plankton.structures.hashmap_get(
sources,
entry.calendar_id
).color
),
"title": event_generate_tooltip(
lib_plankton.structures.hashmap_get(
sources,
entry.calendar_id
).name,
entry.event
),
"name": entry.event.name,
}
)
)
)
).join(""),
}
)
)
)
).join(""),
}
)
)
)
).join(""),
}
);
}
/**
*/
async function calendar_view_list_data(
calendar_ids : Array<type_calendar_id>,
options : {
from ?: _zeitbild.frontend.helpers.type_pit;
to ?: _zeitbild.frontend.helpers.type_pit;
timezone_shift ?: int;
} = {}
) : Promise<
Array<
{
calendar_id : type_calendar_id;
event : type_event;
}
>
>
{
const now_pit : _zeitbild.frontend.helpers.type_pit = _zeitbild.frontend.helpers.pit_now();
options = Object.assign(
{
"from": lib_plankton.call.convey(
now_pit,
[
(x : _zeitbild.frontend.helpers.type_pit) => _zeitbild.frontend.helpers.pit_shift_day(x, -1),
]
),
"to": lib_plankton.call.convey(
now_pit,
[
(x : _zeitbild.frontend.helpers.type_pit) => _zeitbild.frontend.helpers.pit_shift_week(x, +4),
]
),
"timezone_shift": 0,
},
options
);
const entries : Array<
{
calendar_id : type_calendar_id;
event : type_event;
}
> = await _zeitbild.frontend.resources.backend.calendar_gather_events(
calendar_ids,
(options.from as _zeitbild.frontend.helpers.type_pit),
(options.to as _zeitbild.frontend.helpers.type_pit)
);
// TODO: optimize
entries.sort(
(entry_1, entry_2) => (
_zeitbild.frontend.helpers.pit_from_datetime(entry_1.event.begin)
-
_zeitbild.frontend.helpers.pit_from_datetime(entry_2.event.begin)
)
);
return Promise.resolve(entries);
}
/**
*/
export async function calendar_view_list_html(
calendar_ids : Array<type_calendar_id>,
options : {
from ?: _zeitbild.frontend.helpers.type_pit;
to ?: _zeitbild.frontend.helpers.type_pit;
timezone_shift ?: int;
} = {}
) : Promise<string>
{
const stuff : Array<
{
calendar_id : type_calendar_id;
event : type_event;
}
> = await calendar_view_list_data(
calendar_ids,
options
);
return Promise.resolve<string>(
new lib_plankton.xml.class_node_complex(
"div",
{
"class": "list",
},
[
new lib_plankton.xml.class_node_complex(
"style",
{},
[
new lib_plankton.xml.class_node_text(
"html {background-color: #111; color: #FFF; font-family: sans-serif;}\n"
+
"table {width: 100%; border-collapse: collapse;}\n"
)
]
),
new lib_plankton.xml.class_node_complex(
"ul",
{
"class": "list-events",
},
(
stuff
.map(
(entry) => (
new lib_plankton.xml.class_node_complex(
"li",
{
"class": "list-event_entry",
},
[
new lib_plankton.xml.class_node_text(
JSON.stringify(entry)
),
]
)
)
)
)
),
]
).compile()
);
}
}