696 lines
15 KiB
TypeScript
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()
|
|
);
|
|
}
|
|
|
|
}
|