254 lines
8.0 KiB
JavaScript
254 lines
8.0 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();
|
|
|
|
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 = '';
|
|
}
|
|
});
|