import { query, UUID2hex, HEX2uuid } from '@commtool/sql-query';
import { renderObject } from '../../utils/renderTemplates.js';
import { Templates } from '../../utils/compileTemplates.js';
import { getUID } from '../../utils/UUIDs.js';
import { queueAdd } from '../../tree/treeQueue/treeQueue.js';
import { publishEvent } from '../../utils/events.js';
import { diff } from 'deep-object-diff';
/**
* Add visibility filters for event template
* @param {Buffer} UID - Template UID
* @param {Object} eventT - Template object with Data property
* @param {Object} req - Request object for session data
*/
export const addVisibilityFilter = async (UID, eventT, req) => {
// add the filters defining who can use the template and who can administer the template, as stored in the event template
const [UIDs] = await query(`SELECT UIDV1() AS UIDuse, UIDV1() AS UIDadmin`, []);
// add filter to orga for extraction of the usable objects and pointing to template
const filterUse = { job: eventT.Data.templateVisibility };
await query(
`
INSERT INTO ObjectBase(UID,Type,UIDBelongsTo,Title,Display,SortName, FullTextIndex, dindex,Data)
VALUES (?,'visible',?,?,?,'visible','',0,?)
`,
[UIDs.UIDuse, UUID2hex(req.session.root), 'event Template usage', eventT.Display, JSON.stringify(filterUse)]
);
// now put the initial execution of the filters into the queue
await queueAdd(UUID2hex(req.session.root), UUID2hex(req.session.user), 'visible', UIDs.UIDuse, UUID2hex(req.session.root), null, UID);
// add filter to orga for extraction of the usable objects and pointing to template
const filterAdmin = { job: eventT.Data.templateAdministration };
await query(
`
INSERT INTO ObjectBase(UID,Type,UIDBelongsTo,Title,Display,SortName, FullTextIndex, dindex,Data)
VALUES (?,'changeable',?,?,?,'changeable','',0,?)
`,
[UIDs.UIDadmin, UUID2hex(req.session.root), 'event Template admin', eventT.Display, JSON.stringify(filterAdmin)]
);
// now put the initial execution of the filter into the queue
await queueAdd(UUID2hex(req.session.root), UUID2hex(req.session.user), 'changeable', UIDs.UIDadmin, UUID2hex(req.session.root), null, UID);
};
/**
* Delete visibility filters for event template
* @param {Buffer} UID - Template UID
*/
export const deleteVisibilityFilter = async (UID) => {
// delete as well the visibility filter
await query(
`DELETE ObjectBase,Links FROM ObjectBase
LEFT JOIN Links ON (Links.UID=ObjectBase.UID AND Links.Type = 'list')
WHERE Links.UIDTarget =? AND ObjectBase.Type IN ('visible','changeable','admin')`,
[UID]
);
// delete visibility to this object
await query(`DELETE FROM Visible WHERE UID=?`, [UID]);
};
/**
* Create or update an event template
* @param {Object} bodyData - Request body data
* @param {Object} session - User session
* @returns {Promise<Object>} Result with success status and template data
*/
export const createOrUpdateEventTemplate = async (bodyData, session) => {
const template = Templates[session.root].eventTemplate;
const UID = await getUID({ session, body: bodyData });
let oldData = null;
if (bodyData.UID) {
const previous = await query(`SELECT Data FROM ObjectBase WHERE Type='eventT' AND UID=?`, [UID], { cast: ['json'] });
if (previous.length > 0) {
oldData = previous[0].Data;
}
}
const object = await renderObject(template, bodyData, { session }, 'events');
object.Data = { ...bodyData, UID: undefined };
if (!oldData) {
await query(
`
INSERT INTO ObjectBase(UID,Type,UIDBelongsTo,Title,Display,SortName, FullTextIndex, stage,gender,Data)
VALUES (?,'eventT',?,?,?,?,?,?,?,?)
`,
[
UID,
UUID2hex(session.root),
object.Title,
object.Display,
object.SortIndex,
object.FullTextIndex,
object.stage,
object.gender,
JSON.stringify(object.Data),
]
);
publishEvent(`/add/root/eventT/${session.root}`, { organization: session.root, data: { type: 'add', objectType: 'eventT', UID: HEX2uuid(UID) } });
// add the visibility filter
await addVisibilityFilter(UID, object, { session });
} else {
const myDiff = {
UID: HEX2uuid(UID),
diffNew: diff(oldData, object.Data),
diffOld: diff(object.Data, oldData),
user: session.user,
};
await query(`UPDATE ObjectBase SET Title=?,Display=?,SortName=?,FullTextIndex=?,
stage=?,gender=?,Data=?
WHERE UID=?`, [object.Title, object.Display, object.SortIndex, object.FullTextIndex, object.stage, object.gender, JSON.stringify(object.Data), UID]);
// @ts-ignore
if (myDiff.diffNew.templateVisibility || myDiff.diffNew.templateAdministration) {
// rebuild visiblity
// delete the old filters
await deleteVisibilityFilter(UID);
await addVisibilityFilter(UID, object, { session });
}
publishEvent(`/change/root/eventT/${session.root}`, { organization: session.root, data: { type: 'change', objectType: 'eventT', diff: myDiff } });
}
return { success: true, result: { ...object, UID: HEX2uuid(UID) } };
};
/**
* Update an existing event template
* @param {Buffer} UID - Template UID
* @param {Object} bodyData - Request body data
* @param {Object} session - User session
* @returns {Promise<Object>} Result with success status and diff data
*/
export const updateEventTemplate = async (UID, bodyData, session) => {
const previous = await query(`SELECT Data FROM ObjectBase WHERE Type='eventT' AND UID=?`, [UID], { cast: ['json'] });
if (previous.length === 0) {
throw new Error('event template not found');
}
const oldData = previous[0].Data;
const template = Templates[session.root].eventTemplate;
const object = await renderObject(template, { ...oldData, ...bodyData }, { session }, 'events');
object.Data = { ...oldData, ...bodyData };
delete object.Data.UID;
const myDiff = {
UID: HEX2uuid(UID),
diffNew: diff(oldData, object.Data),
diffOld: diff(object.Data, oldData),
user: session.user,
};
await query(`UPDATE ObjectBase SET Title=?,Display=?,SortName=?,FullTextIndex=?,
stage=?,gender=?,Data=?
WHERE UID=?`, [object.Title, object.Display, object.SortIndex, object.FullTextIndex, object.stage, object.gender, JSON.stringify(object.Data), UID]);
// @ts-ignore
if (myDiff.diffNew.templateVisibility || myDiff.diffNew.templateAdministration) {
// rebuild visiblity
// delete the old filters
await deleteVisibilityFilter(UID);
await addVisibilityFilter(UID, object, { session });
}
publishEvent(`/change/root/eventT/${session.root}`, { organization: session.root, data: { type: 'change', objectType: 'eventT', diff: myDiff } });
return { success: true, result: myDiff };
};
/**
* Delete an event template
* @param {Buffer} UID - Template UID
* @param {string} root - Organization root UID
* @returns {Promise<Object>} Result with success status
*/
export const deleteEventTemplate = async (UID, root) => {
await query(`DELETE FROM ObjectBase WHERE UID=? AND Type='eventT'
AND UIDBelongsTo=?`, [UID, UUID2hex(root)]);
await deleteVisibilityFilter(UID);
publishEvent(`/remove/root/eventT/${root}`, { organization: root, data: { type: 'remove', objectType: 'eventT', UID: HEX2uuid(UID) } });
return { success: true };
};
/**
* Get all templates for the organization
* @param {string} root - Organization root UID
* @param {string} user - User UID
* @param {boolean} isAdminUser - Whether user is admin
* @returns {Promise<Array>} List of templates
*/
export const getAllEventTemplates = async (root, user, isAdminUser) => {
let visibleSql = '';
if (!isAdminUser) visibleSql = `INNER JOIN Visible ON (Visible.UID=Main.UID AND Visible.UIDUser=U_UUID2BIN('${user}'))`;
const result = await query(
`
SELECT
Main.UID, Main.Display , Main.SortName
FROM
ObjectBase AS Main
${visibleSql}
WHERE
Main.UIDBelongsTo=? AND Main.Type='eventT'
GROUP BY
Main.UID
ORDER BY
Main.dindex
`,
[UUID2hex(root)],
{ cast: ['UUID', 'json'] }
);
return result;
};
/**
* Get all templates with data for the organization
* @param {string} root - Organization root UID
* @param {string} user - User UID
* @param {boolean} isAdminUser - Whether user is admin
* @returns {Promise<Array>} List of templates with data
*/
export const getAllEventTemplatesWithData = async (root, user, isAdminUser) => {
let visibleSql = '';
if (!isAdminUser) visibleSql = `INNER JOIN Visible ON (Visible.UID=Main.UID AND Visible.UIDUser=U_UUID2BIN('${user}'))`;
const result = await query(
`
SELECT
Main.UID, Main.Display , Main.SortName, Main.Data
FROM
ObjectBase AS Main
${visibleSql}
WHERE
Main.UIDBelongsTo=? AND Main.Type='eventT'
GROUP BY
Main.UID
ORDER BY
Main.dindex
`,
[UUID2hex(root)],
{
log: false,
cast: ['UUID', 'json'],
}
);
return result;
};
/**
* Get all templates the user can administer
* @param {string} root - Organization root UID
* @param {string} user - User UID
* @param {boolean} isAdminUser - Whether user is admin
* @returns {Promise<Array>} List of administrable templates
*/
export const getAdminEventTemplates = async (root, user, isAdminUser) => {
let visibleSql = '';
if (!isAdminUser)
visibleSql = `INNER JOIN Visible ON (Visible.UID=Main.UID AND Visible.UIDUser=U_UUID2BIN('${user}') AND Visible.Type='changeable')`;
const result = await query(
`
SELECT
Main.UID, Main.Display , Main.SortName, Main.Data
FROM
ObjectBase AS Main
${visibleSql}
WHERE
Main.UIDBelongsTo=? AND Main.Type='eventT'
GROUP BY
Main.UID
ORDER BY
Main.dindex
`,
[UUID2hex(root)],
{ cast: ['UUID', 'json'] }
);
return result;
};
/**
* Get a specific event template by UID
* @param {Buffer} UID - Template UID
* @param {string} root - Organization root UID
* @returns {Promise<Object>} Template data
*/
export const getEventTemplateByUID = async (UID, root) => {
const result = await query(
`
SELECT
Main.UID, Main.Display , Main.SortName, Main.Data
FROM
ObjectBase AS Main
WHERE
Main.UIDBelongsTo=? AND Main.Type='eventT' AND Main.UID=?
GROUP BY
Main.UID
ORDER BY
Main.dindex
`,
[UUID2hex(root), UID],
{ cast: ['UUID', 'json'] }
);
return result[0];
};
/**
* Get the template for an event with that UID
* @param {Buffer} UID - Event UID
* @param {string} root - Organization root UID
* @returns {Promise<Object>} Template data
*/
export const getEventTemplateByEventUID = async (UID, root) => {
const result = await query(
`
SELECT
Main.UID, Main.Display , Main.SortName, Main.Data
FROM
ObjectBase AS Main
INNER JOIN Links ON (Links.UIDTarget=Main.UID AND Links.Type='event' )
WHERE
Main.UIDBelongsTo=? AND Main.Type='eventT' AND Links.UID=?
GROUP BY
Main.UID
`,
[UUID2hex(root), UID],
{ cast: ['UUID', 'json'] }
);
return result[0];
};