Publish curated ITWorx-Pulse source from 0e0633c8ac91cb71312a26837f791035a78d81b8
Public source validation / validate (push) Failing after 2m10s
Public source validation / validate (push) Failing after 2m10s
This commit is contained in:
1 parent
a4956c2af9
commit
db8093b608
88 files changed
+3685
-469
No files matched your search
@@ -0,0 +1,97 @@
|
||||
export type WorkspaceItem = {
|
||||
id: string;
|
||||
label: string;
|
||||
path: string;
|
||||
kind: 'favorite' | 'view' | 'recent';
|
||||
updatedAt: string;
|
||||
};
|
||||
|
||||
type WorkspaceState = {
|
||||
favorites: WorkspaceItem[];
|
||||
views: WorkspaceItem[];
|
||||
recent: WorkspaceItem[];
|
||||
};
|
||||
|
||||
const STORAGE_KEY = 'pulse.operator.workspace.v1';
|
||||
export const WORKSPACE_EVENT = 'pulse-workspace-changed';
|
||||
|
||||
const emptyState = (): WorkspaceState => ({ favorites: [], views: [], recent: [] });
|
||||
|
||||
function validItem(value: unknown): value is WorkspaceItem {
|
||||
if (!value || typeof value !== 'object') return false;
|
||||
const item = value as Partial<WorkspaceItem>;
|
||||
return typeof item.id === 'string' && typeof item.label === 'string' && typeof item.path === 'string'
|
||||
&& ['favorite', 'view', 'recent'].includes(String(item.kind)) && typeof item.updatedAt === 'string';
|
||||
}
|
||||
|
||||
export function readWorkspaceState(): WorkspaceState {
|
||||
try {
|
||||
const raw = window.localStorage.getItem(STORAGE_KEY);
|
||||
if (!raw) return emptyState();
|
||||
const parsed = JSON.parse(raw) as Partial<WorkspaceState>;
|
||||
return {
|
||||
favorites: Array.isArray(parsed.favorites) ? parsed.favorites.filter(validItem).slice(0, 24) : [],
|
||||
views: Array.isArray(parsed.views) ? parsed.views.filter(validItem).slice(0, 24) : [],
|
||||
recent: Array.isArray(parsed.recent) ? parsed.recent.filter(validItem).slice(0, 12) : [],
|
||||
};
|
||||
} catch {
|
||||
return emptyState();
|
||||
}
|
||||
}
|
||||
|
||||
function writeWorkspaceState(state: WorkspaceState): void {
|
||||
try {
|
||||
window.localStorage.setItem(STORAGE_KEY, JSON.stringify(state));
|
||||
} catch {
|
||||
return;
|
||||
}
|
||||
window.dispatchEvent(new CustomEvent(WORKSPACE_EVENT));
|
||||
}
|
||||
|
||||
function timestamp(): string { return new Date().toISOString(); }
|
||||
function cleanPath(path: string): string {
|
||||
if (!path.startsWith('/')) return '/';
|
||||
return path.slice(0, 2048);
|
||||
}
|
||||
function cleanLabel(label: string): string { return label.trim().slice(0, 160) || 'Pulse'; }
|
||||
|
||||
export function isFavorite(path: string): boolean {
|
||||
const clean = cleanPath(path);
|
||||
return readWorkspaceState().favorites.some((item) => item.path === clean);
|
||||
}
|
||||
|
||||
export function toggleFavorite(label: string, path: string): boolean {
|
||||
const state = readWorkspaceState();
|
||||
const clean = cleanPath(path);
|
||||
const existing = state.favorites.some((item) => item.path === clean);
|
||||
const favorite: WorkspaceItem = { id: 'favorite:' + clean, label: cleanLabel(label), path: clean, kind: 'favorite', updatedAt: timestamp() };
|
||||
state.favorites = existing
|
||||
? state.favorites.filter((item) => item.path !== clean)
|
||||
: [favorite, ...state.favorites].slice(0, 24);
|
||||
writeWorkspaceState(state);
|
||||
return !existing;
|
||||
}
|
||||
|
||||
export function saveCurrentView(label: string, path: string): void {
|
||||
const state = readWorkspaceState();
|
||||
const clean = cleanPath(path);
|
||||
const item: WorkspaceItem = { id: 'view:' + clean, label: cleanLabel(label), path: clean, kind: 'view', updatedAt: timestamp() };
|
||||
state.views = [item, ...state.views.filter((value) => value.path !== clean)].slice(0, 24);
|
||||
writeWorkspaceState(state);
|
||||
}
|
||||
|
||||
export function removeSavedView(path: string): void {
|
||||
const state = readWorkspaceState();
|
||||
const clean = cleanPath(path);
|
||||
state.views = state.views.filter((item) => item.path !== clean);
|
||||
writeWorkspaceState(state);
|
||||
}
|
||||
|
||||
export function recordRecent(label: string, path: string): void {
|
||||
const state = readWorkspaceState();
|
||||
const clean = cleanPath(path);
|
||||
if (clean === '/404') return;
|
||||
const item: WorkspaceItem = { id: 'recent:' + clean, label: cleanLabel(label), path: clean, kind: 'recent', updatedAt: timestamp() };
|
||||
state.recent = [item, ...state.recent.filter((value) => value.path !== clean)].slice(0, 12);
|
||||
writeWorkspaceState(state);
|
||||
}
|
||||
Reference in new issue
Block a user