[int]
This commit is contained in:
parent
7ead0d85bc
commit
ec775a0178
10 changed files with 641 additions and 194 deletions
|
@ -11,14 +11,30 @@ namespace _zeitbild.api
|
||||||
register<
|
register<
|
||||||
{
|
{
|
||||||
name : string;
|
name : string;
|
||||||
public : boolean;
|
access : {
|
||||||
members : Array<
|
default_level : ("none" | "view" | "edit" | "admin");
|
||||||
|
attributed : Array<
|
||||||
|
{
|
||||||
|
user_id : int;
|
||||||
|
level : ("none" | "view" | "edit" | "admin");
|
||||||
|
}
|
||||||
|
>;
|
||||||
|
};
|
||||||
|
resource : (
|
||||||
{
|
{
|
||||||
user_id : user_id;
|
kind : "local";
|
||||||
role : role;
|
data : {
|
||||||
|
};
|
||||||
}
|
}
|
||||||
>;
|
|
|
||||||
resource_id : resource_id;
|
{
|
||||||
|
kind : "caldav";
|
||||||
|
data : {
|
||||||
|
url : string;
|
||||||
|
read_only : boolean;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
);
|
||||||
},
|
},
|
||||||
int
|
int
|
||||||
>(
|
>(
|
||||||
|
@ -33,12 +49,65 @@ namespace _zeitbild.api
|
||||||
}),
|
}),
|
||||||
"restriction": restriction_logged_in,
|
"restriction": restriction_logged_in,
|
||||||
"execution": async (stuff) => {
|
"execution": async (stuff) => {
|
||||||
|
const session : {key : string; value : lib_plankton.session.type_session;} = await session_from_stuff(stuff);
|
||||||
|
const user_id : _zeitbild.type_user_id = await _zeitbild.service.user.identify(session.value.name);
|
||||||
|
|
||||||
|
// TODO move logic to calendar service
|
||||||
|
const resource_object : _zeitbild.type_resource_object = (
|
||||||
|
{
|
||||||
|
"local": {
|
||||||
|
"kind": "local",
|
||||||
|
"data": {
|
||||||
|
"events": [],
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"caldav": {
|
||||||
|
"kind": "caldav",
|
||||||
|
"data": {
|
||||||
|
"url": stuff.input.resource.data.url,
|
||||||
|
"read_only": stuff.input.resource.data.read_only,
|
||||||
|
}
|
||||||
|
},
|
||||||
|
}[stuff.input.resource.kind]
|
||||||
|
);
|
||||||
|
const resource_id : _zeitbild.type_resource_id = _zeitbild.service.resource.add(
|
||||||
|
resource_object
|
||||||
|
);
|
||||||
|
const calendar_object : _zeitbild.type_calendar_object = {
|
||||||
|
"name": stuff.input.name,
|
||||||
|
"access": {
|
||||||
|
"default_level": _zeitbild.value_object.access_level.from_string(stuff.input.access.default_level),
|
||||||
|
"attributed": lib_plankton.map.hashmap.make(
|
||||||
|
x => x.toFixed(0),
|
||||||
|
{
|
||||||
|
"pairs": (
|
||||||
|
stuff.input.access.attributed
|
||||||
|
.map(
|
||||||
|
(entry) => ({
|
||||||
|
"key": entry.user_id,
|
||||||
|
"value": _zeitbild.value_object.access_level.from_string(entry.level),
|
||||||
|
})
|
||||||
|
)
|
||||||
|
.concat(
|
||||||
|
[
|
||||||
|
{
|
||||||
|
"key": user_id,
|
||||||
|
"value": _zeitbild.enum_access_level.admin,
|
||||||
|
}
|
||||||
|
]
|
||||||
|
)
|
||||||
|
),
|
||||||
|
}
|
||||||
|
)
|
||||||
|
},
|
||||||
|
"resource_id": resource_id
|
||||||
|
};
|
||||||
return (
|
return (
|
||||||
_zeitbild.service.calendar.overview(user_id)
|
_zeitbild.service.calendar.add(calendar_object)
|
||||||
.then(
|
.then(
|
||||||
data => Promise.resolve({
|
(calendar_id : _zeitbild.type_calendar_id) => Promise.resolve({
|
||||||
"status_code": 200,
|
"status_code": 200,
|
||||||
"data": data,
|
"data": calendar_id,
|
||||||
})
|
})
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
|
|
101
source/api/actions/calendar_event_add.ts
Normal file
101
source/api/actions/calendar_event_add.ts
Normal file
|
@ -0,0 +1,101 @@
|
||||||
|
|
||||||
|
namespace _zeitbild.api
|
||||||
|
{
|
||||||
|
|
||||||
|
/**
|
||||||
|
*/
|
||||||
|
export function register_calendar_event_add(
|
||||||
|
rest_subject : lib_plankton.rest.type_rest
|
||||||
|
) : void
|
||||||
|
{
|
||||||
|
register<
|
||||||
|
{
|
||||||
|
calendar_id : int;
|
||||||
|
event : _zeitbild.type_event_object; // TODO aufdröseln
|
||||||
|
},
|
||||||
|
null
|
||||||
|
>(
|
||||||
|
rest_subject,
|
||||||
|
lib_plankton.http.enum_method.post,
|
||||||
|
"/calendar/event_add",
|
||||||
|
{
|
||||||
|
"description": "fügt einen Termin hinzu",
|
||||||
|
"input_schema": () => ({
|
||||||
|
"nullable": false,
|
||||||
|
"type": "object",
|
||||||
|
"properties": {
|
||||||
|
"calendar_id": {
|
||||||
|
"nullable": false,
|
||||||
|
"type": "integer",
|
||||||
|
},
|
||||||
|
"event": {
|
||||||
|
"nullable": false,
|
||||||
|
"type": "object",
|
||||||
|
"properties": {
|
||||||
|
"name": {
|
||||||
|
"nullable": false,
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"name": {
|
||||||
|
"nullable": false,
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
// TODO: fix
|
||||||
|
"begin": {
|
||||||
|
"type": "int",
|
||||||
|
"nullable": false,
|
||||||
|
},
|
||||||
|
// TODO: fix
|
||||||
|
"end": {
|
||||||
|
"type": "int",
|
||||||
|
"nullable": true,
|
||||||
|
},
|
||||||
|
"location": {
|
||||||
|
"type": "string",
|
||||||
|
"nullable": true,
|
||||||
|
},
|
||||||
|
"description": {
|
||||||
|
"type": "string",
|
||||||
|
"nullable": true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
"required": [
|
||||||
|
"name",
|
||||||
|
"begin",
|
||||||
|
"end",
|
||||||
|
"location",
|
||||||
|
"description",
|
||||||
|
],
|
||||||
|
"additionalProperties": false
|
||||||
|
},
|
||||||
|
},
|
||||||
|
"required": [
|
||||||
|
"calendar_id",
|
||||||
|
"event",
|
||||||
|
],
|
||||||
|
"additionalProperties": false
|
||||||
|
}),
|
||||||
|
"output_schema": () => ({
|
||||||
|
"nullable": true,
|
||||||
|
"type": "null"
|
||||||
|
}),
|
||||||
|
"restriction": restriction_logged_in,
|
||||||
|
"execution": async (stuff) => {
|
||||||
|
return (
|
||||||
|
_zeitbild.service.calendar.event_add(
|
||||||
|
stuff.input.calendar_id,
|
||||||
|
stuff.input.event
|
||||||
|
)
|
||||||
|
.then(
|
||||||
|
() => Promise.resolve({
|
||||||
|
"status_code": 200,
|
||||||
|
"data": null,
|
||||||
|
})
|
||||||
|
)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -67,10 +67,12 @@ namespace _zeitbild.api
|
||||||
"type": "string",
|
"type": "string",
|
||||||
"nullable": false,
|
"nullable": false,
|
||||||
},
|
},
|
||||||
|
// TODO: fix
|
||||||
"begin": {
|
"begin": {
|
||||||
"type": "int",
|
"type": "int",
|
||||||
"nullable": false,
|
"nullable": false,
|
||||||
},
|
},
|
||||||
|
// TODO: fix
|
||||||
"end": {
|
"end": {
|
||||||
"type": "int",
|
"type": "int",
|
||||||
"nullable": true,
|
"nullable": true,
|
||||||
|
@ -100,7 +102,7 @@ namespace _zeitbild.api
|
||||||
],
|
],
|
||||||
}
|
}
|
||||||
}),
|
}),
|
||||||
"restriction": restriction_none, // TODO
|
"restriction": restriction_logged_in,
|
||||||
"execution": async (stuff) => {
|
"execution": async (stuff) => {
|
||||||
const session : {key : string; value : lib_plankton.session.type_session;} = await session_from_stuff(stuff);
|
const session : {key : string; value : lib_plankton.session.type_session;} = await session_from_stuff(stuff);
|
||||||
const user_id : _zeitbild.type_user_id = await _zeitbild.service.user.identify(session.value.name);
|
const user_id : _zeitbild.type_user_id = await _zeitbild.service.user.identify(session.value.name);
|
||||||
|
|
|
@ -34,6 +34,8 @@ namespace _zeitbild.api
|
||||||
// calendar
|
// calendar
|
||||||
{
|
{
|
||||||
_zeitbild.api.register_calendar_list(rest_subject);
|
_zeitbild.api.register_calendar_list(rest_subject);
|
||||||
|
_zeitbild.api.register_calendar_add(rest_subject);
|
||||||
|
_zeitbild.api.register_calendar_event_add(rest_subject);
|
||||||
}
|
}
|
||||||
// misc
|
// misc
|
||||||
{
|
{
|
||||||
|
|
182
source/repositories/local_resource_event.ts
Normal file
182
source/repositories/local_resource_event.ts
Normal file
|
@ -0,0 +1,182 @@
|
||||||
|
|
||||||
|
namespace _zeitbild.repository.local_resource_event
|
||||||
|
{
|
||||||
|
|
||||||
|
/**
|
||||||
|
*/
|
||||||
|
var _store : (
|
||||||
|
null
|
||||||
|
|
|
||||||
|
lib_plankton.storage.type_store<
|
||||||
|
int,
|
||||||
|
Record<string, any>,
|
||||||
|
{},
|
||||||
|
lib_plankton.storage.type_sql_table_autokey_search_term,
|
||||||
|
Record<string, any>
|
||||||
|
>
|
||||||
|
) = null;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
*/
|
||||||
|
function get_store(
|
||||||
|
) : lib_plankton.storage.type_store<
|
||||||
|
int,
|
||||||
|
Record<string, any>,
|
||||||
|
{},
|
||||||
|
lib_plankton.storage.type_sql_table_autokey_search_term,
|
||||||
|
Record<string, any>
|
||||||
|
>
|
||||||
|
{
|
||||||
|
if (_store === null) {
|
||||||
|
_store = lib_plankton.storage.sql_table_autokey_store(
|
||||||
|
{
|
||||||
|
"database_implementation": _zeitbild.database.get_implementation(),
|
||||||
|
"table_name": "events",
|
||||||
|
"key_name": "id",
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
// do nothing
|
||||||
|
}
|
||||||
|
return _store;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
*/
|
||||||
|
function encode(
|
||||||
|
event : _zeitbild.type_event_object,
|
||||||
|
local_resource_id : int
|
||||||
|
) : Record<string, any>
|
||||||
|
{
|
||||||
|
const encode_datetime : ((datetime : _zeitbild.helpers.type_datetime) => string) = ((datetime) => {
|
||||||
|
return lib_plankton.string.coin(
|
||||||
|
"{{timezone_shift}}|{{date}}{{macro_time}}",
|
||||||
|
{
|
||||||
|
"timezone_shift": datetime.timezone_shift.toFixed(0).padStart(2, "0"),
|
||||||
|
"date": lib_plankton.string.coin(
|
||||||
|
"{{year}}-{{month}}-{{day}}",
|
||||||
|
{
|
||||||
|
"year": datetime.date.year.toFixed(0).padStart(4, "0"),
|
||||||
|
"month": datetime.date.month.toFixed(0).padStart(2, "0"),
|
||||||
|
"day": datetime.date.day.toFixed(0).padStart(2, "0"),
|
||||||
|
}
|
||||||
|
),
|
||||||
|
"macro_time": (
|
||||||
|
(datetime.time === null)
|
||||||
|
?
|
||||||
|
""
|
||||||
|
:
|
||||||
|
lib_plankton.string.coin(
|
||||||
|
"T{{hour}}:{{minute}}:{{second}}",
|
||||||
|
{
|
||||||
|
"hour": datetime.time.hour.toFixed(0).padStart(2, "0"),
|
||||||
|
"minute": datetime.time.minute.toFixed(0).padStart(2, "0"),
|
||||||
|
"second": datetime.time.second.toFixed(0).padStart(2, "0"),
|
||||||
|
}
|
||||||
|
)
|
||||||
|
),
|
||||||
|
}
|
||||||
|
);
|
||||||
|
});
|
||||||
|
return {
|
||||||
|
"local_resource_id": local_resource_id,
|
||||||
|
"name": event.name,
|
||||||
|
"begin": encode_datetime(event.begin),
|
||||||
|
"end": (
|
||||||
|
(event.end === null)
|
||||||
|
?
|
||||||
|
null
|
||||||
|
:
|
||||||
|
encode_datetime(event.end)
|
||||||
|
),
|
||||||
|
"location": event.location,
|
||||||
|
"description": event.description,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
*/
|
||||||
|
function decode(
|
||||||
|
row : Record<string, any>
|
||||||
|
) : _zeitbild.type_event_object
|
||||||
|
{
|
||||||
|
const decode_datetime : ((datetime_raw : string) => _zeitbild.helpers.type_datetime) = ((datetime_raw) => {
|
||||||
|
const parts : Array<string> = datetime_raw.split("|");
|
||||||
|
const timezone_shift : int = parseInt(parts[0]);
|
||||||
|
if (parts[1].length <= 10) {
|
||||||
|
return {
|
||||||
|
"timezone_shift": timezone_shift,
|
||||||
|
"date": {
|
||||||
|
"year": parseInt(parts[1].slice(0, 4)),
|
||||||
|
"month": parseInt(parts[1].slice(5, 7)),
|
||||||
|
"day": parseInt(parts[1].slice(8, 10)),
|
||||||
|
},
|
||||||
|
"time": null
|
||||||
|
};
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
return {
|
||||||
|
"timezone_shift": timezone_shift,
|
||||||
|
"date": {
|
||||||
|
"year": parseInt(parts[1].slice(0, 4)),
|
||||||
|
"month": parseInt(parts[1].slice(5, 7)),
|
||||||
|
"day": parseInt(parts[1].slice(8, 10)),
|
||||||
|
},
|
||||||
|
"time": {
|
||||||
|
"hour": parseInt(parts[1].slice(11, 13)),
|
||||||
|
"minute": parseInt(parts[1].slice(14, 16)),
|
||||||
|
"second": parseInt(parts[1].slice(17, 19)),
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
});
|
||||||
|
return {
|
||||||
|
"name": row["name"],
|
||||||
|
"begin": decode_datetime(row["begin"]),
|
||||||
|
"end": (
|
||||||
|
(row["end"] === null)
|
||||||
|
?
|
||||||
|
null
|
||||||
|
:
|
||||||
|
decode_datetime(row["end"])
|
||||||
|
),
|
||||||
|
"location": row["location"],
|
||||||
|
"description": row["description"],
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
*/
|
||||||
|
function read(
|
||||||
|
event_id : _zeitbild.type_local_resource_event_id
|
||||||
|
) : Promise<_zeitbild.type_event_object>
|
||||||
|
{
|
||||||
|
return (
|
||||||
|
get_store().read(event_id)
|
||||||
|
.then(
|
||||||
|
row => Promise.resolve<_zeitbild.type_event_object>(decode(row))
|
||||||
|
)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
*/
|
||||||
|
function create(
|
||||||
|
event_object : _zeitbild.type_event_object
|
||||||
|
) : Promise<_zeitbild.type_local_resource_event_id>
|
||||||
|
{
|
||||||
|
return (
|
||||||
|
Promise.resolve(encode(event_object))
|
||||||
|
.then(
|
||||||
|
(row) => get_store().create(row)
|
||||||
|
)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -4,14 +4,14 @@ namespace _zeitbild.repository.resource
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*/
|
*/
|
||||||
var _local_resource_core_store : (
|
var _local_resource_event_chest : (
|
||||||
null
|
null
|
||||||
|
|
|
|
||||||
lib_plankton.storage.type_store<
|
lib_plankton.storage.type_chest<
|
||||||
int,
|
Array<any>,
|
||||||
Record<string, any>,
|
Record<string, any>,
|
||||||
{},
|
lib_plankton.database.type_description_create_table,
|
||||||
lib_plankton.storage.type_sql_table_autokey_search_term,
|
lib_plankton.storage.sql_table_common.type_sql_table_common_search_term,
|
||||||
Record<string, any>
|
Record<string, any>
|
||||||
>
|
>
|
||||||
) = null;
|
) = null;
|
||||||
|
@ -19,7 +19,7 @@ namespace _zeitbild.repository.resource
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*/
|
*/
|
||||||
var _local_resource_event_store : (
|
var _local_resource_core_store : (
|
||||||
null
|
null
|
||||||
|
|
|
|
||||||
lib_plankton.storage.type_store<
|
lib_plankton.storage.type_store<
|
||||||
|
@ -62,6 +62,33 @@ namespace _zeitbild.repository.resource
|
||||||
) = null;
|
) = null;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
*/
|
||||||
|
function get_local_resource_event_chest(
|
||||||
|
) : lib_plankton.storage.type_chest<
|
||||||
|
Array<any>,
|
||||||
|
Record<string, any>,
|
||||||
|
lib_plankton.database.type_description_create_table,
|
||||||
|
lib_plankton.storage.sql_table_common.type_sql_table_common_search_term,
|
||||||
|
Record<string, any>
|
||||||
|
>
|
||||||
|
{
|
||||||
|
if (_local_resource_event_chest === null) {
|
||||||
|
_local_resource_event_chest = lib_plankton.storage.sql_table_common.chest(
|
||||||
|
{
|
||||||
|
"database_implementation": _zeitbild.database.get_implementation(),
|
||||||
|
"table_name": "local_resource_events",
|
||||||
|
"key_names": ["local_resource_id","event_id"],
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
// do nothing
|
||||||
|
}
|
||||||
|
return _local_resource_event_chest;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*/
|
*/
|
||||||
function get_local_resource_core_store(
|
function get_local_resource_core_store(
|
||||||
|
@ -89,33 +116,6 @@ namespace _zeitbild.repository.resource
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
*/
|
|
||||||
function get_local_resource_event_store(
|
|
||||||
) : lib_plankton.storage.type_store<
|
|
||||||
int,
|
|
||||||
Record<string, any>,
|
|
||||||
{},
|
|
||||||
lib_plankton.storage.type_sql_table_autokey_search_term,
|
|
||||||
Record<string, any>
|
|
||||||
>
|
|
||||||
{
|
|
||||||
if (_local_resource_event_store === null) {
|
|
||||||
_local_resource_event_store = lib_plankton.storage.sql_table_autokey_store(
|
|
||||||
{
|
|
||||||
"database_implementation": _zeitbild.database.get_implementation(),
|
|
||||||
"table_name": "local_resource_events",
|
|
||||||
"key_name": "id",
|
|
||||||
}
|
|
||||||
);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
// do nothing
|
|
||||||
}
|
|
||||||
return _local_resource_event_store;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*/
|
*/
|
||||||
function get_caldav_resource_store(
|
function get_caldav_resource_store(
|
||||||
|
@ -210,144 +210,6 @@ namespace _zeitbild.repository.resource
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
*/
|
|
||||||
function encode_event(
|
|
||||||
event : _zeitbild.type_event_object,
|
|
||||||
local_resource_id : int
|
|
||||||
) : Record<string, any>
|
|
||||||
{
|
|
||||||
/*
|
|
||||||
const decode_datetime : ((datetime_raw : string) => _zeitbild.helpers.type_datetime) = ((datetime_raw) => {
|
|
||||||
const parts : Array<string> = datetime_raw.split("|");
|
|
||||||
const timezone_shift : int = parseInt(parts[0]);
|
|
||||||
if (parts[1].length <= 10) {
|
|
||||||
return {
|
|
||||||
"timezone_shift": timezone_shift,
|
|
||||||
"date": {
|
|
||||||
"year": parseInt(parts[1].slice(0, 4)),
|
|
||||||
"month": parseInt(parts[1].slice(5, 7)),
|
|
||||||
"day": parseInt(parts[1].slice(8, 10)),
|
|
||||||
},
|
|
||||||
"time": null
|
|
||||||
};
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
return {
|
|
||||||
"timezone_shift": timezone_shift,
|
|
||||||
"date": {
|
|
||||||
"year": parseInt(parts[1].slice(0, 4)),
|
|
||||||
"month": parseInt(parts[1].slice(5, 7)),
|
|
||||||
"day": parseInt(parts[1].slice(8, 10)),
|
|
||||||
},
|
|
||||||
"time": {
|
|
||||||
"hour": parseInt(parts[1].slice(11, 13)),
|
|
||||||
"minute": parseInt(parts[1].slice(14, 16)),
|
|
||||||
"second": parseInt(parts[1].slice(17, 19)),
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
});
|
|
||||||
*/
|
|
||||||
const encode_datetime : ((datetime : _zeitbild.helpers.type_datetime) => string) = ((datetime) => {
|
|
||||||
return lib_plankton.string.coin(
|
|
||||||
"{{timezone_shift}}|{{date}}{{macro_time}}",
|
|
||||||
{
|
|
||||||
"timezone_shift": datetime.timezone_shift.toFixed(0).padStart(2, "0"),
|
|
||||||
"date": lib_plankton.string.coin(
|
|
||||||
"{{year}}-{{month}}-{{day}}",
|
|
||||||
{
|
|
||||||
"year": datetime.date.year.toFixed(0).padStart(4, "0"),
|
|
||||||
"month": datetime.date.month.toFixed(0).padStart(2, "0"),
|
|
||||||
"day": datetime.date.day.toFixed(0).padStart(2, "0"),
|
|
||||||
}
|
|
||||||
),
|
|
||||||
"macro_time": (
|
|
||||||
(datetime.time === null)
|
|
||||||
?
|
|
||||||
""
|
|
||||||
:
|
|
||||||
lib_plankton.string.coin(
|
|
||||||
"T{{hour}}:{{minute}}:{{second}}",
|
|
||||||
{
|
|
||||||
"hour": datetime.time.hour.toFixed(0).padStart(2, "0"),
|
|
||||||
"minute": datetime.time.minute.toFixed(0).padStart(2, "0"),
|
|
||||||
"second": datetime.time.second.toFixed(0).padStart(2, "0"),
|
|
||||||
}
|
|
||||||
)
|
|
||||||
),
|
|
||||||
}
|
|
||||||
);
|
|
||||||
});
|
|
||||||
return {
|
|
||||||
"local_resource_id": local_resource_id,
|
|
||||||
"name": event.name,
|
|
||||||
"begin": encode_datetime(event.begin),
|
|
||||||
"end": (
|
|
||||||
(event.end === null)
|
|
||||||
?
|
|
||||||
null
|
|
||||||
:
|
|
||||||
encode_datetime(event.end)
|
|
||||||
),
|
|
||||||
"location": event.location,
|
|
||||||
"description": event.description,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
*/
|
|
||||||
function decode_event(
|
|
||||||
row : Record<string, any>
|
|
||||||
) : _zeitbild.type_event_object
|
|
||||||
{
|
|
||||||
const decode_datetime : ((datetime_raw : string) => _zeitbild.helpers.type_datetime) = ((datetime_raw) => {
|
|
||||||
const parts : Array<string> = datetime_raw.split("|");
|
|
||||||
const timezone_shift : int = parseInt(parts[0]);
|
|
||||||
if (parts[1].length <= 10) {
|
|
||||||
return {
|
|
||||||
"timezone_shift": timezone_shift,
|
|
||||||
"date": {
|
|
||||||
"year": parseInt(parts[1].slice(0, 4)),
|
|
||||||
"month": parseInt(parts[1].slice(5, 7)),
|
|
||||||
"day": parseInt(parts[1].slice(8, 10)),
|
|
||||||
},
|
|
||||||
"time": null
|
|
||||||
};
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
return {
|
|
||||||
"timezone_shift": timezone_shift,
|
|
||||||
"date": {
|
|
||||||
"year": parseInt(parts[1].slice(0, 4)),
|
|
||||||
"month": parseInt(parts[1].slice(5, 7)),
|
|
||||||
"day": parseInt(parts[1].slice(8, 10)),
|
|
||||||
},
|
|
||||||
"time": {
|
|
||||||
"hour": parseInt(parts[1].slice(11, 13)),
|
|
||||||
"minute": parseInt(parts[1].slice(14, 16)),
|
|
||||||
"second": parseInt(parts[1].slice(17, 19)),
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
});
|
|
||||||
return {
|
|
||||||
"name": row["name"],
|
|
||||||
"begin": decode_datetime(row["begin"]),
|
|
||||||
"end": (
|
|
||||||
(row["end"] === null)
|
|
||||||
?
|
|
||||||
null
|
|
||||||
:
|
|
||||||
decode_datetime(row["end"])
|
|
||||||
),
|
|
||||||
"location": row["location"],
|
|
||||||
"description": row["description"],
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*/
|
*/
|
||||||
export async function read(
|
export async function read(
|
||||||
|
@ -358,7 +220,7 @@ namespace _zeitbild.repository.resource
|
||||||
switch (dataset_core.kind) {
|
switch (dataset_core.kind) {
|
||||||
case "local": {
|
case "local": {
|
||||||
const dataset_extra_local_core : Record<string, any> = await get_local_resource_core_store().read(dataset_core.sub_id);
|
const dataset_extra_local_core : Record<string, any> = await get_local_resource_core_store().read(dataset_core.sub_id);
|
||||||
const datasets_extra_local_events : Array<Record<string, any>> = await get_local_resource_event_store().search(
|
const datasets_extra_local_event_ids : Array<Record<string, any>> = await get_local_resource_event_chest().search(
|
||||||
{
|
{
|
||||||
"expression": "(local_resource_id = $local_resource_id)",
|
"expression": "(local_resource_id = $local_resource_id)",
|
||||||
"arguments": {
|
"arguments": {
|
||||||
|
@ -370,7 +232,10 @@ namespace _zeitbild.repository.resource
|
||||||
{
|
{
|
||||||
"kind": "local",
|
"kind": "local",
|
||||||
"data": {
|
"data": {
|
||||||
"events": datasets_extra_local_events.map(x => decode_event(x.preview)),
|
"event_ids": (
|
||||||
|
datasets_extra_local_event_ids
|
||||||
|
.map((hit) => hit.preview["event_id"])
|
||||||
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
@ -411,12 +276,9 @@ namespace _zeitbild.repository.resource
|
||||||
"_dummy": null,
|
"_dummy": null,
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
for await (const event of resource_object.data.events) {
|
for await (const event_id of resource_object.data.event_ids) {
|
||||||
get_local_resource_event_store().create(
|
await get_local_resource_event_chest().create(
|
||||||
encode_event(
|
[local_resource_id, event_id]
|
||||||
event,
|
|
||||||
local_resource_id
|
|
||||||
)
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
const resource_id : _zeitbild.type_resource_id = await get_resource_core_store().create(
|
const resource_id : _zeitbild.type_resource_id = await get_resource_core_store().create(
|
||||||
|
@ -445,10 +307,138 @@ namespace _zeitbild.repository.resource
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
default: {
|
default: {
|
||||||
throw (new Error("not implemended"));
|
throw (new Error("invalid resource kind: " + resource_object.kind));
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @todo allow kind change?
|
||||||
|
*/
|
||||||
|
export async function update(
|
||||||
|
resource_id : _zeitbild.type_resource_id,
|
||||||
|
resource_object : _zeitbild.type_resource_object
|
||||||
|
) : Promise<void>
|
||||||
|
{
|
||||||
|
const dataset_core : Record<string, any> = await get_resource_core_store().read(resource_id);
|
||||||
|
if (dataset_core["kind"] !== resource_object.kind) {
|
||||||
|
return Promise.reject(new Error("resource kind may not be altered"));
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
switch (resource_object.kind) {
|
||||||
|
case "local": {
|
||||||
|
// event_id list may not be altered directly
|
||||||
|
/*
|
||||||
|
const current_event_id_rows : {key : int; preview : Array<Record<string, any>>;} = await get_local_resource_event_chest().search(
|
||||||
|
{
|
||||||
|
"expression": "(local_resource_id = $local_resource_id)",
|
||||||
|
"arguments": {
|
||||||
|
"local_resource_id": dataset_core["sub_id"]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
);
|
||||||
|
const contrast : {
|
||||||
|
only_left : Array<{key : int; left : any;}>;
|
||||||
|
both : Array<{key : int; left : any; right : any;}>;
|
||||||
|
only_right : Array<{key : int; right : any;}>;
|
||||||
|
} = lib_plankton.list.contrast<
|
||||||
|
{key : Array<any>; preview : Record<string, any>;},
|
||||||
|
_zeitbild.type_local_resource_event_id
|
||||||
|
>(
|
||||||
|
event_rows,
|
||||||
|
(hit => hit.key),
|
||||||
|
resource_object.data.event_ids,
|
||||||
|
(x => x)
|
||||||
|
);
|
||||||
|
// TODO: single delete?
|
||||||
|
for await (const entry of constrast.only_left) {
|
||||||
|
await get_local_resource_event_store().delete(
|
||||||
|
entry.key
|
||||||
|
);
|
||||||
|
}
|
||||||
|
/*
|
||||||
|
for await (const entry of contrast.both) {
|
||||||
|
await get_local_resource_event_store().update(
|
||||||
|
entry.left.key,
|
||||||
|
encode_event(entry.right.object)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
for await (const entry of contrast.only_right) {
|
||||||
|
const event_id : type_local_resource_event_id = await get_local_resource_event_store().create(
|
||||||
|
encode_event(entry.right.object)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case "caldav": {
|
||||||
|
await get_caldav_resource_store().update(
|
||||||
|
dataset_core["sub_id"],
|
||||||
|
{
|
||||||
|
"url": resource_object.data.url,
|
||||||
|
"read_only": resource_object.data.read_only,
|
||||||
|
}
|
||||||
|
);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
default: {
|
||||||
|
throw (new Error("invalid resource kind: " + resource_object.kind));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
*/
|
||||||
|
export function local_resource_event_add(
|
||||||
|
resource_id : _zeitbild.type_resource_id,
|
||||||
|
event_id : _zeitbild.type_event_id
|
||||||
|
) : Promise<void>
|
||||||
|
{
|
||||||
|
const dataset_core : Record<string, any> = await get_resource_core_store().read(resource_id);
|
||||||
|
if (! (dataset_core.kind === "local")) {
|
||||||
|
throw (new Error("not a local resource"));
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
return (
|
||||||
|
get_local_resource_event_chest().write(
|
||||||
|
[dataset_core["sub_id"], event_id],
|
||||||
|
{}
|
||||||
|
)
|
||||||
|
.then(
|
||||||
|
() => Promise.resolve(undefined)
|
||||||
|
)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
*/
|
||||||
|
export function local_resource_event_delete(
|
||||||
|
resource_id : _zeitbild.type_resource_id,
|
||||||
|
event_id : _zeitbild.type_event_id
|
||||||
|
) : Promise<void>
|
||||||
|
{
|
||||||
|
const dataset_core : Record<string, any> = await get_resource_core_store().read(resource_id);
|
||||||
|
if (! (dataset_core.kind === "local")) {
|
||||||
|
throw (new Error("not a local resource"));
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
return (
|
||||||
|
get_local_resource_event_chest().delete(
|
||||||
|
[dataset_core["sub_id"], event_id],
|
||||||
|
{}
|
||||||
|
)
|
||||||
|
.then(
|
||||||
|
() => Promise.resolve(undefined)
|
||||||
|
)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -69,6 +69,23 @@ namespace _zeitbild.service.calendar
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
*/
|
||||||
|
export async function event_add(
|
||||||
|
calendar_id : _zeitbild.type_calendar_id,
|
||||||
|
event_object : _zeitbild.type_event_object
|
||||||
|
) : Promise<void>
|
||||||
|
{
|
||||||
|
const calendar_object : _zeitbild.type_calendar_object = _zeitbild.repository.calendar.read(
|
||||||
|
calendar_id
|
||||||
|
);
|
||||||
|
return _zeitbild.repository.resource.event_add(
|
||||||
|
calendar_object.resource_id,
|
||||||
|
event_object
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*/
|
*/
|
||||||
async function get_events(
|
async function get_events(
|
||||||
|
|
|
@ -11,4 +11,82 @@ namespace _zeitbild.service.resource
|
||||||
return _zeitbild.repository.resource.create(resource_object);
|
return _zeitbild.repository.resource.create(resource_object);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
*/
|
||||||
|
export async function event_add(
|
||||||
|
resource_id : _zeitbild.type_resource_id,
|
||||||
|
event_object : _zeitbild.type_event_object
|
||||||
|
) : Promise<void>
|
||||||
|
{
|
||||||
|
const resource_object : _zeitbild.type_resource_object = _zeitbild.repository.resource.read(
|
||||||
|
resource_id
|
||||||
|
);
|
||||||
|
switch (resource_object.kind) {
|
||||||
|
case "local": {
|
||||||
|
const event_id : _zeitbild.type_event_id = await _zeitbild.repository.local_resource_event.create(
|
||||||
|
event_object
|
||||||
|
);
|
||||||
|
await _zeitbild.repository.resource.local_resource_event_add(
|
||||||
|
resource_id,
|
||||||
|
event_id
|
||||||
|
);
|
||||||
|
return Promise.resolve<void>(undefined);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case "caldav": {
|
||||||
|
if (resource_object.data.read_only) {
|
||||||
|
return Promise.reject(new Error("can not add event to read only caldav resource"));
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
// TODO
|
||||||
|
return Promise.reject(new Error("not implemented"));
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
default: {
|
||||||
|
throw (new Error("unhandled resource kind: " + resource_object.kind));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
*/
|
||||||
|
export async function event_remove(
|
||||||
|
resource_id : _zeitbild.type_resource_id,
|
||||||
|
event_object : _zeitbild.type_event_object
|
||||||
|
) : Promise<void>
|
||||||
|
{
|
||||||
|
const resource_object : _zeitbild.type_resource_object = _zeitbild.repository.resource.read(
|
||||||
|
resource_id
|
||||||
|
);
|
||||||
|
switch (resource_object.kind) {
|
||||||
|
case "local": {
|
||||||
|
const event_id : _zeitbild.type_event_id = await _zeitbild.repository.local_resource_event.create(
|
||||||
|
event_object
|
||||||
|
);
|
||||||
|
await _zeitbild.repository.resource.local_resource_event_delete(
|
||||||
|
resource_id,
|
||||||
|
event_id
|
||||||
|
);
|
||||||
|
return Promise.resolve<void>(undefined);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case "caldav": {
|
||||||
|
if (resource_object.data.read_only) {
|
||||||
|
return Promise.reject(new Error("can not delete event from read only caldav resource"));
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
// TODO
|
||||||
|
return Promise.reject(new Error("not implemented"));
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
default: {
|
||||||
|
throw (new Error("unhandled resource kind: " + resource_object.kind));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -31,6 +31,11 @@ namespace _zeitbild
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
*/
|
||||||
|
export type type_event_id = int;
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*/
|
*/
|
||||||
export type type_event_object = {
|
export type type_event_object = {
|
||||||
|
@ -65,17 +70,15 @@ namespace _zeitbild
|
||||||
{
|
{
|
||||||
kind : "local";
|
kind : "local";
|
||||||
data : {
|
data : {
|
||||||
events : Array<
|
event_ids : Array<type_event_id>;
|
||||||
type_event_object
|
|
||||||
>;
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
|
|
||||||
{
|
{
|
||||||
kind : "caldav";
|
kind : "caldav";
|
||||||
data : {
|
data : {
|
||||||
read_only : boolean;
|
|
||||||
url : string;
|
url : string;
|
||||||
|
read_only : boolean;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
|
@ -43,6 +43,7 @@ ${dir_temp}/zeitbild-unlinked.js: \
|
||||||
${dir_source}/value_objects/access_level.ts \
|
${dir_source}/value_objects/access_level.ts \
|
||||||
${dir_source}/repositories/auth_internal.ts \
|
${dir_source}/repositories/auth_internal.ts \
|
||||||
${dir_source}/repositories/user.ts \
|
${dir_source}/repositories/user.ts \
|
||||||
|
${dir_source}/repositories/local_resource_event.ts \
|
||||||
${dir_source}/repositories/resource.ts \
|
${dir_source}/repositories/resource.ts \
|
||||||
${dir_source}/repositories/calendar.ts \
|
${dir_source}/repositories/calendar.ts \
|
||||||
${dir_source}/services/auth_internal.ts \
|
${dir_source}/services/auth_internal.ts \
|
||||||
|
@ -57,6 +58,8 @@ ${dir_temp}/zeitbild-unlinked.js: \
|
||||||
${dir_source}/api/actions/session_oidc.ts \
|
${dir_source}/api/actions/session_oidc.ts \
|
||||||
${dir_source}/api/actions/session_end.ts \
|
${dir_source}/api/actions/session_end.ts \
|
||||||
${dir_source}/api/actions/calendar_list.ts \
|
${dir_source}/api/actions/calendar_list.ts \
|
||||||
|
${dir_source}/api/actions/calendar_add.ts \
|
||||||
|
${dir_source}/api/actions/calendar_event_add.ts \
|
||||||
${dir_source}/api/actions/events.ts \
|
${dir_source}/api/actions/events.ts \
|
||||||
${dir_source}/api/functions.ts \
|
${dir_source}/api/functions.ts \
|
||||||
${dir_source}/main.ts
|
${dir_source}/main.ts
|
||||||
|
|
Loading…
Add table
Reference in a new issue