6698ef1a92
- Ändern, Entfernen, Logo-Upload und -Abruf, Sammelprüfung nur mit Verwalten - Stündlicher Auftrag beim Start registriert, Prüfung je Cloud an ihren Mandanten gebunden - Sortierung nach Kundenname, Status, Version und Support-Ende, je Benutzer gemerkt - Formular zum Anlegen und Bearbeiten, Zugriffsinventar angepasst Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
84 lines
2.8 KiB
TypeScript
84 lines
2.8 KiB
TypeScript
import type { NextcloudInstance, RatingLevel } from '@/lib/nextcloud-status-api';
|
|
|
|
/**
|
|
* Sortierung der Cloud-Kacheln (quick-261002-k67, L-07, D-G) — reine
|
|
* Funktionen, kein React.
|
|
*/
|
|
export type SortKey = 'name' | 'status' | 'version' | 'eol';
|
|
|
|
export const SORT_KEYS: readonly SortKey[] = ['name', 'status', 'version', 'eol'];
|
|
|
|
/** Rot zuerst, dann Gelb, Grau, Gruen. */
|
|
const LEVEL_ORDER: Record<RatingLevel, number> = { red: 0, yellow: 1, unknown: 2, green: 3 };
|
|
|
|
function byName(a: NextcloudInstance, b: NextcloudInstance): number {
|
|
return a.customerName.localeCompare(b.customerName, 'de', { sensitivity: 'base' });
|
|
}
|
|
|
|
function versionTriple(raw: string | null): [number, number, number] | null {
|
|
if (!raw) return null;
|
|
const m = /^(\d+)\.(\d+)\.(\d+)/.exec(raw.trim());
|
|
return m ? [Number(m[1]), Number(m[2]), Number(m[3])] : null;
|
|
}
|
|
|
|
function compareVersions(a: NextcloudInstance, b: NextcloudInstance): number {
|
|
const va = versionTriple(a.status.versionString);
|
|
const vb = versionTriple(b.status.versionString);
|
|
if (!va && !vb) return 0;
|
|
if (!va) return 1; // unbekannt zuletzt
|
|
if (!vb) return -1;
|
|
for (let i = 0; i < 3; i++) {
|
|
if (va[i] !== vb[i]) return va[i] - vb[i];
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
function compareEol(a: NextcloudInstance, b: NextcloudInstance): number {
|
|
const ea = a.rating.eolDate;
|
|
const eb = b.rating.eolDate;
|
|
if (!ea && !eb) return 0;
|
|
if (!ea) return 1; // unbekannt zuletzt
|
|
if (!eb) return -1;
|
|
return ea < eb ? -1 : ea > eb ? 1 : 0;
|
|
}
|
|
|
|
/** Liefert eine neue, sortierte Liste; die Eingabe bleibt unveraendert. Gleiche Werte nach Kundenname. */
|
|
export function sortClouds(items: NextcloudInstance[], key: SortKey): NextcloudInstance[] {
|
|
const compare = (a: NextcloudInstance, b: NextcloudInstance): number => {
|
|
switch (key) {
|
|
case 'status':
|
|
return LEVEL_ORDER[a.rating.level] - LEVEL_ORDER[b.rating.level];
|
|
case 'version':
|
|
return compareVersions(a, b);
|
|
case 'eol':
|
|
return compareEol(a, b);
|
|
default:
|
|
return 0;
|
|
}
|
|
};
|
|
return [...items].sort((a, b) => compare(a, b) || byName(a, b));
|
|
}
|
|
|
|
function storageKey(userId: string): string {
|
|
return `tessera:nextcloud-status:sort:${userId}`;
|
|
}
|
|
|
|
/** Gemerkte Sortierung dieses Benutzers; unbekannter Wert oder gesperrter Speicher ergeben 'name'. */
|
|
export function readSortPreference(userId: string): SortKey {
|
|
try {
|
|
const stored = window.localStorage.getItem(storageKey(userId));
|
|
return (SORT_KEYS as readonly string[]).includes(stored ?? '') ? (stored as SortKey) : 'name';
|
|
} catch {
|
|
return 'name';
|
|
}
|
|
}
|
|
|
|
/** Merkt die Sortierung; ein gesperrter Speicher wird still uebergangen. */
|
|
export function writeSortPreference(userId: string, key: SortKey): void {
|
|
try {
|
|
window.localStorage.setItem(storageKey(userId), key);
|
|
} catch {
|
|
/* Speicher gesperrt oder voll — die Auswahl gilt dann nur fuer diese Sitzung */
|
|
}
|
|
}
|