/** */ namespace _zeitbild.frontend_web.view { /** */ function event_generate_tooltip( calendar_name : string, event : _zeitbild.frontend_web.type.event_object ) : 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 : ( null | Array<_zeitbild.frontend_web.type.calendar_id> ), from : { year : int; week : int; }, to : { year : int; week : int; }, timezone_shift : int, ) : Promise< { sources : lib_plankton.map.type_map< _zeitbild.frontend_web.type.calendar_id, { name : string; access_level : _zeitbild.frontend_web.type.enum_access_level; } >; rows : Array< { week : int; data : Array< { pit : lib_plankton.pit.type_pit; entries : Array< { calendar_id : _zeitbild.frontend_web.type.calendar_id; event_id : (null | _zeitbild.frontend_web.type.local_resource_event_id); event_object : _zeitbild.frontend_web.type.event_object; } >; today : boolean; } >; } > } > { const now_pit : lib_plankton.pit.type_pit = lib_plankton.pit.now(); const from_pit : lib_plankton.pit.type_pit = lib_plankton.pit.from_ywd( { "year": (from as {year : int; week : int}).year, "week": (from as {year : int; week : int}).week, "day": 1, }, { "timezone_shift": (timezone_shift as int), } ); const to_pit : lib_plankton.pit.type_pit = lib_plankton.pit.from_ywd( { "year": (to as {year : int; week : int}).year, "week": (to as {year : int; week : int}).week, "day": 1, }, { "timezone_shift": (timezone_shift as int), } ); // prepare const entries : Array< { calendar_id : _zeitbild.frontend_web.type.calendar_id; calendar_name : string; access_level : _zeitbild.frontend_web.type.enum_access_level; event_id : (null | _zeitbild.frontend_web.type.local_resource_event_id); event_object : _zeitbild.frontend_web.type.event_object; } > = await _zeitbild.frontend_web.backend.events( from_pit, to_pit, { "calendar_ids": calendar_ids, } ); let result : { sources : lib_plankton.map.type_map< _zeitbild.frontend_web.type.calendar_id, { name : string; access_level : _zeitbild.frontend_web.type.enum_access_level; } >; rows : Array< { week : int; data : Array< { pit : lib_plankton.pit.type_pit; entries : Array< { calendar_id : _zeitbild.frontend_web.type.calendar_id; event_id : (null | _zeitbild.frontend_web.type.local_resource_event_id); event_object : _zeitbild.frontend_web.type.event_object; } >; today : boolean; } >; } >; } = { "sources": lib_plankton.map.hashmap.implementation_map( lib_plankton.map.hashmap.make( x => x.toFixed(0), { "pairs": ( entries .map( (entry) => ( { "key": entry.calendar_id, "value": { "name": entry.calendar_name, "access_level": entry.access_level, } } ) ) ) } ) ), "rows": [], }; let row : Array< { pit : lib_plankton.pit.type_pit; entries : Array< { calendar_id : _zeitbild.frontend_web.type.calendar_id; event_id : (null | _zeitbild.frontend_web.type.local_resource_event_id); event_object : _zeitbild.frontend_web.type.event_object; } >; today : boolean; } > = []; let day : int = 0; while (true) { const pit_current : lib_plankton.pit.type_pit = lib_plankton.pit.shift_day( from_pit, day ); if ( lib_plankton.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": ( (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 = ( lib_plankton.pit.from_datetime(entry.event_object.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( options : { calendar_ids ?: ( null | Array<_zeitbild.frontend_web.type.calendar_id> ); from ?: { year : int; week : int; }; to ?: { year : int; week : int; }; timezone_shift ?: int; action_select ?: ( ( calendar_id : _zeitbild.frontend_web.type.calendar_id, event_id : _zeitbild.frontend_web.type.local_resource_event_id ) => void ) } = {} ) : Promise { const now_pit : lib_plankton.pit.type_pit = lib_plankton.pit.now(); options = Object.assign( { "calendar_ids": null, "from": lib_plankton.call.convey( now_pit, [ (x : lib_plankton.pit.type_pit) => lib_plankton.pit.shift_week(x, -1), lib_plankton.pit.to_ywd, x => ({"year": x.year, "week": x.week}), ] ), "to": lib_plankton.call.convey( now_pit, [ (x : lib_plankton.pit.type_pit) => lib_plankton.pit.shift_week(x, +4), lib_plankton.pit.to_ywd, x => ({"year": x.year, "week": x.week}), ] ), "timezone_shift": 0, }, options ); const stuff : { sources : lib_plankton.map.type_map< _zeitbild.frontend_web.type.calendar_id, { name : string; access_level : _zeitbild.frontend_web.type.enum_access_level; } >; rows : Array< { week : int; data : Array< { pit : lib_plankton.pit.type_pit; entries : Array< { calendar_id : _zeitbild.frontend_web.type.calendar_id; event_id : (null | _zeitbild.frontend_web.type.local_resource_event_id); event_object : _zeitbild.frontend_web.type.event_object; } >; today : boolean; } >; } >; } = await calendar_view_table_data( options.calendar_ids, options.from, options.to, options.timezone_shift ); const sources : lib_plankton.map.type_map< _zeitbild.frontend_web.type.calendar_id, { name : string; access_level : _zeitbild.frontend_web.type.enum_access_level; color : lib_plankton.color.type_color; } > = lib_plankton.map.hashmap.implementation_map( lib_plankton.map.hashmap.make( (x => x.toFixed(0)), { "pairs": ( lib_plankton.map.dump( stuff.sources ) .map( (pair) => ({ "key": pair.key, "value": { "name": pair.value.name, "access_level": pair.value.access_level, "color": lib_plankton.color.give_generic( (pair.key - 1), { "saturation": 0.375, "value": 0.375, } ), } }) ) ) } ) ); return _zeitbild.frontend_web.helpers.template_coin( "tableview", { "sources": ( await _zeitbild.frontend_web.helpers.promise_row( lib_plankton.map.dump(sources) .map( ({"key": calendar_id, "value": data}) => async () => _zeitbild.frontend_web.helpers.template_coin( "tableview-sources-entry", { "name": data.name, // "access_level": data.access_level, "color": lib_plankton.color.output_hex(data.color), "rel": calendar_id.toFixed(0), } ) ) ) ).join(""), "rows": ( await _zeitbild.frontend_web.helpers.promise_row( stuff.rows .map( (row) => async () => _zeitbild.frontend_web.helpers.template_coin( "tableview-row", { "week": row.week.toFixed(0).padStart(2, "0"), "cells": ( await _zeitbild.frontend_web.helpers.promise_row( row.data .map( (cell) => async () => _zeitbild.frontend_web.helpers.template_coin( "tableview-cell", { "extra_classes": ( [""] .concat(cell.today ? ["calendar-cell-today"] : []) .join(" ") ), "title": lib_plankton.call.convey( cell.pit, [ lib_plankton.pit.to_datetime, (x : lib_plankton.pit.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, [ lib_plankton.pit.to_datetime, (x : lib_plankton.pit.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"), } ), ] ), "rel": lib_plankton.call.convey( cell.pit, [ lib_plankton.pit.to_datetime, (x : lib_plankton.pit.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"), } ) ] ), "entries": ( await _zeitbild.frontend_web.helpers.promise_row( cell.entries .map( (entry) => () => _zeitbild.frontend_web.helpers.template_coin( "tableview-cell-entry", { "color": lib_plankton.color.output_hex( sources.get( entry.calendar_id ).color ), "title": event_generate_tooltip( sources.get( entry.calendar_id ).name, entry.event_object ), "name": entry.event_object.name, "rel": lib_plankton.string.coin( "{{calendar_id}}/{{event_id}}/{{access_level}}", { "calendar_id": entry.calendar_id.toFixed(0), "event_id": ( (entry.event_id === null) ? "-" : entry.event_id.toFixed(0) ), "access_level": (() => { const access_level : _zeitbild.frontend_web.type.enum_access_level = sources.get(entry.calendar_id).access_level; switch (access_level) { case _zeitbild.frontend_web.type.enum_access_level.none: return "none"; case _zeitbild.frontend_web.type.enum_access_level.view: return "view"; case _zeitbild.frontend_web.type.enum_access_level.edit: return "edit"; case _zeitbild.frontend_web.type.enum_access_level.admin: return "admin"; } }) (), } ), "additional_classes": lib_plankton.string.coin( " access_level-{{access_level}}", { "access_level": (() => { const access_level : _zeitbild.frontend_web.type.enum_access_level = sources.get(entry.calendar_id).access_level; switch (access_level) { case _zeitbild.frontend_web.type.enum_access_level.none: return "none"; case _zeitbild.frontend_web.type.enum_access_level.view: return "view"; case _zeitbild.frontend_web.type.enum_access_level.edit: return "edit"; case _zeitbild.frontend_web.type.enum_access_level.admin: return "admin"; } }) (), } ), } ) ) ) ).join(""), } ) ) ) ).join(""), } ) ) ) ).join(""), } ); } /** */ async function calendar_view_list_data( calendar_ids : Array<_zeitbild.frontend_web.type.calendar_id>, options : { from ?: lib_plankton.pit.type_pit; to ?: lib_plankton.pit.type_pit; timezone_shift ?: int; } = {} ) : Promise< Array< { calendar_id : _zeitbild.frontend_web.type.calendar_id; event_id : (null | _zeitbild.frontend_web.type.local_resource_event_id); event_object : _zeitbild.frontend_web.type.event_object; } > > { const now_pit : lib_plankton.pit.type_pit = lib_plankton.pit.now(); options = Object.assign( { "from": lib_plankton.call.convey( now_pit, [ (x : lib_plankton.pit.type_pit) => lib_plankton.pit.shift_day(x, -1), ] ), "to": lib_plankton.call.convey( now_pit, [ (x : lib_plankton.pit.type_pit) => lib_plankton.pit.shift_week(x, +4), ] ), "timezone_shift": 0, }, options ); const entries : Array< { calendar_id : _zeitbild.frontend_web.type.calendar_id; event_id : (null | _zeitbild.frontend_web.type.local_resource_event_id); event_object : _zeitbild.frontend_web.type.event_object; } > = await _zeitbild.frontend_web.backend.events( (options.from as lib_plankton.pit.type_pit), (options.to as lib_plankton.pit.type_pit), { "calendar_ids": calendar_ids, } ); // TODO: optimize entries.sort( (entry_1, entry_2) => ( lib_plankton.pit.from_datetime(entry_1.event_object.begin) - lib_plankton.pit.from_datetime(entry_2.event_object.begin) ) ); return Promise.resolve(entries); } /** */ export async function calendar_view_list_html( calendar_ids : Array<_zeitbild.frontend_web.type.calendar_id>, options : { from ?: lib_plankton.pit.type_pit; to ?: lib_plankton.pit.type_pit; timezone_shift ?: int; } = {} ) : Promise { const stuff : Array< { calendar_id : _zeitbild.frontend_web.type.calendar_id; event_id : (null | _zeitbild.frontend_web.type.local_resource_event_id); event_object : _zeitbild.frontend_web.type.event_object; } > = await calendar_view_list_data( calendar_ids, options ); return Promise.resolve( 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() ); } }