[ini]
This commit is contained in:
commit
bd1626f3a6
4 changed files with 951 additions and 0 deletions
2
.gitignore
vendored
Normal file
2
.gitignore
vendored
Normal file
|
@ -0,0 +1,2 @@
|
||||||
|
/build/
|
||||||
|
/temp/
|
914
source/main.ts
Normal file
914
source/main.ts
Normal file
|
@ -0,0 +1,914 @@
|
||||||
|
declare var process : any;
|
||||||
|
|
||||||
|
|
||||||
|
type int = number;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
*/
|
||||||
|
function date_object_get_week_of_year(
|
||||||
|
date : Date
|
||||||
|
) : int
|
||||||
|
{
|
||||||
|
let date_ : Date = new Date(date.getTime());
|
||||||
|
date_.setHours(0, 0, 0, 0);
|
||||||
|
// Thursday in current week decides the year.
|
||||||
|
date_.setDate(date_.getDate() + 3 - (date_.getDay() + 6) % 7);
|
||||||
|
// January 4 is always in week 1.
|
||||||
|
let week1 : Date = new Date(date_.getFullYear(), 0, 4);
|
||||||
|
// Adjust to Thursday in week 1 and count number of weeks from date to week1.
|
||||||
|
return (
|
||||||
|
1
|
||||||
|
+
|
||||||
|
Math.round(
|
||||||
|
(
|
||||||
|
((date_.getTime() - week1.getTime()) / 86400000)
|
||||||
|
-
|
||||||
|
3
|
||||||
|
+
|
||||||
|
(week1.getDay() + 6) % 7
|
||||||
|
)
|
||||||
|
/
|
||||||
|
7
|
||||||
|
)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
type type_date = {
|
||||||
|
year : int;
|
||||||
|
month : int;
|
||||||
|
day : int;
|
||||||
|
};
|
||||||
|
|
||||||
|
type type_time = {
|
||||||
|
hour : int;
|
||||||
|
minute : int;
|
||||||
|
second : int;
|
||||||
|
};
|
||||||
|
|
||||||
|
type type_datetime = {
|
||||||
|
timezone : string;
|
||||||
|
date : type_date;
|
||||||
|
time : (
|
||||||
|
null
|
||||||
|
|
|
||||||
|
type_time
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
type type_pit = int;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
*/
|
||||||
|
function pit_to_date_object(
|
||||||
|
pit : type_pit
|
||||||
|
) : Date
|
||||||
|
{
|
||||||
|
return (new Date(pit * 1000));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
*/
|
||||||
|
function pit_from_date_object(
|
||||||
|
date_object : Date
|
||||||
|
) : type_pit
|
||||||
|
{
|
||||||
|
return Math.round(date_object.getTime() / 1000);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
*/
|
||||||
|
function pit_now(
|
||||||
|
) : type_pit
|
||||||
|
{
|
||||||
|
return pit_from_date_object(new Date(Date.now()));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
*/
|
||||||
|
function pit_to_datetime(
|
||||||
|
pit : type_pit
|
||||||
|
) : type_datetime
|
||||||
|
{
|
||||||
|
const date_object : Date = pit_to_date_object(pit);
|
||||||
|
return {
|
||||||
|
"timezone": "Europe/Berlin", // TODO
|
||||||
|
"date": {
|
||||||
|
"year": date_object.getFullYear(),
|
||||||
|
"month": (date_object.getMonth() + 1),
|
||||||
|
"day": (date_object.getDate()),
|
||||||
|
},
|
||||||
|
"time": {
|
||||||
|
"hour": date_object.getHours(),
|
||||||
|
"minute": date_object.getMinutes(),
|
||||||
|
"second": date_object.getSeconds(),
|
||||||
|
},
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
*/
|
||||||
|
function pit_from_datetime(
|
||||||
|
datetime : type_datetime
|
||||||
|
) : type_pit
|
||||||
|
{
|
||||||
|
// TODO: timezone
|
||||||
|
const date_object : Date = new Date(
|
||||||
|
datetime.date.year,
|
||||||
|
(datetime.date.month - 1), // TODO
|
||||||
|
datetime.date.day,
|
||||||
|
((datetime.time === null) ? 0 : datetime.time.hour),
|
||||||
|
((datetime.time === null) ? 0 : datetime.time.minute),
|
||||||
|
((datetime.time === null) ? 0 : datetime.time.second)
|
||||||
|
);
|
||||||
|
return pit_from_date_object(date_object);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
*/
|
||||||
|
function pit_is_before(
|
||||||
|
pit : type_pit,
|
||||||
|
reference : type_pit
|
||||||
|
) : boolean
|
||||||
|
{
|
||||||
|
return (pit < reference);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
*/
|
||||||
|
function pit_is_after(
|
||||||
|
pit : type_pit,
|
||||||
|
reference : type_pit
|
||||||
|
) : boolean
|
||||||
|
{
|
||||||
|
return (pit > reference);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
*/
|
||||||
|
function pit_is_between(
|
||||||
|
pit : type_pit,
|
||||||
|
reference_left : type_pit,
|
||||||
|
reference_right : type_pit
|
||||||
|
) : boolean
|
||||||
|
{
|
||||||
|
return (
|
||||||
|
pit_is_after(pit, reference_left)
|
||||||
|
&&
|
||||||
|
pit_is_before(pit, reference_right)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
*/
|
||||||
|
function pit_shift_hour(
|
||||||
|
pit : type_pit,
|
||||||
|
increment : int
|
||||||
|
) : type_pit
|
||||||
|
{
|
||||||
|
return (pit + (60 * 60 * increment));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
*/
|
||||||
|
function pit_shift_day(
|
||||||
|
pit : type_pit,
|
||||||
|
increment : int
|
||||||
|
) : type_pit
|
||||||
|
{
|
||||||
|
return (pit + (60 * 60 * 24 * increment));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
*/
|
||||||
|
function pit_shift_week(
|
||||||
|
pit : type_pit,
|
||||||
|
increment : int
|
||||||
|
) : type_pit
|
||||||
|
{
|
||||||
|
return (pit + (60 * 60 * 24 * 7 * increment));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
*/
|
||||||
|
function pit_shift_year(
|
||||||
|
pit : type_pit,
|
||||||
|
increment : int
|
||||||
|
) : type_pit
|
||||||
|
{
|
||||||
|
return (pit + (60 * 60 * 24 * 365 * increment));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
*/
|
||||||
|
function pit_trunc_minute(
|
||||||
|
pit : type_pit
|
||||||
|
) : type_pit
|
||||||
|
{
|
||||||
|
const datetime_input : type_datetime = pit_to_datetime(pit);
|
||||||
|
const datetime_output : type_datetime = {
|
||||||
|
"timezone": "Europe/Berlin", // TODO
|
||||||
|
"date": {
|
||||||
|
"year": datetime_input.date.year,
|
||||||
|
"month": datetime_input.date.month,
|
||||||
|
"day": datetime_input.date.day,
|
||||||
|
},
|
||||||
|
"time": {
|
||||||
|
"hour": ((datetime_input.time === null) ? 0 : datetime_input.time.hour),
|
||||||
|
"minute": ((datetime_input.time === null) ? 0 : datetime_input.time.minute),
|
||||||
|
"second": 0,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
return pit_from_datetime(datetime_output);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
*/
|
||||||
|
function pit_trunc_hour(
|
||||||
|
pit : type_pit
|
||||||
|
) : type_pit
|
||||||
|
{
|
||||||
|
const datetime_input : type_datetime = pit_to_datetime(pit);
|
||||||
|
const datetime_output : type_datetime = {
|
||||||
|
"timezone": "Europe/Berlin", // TODO
|
||||||
|
"date": {
|
||||||
|
"year": datetime_input.date.year,
|
||||||
|
"month": datetime_input.date.month,
|
||||||
|
"day": datetime_input.date.day,
|
||||||
|
},
|
||||||
|
"time": {
|
||||||
|
"hour": ((datetime_input.time === null) ? 0 : datetime_input.time.hour),
|
||||||
|
"minute": 0,
|
||||||
|
"second": 0,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
return pit_from_datetime(datetime_output);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
*/
|
||||||
|
function pit_trunc_day(
|
||||||
|
pit : type_pit
|
||||||
|
) : type_pit
|
||||||
|
{
|
||||||
|
const datetime_input : type_datetime = pit_to_datetime(pit);
|
||||||
|
const datetime_output : type_datetime = {
|
||||||
|
"timezone": "Europe/Berlin", // TODO
|
||||||
|
"date": {
|
||||||
|
"year": datetime_input.date.year,
|
||||||
|
"month": datetime_input.date.month,
|
||||||
|
"day": datetime_input.date.day,
|
||||||
|
},
|
||||||
|
"time": {
|
||||||
|
"hour": 0,
|
||||||
|
"minute": 0,
|
||||||
|
"second": 0,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
return pit_from_datetime(datetime_output);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
*/
|
||||||
|
function pit_trunc_week(
|
||||||
|
pit : type_pit
|
||||||
|
) : type_pit
|
||||||
|
{
|
||||||
|
const date_object : Date = pit_to_date_object(pit);
|
||||||
|
return pit_shift_day(
|
||||||
|
pit,
|
||||||
|
-(date_object.getDay())
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
*/
|
||||||
|
function pit_trunc_month(
|
||||||
|
pit : type_pit
|
||||||
|
) : type_pit
|
||||||
|
{
|
||||||
|
const datetime_input : type_datetime = pit_to_datetime(pit);
|
||||||
|
const datetime_output : type_datetime = {
|
||||||
|
"timezone": "Europe/Berlin", // TODO
|
||||||
|
"date": {
|
||||||
|
"year": datetime_input.date.year,
|
||||||
|
"month": datetime_input.date.month,
|
||||||
|
"day": 1,
|
||||||
|
},
|
||||||
|
"time": {
|
||||||
|
"hour": 0,
|
||||||
|
"minute": 0,
|
||||||
|
"second": 0,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
return pit_from_datetime(datetime_output);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
*/
|
||||||
|
function pit_trunc_year(
|
||||||
|
pit : type_pit
|
||||||
|
) : type_pit
|
||||||
|
{
|
||||||
|
const datetime_input : type_datetime = pit_to_datetime(pit);
|
||||||
|
const datetime_output : type_datetime = {
|
||||||
|
"timezone": "Europe/Berlin", // TODO
|
||||||
|
"date": {
|
||||||
|
"year": datetime_input.date.year,
|
||||||
|
"month": 1,
|
||||||
|
"day": 1,
|
||||||
|
},
|
||||||
|
"time": {
|
||||||
|
"hour": 0,
|
||||||
|
"minute": 0,
|
||||||
|
"second": 0,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
return pit_from_datetime(datetime_output);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
*/
|
||||||
|
function pit_from_year_and_week(
|
||||||
|
year : int,
|
||||||
|
week : int
|
||||||
|
) : type_pit
|
||||||
|
{
|
||||||
|
return pit_trunc_week(
|
||||||
|
pit_shift_week(
|
||||||
|
pit_from_datetime(
|
||||||
|
{
|
||||||
|
"timezone": "Europe/Berlin", // TODO
|
||||||
|
"date": {
|
||||||
|
"year": year,
|
||||||
|
"month": 1,
|
||||||
|
"day": 1,
|
||||||
|
},
|
||||||
|
"time": {
|
||||||
|
"hour": 12,
|
||||||
|
"minute": 0,
|
||||||
|
"second": 0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
),
|
||||||
|
week
|
||||||
|
)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// ---
|
||||||
|
|
||||||
|
type type_role = (
|
||||||
|
"editor"
|
||||||
|
|
|
||||||
|
"viewer"
|
||||||
|
);
|
||||||
|
|
||||||
|
type type_user_id = int;
|
||||||
|
|
||||||
|
type type_user_object = {
|
||||||
|
name : string;
|
||||||
|
};
|
||||||
|
|
||||||
|
type type_event = {
|
||||||
|
name : string;
|
||||||
|
begin : type_datetime;
|
||||||
|
end : (
|
||||||
|
null
|
||||||
|
|
|
||||||
|
type_datetime
|
||||||
|
);
|
||||||
|
description : (
|
||||||
|
null
|
||||||
|
|
|
||||||
|
string
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
type type_calendar_id = int;
|
||||||
|
|
||||||
|
type type_calendar_object = (
|
||||||
|
{
|
||||||
|
kind : "concrete";
|
||||||
|
data : {
|
||||||
|
name : string;
|
||||||
|
users : Array<
|
||||||
|
{
|
||||||
|
id : type_user_id;
|
||||||
|
role : type_role;
|
||||||
|
}
|
||||||
|
>;
|
||||||
|
events : Array<type_event>;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
|
||||||
|
{
|
||||||
|
kind : "collection";
|
||||||
|
data : {
|
||||||
|
name : string;
|
||||||
|
sources : Array<
|
||||||
|
type_calendar_id
|
||||||
|
>;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
type type_datamodel = {
|
||||||
|
users : Array<
|
||||||
|
{
|
||||||
|
id : type_user_id;
|
||||||
|
object : type_user_object;
|
||||||
|
}
|
||||||
|
>;
|
||||||
|
calendars : Array<
|
||||||
|
{
|
||||||
|
id : type_calendar_id;
|
||||||
|
object : type_calendar_object;
|
||||||
|
}
|
||||||
|
>;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
*/
|
||||||
|
function calendar_list(
|
||||||
|
data : type_datamodel
|
||||||
|
) : Array<
|
||||||
|
{
|
||||||
|
key : type_calendar_id;
|
||||||
|
preview : {
|
||||||
|
name : string;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
>
|
||||||
|
{
|
||||||
|
return (
|
||||||
|
data.calendars
|
||||||
|
.map(
|
||||||
|
(calendar_entry) => ({
|
||||||
|
"key": calendar_entry.id,
|
||||||
|
"preview": {
|
||||||
|
"name": calendar_entry.object.data.name,
|
||||||
|
}
|
||||||
|
})
|
||||||
|
)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
*/
|
||||||
|
function calendar_read(
|
||||||
|
data : type_datamodel,
|
||||||
|
calendar_id : type_calendar_id
|
||||||
|
) : type_calendar_object
|
||||||
|
{
|
||||||
|
const hits = (
|
||||||
|
data.calendars
|
||||||
|
.filter(
|
||||||
|
(calendar_entry) => (calendar_entry.id === calendar_id)
|
||||||
|
)
|
||||||
|
);
|
||||||
|
if (hits.length <= 0) {
|
||||||
|
throw (new Error("not found"));
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
return hits[0].object;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
*/
|
||||||
|
function calendar_gather_events(
|
||||||
|
data : type_datamodel,
|
||||||
|
calendar_id : type_calendar_id,
|
||||||
|
from_pit : type_pit,
|
||||||
|
to_pit : type_pit
|
||||||
|
) : Array<
|
||||||
|
{
|
||||||
|
calendar_id : type_calendar_id;
|
||||||
|
event : type_event;
|
||||||
|
}
|
||||||
|
>
|
||||||
|
{
|
||||||
|
const calendar_object : type_calendar_object = calendar_read(
|
||||||
|
data,
|
||||||
|
calendar_id
|
||||||
|
);
|
||||||
|
switch (calendar_object.kind) {
|
||||||
|
case "concrete": {
|
||||||
|
return (
|
||||||
|
calendar_object.data.events
|
||||||
|
.filter(
|
||||||
|
(event) => pit_is_between(
|
||||||
|
pit_from_datetime(event.begin),
|
||||||
|
from_pit,
|
||||||
|
to_pit
|
||||||
|
)
|
||||||
|
)
|
||||||
|
.map(
|
||||||
|
(event) => ({"calendar_id": calendar_id, "event": event})
|
||||||
|
)
|
||||||
|
);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case "collection": {
|
||||||
|
return (
|
||||||
|
calendar_object.data.sources
|
||||||
|
.map(
|
||||||
|
(source_calendar_id) => calendar_gather_events(
|
||||||
|
data,
|
||||||
|
source_calendar_id,
|
||||||
|
from_pit,
|
||||||
|
to_pit
|
||||||
|
)
|
||||||
|
)
|
||||||
|
.reduce(
|
||||||
|
(x, y) => x.concat(y),
|
||||||
|
[]
|
||||||
|
)
|
||||||
|
);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
*/
|
||||||
|
function calendar_view_table(
|
||||||
|
data : type_datamodel,
|
||||||
|
calendar_id : type_calendar_id,
|
||||||
|
from : {
|
||||||
|
year : int;
|
||||||
|
week : int;
|
||||||
|
},
|
||||||
|
to : {
|
||||||
|
year : int;
|
||||||
|
week : int;
|
||||||
|
}
|
||||||
|
) : Array<
|
||||||
|
Array<
|
||||||
|
{
|
||||||
|
date : type_date;
|
||||||
|
entries : Array<
|
||||||
|
{
|
||||||
|
calendar_id : type_calendar_id;
|
||||||
|
event : type_event;
|
||||||
|
}
|
||||||
|
>;
|
||||||
|
}
|
||||||
|
>
|
||||||
|
>
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
const calendar_object : type_calendar_object = calendar_read(
|
||||||
|
data,
|
||||||
|
calendar_id
|
||||||
|
);
|
||||||
|
*/
|
||||||
|
const from_pit : type_pit = pit_from_year_and_week(from.year, from.week);
|
||||||
|
const to_pit : type_pit = pit_from_year_and_week(to.year, to.week);
|
||||||
|
|
||||||
|
// prepare
|
||||||
|
const entries : Array<
|
||||||
|
{
|
||||||
|
calendar_id : type_calendar_id;
|
||||||
|
event : type_event;
|
||||||
|
}
|
||||||
|
> = calendar_gather_events(
|
||||||
|
data,
|
||||||
|
calendar_id,
|
||||||
|
from_pit,
|
||||||
|
to_pit
|
||||||
|
);
|
||||||
|
let result : Array<
|
||||||
|
Array<
|
||||||
|
{
|
||||||
|
date : type_date;
|
||||||
|
entries : Array<
|
||||||
|
{
|
||||||
|
calendar_id : type_calendar_id;
|
||||||
|
event : type_event;
|
||||||
|
}
|
||||||
|
>;
|
||||||
|
}
|
||||||
|
>
|
||||||
|
> = [];
|
||||||
|
let row : Array<
|
||||||
|
{
|
||||||
|
date : type_date;
|
||||||
|
entries : Array<
|
||||||
|
{
|
||||||
|
calendar_id : type_calendar_id;
|
||||||
|
event : type_event;
|
||||||
|
}
|
||||||
|
>;
|
||||||
|
}
|
||||||
|
> = [];
|
||||||
|
let day : int = 0;
|
||||||
|
while (true) {
|
||||||
|
let pit_current : type_pit = pit_shift_day(from_pit, day);
|
||||||
|
if (pit_is_before(pit_current, to_pit)) {
|
||||||
|
day += 1;
|
||||||
|
row.push(
|
||||||
|
{
|
||||||
|
"date": pit_to_datetime(pit_shift_hour(pit_current, 12)).date,
|
||||||
|
"entries": [],
|
||||||
|
}
|
||||||
|
);
|
||||||
|
if (day % 7 === 0) {
|
||||||
|
result.push(row);
|
||||||
|
row = [];
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
// do nothing
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// fill
|
||||||
|
(
|
||||||
|
entries
|
||||||
|
.forEach(
|
||||||
|
(entry) => {
|
||||||
|
const distance_seconds : int = (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);
|
||||||
|
|
||||||
|
// process.stdout.write(JSON.stringify({entry, week, day}, undefined, "\t") + "\n");
|
||||||
|
|
||||||
|
result[week][day].entries.push(entry);
|
||||||
|
}
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
*/
|
||||||
|
function calendar_view_table_html(
|
||||||
|
data : type_datamodel,
|
||||||
|
calendar_id : type_calendar_id,
|
||||||
|
from : {
|
||||||
|
year : int;
|
||||||
|
week : int;
|
||||||
|
},
|
||||||
|
to : {
|
||||||
|
year : int;
|
||||||
|
week : int;
|
||||||
|
}
|
||||||
|
) : string
|
||||||
|
{
|
||||||
|
const rows = calendar_view_table(
|
||||||
|
data,
|
||||||
|
calendar_id,
|
||||||
|
from,
|
||||||
|
to
|
||||||
|
);
|
||||||
|
return (
|
||||||
|
"<table>\n"
|
||||||
|
+
|
||||||
|
(
|
||||||
|
"\t<thead>\n"
|
||||||
|
+
|
||||||
|
"\t</thead>\n"
|
||||||
|
)
|
||||||
|
+
|
||||||
|
(
|
||||||
|
"\t<tbody>\n"
|
||||||
|
+
|
||||||
|
(
|
||||||
|
rows
|
||||||
|
.map(
|
||||||
|
(row) => (
|
||||||
|
"\t\t<tr>\n"
|
||||||
|
+
|
||||||
|
(
|
||||||
|
row
|
||||||
|
.map(
|
||||||
|
(cell) => (
|
||||||
|
"\t\t\t<td>\n"
|
||||||
|
+
|
||||||
|
// (cell.entries.map(entry => entry.event.name).join(" | ") + "\n")
|
||||||
|
JSON.stringify(cell) + "\n"
|
||||||
|
+
|
||||||
|
"\t\t\t</td>\n"
|
||||||
|
)
|
||||||
|
)
|
||||||
|
.join("")
|
||||||
|
)
|
||||||
|
+
|
||||||
|
"\t\t</tr>\n"
|
||||||
|
)
|
||||||
|
)
|
||||||
|
.join("")
|
||||||
|
)
|
||||||
|
+
|
||||||
|
"\t</tbody>\n"
|
||||||
|
)
|
||||||
|
+
|
||||||
|
"</table>\n"
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
*/
|
||||||
|
function main(
|
||||||
|
) : void
|
||||||
|
{
|
||||||
|
const data : type_datamodel = {
|
||||||
|
"users": [
|
||||||
|
{
|
||||||
|
"id": 1,
|
||||||
|
"object": {
|
||||||
|
"name": "Anton"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 2,
|
||||||
|
"object": {
|
||||||
|
"name": "Berta"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 3,
|
||||||
|
"object": {
|
||||||
|
"name": "Caesar"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
],
|
||||||
|
"calendars": [
|
||||||
|
{
|
||||||
|
"id": 1,
|
||||||
|
"object": {
|
||||||
|
"kind": "concrete",
|
||||||
|
"data": {
|
||||||
|
"name": "Garten",
|
||||||
|
"users": [
|
||||||
|
{
|
||||||
|
"id": 1,
|
||||||
|
"role": "editor"
|
||||||
|
},
|
||||||
|
],
|
||||||
|
"events": [
|
||||||
|
{
|
||||||
|
"name": "Unkraut jähten",
|
||||||
|
"begin": {
|
||||||
|
"timezone": "Europe/Berlin",
|
||||||
|
"date": {"year": 2024, "month": 9, "day": 19},
|
||||||
|
"time": {"hour": 10, "minute": 0, "second": 0}
|
||||||
|
},
|
||||||
|
"end": null,
|
||||||
|
"description": null
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Kartoffeln ernten",
|
||||||
|
"begin": {
|
||||||
|
"timezone": "Europe/Berlin",
|
||||||
|
"date": {"year": 2024, "month": 9, "day": 24},
|
||||||
|
"time": {"hour": 17, "minute": 0, "second": 0}
|
||||||
|
},
|
||||||
|
"end": {
|
||||||
|
"timezone": "Europe/Berlin",
|
||||||
|
"date": {"year": 2024, "month": 9, "day": 24},
|
||||||
|
"time": {"hour": 20, "minute": 0, "second": 0}
|
||||||
|
},
|
||||||
|
"description": null
|
||||||
|
},
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 2,
|
||||||
|
"object": {
|
||||||
|
"kind": "concrete",
|
||||||
|
"data": {
|
||||||
|
"name": "Kochen",
|
||||||
|
"users": [
|
||||||
|
{
|
||||||
|
"id": 1,
|
||||||
|
"role": "editor"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 2,
|
||||||
|
"role": "viewer"
|
||||||
|
},
|
||||||
|
],
|
||||||
|
"events": [
|
||||||
|
{
|
||||||
|
"name": "38.KW",
|
||||||
|
"begin": {
|
||||||
|
"timezone": "Europe/Berlin",
|
||||||
|
"date": {"year": 2024, "month": 9, "day": 20},
|
||||||
|
"time": {"hour": 17, "minute": 0, "second": 0}
|
||||||
|
},
|
||||||
|
"end": {
|
||||||
|
"timezone": "Europe/Berlin",
|
||||||
|
"date": {"year": 2024, "month": 9, "day": 20},
|
||||||
|
"time": {"hour": 19, "minute": 0, "second": 0}
|
||||||
|
},
|
||||||
|
"description": "Krautnudeln"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 3,
|
||||||
|
"object": {
|
||||||
|
"kind": "concrete",
|
||||||
|
"data": {
|
||||||
|
"name": "Band",
|
||||||
|
"users": [
|
||||||
|
{
|
||||||
|
"id": 2,
|
||||||
|
"role": "editor"
|
||||||
|
},
|
||||||
|
],
|
||||||
|
"events": [
|
||||||
|
{
|
||||||
|
"name": "Auftritt im Park",
|
||||||
|
"begin": {
|
||||||
|
"timezone": "Europe/Berlin",
|
||||||
|
"date": {"year": 2024, "month": 9, "day": 21},
|
||||||
|
"time": {"hour": 20, "minute": 0, "second": 0}
|
||||||
|
},
|
||||||
|
"end": {
|
||||||
|
"timezone": "Europe/Berlin",
|
||||||
|
"date": {"year": 2024, "month": 9, "day": 21},
|
||||||
|
"time": {"hour": 21, "minute": 0, "second": 0}
|
||||||
|
},
|
||||||
|
"description": null
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 4,
|
||||||
|
"object": {
|
||||||
|
"kind": "collection",
|
||||||
|
"data": {
|
||||||
|
"name": "Überblick",
|
||||||
|
"sources": [
|
||||||
|
1,
|
||||||
|
2,
|
||||||
|
3
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
]
|
||||||
|
};
|
||||||
|
const output : string = calendar_view_table_html(
|
||||||
|
data,
|
||||||
|
4,
|
||||||
|
{
|
||||||
|
"year": 2024,
|
||||||
|
"week": 37
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"year": 2024,
|
||||||
|
"week": 40
|
||||||
|
}
|
||||||
|
);
|
||||||
|
process.stdout.write(output);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
main();
|
||||||
|
|
4
tools/build
Executable file
4
tools/build
Executable file
|
@ -0,0 +1,4 @@
|
||||||
|
#!/usr/bin/env sh
|
||||||
|
|
||||||
|
make -f tools/makefile
|
||||||
|
|
31
tools/makefile
Normal file
31
tools/makefile
Normal file
|
@ -0,0 +1,31 @@
|
||||||
|
## dirs
|
||||||
|
|
||||||
|
dir_source := source
|
||||||
|
dir_temp := temp
|
||||||
|
dir_build := build
|
||||||
|
|
||||||
|
|
||||||
|
## cmds
|
||||||
|
|
||||||
|
cmd_log := echo "--"
|
||||||
|
cmd_tsc := tsc --strict
|
||||||
|
cmd_cat := cat
|
||||||
|
cmd_mkdir := mkdir -p
|
||||||
|
|
||||||
|
|
||||||
|
## rules
|
||||||
|
|
||||||
|
.PHONY: _default
|
||||||
|
_default: ${dir_build}/kalender
|
||||||
|
|
||||||
|
${dir_temp}/kalender-unlinked.js: ${dir_source}/main.ts
|
||||||
|
@ ${cmd_log} "compiling …"
|
||||||
|
@ ${cmd_mkdir} $(dir $@)
|
||||||
|
@ ${cmd_tsc} $^ --outFile $@
|
||||||
|
|
||||||
|
${dir_build}/kalender: ${dir_temp}/kalender-unlinked.js
|
||||||
|
@ ${cmd_log} "linking …"
|
||||||
|
@ ${cmd_mkdir} $(dir $@)
|
||||||
|
@ ${cmd_cat} $^ > $@
|
||||||
|
@ chmod +x $@
|
||||||
|
|
Loading…
Add table
Reference in a new issue