import { getJSONFromStr } from "@web3r/flowerkit/json"; import { getFromServer } from "@web3r/flowerkit/net"; import { isObjEmpty, isObjHasOwnProp } from "@web3r/flowerkit/obj"; import { isStrUrl } from "@web3r/flowerkit/str"; import { getDocument } from "ssr-window"; import { getSanitizedHTML } from "../../../utils/getSanitizedHTML"; import type { TLocales } from "../config/locales"; import type { TAsset, TAsyncCfg, TModalCfg } from "../config/types"; /** * Получает асинхронный контент модального окна * @returns {Promise} */ const getAsyncModalLayout = async ({ url, method, data, getFromServerProps, }: TAsyncCfg): Promise => { const prefix = "Unable to load modal data from backend: "; return await getFromServer({ url, method, type: "text", data, ...getFromServerProps, }) .then((data) => { if (!!data) { const json = getJSONFromStr<{ isSuccess?: boolean; data?: { html?: string; }; }>(data); if (isObjEmpty(json)) { // non-json if (typeof data === "string" && data.length) { return Promise.resolve(data); } else { return Promise.reject(prefix + "response is empty"); } } else { // json response if (json.isSuccess) { const html = json?.data?.html; if (typeof html === "string" && html.length) { return Promise.resolve(html); } else { return Promise.reject(prefix + "html prop is missing or empty"); } } else { return Promise.reject(prefix + "unsuccessful result"); } } } else { return Promise.reject(prefix + "response is empty"); } }) .then((html) => { return getSanitizedHTML(html); }) .catch((reason: string | Response) => { if (typeof reason === "string") { return Promise.reject(reason); } else { return Promise.reject(prefix + "network problem"); } }); }; /** * Получает HTML-разметку из тега `template`, преобразуя ее в блок `div` * @param el{HTMLTemplateElement=} * @returns {string} */ const getTemplateLayout = (el: HTMLTemplateElement): string => { if (el) { const content = el.innerHTML; if (content.length) { const wrapper = getDocument().createElement("div"); const modal = getDocument().createElement("div"); for (const attr of el.attributes) { modal.setAttribute(attr.name, attr.value); } const html = getSanitizedHTML(content); modal.insertAdjacentHTML("afterbegin", html); wrapper.appendChild(modal); return wrapper.outerHTML; } else { return ""; } } else { return ""; } }; /** * Получает значение пользовательского свойства из конфигурации модального окна * @param propName{String} * @param handlerNode{Element} * @param parsedCfg{TModalCfg} * @returns {string|null} */ const getCfgProp = (propName: "src" | "id" | "type", handlerNode: Element, parsedCfg: TModalCfg): string | null => { switch (propName) { case "src": { switch (true) { case isObjHasOwnProp(parsedCfg, "src"): return parsedCfg?.src ?? null; case handlerNode.hasAttribute("href"): return handlerNode.getAttribute("href") || null; default: return null; } } case "id": { if (isObjHasOwnProp(parsedCfg, "preset")) { switch (parsedCfg.preset) { case "success": return "modalSuccess"; case "error": return "modalError"; case "confirm": return "modalConfirm"; case "assets": return "modalAssets"; default: return null; } } else { return parsedCfg?.id ?? null; } } case "type": { switch (true) { case isObjHasOwnProp(parsedCfg, "type"): { if (parsedCfg.type === "inline" || parsedCfg.type === "async" || parsedCfg.type === "html") { return parsedCfg.type; } else { return null; } } case handlerNode.hasAttribute("href"): { const href = handlerNode.getAttribute("href") || null; if (href) { switch (true) { case href.startsWith("#"): return "inline"; case isStrUrl(href): return "async"; default: return null; } } else { return null; } } default: return null; } } default: return null; } }; /** * Получение указанного кластера локализации * @param locales{Object} * @param lang{String} * @param langList{Array} * @returns Object */ const getLocaleCluster = (locales: TLocales, lang: string, langList: string[]) => { const currentLangIndex = langList.findIndex((item) => item === lang); return Object.fromEntries(Object.entries(locales) .map(([ name, items ]: [ string, string[] | string ]) => { const val = Array.isArray(items) ? items[currentLangIndex] : items; return [ name, val ]; })); }; /** * Проверяет, валиден ли массив assets * @returns {boolean} */ const isAssetsValid = (assets: TAsset[]) => { return Array.isArray(assets) && assets.length > 0 && assets.every((item) => { return typeof item?.src === "string" && item.src.length > 0 && !!item.type; }); }; export { getAsyncModalLayout, getCfgProp, getLocaleCluster, getTemplateLayout, isAssetsValid, };