backend/source/repositories/calendar.ts
2024-09-30 20:19:19 +02:00

444 lines
8.8 KiB
TypeScript

namespace _zeitbild.repository.calendar
{
/**
*/
type type_dispersal = {
core_row : Record<
string,
any
>;
access_attributed_rows : Array<
Record<
string,
any
>
>;
};
/**
*/
var _core_store : (
null
|
lib_plankton.storage.type_store<
_zeitbild.type_calendar_id,
Record<string, any>,
{},
lib_plankton.storage.type_sql_table_autokey_search_term,
Record<string, any>
>
) = null;
/**
*/
var _access_attributed_chest : (
null
|
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>
>
) = null;
/**
*/
function get_core_store(
) : lib_plankton.storage.type_store<
_zeitbild.type_calendar_id,
Record<string, any>,
{},
lib_plankton.storage.type_sql_table_autokey_search_term,
Record<string, any>
>
{
if (_core_store === null) {
_core_store = lib_plankton.storage.sql_table_autokey_store(
{
"database_implementation": _zeitbild.database.get_implementation(),
"table_name": "calendars",
"key_name": "id",
}
);
}
else {
// do nothing
}
return _core_store;
}
/**
*/
function get_access_attributed_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 (_access_attributed_chest === null) {
_access_attributed_chest = lib_plankton.storage.sql_table_common.chest(
{
"database_implementation": _zeitbild.database.get_implementation(),
"table_name": "calendar_access_attributed",
"key_names": ["calendar_id","user_id"],
}
);
}
else {
// do nothing
}
return _access_attributed_chest;
}
/**
*/
function encode_access_level(
access_level : _zeitbild.enum_access_level
) : int
{
return (
[
_zeitbild.enum_access_level.none,
_zeitbild.enum_access_level.view,
_zeitbild.enum_access_level.edit,
_zeitbild.enum_access_level.admin,
].indexOf(access_level)
);
}
/**
*/
function decode_access_level(
access_level_encoded : int
) : _zeitbild.enum_access_level
{
return (
[
_zeitbild.enum_access_level.none,
_zeitbild.enum_access_level.view,
_zeitbild.enum_access_level.edit,
_zeitbild.enum_access_level.admin,
][access_level_encoded]
);
}
/**
*/
function encode(
object : _zeitbild.type_calendar_object
) : type_dispersal
{
return {
"core_row": {
"name": object.name,
"access_level_default": encode_access_level(object.access.default_level),
"resource_id": object.resource_id,
},
"access_attributed_rows": (
lib_plankton.map.dump(object.access.attributed)
.map(
({"key": user_id, "value": level}) => ({
// "calendar_id": calendar_id,
"user_id": user_id,
"level": encode_access_level(level),
})
)
),
};
}
/**
*/
function decode(
dispersal : type_dispersal
) : _zeitbild.type_calendar_object
{
return {
"name": dispersal.core_row["name"],
"access": {
"default_level": decode_access_level(dispersal.core_row["access_level_default"]),
"attributed": lib_plankton.map.hashmap.implementation_map(
lib_plankton.map.hashmap.make<_zeitbild.type_user_id, _zeitbild.enum_access_level>(
x => x.toFixed(0),
{
"pairs": (
dispersal.access_attributed_rows
.map(
(access_attributed_row) => ({
// "calendar_id": access_attributed_row["calendar_id"],
"key": access_attributed_row["preview"]["user_id"],
"value": decode_access_level(access_attributed_row["preview"]["level"]),
})
)
),
}
)
),
},
"resource_id": dispersal.core_row["resource_id"],
};
}
/**
* @todo optimize
*/
export async function list(
search_term : (null | string)
) : Promise<
Array<
{
id : _zeitbild.type_calendar_id;
preview : {
name : string;
};
}
>
>
{
return (
(
await get_core_store().search(
{
"expression": "(public = TRUE)",
"arguments": {
}
}
)
)
.filter(
({"key": key, "preview": preview}) => (
(
(search_term === null)
||
(search_term.length <= 1)
)
? true
: (
preview["name"].toLowerCase().includes(search_term.toLowerCase())
)
)
)
.map(
({"key": key, "preview": preview}) => ({
"id": key,
"preview": {
"name": preview["name"],
}
})
)
);
}
/**
*/
export function read(
id : _zeitbild.type_calendar_id
) : Promise<_zeitbild.type_calendar_object>
{
return (
get_core_store().read(id)
.then(
(core_row) => (
get_access_attributed_chest().search(
{
"expression": "(calendar_id = $calendar_id)",
"arguments": {
"calendar_id": id,
}
}
)
.then(
(access_attributed_rows) => Promise.resolve<type_dispersal>(
{
"core_row": core_row,
"access_attributed_rows": access_attributed_rows,
}
)
)
.then(
(dispersal) => Promise.resolve<_zeitbild.type_calendar_object>(
decode(dispersal)
)
)
)
)
);
}
/**
*/
export async function create(
calendar_object : _zeitbild.type_calendar_object
) : Promise<_zeitbild.type_calendar_id>
{
const dispersal : type_dispersal = encode(calendar_object);
const core_store = get_core_store();
const calendar_id : _zeitbild.type_calendar_id = await core_store.create(
dispersal.core_row
);
for await (const access_attributed_row of dispersal.access_attributed_rows) {
get_access_attributed_chest().write(
[calendar_id, access_attributed_row["user_id"]],
{"level": access_attributed_row["level"]}
);
}
return Promise.resolve<_zeitbild.type_calendar_id>(calendar_id);
}
/**
*/
export async function update(
calendar_id : _zeitbild.type_calendar_id,
calendar_object : _zeitbild.type_calendar_object
) : Promise<void>
{
const dispersal : type_dispersal = encode(calendar_object);
// core
{
const core_store = get_core_store();
await core_store.update(
calendar_id,
dispersal.core_row
);
}
// attributed access
{
const access_attributed_chest = get_access_attributed_chest();
const hits : Array<Record<string, any>> = await access_attributed_chest.search(
{
"expression": "(calendar_id = $calendar_id)",
"arguments": {
"calendar_id": calendar_id,
}
}
);
const contrast = lib_plankton.list.contrast<
Record<string, any>,
Record<string, any>
>(
hits,
hit => hit["user_id"],
dispersal.access_attributed_rows,
row => row["user_id"]
);
// delete
for await (const entry of contrast.only_left) {
await access_attributed_chest.delete(
[calendar_id, entry.left["user_id"]]
);
}
// update
for await (const entry of contrast.both) {
await access_attributed_chest.write(
[calendar_id, entry.right["user_id"]],
{"level": entry.right["level"]}
);
}
// create
for await (const entry of contrast.only_right) {
await access_attributed_chest.write(
[calendar_id, entry.right["user_id"]],
{"level": entry.right["level"]}
);
}
}
return Promise.resolve<void>(undefined);
}
/**
* @todo remove events from resource?
*/
export async function delete_(
calendar_id : _zeitbild.type_calendar_id
) : Promise<void>
{
const core_store = get_core_store();
const access_attributed_chest = get_access_attributed_chest();
// attributed access
{
const hits : Array<Record<string, any>> = await access_attributed_chest.search(
{
"expression": "(calendar_id = $calendar_id)",
"arguments": {
"calendar_id": calendar_id,
}
}
);
for await (const hit of hits) {
await access_attributed_chest.delete(
[calendar_id, hit["user_id"]]
);
}
}
// core
{
await core_store.delete(
calendar_id
);
}
return Promise.resolve<void>(undefined);
}
/**
*/
export async function overview(
user_id : _zeitbild.type_user_id
) : Promise<
Array<
{
id : _zeitbild.type_calendar_id;
name : string;
access_level : _zeitbild.enum_access_level;
}
>
>
{
return (
lib_plankton.file.read("sql/calendar_overview.sql")
.then(
(template) => _zeitbild.database.get_implementation().query_free_get(
{
"template": template,
"arguments": {
"user_id": user_id,
}
}
)
)
.then(
(rows) => Promise.resolve(
rows
.map(
(row) => ({
"id": row["id"],
"name": row["name"],
"access_level": decode_access_level(row["access_level"]),
})
)
)
)
)
}
}