Files
GIA/core/static/js/compose-panel-core.js

140 lines
4.1 KiB
JavaScript

(function () {
if (window.GIAComposePanelCore) {
return;
}
const PANEL_SELECTOR = ".compose-shell[data-compose-panel='1']";
window.giaComposePanels = window.giaComposePanels || {};
const collectPanels = function (root) {
const panels = [];
if (!root) {
return panels;
}
if (root.matches && root.matches(PANEL_SELECTOR)) {
panels.push(root);
}
if (root.querySelectorAll) {
root.querySelectorAll(PANEL_SELECTOR).forEach(function (panel) {
panels.push(panel);
});
}
return panels;
};
const toInt = function (value) {
const parsed = parseInt(value || "0", 10);
return Number.isFinite(parsed) ? parsed : 0;
};
const parseJsonSafe = function (value, fallback) {
try {
return JSON.parse(String(value || ""));
} catch (_err) {
return fallback;
}
};
const createNode = function (tagName, className, text) {
const node = document.createElement(tagName);
if (className) {
node.className = className;
}
if (text !== undefined && text !== null) {
node.textContent = String(text);
}
return node;
};
const normalizeSnippet = function (value) {
const compact = String(value || "").replace(/\s+/g, " ").trim();
if (!compact) {
return "(no text)";
}
if (compact.length <= 120) {
return compact;
}
return compact.slice(0, 117).trimEnd() + "...";
};
const titleCase = function (value) {
const raw = String(value || "").trim().toLowerCase();
if (!raw) {
return "";
}
if (raw === "whatsapp") {
return "WhatsApp";
}
if (raw === "xmpp") {
return "XMPP";
}
return raw.charAt(0).toUpperCase() + raw.slice(1);
};
const normalizeIdentifierForService = function (service, identifier) {
const serviceKey = String(service || "").trim().toLowerCase();
const raw = String(identifier || "").trim();
if (serviceKey === "whatsapp" && raw.includes("@")) {
return raw.split("@", 1)[0].trim();
}
return raw;
};
const buildComposeUrl = function (renderMode, service, identifier, personId) {
const serviceKey = String(service || "").trim().toLowerCase();
const identifierValue = normalizeIdentifierForService(serviceKey, identifier);
if (!serviceKey || !identifierValue) {
return "";
}
const params = new URLSearchParams();
params.set("service", serviceKey);
params.set("identifier", identifierValue);
if (personId) {
params.set("person", String(personId || "").trim());
}
return (renderMode === "page" ? "/compose/page/" : "/compose/widget/")
+ "?"
+ params.toString();
};
const parseServiceMap = function (optionNode) {
const fallbackService = String(
(optionNode && optionNode.dataset && optionNode.dataset.service) || ""
).trim().toLowerCase();
const fallbackIdentifier = String((optionNode && optionNode.value) || "").trim();
const fallback = {};
if (fallbackService && fallbackIdentifier) {
fallback[fallbackService] = fallbackIdentifier;
}
if (!optionNode || !optionNode.dataset) {
return fallback;
}
const parsed = parseJsonSafe(optionNode.dataset.serviceMap || "{}", fallback);
if (!parsed || typeof parsed !== "object" || Array.isArray(parsed)) {
return fallback;
}
const normalized = {};
Object.keys(parsed).forEach(function (key) {
const serviceKey = String(key || "").trim().toLowerCase();
const identifierValue = String(parsed[key] || "").trim();
if (serviceKey && identifierValue) {
normalized[serviceKey] = identifierValue;
}
});
return Object.keys(normalized).length ? normalized : fallback;
};
window.GIAComposePanelCore = {
PANEL_SELECTOR: PANEL_SELECTOR,
buildComposeUrl: buildComposeUrl,
collectPanels: collectPanels,
createNode: createNode,
normalizeIdentifierForService: normalizeIdentifierForService,
normalizeSnippet: normalizeSnippet,
parseJsonSafe: parseJsonSafe,
parseServiceMap: parseServiceMap,
titleCase: titleCase,
toInt: toInt,
};
})();