440 lines
9.4 KiB
TypeScript
440 lines
9.4 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_public": object.access.public,
|
|
"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": {
|
|
"public": dispersal.core_row["access_public"],
|
|
"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"],
|
|
};
|
|
}
|
|
|
|
|
|
/**
|
|
*/
|
|
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);
|
|
}
|
|
|
|
|
|
/**
|
|
*/
|
|
type type_overview_entry = {
|
|
id : _zeitbild.type_calendar_id;
|
|
name : string;
|
|
access_level : _zeitbild.enum_access_level;
|
|
}
|
|
|
|
|
|
/**
|
|
* @todo caching
|
|
*/
|
|
export async function overview(
|
|
user_id : (null | _zeitbild.type_user_id)
|
|
) : Promise<
|
|
Array<
|
|
type_overview_entry
|
|
>
|
|
>
|
|
{
|
|
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(
|
|
lib_plankton.call.convey(
|
|
rows,
|
|
[
|
|
(x : Array<Record<string, any>>) => x.map(
|
|
(row : Record<string, any>) => ({
|
|
"id": row["id"],
|
|
"name": row["name"],
|
|
/**
|
|
* @todo unite with _zeitbild.service.calendar.get_access_level
|
|
*/
|
|
"access_level": decode_access_level(
|
|
Math.max(
|
|
(row["access_public"] ? 1 : 0),
|
|
(
|
|
(user_id === null)
|
|
?
|
|
0
|
|
:
|
|
(row["access_level_attributed"] ?? row["access_level_default"])
|
|
)
|
|
)
|
|
),
|
|
})
|
|
),
|
|
(x : Array<type_overview_entry>) => x.filter(
|
|
(row) => (
|
|
! _zeitbild.value_object.access_level.order(
|
|
row.access_level,
|
|
_zeitbild.enum_access_level.none
|
|
)
|
|
)
|
|
),
|
|
(x : Array<type_overview_entry>) => lib_plankton.list.sorted<type_overview_entry>(
|
|
x,
|
|
{
|
|
"compare_element": lib_plankton.order.order_lexicographic_pair_wrapped<type_overview_entry, _zeitbild.enum_access_level, int>(
|
|
row => row.access_level,
|
|
row => row.id,
|
|
{
|
|
"order_first": _zeitbild.value_object.access_level.order,
|
|
"order_second": (a, b) => (a <= b)
|
|
}
|
|
),
|
|
}
|
|
),
|
|
]
|
|
)
|
|
)
|
|
)
|
|
)
|
|
}
|
|
}
|
|
|