mirror of
https://github.com/suitenumerique/drive.git
synced 2026-08-17 20:15:40 +02:00
✨(frontend) add a button mode to the messages widget hook
The homepage needs the widget floating button while the help menu opens the form directly. A WidgetHelper now owns the command queue and script injection so both entry points share the same bootstrap, and it fills the legacy queue key so older widget runtimes keep working. The hook exposes showButton to init the loader script and canLoadWidget so callers can check the config before rendering.
This commit is contained in:
@@ -1,6 +1,7 @@
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { useAuth } from "../auth/Auth";
|
||||
import { useConfig } from "../config/ConfigProvider";
|
||||
import { WidgetHelper } from "./widget-helper";
|
||||
|
||||
/**
|
||||
* Hook that opens the feedback widget
|
||||
@@ -14,59 +15,71 @@ export const useMessagesWidget = () => {
|
||||
const widgetPath = config?.FRONTEND_FEEDBACK_MESSAGES_WIDGET_PATH;
|
||||
const channel = config?.FRONTEND_FEEDBACK_MESSAGES_WIDGET_CHANNEL;
|
||||
|
||||
const title: string = t("feedback_widget.title");
|
||||
const placeholder: string = t("feedback_widget.placeholder");
|
||||
const emailPlaceholder: string = t("feedback_widget.email_placeholder");
|
||||
const submitText: string = t("feedback_widget.submit_text");
|
||||
const successText: string = t("feedback_widget.success_text");
|
||||
const successText2: string = t("feedback_widget.success_text2");
|
||||
const getWidgetConfig = () => {
|
||||
const title: string = t("feedback_widget.title");
|
||||
const placeholder: string = t("feedback_widget.placeholder");
|
||||
const emailPlaceholder: string = t("feedback_widget.email_placeholder");
|
||||
const submitText: string = t("feedback_widget.submit_text");
|
||||
const successText: string = t("feedback_widget.success_text");
|
||||
const successText2: string = t("feedback_widget.success_text2");
|
||||
return {
|
||||
title,
|
||||
placeholder,
|
||||
emailPlaceholder,
|
||||
submitText,
|
||||
successText,
|
||||
successText2,
|
||||
};
|
||||
};
|
||||
|
||||
const canLoadWidget = Boolean(channel && apiUrl && widgetPath);
|
||||
|
||||
const showWidget = () => {
|
||||
if (!channel || !apiUrl || !widgetPath) {
|
||||
if (!canLoadWidget) {
|
||||
throw new Error(
|
||||
"FRONTEND_FEEDBACK_MESSAGES_WIDGET_API_URL, FRONTEND_FEEDBACK_MESSAGES_WIDGET_PATH or FRONTEND_FEEDBACK_MESSAGES_WIDGET_CHANNEL is not set"
|
||||
"FRONTEND_FEEDBACK_MESSAGES_WIDGET_API_URL, FRONTEND_FEEDBACK_MESSAGES_WIDGET_PATH or FRONTEND_FEEDBACK_MESSAGES_WIDGET_CHANNEL is not set",
|
||||
);
|
||||
}
|
||||
|
||||
// Initialize the widget array if it doesn't exist
|
||||
if (typeof window !== "undefined" && widgetPath) {
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
(window as any)._stmsg_widget = (window as any)._stmsg_widget || [];
|
||||
WidgetHelper.pushCommand([
|
||||
"feedback",
|
||||
"init",
|
||||
{
|
||||
api: apiUrl,
|
||||
channel,
|
||||
...getWidgetConfig(),
|
||||
// Add email parameter if user is logged in
|
||||
...(user?.email && { email: user.email }),
|
||||
},
|
||||
]);
|
||||
|
||||
// Construct script URLs from the base path
|
||||
const feedbackScript = `${widgetPath}feedback.js`;
|
||||
WidgetHelper.loadScript(`${widgetPath}feedback.js`);
|
||||
};
|
||||
|
||||
// Push the widget configuration
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
(window as any)._stmsg_widget.push([
|
||||
"feedback",
|
||||
"init",
|
||||
{
|
||||
title,
|
||||
const showButton = () => {
|
||||
if (!canLoadWidget) {
|
||||
throw new Error(
|
||||
"FRONTEND_FEEDBACK_MESSAGES_WIDGET_API_URL, FRONTEND_FEEDBACK_MESSAGES_WIDGET_PATH or FRONTEND_FEEDBACK_MESSAGES_WIDGET_CHANNEL is not set",
|
||||
);
|
||||
}
|
||||
|
||||
WidgetHelper.pushCommand([
|
||||
"loader",
|
||||
"init",
|
||||
{
|
||||
params: {
|
||||
api: apiUrl,
|
||||
channel,
|
||||
placeholder,
|
||||
emailPlaceholder,
|
||||
submitText,
|
||||
successText,
|
||||
successText2,
|
||||
...getWidgetConfig(),
|
||||
// Add email parameter if user is logged in
|
||||
...(user?.email && { email: user.email }),
|
||||
},
|
||||
]);
|
||||
script: `${widgetPath}feedback.js`,
|
||||
},
|
||||
]);
|
||||
|
||||
// Load the loader script if not already loaded
|
||||
if (!document.querySelector(`script[src="${feedbackScript}"]`)) {
|
||||
const script = document.createElement("script");
|
||||
script.async = true;
|
||||
script.src = feedbackScript;
|
||||
const firstScript = document.getElementsByTagName("script")[0];
|
||||
if (firstScript && firstScript.parentNode) {
|
||||
firstScript.parentNode.insertBefore(script, firstScript);
|
||||
}
|
||||
}
|
||||
}
|
||||
WidgetHelper.loadScript(`${widgetPath}loader.js`);
|
||||
};
|
||||
|
||||
return { showWidget };
|
||||
return { showWidget, showButton, canLoadWidget };
|
||||
};
|
||||
|
||||
@@ -0,0 +1,34 @@
|
||||
// Widget helper functions to share common logic
|
||||
|
||||
declare global {
|
||||
interface Window {
|
||||
_lasuite_widget?: unknown[];
|
||||
_stmsg_widget?: unknown[];
|
||||
}
|
||||
}
|
||||
|
||||
export class WidgetHelper {
|
||||
// Both keys are populated so that legacy and current widget runtimes
|
||||
// can consume the same command queue.
|
||||
static #QUEUE_KEYS = ["_lasuite_widget", "_stmsg_widget"] as const;
|
||||
|
||||
static pushCommand(command: unknown[]) {
|
||||
for (const key of WidgetHelper.#QUEUE_KEYS) {
|
||||
const queue = window[key] ?? [];
|
||||
queue.push(command);
|
||||
window[key] = queue;
|
||||
}
|
||||
}
|
||||
|
||||
static loadScript(scriptUrl: string) {
|
||||
if (document.querySelector(`script[src="${scriptUrl}"]`)) return;
|
||||
|
||||
const script = document.createElement("script");
|
||||
script.async = true;
|
||||
script.src = scriptUrl;
|
||||
const firstScript = document.getElementsByTagName("script")[0];
|
||||
if (firstScript && firstScript.parentNode) {
|
||||
firstScript.parentNode.insertBefore(script, firstScript);
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user