feat: persist current workspace in user sessions

This commit is contained in:
a.tolmachev
2026-03-31 15:17:07 +03:00
parent 84f4437ce0
commit 86b61523bd
15 changed files with 331 additions and 57 deletions
+7
View File
@@ -162,6 +162,13 @@
body: JSON.stringify(payload),
});
},
setCurrentWorkspace: function(workspaceId) {
return request(AUTH_BASE + '/current-workspace', {
method: 'POST',
headers: headers({ 'Content-Type': 'application/json' }),
body: JSON.stringify({ workspace_id: workspaceId }),
});
},
listWorkspaces: function() {
return get('/workspaces');
},
+24 -3
View File
@@ -24,9 +24,29 @@
}
function primaryMembership(session) {
return session && session.memberships && session.memberships.length
? session.memberships[0]
: null;
if (!(session && session.memberships && session.memberships.length)) {
return null;
}
if (session.current_workspace_id) {
var currentMembership = session.memberships.find(function(item) {
return item.workspace && item.workspace.id === session.current_workspace_id;
});
if (currentMembership) {
return currentMembership;
}
}
if (window.getCurrentWorkspace) {
var currentWorkspace = window.getCurrentWorkspace();
if (currentWorkspace) {
var matched = session.memberships.find(function(item) {
return item.workspace && item.workspace.id === currentWorkspace.id;
});
if (matched) {
return matched;
}
}
}
return session.memberships[0];
}
function initials(displayName, email) {
@@ -138,6 +158,7 @@
window.CrankAuth = {
fetchSession: fetchSession,
replaceSession: replaceSession,
getCachedSession: function() { return sessionCache; },
guardProtectedPage: guardProtectedPage,
guardLoginPage: guardLoginPage,
login: login,
+1 -1
View File
@@ -249,7 +249,7 @@ async function loadWorkspaceSettings() {
var workspaces = await window.refreshWorkspaces();
var updated = workspaces.find(function (entry) { return entry.id === item.id; });
if (updated && window.setCurrentWorkspace) {
window.setCurrentWorkspace(updated);
await window.setCurrentWorkspace(updated);
}
}
+1 -1
View File
@@ -324,7 +324,7 @@ async function submitForm() {
settings: payload.settings,
};
window.setCurrentWorkspace(mapped);
await window.setCurrentWorkspace(mapped);
workspaceFormState.workspaceId = workspace.id;
workspaceFormState.workspaceRecord = { workspace: workspace };
setFormDirty(false);
+85 -20
View File
@@ -4,6 +4,7 @@ var WS_LIST = [
var workspaceLoadPromise = null;
var workspaceLoadFailed = false;
var lastWorkspaceId = null;
function workspaceColor(index) {
return ['#0d9488', '#7c3aed', '#0891b2', '#f59e0b', '#2563eb'][index % 5];
@@ -13,11 +14,14 @@ function mapWorkspace(record, index) {
var workspace = record && record.workspace ? record.workspace : record;
var displayName = workspace.display_name || workspace.slug || workspace.id;
var settings = workspace.settings || {};
var role = record && record.role
? String(record.role).replace(/^\w/, function(char) { return char.toUpperCase(); })
: 'Owner';
return {
id: workspace.id,
slug: workspace.slug,
name: displayName,
role: 'Owner',
role: role,
letter: displayName.charAt(0).toUpperCase(),
color: settings.color || workspaceColor(index),
status: workspace.status,
@@ -25,29 +29,60 @@ function mapWorkspace(record, index) {
};
}
function selectedWorkspaceId() {
return localStorage.getItem('crank_workspace_id');
function cachedWorkspaceId() {
try {
return localStorage.getItem('crank_workspace_id');
} catch (_error) {
return null;
}
}
function selectedWorkspaceSlug() {
return localStorage.getItem('crank_workspace_slug');
function cachedWorkspaceSlug() {
try {
return localStorage.getItem('crank_workspace_slug');
} catch (_error) {
return null;
}
}
function persistCurrentWorkspace(workspace) {
function sessionWorkspaceId() {
if (!window.CrankAuth || typeof window.CrankAuth.getCachedSession !== 'function') {
return null;
}
var session = window.CrankAuth.getCachedSession();
return session && session.current_workspace_id ? session.current_workspace_id : null;
}
function cacheCurrentWorkspace(workspace) {
if (!workspace) return;
localStorage.setItem('crank_workspace_id', workspace.id);
localStorage.setItem('crank_workspace_slug', workspace.slug);
try {
localStorage.setItem('crank_workspace_id', workspace.id);
localStorage.setItem('crank_workspace_slug', workspace.slug);
} catch (_error) {}
}
function resolveCurrentWorkspace() {
var workspaceId = sessionWorkspaceId() || cachedWorkspaceId();
var workspaceSlug = cachedWorkspaceSlug();
return WS_LIST.find(function(item) { return item.id === workspaceId; })
|| WS_LIST.find(function(item) { return item.slug === workspaceSlug; })
|| WS_LIST[0]
|| null;
}
function emitWorkspaceChange(workspace) {
if (!workspace) {
return;
}
lastWorkspaceId = workspace.id;
window.dispatchEvent(new CustomEvent('crank:workspacechange', { detail: workspace }));
}
function getCurrentWs() {
var workspaceId = selectedWorkspaceId();
var workspaceSlug = selectedWorkspaceSlug();
var workspace = WS_LIST.find(function(item) { return item.id === workspaceId; })
|| WS_LIST.find(function(item) { return item.slug === workspaceSlug; })
|| WS_LIST[0];
var workspace = resolveCurrentWorkspace();
if (workspace) {
persistCurrentWorkspace(workspace);
cacheCurrentWorkspace(workspace);
}
return workspace;
@@ -134,17 +169,39 @@ function toggleWsSwitcher(e) {
function switchWorkspace(workspaceId) {
var workspace = WS_LIST.find(function(item) { return item.id === workspaceId; });
if (!workspace) return;
persistCurrentWorkspace(workspace);
var dd = document.getElementById('ws-dropdown');
if (dd) dd.style.display = 'none';
renderWorkspaceList();
window.dispatchEvent(new CustomEvent('crank:workspacechange', { detail: workspace }));
if (!window.CrankApi || !window.CrankAuth || typeof window.CrankAuth.replaceSession !== 'function') {
cacheCurrentWorkspace(workspace);
renderWorkspaceList();
emitWorkspaceChange(workspace);
return;
}
return window.CrankApi
.setCurrentWorkspace(workspace.id)
.then(function(session) {
window.CrankAuth.replaceSession(session);
cacheCurrentWorkspace(workspace);
renderWorkspaceList();
emitWorkspaceChange(workspace);
return workspace;
})
.catch(function(error) {
if (window.CrankUi) {
window.CrankUi.error(error.message || 'Failed to switch workspace', 'Workspace switch failed');
}
throw error;
});
}
function setCurrentWorkspace(workspace) {
persistCurrentWorkspace(workspace);
renderWorkspaceList();
window.dispatchEvent(new CustomEvent('crank:workspacechange', { detail: workspace }));
if (!workspace) {
return Promise.resolve(null);
}
return Promise.resolve(switchWorkspace(workspace.id));
}
window.getCurrentWorkspace = getCurrentWs;
@@ -155,6 +212,14 @@ window.hasWorkspaceApiFailure = function() { return workspaceLoadFailed; };
document.addEventListener('DOMContentLoaded', initWorkspaceSwitcher);
window.addEventListener('crank:sessionchange', function() {
var workspace = getCurrentWs();
renderWorkspaceList();
if (workspace && workspace.id !== lastWorkspaceId) {
emitWorkspaceChange(workspace);
}
});
document.addEventListener('click', function(e) {
if (!e.target.closest('#ws-switcher')) {
var dd = document.getElementById('ws-dropdown');