chore: publish clean community baseline
This commit is contained in:
@@ -0,0 +1,253 @@
|
||||
(function() {
|
||||
var STORAGE_KEY = 'crank_user';
|
||||
var sessionCache = null;
|
||||
var sessionPromise = null;
|
||||
function tKey(key) {
|
||||
return typeof t === 'function' ? t(key) : key;
|
||||
}
|
||||
function tfKey(key, vars) {
|
||||
return typeof tf === 'function' ? tf(key, vars) : key;
|
||||
}
|
||||
function roleLabel(role) {
|
||||
var normalized = String(role || 'viewer').toLowerCase();
|
||||
if (normalized === 'operator') return tKey('workspace_setup.role.operator');
|
||||
if (normalized === 'owner') return tKey('workspace_setup.role.owner');
|
||||
if (normalized === 'admin') return tKey('workspace_setup.role.admin');
|
||||
if (normalized === 'viewer') return tKey('workspace_setup.role.viewer');
|
||||
return normalized.replace(/^\w/, function(char) { return char.toUpperCase(); });
|
||||
}
|
||||
|
||||
function currentWorkspaceLabel() {
|
||||
if (window.getCurrentWorkspace) {
|
||||
var workspace = window.getCurrentWorkspace();
|
||||
if (workspace && workspace.name) {
|
||||
return workspace.name;
|
||||
}
|
||||
}
|
||||
try {
|
||||
return localStorage.getItem('crank_workspace_slug') || tKey('settings.nav.workspace');
|
||||
} catch (_error) {
|
||||
return tKey('settings.nav.workspace');
|
||||
}
|
||||
}
|
||||
|
||||
function isLoginPage() {
|
||||
return /\/(?:html\/login\.html|login)\/?$/.test(window.location.pathname);
|
||||
}
|
||||
|
||||
function loginUrl() {
|
||||
return (window.CrankRoutes && window.CrankRoutes.login) || '/login';
|
||||
}
|
||||
|
||||
function homeUrl() {
|
||||
return (window.CrankRoutes && window.CrankRoutes.home) || '/';
|
||||
}
|
||||
|
||||
function clearUserMirror() {
|
||||
sessionCache = null;
|
||||
sessionPromise = null;
|
||||
try {
|
||||
localStorage.removeItem(STORAGE_KEY);
|
||||
} catch (_error) {}
|
||||
renderShellIdentity(null);
|
||||
}
|
||||
|
||||
function primaryMembership(session) {
|
||||
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) {
|
||||
var source = displayName || email || 'Crank';
|
||||
return source
|
||||
.split(/\s+/)
|
||||
.filter(Boolean)
|
||||
.slice(0, 2)
|
||||
.map(function(part) { return part.charAt(0).toUpperCase(); })
|
||||
.join('') || 'CR';
|
||||
}
|
||||
|
||||
function persistUserMirror(session) {
|
||||
var membership = primaryMembership(session);
|
||||
var user = {
|
||||
id: session.user.id,
|
||||
name: session.user.display_name,
|
||||
email: session.user.email,
|
||||
role: membership ? roleLabel(membership.role) : tKey('workspace_setup.role.viewer'),
|
||||
workspace: membership ? membership.workspace.slug : '',
|
||||
workspaceId: membership ? membership.workspace.id : '',
|
||||
initials: initials(session.user.display_name, session.user.email),
|
||||
};
|
||||
|
||||
try {
|
||||
localStorage.setItem(STORAGE_KEY, JSON.stringify(user));
|
||||
} catch (_error) {}
|
||||
}
|
||||
|
||||
function mirroredUser() {
|
||||
try {
|
||||
return JSON.parse(localStorage.getItem(STORAGE_KEY));
|
||||
} catch (_error) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
function renderShellIdentity(session) {
|
||||
var membership = primaryMembership(session);
|
||||
var fallbackUser = mirroredUser();
|
||||
var displayName = session && session.user
|
||||
? (session.user.display_name || session.user.email || 'Crank')
|
||||
: (fallbackUser && fallbackUser.name) || 'Crank';
|
||||
var email = session && session.user
|
||||
? session.user.email
|
||||
: fallbackUser && fallbackUser.email;
|
||||
var role = membership
|
||||
? roleLabel(membership.role)
|
||||
: (fallbackUser && fallbackUser.role) || tKey('workspace_setup.role.viewer');
|
||||
var workspace = membership && membership.workspace
|
||||
? (membership.workspace.display_name || membership.workspace.slug || membership.workspace.id)
|
||||
: currentWorkspaceLabel();
|
||||
var avatarValue = initials(displayName, email);
|
||||
|
||||
document.querySelectorAll('.nav-avatar').forEach(function(element) {
|
||||
element.textContent = avatarValue;
|
||||
});
|
||||
document.querySelectorAll('.user-dropdown-name').forEach(function(element) {
|
||||
element.textContent = displayName;
|
||||
});
|
||||
document.querySelectorAll('.user-dropdown-role').forEach(function(element) {
|
||||
element.textContent = role + ' · ' + workspace;
|
||||
});
|
||||
if (window.CrankDiagnostics && typeof window.CrankDiagnostics.ensureShellTestIds === 'function') {
|
||||
window.CrankDiagnostics.ensureShellTestIds();
|
||||
}
|
||||
}
|
||||
|
||||
function replaceSession(session) {
|
||||
sessionCache = session;
|
||||
persistUserMirror(session);
|
||||
renderShellIdentity(session);
|
||||
window.dispatchEvent(new CustomEvent('crank:sessionchange', { detail: session }));
|
||||
return session;
|
||||
}
|
||||
|
||||
async function fetchSession(force) {
|
||||
if (!force && sessionCache) {
|
||||
return sessionCache;
|
||||
}
|
||||
if (!force && sessionPromise) {
|
||||
return sessionPromise;
|
||||
}
|
||||
|
||||
sessionPromise = window.CrankApi.getSession()
|
||||
.then(function(session) {
|
||||
return replaceSession(session);
|
||||
})
|
||||
.catch(function(error) {
|
||||
clearUserMirror();
|
||||
throw error;
|
||||
})
|
||||
.finally(function() {
|
||||
sessionPromise = null;
|
||||
});
|
||||
|
||||
return sessionPromise;
|
||||
}
|
||||
|
||||
async function guardProtectedPage() {
|
||||
try {
|
||||
return await fetchSession(false);
|
||||
} catch (error) {
|
||||
if (error && error.status === 401) {
|
||||
window.location.replace(loginUrl());
|
||||
return null;
|
||||
}
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
|
||||
async function guardLoginPage() {
|
||||
try {
|
||||
await fetchSession(false);
|
||||
window.location.replace(homeUrl());
|
||||
} catch (error) {
|
||||
if (!error || error.status !== 401) {
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
async function login(email, password) {
|
||||
var session = await window.CrankApi.login({
|
||||
email: email,
|
||||
password: password,
|
||||
});
|
||||
replaceSession(session);
|
||||
window.location.href = homeUrl();
|
||||
}
|
||||
|
||||
async function logout() {
|
||||
try {
|
||||
await window.CrankApi.logout();
|
||||
} finally {
|
||||
clearUserMirror();
|
||||
window.location.href = loginUrl();
|
||||
}
|
||||
}
|
||||
|
||||
function handleUnauthorized() {
|
||||
if (isLoginPage()) {
|
||||
clearUserMirror();
|
||||
return;
|
||||
}
|
||||
clearUserMirror();
|
||||
window.location.replace(loginUrl());
|
||||
}
|
||||
|
||||
window.CrankAuth = {
|
||||
fetchSession: fetchSession,
|
||||
replaceSession: replaceSession,
|
||||
getCachedSession: function() { return sessionCache; },
|
||||
renderShellIdentity: function() {
|
||||
renderShellIdentity(sessionCache);
|
||||
},
|
||||
guardProtectedPage: guardProtectedPage,
|
||||
guardLoginPage: guardLoginPage,
|
||||
login: login,
|
||||
logout: logout,
|
||||
handleUnauthorized: handleUnauthorized,
|
||||
};
|
||||
|
||||
window.addEventListener('crank:workspacechange', function() {
|
||||
renderShellIdentity(sessionCache);
|
||||
});
|
||||
|
||||
window.addEventListener('crank:sessionchange', function(event) {
|
||||
renderShellIdentity(event.detail || sessionCache);
|
||||
});
|
||||
|
||||
document.addEventListener('DOMContentLoaded', function() {
|
||||
renderShellIdentity(sessionCache);
|
||||
});
|
||||
}());
|
||||
Reference in New Issue
Block a user