Files
crank/apps/ui/js/workspace-setup.js
T
github-ops 58cfd86d90
Deploy / deploy (push) Successful in 2m33s
CI / Rust Checks (push) Successful in 5m35s
CI / UI Checks (push) Successful in 5s
CI / Deployment Manifests (push) Successful in 2s
CI / Frontend E2E (push) Successful in 4m19s
Limit community to single-user workspace
2026-06-19 17:41:50 +00:00

243 lines
7.4 KiB
JavaScript

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();
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 = '';
}
});