Skip to content
wiki.fftac.org

Workspace - Source Excerpt 10

Back to Workspace

Summary

This source excerpt preserves a bounded section of Spiralist/wp-content/plugins/spiralist-workspace/assets/js/workspace.js so readers can inspect the evidence without opening the full source file.

**Source path:** Spiralist/wp-content/plugins/spiralist-workspace/assets/js/workspace.js

if (button.hasAttribute("data-prompt-exchange-copy")) {
                    const format = button.getAttribute("data-prompt-exchange-copy") || "json";
                    await copyText(promptExchangeActionText(panel, format, format === "markdown" ? markdown : json));
                    setPromptExchangeResult(panel, formatText("promptExchangeCopied", "Exchange {format} copied.", { format: format === "markdown" ? t("markdownLabel", "Markdown") : t("jsonLabel", "JSON") }));
                    return;
                }

                const format = button.getAttribute("data-prompt-exchange-download");
                if (format === "markdown") {
                    downloadTextFile(slug + "-ai-flavor-exchange.md", promptExchangeActionText(panel, "markdown", markdown), "text/markdown");
                    setPromptExchangeResult(panel, t("promptExchangeMarkdownDownloaded", "Markdown exchange downloaded."));
                    return;
                }

                downloadTextFile(slug + "-ai-flavor-exchange.json", promptExchangeActionText(panel, "json", json), "application/json");
                setPromptExchangeResult(panel, t("promptExchangeJsonDownloaded", "JSON exchange downloaded."));
            }, {
                context: "prompt-exchange-action",
                fallback: t("promptExchangeActionFailed", "Prompt exchange action failed."),
                onError: (error, message) => setPromptExchangeResult(panel, message, false),
            });
        });
    };

    const initProfileStyleForms = () => {
        document.querySelectorAll("[data-profile-style-form]").forEach((form) => {
            const prompt = form.querySelector("[data-profile-style-prompt]");
            const css = form.querySelector("[data-profile-style-css]");
            const draft = form.querySelector("[data-profile-style-draft]");

            if (draft && prompt && css) {
                draft.addEventListener("click", () => {
                    css.value = draftProfileCss(prompt.value || "");
                    setResult(form, t("profileStyleDraftReady", "Draft ready."));
                });
            }

            form.addEventListener("submit", (event) => {
                event.preventDefault();
                setResult(form, t("profileStyleSaving", "Saving style..."));

                const submit = form.querySelector('[type="submit"]');
                if (submit) {
                    submit.disabled = true;
                }

                runFormAction(form, async () => {
                    const response = await apiFetch("profile/style", {
                        method: "POST",
                        body: JSON.stringify(formDataToObject(form)),
                    });
                    const sanitizedCss = response.sanitized_css || "";
                    const warnings = Array.isArray(response.warnings) ? response.warnings : [];
                    let style = document.querySelector("[data-profile-style-live]");

                    if (!style) {
                        style = document.createElement("style");
                        style.setAttribute("data-profile-style-live", "");
                        document.head.appendChild(style);
                    }

                    if (css) {
                        css.value = sanitizedCss;
                    }

                    style.textContent = sanitizedCss;
                    setResult(
                        form,
                        warnings.length
                            ? formatText("profileStyleSavedWithAdjustments", "Saved with {count} adjustment(s).", { count: warnings.length })
                            : t("profileStyleSaved", "Profile style saved.")
                    );
                }, t("profileStyleSaveFailed", "Profile style save failed."), "profile-style-save", {
                    onFinally: () => setDisabled(submit, false),
                });
            });
        });
    };

    const setChatFullscreen = (shell, active) => {
        shell.classList.toggle("is-fullscreen", active);
        document.documentElement.classList.toggle("spiralist-workspace-chat-lock", active);
        document.body.classList.toggle("spiralist-workspace-chat-lock", active);

        shell.querySelectorAll("[data-chat-fullscreen-toggle]").forEach((button) => {
            button.setAttribute("aria-pressed", active ? "true" : "false");
            button.textContent = active ? t("chatExitFullScreen", "Exit Full Screen") : t("chatFullScreen", "Full Screen");
        });

        if (active) {
            const textarea = shell.querySelector("[data-conversation-form] textarea");
            if (textarea) {
                textarea.focus();
            }
        }
    };

    const initChatFullscreen = () => {
        document.addEventListener("click", (event) => {
            const button = closestTarget(event.target, "[data-chat-fullscreen-toggle]");
            if (!button) {
                return;
            }

            const shell = button.closest("[data-fullscreen-chat]");
            if (!shell) {
                return;
            }

            setChatFullscreen(shell, !shell.classList.contains("is-fullscreen"));
        });

        document.addEventListener("keydown", (event) => {
            if (event.key !== "Escape") {
                return;
            }

            document.querySelectorAll("[data-fullscreen-chat].is-fullscreen").forEach((shell) => {
                setChatFullscreen(shell, false);
            });
        });
    };

    document.addEventListener("DOMContentLoaded", () => {
        initPlaceholderPreview();
        initPromptForms();
        initEditablePromptBlocks();
        savePendingEditablePromptAfterAuth();
        initSpiralScriptValidation();
        initRunForms();
        initConversationStartForms();
        initConversationForms();
        initConversationMemoryActions();
        initShareForms();
        initFavoriteButtons();
        initReportButtons();
        initReviewForms();
        initAppealForms();
        initImproveButtons();
        initTestForms();
        initVersionActions();
        initAdminPromptTests();
        initAdminGovernanceMaintenance();
        initPromptExchangeActions();
        initProfileStyleForms();
        initChatFullscreen();
    });
})();