var workspaceFormState = { selectedColor: '#0d9488', slugManual: false, isCreateMode: false, formDirty: false, workspaceId: null, workspaceRecord: null, }; function tKey(key) { return typeof t === 'function' ? t(key) : key; } function normalizeSlug(value) { return value .toLowerCase() .replace(/[^a-z0-9-]/g, '') .replace(/-+/g, '-') .replace(/^-|-$/g, ''); } function setFormDirty(value) { workspaceFormState.formDirty = value; } function formElements() { return { name: document.getElementById('ws-name'), slug: document.getElementById('ws-slug'), desc: document.getElementById('ws-desc'), submit: document.getElementById('submit-btn'), avatar: document.getElementById('ws-avatar-preview'), }; } function workspacePayload() { var elements = formElements(); return { slug: elements.slug.value.trim(), display_name: elements.name.value.trim(), settings: { description: elements.desc.value.trim(), color: workspaceFormState.selectedColor, }, }; } function applyWorkspaceRecord(record) { var workspace = record.workspace; var settings = workspace.settings || {}; var elements = formElements(); workspaceFormState.workspaceId = workspace.id; workspaceFormState.workspaceRecord = record; workspaceFormState.selectedColor = settings.color || '#0d9488'; workspaceFormState.slugManual = true; elements.name.value = workspace.display_name || ''; elements.slug.value = workspace.slug || ''; elements.desc.value = settings.description || ''; elements.avatar.textContent = (workspace.display_name || workspace.slug || '?').charAt(0).toUpperCase(); elements.avatar.style.background = workspaceFormState.selectedColor; document.querySelectorAll('.ws-color-swatch').forEach(function (swatch) { swatch.classList.toggle('active', swatch.dataset.color === workspaceFormState.selectedColor); }); setFormDirty(false); } function updatePageMode() { var params = new URLSearchParams(window.location.search); workspaceFormState.isCreateMode = params.get('mode') === 'create'; if (workspaceFormState.isCreateMode) { window.location.replace((window.CrankRoutes && window.CrankRoutes.workspaceSetup) || '/workspace-setup'); return; } var submit = document.getElementById('submit-btn'); var footerNote = document.getElementById('footer-note'); if (footerNote) { footerNote.hidden = true; } var dangerSection = document.getElementById('section-danger'); if (dangerSection) { dangerSection.hidden = false; } submit.textContent = tKey('workspace_setup.actions.save'); submit.classList.remove('is-disabled'); } function onWsNameInput(value) { var elements = formElements(); var normalized = value.trim(); elements.avatar.textContent = normalized ? normalized.charAt(0).toUpperCase() : '?'; if (!workspaceFormState.slugManual) { elements.slug.value = normalizeSlug(value); } if (workspaceFormState.isCreateMode) { validateCreateForm(); } setFormDirty(true); } function onWsSlugInput(value) { formElements().slug.value = normalizeSlug(value); workspaceFormState.slugManual = true; if (workspaceFormState.isCreateMode) { validateCreateForm(); } setFormDirty(true); } function pickColor(element) { workspaceFormState.selectedColor = element.dataset.color; document.querySelectorAll('.ws-color-swatch').forEach(function (swatch) { swatch.classList.remove('active'); }); element.classList.add('active'); formElements().avatar.style.background = workspaceFormState.selectedColor; setFormDirty(true); } function validateCreateForm() { var elements = formElements(); var valid = Boolean(elements.name.value.trim() && elements.slug.value.trim()); elements.submit.disabled = !valid; elements.submit.classList.toggle('is-disabled', !valid); } async function submitForm() { var payload = workspacePayload(); if (!payload.display_name || !payload.slug || !window.CrankApi) { return; } var submit = document.getElementById('submit-btn'); var originalLabel = submit.textContent; submit.disabled = true; submit.textContent = workspaceFormState.isCreateMode ? tKey('workspace_setup.saving_create') : tKey('workspace_setup.saving_update'); try { var response = await window.CrankApi.updateWorkspace(workspaceFormState.workspaceId, payload); var record = response && response.workspace ? response : { workspace: response.workspace || response }; var workspace = record.workspace; var workspaces = await window.refreshWorkspaces(); var mapped = workspaces.find(function (item) { return item.id === workspace.id; }) || { id: workspace.id, slug: workspace.slug, name: workspace.display_name, role: tKey('workspace_setup.role.owner'), letter: (workspace.display_name || workspace.slug).charAt(0).toUpperCase(), color: payload.settings.color || '#0d9488', status: workspace.status, settings: payload.settings, }; await window.setCurrentWorkspace(mapped); workspaceFormState.workspaceId = workspace.id; workspaceFormState.workspaceRecord = { workspace: workspace }; setFormDirty(false); applyWorkspaceRecord({ workspace: workspace }); submit.textContent = tKey('workspace_setup.saved'); setTimeout(function () { submit.textContent = originalLabel; submit.disabled = false; }, 1400); } catch (error) { if (window.CrankUi) { window.CrankUi.error(error.message || tKey('workspace_setup.save_error'), tKey('workspace_setup.save_error_title')); } submit.disabled = false; submit.textContent = originalLabel; } } function downloadJsonFile(fileName, value) { var blob = new Blob([JSON.stringify(value, null, 2)], { type: 'application/json;charset=utf-8' }); var url = URL.createObjectURL(blob); var link = document.createElement('a'); link.href = url; link.download = fileName; link.click(); URL.revokeObjectURL(url); } async function exportWorkspaceSnapshot() { if (!workspaceFormState.workspaceId || !window.CrankApi) { return; } try { var snapshot = await window.CrankApi.exportWorkspace(workspaceFormState.workspaceId); var slug = workspaceFormState.workspaceRecord && workspaceFormState.workspaceRecord.workspace ? workspaceFormState.workspaceRecord.workspace.slug : tKey('settings.nav.workspace'); downloadJsonFile(slug + '-snapshot.json', snapshot); } catch (error) { if (window.CrankUi) { window.CrankUi.error(error.message || tKey('workspace_setup.export_error'), tKey('workspace_setup.export_error_title')); } } } async function initPage() { updatePageMode(); document.querySelectorAll('.ws-color-swatch').forEach(function(swatch) { swatch.addEventListener('click', function() { pickColor(swatch); }); }); document.querySelectorAll('[data-history-back]').forEach(function(button) { button.addEventListener('click', function() { window.history.back(); }); }); var elements = formElements(); elements.name.addEventListener('input', function(event) { onWsNameInput(event.target.value); }); elements.slug.addEventListener('input', function(event) { onWsSlugInput(event.target.value); }); elements.submit.addEventListener('click', submitForm); var exportButton = document.getElementById('export-workspace-btn'); if (exportButton) { exportButton.addEventListener('click', exportWorkspaceSnapshot); } if (workspaceFormState.isCreateMode) { return; } await window.whenWorkspacesReady(); var workspace = window.getCurrentWorkspace ? window.getCurrentWorkspace() : null; if (!workspace || !window.CrankApi) { return; } try { var record = await window.CrankApi.getWorkspace(workspace.id); applyWorkspaceRecord(record); } catch (error) { if (window.CrankUi) { window.CrankUi.error(error.message || 'Failed to load workspace', 'Workspace load failed'); } } } document.addEventListener('DOMContentLoaded', initPage); window.addEventListener('beforeunload', function (event) { if (workspaceFormState.formDirty) { event.preventDefault(); event.returnValue = ''; } });