From 5b88d8c0d73bbc6f82f24a2864589b5de7cd7931 Mon Sep 17 00:00:00 2001 From: DanielGherjavca Date: Fri, 27 Oct 2023 21:06:48 +0300 Subject: [PATCH] feat(ministry brands): handler in editor-client --- public/editor-client/src/config.ts | 4 +- public/editor-client/src/ekklesia/index.s.ts | 79 ++++++++++++++++++++ public/editor-client/src/ekklesia/utils.ts | 63 ++++++++++++++++ public/editor-client/src/index.ts | 7 ++ public/editor-client/src/types/Ekklesia.ts | 57 ++++++++++++++ 5 files changed, 209 insertions(+), 1 deletion(-) create mode 100644 public/editor-client/src/ekklesia/index.s.ts create mode 100644 public/editor-client/src/ekklesia/utils.ts create mode 100644 public/editor-client/src/types/Ekklesia.ts diff --git a/public/editor-client/src/config.ts b/public/editor-client/src/config.ts index 5de91a106b..5c1507a2c4 100644 --- a/public/editor-client/src/config.ts +++ b/public/editor-client/src/config.ts @@ -48,6 +48,7 @@ interface API { mediaResizeUrl: string; fileUrl: string; templates: DefaultTemplates; + ekklesiaApiUrl?: string; } export interface Config { hash: string; @@ -107,7 +108,8 @@ const apiReader = parseStrict({ templates: pipe( mPipe(Obj.readKey("templates"), Obj.read, templatesReader), throwOnNullish("Invalid API: templates") - ) + ), + ekklesiaApiUrl: optional(mPipe(Obj.readKey("ekklesiaApiUrl"), Str.read)) }); const actionsReader = parseStrict({ diff --git a/public/editor-client/src/ekklesia/index.s.ts b/public/editor-client/src/ekklesia/index.s.ts new file mode 100644 index 0000000000..25b7f37d02 --- /dev/null +++ b/public/editor-client/src/ekklesia/index.s.ts @@ -0,0 +1,79 @@ +import { Config } from "config"; +import { ChoicesAsync, ChoicesSync } from "types/Choices"; +import { + EkklesiaFieldMap, + EkklesiaFields, + EkklesiaKeys, + EkklesiaParams +} from "types/Ekklesia"; +import { Response } from "../types/Response"; +import { t } from "../utils/i18n"; +import { getFields } from "./utils"; + +export const getEkklesiaFields = (config: Config) => ({ + async handler( + res: Response, + rej: Response, + keys: EkklesiaParams + ): Promise { + const { ekklesiaApiUrl } = config.api; + if (!ekklesiaApiUrl) { + if (process.env.NODE_ENV === "development") { + console.error("Missing Ekklesia api url!"); + } + res([{ value: "", title: t("None") }]); + return; + } + try { + const fields = await getFields(ekklesiaApiUrl, keys); + res(fields); + } catch (error) { + rej(t("Failed to load ekklesia fields")); + } + } +}); + +export const updateEkklesiaFields = (config: Config) => ({ + async handler( + res: Response, + rej: Response, + keys: { + fields: Array; + } + ): Promise { + const { ekklesiaApiUrl } = config.api; + + if (!ekklesiaApiUrl) { + if (process.env.NODE_ENV === "development") { + console.error("Missing Ekklesia api url!"); + } + rej(t("Missing Ekklesia api url!")); + return; + } + + const dataToChange: EkklesiaKeys = {}; + try { + for (const field of keys.fields) { + const choiches = await getFields(ekklesiaApiUrl, field.module); + if (!choiches.length) continue; + const updatedField = Object.keys(field.value).reduce((acc, key) => { + const value = field.value[key]; + const currentField = choiches.find( + (choice) => choice.value === value + ); + + if (!currentField) { + acc[key] = ""; + } + + return acc; + }, {} as EkklesiaKeys); + + Object.assign(dataToChange, updatedField); + } + res(Object.keys(dataToChange).length ? dataToChange : undefined); + } catch (error) { + rej(t("Failed to load ekklesia fields")); + } + } +}); diff --git a/public/editor-client/src/ekklesia/utils.ts b/public/editor-client/src/ekklesia/utils.ts new file mode 100644 index 0000000000..3333924520 --- /dev/null +++ b/public/editor-client/src/ekklesia/utils.ts @@ -0,0 +1,63 @@ +import { ChoicesSync } from "types/Choices"; +import { + EkklesiaChoiceParamsWithSubKey, + EkklesiaFields, + EkklesiaParams, + EkklesiaParentsChilds, + EkklesiaResponse +} from "types/Ekklesia"; +import { Literal } from "utils/types"; +import { t } from "../utils/i18n"; + +export const request = (url: string): Promise => { + return fetch(url).then((res) => res.json()); +}; + +export const fieldHaveParentsChildsKeys = ( + key: Record | EkklesiaParentsChilds +): key is EkklesiaParentsChilds => { + return "childs" in key && "parents" in key; +}; + +export const keysHaveSubkey = ( + keys: EkklesiaParams +): keys is EkklesiaChoiceParamsWithSubKey => { + return "subKey" in keys; +}; + +export const getOption = ( + obj: Record | undefined +): ChoicesSync => { + return obj + ? [ + { title: t("None"), value: "" }, + ...Object.entries(obj).map(([key, value]) => { + return { + title: String(value), + value: key + }; + }) + ] + : []; +}; + +export const getFields = async < + T extends keyof EkklesiaFields = keyof EkklesiaFields +>( + url: string, + keys: EkklesiaParams +): Promise => { + const { key } = keys; + + const { data = {} } = await request(url.concat("?module=", key)); + const field = data[key]; + + if (field && fieldHaveParentsChildsKeys(field)) { + if (keysHaveSubkey(keys)) { + return getOption(field[keys.subKey]); + } + return []; + } else { + return getOption(field); + } +}; diff --git a/public/editor-client/src/index.ts b/public/editor-client/src/index.ts index d2a4b7f26f..b99909dd49 100644 --- a/public/editor-client/src/index.ts +++ b/public/editor-client/src/index.ts @@ -1,3 +1,4 @@ +import { getEkklesiaFields, updateEkklesiaFields } from "ekklesia/index.s"; import set from "lodash/set"; import { autoSave } from "./autoSave"; import { getCollectionItemsIds } from "./collectionItems/getCollectionItemsIds"; @@ -50,6 +51,12 @@ const api = { searchCollectionItems, getCollectionItemsIds }, + modules: { + ekklesia: { + getEkklesiaFields: getEkklesiaFields(config), + updateEkklesiaFields: updateEkklesiaFields(config) + } + }, collectionTypes: { loadCollectionTypes }, diff --git a/public/editor-client/src/types/Ekklesia.ts b/public/editor-client/src/types/Ekklesia.ts new file mode 100644 index 0000000000..c45a23f9ef --- /dev/null +++ b/public/editor-client/src/types/Ekklesia.ts @@ -0,0 +1,57 @@ +import { Literal } from "utils/types"; + +export interface EkklesiaResponse { + data: Partial; +} + +export interface EkklesiaFields { + groups: Record; + events: Record; + series: Record; + recentSermons: Record; + smallgroups: Record; + forms: Record; + sermon: Record; + event: Record; + smallgroup: Record; + eventsLvl: EkklesiaParentsChilds; + smallgroupsLvl: EkklesiaParentsChilds; +} + +export interface EkklesiaParentsChilds { + parents: Record; + childs: Record; +} + +export interface EkklesiaChoiceParams< + T extends keyof EkklesiaFields = keyof EkklesiaFields +> { + key: T; +} + +export interface EkklesiaChoiceParamsWithSubKey< + T extends keyof EkklesiaFields = keyof EkklesiaFields +> extends EkklesiaChoiceParams { + subKey: keyof EkklesiaFields[T]; +} + +export type EkklesiaParams< + T extends keyof EkklesiaFields = keyof EkklesiaFields +> = EkklesiaFields[T] extends EkklesiaParentsChilds + ? EkklesiaChoiceParamsWithSubKey + : EkklesiaChoiceParams; + +export interface EkklesiaKeys { + [key: string]: string; +} + +export type EkklesiaFieldMap = { + [K in keyof EkklesiaFields]: EkklesiaModuleFields; +}; + +export interface EkklesiaModuleFields< + T extends keyof EkklesiaFields = keyof EkklesiaFields +> { + value: Record; + module: EkklesiaParams; +}