diff --git a/README.md b/README.md index e71a377..c3f0f7a 100644 --- a/README.md +++ b/README.md @@ -23,7 +23,7 @@ Bestätigung startet den Build. Audio Separator besitzt einen eigenen Installer BS-/MelBand-RoFormer-Pakete werden einschließlich passender YAML-Konfiguration geladen; ungeprüfte Hub-Dateien werden dadurch nicht freigeschaltet. Die einzelnen Laufzeiten stehen nicht mehr separat in der Seitenleiste. Bibliothek und Profile verwenden -kompakte, aufklappbare Zeilen: Details, API-Freigabe, Komponenten und Aktionen +kompakte, aufklappbare Zeilen. Bibliotheken gruppieren die Dateien nach Hauptgewichten, Vision-/Audio-Projektoren, Textencodern, VAE, Konfigurationen und weiteren Zusatzkomponenten; nur vorhandene Gruppen werden angezeigt. Unbekannte Rollen bleiben separat sichtbar. In den Zeilen: Details, API-Freigabe, Komponenten und Aktionen stehen in der geöffneten Zeile. Downloads behalten Fortschritt, Geschwindigkeit, Restzeit und Warteschlangenaktionen. Der laufende Betrieb wird zentral unter **Steuerung** angezeigt; Testbereiche behalten ihre jeweiligen Formulare. diff --git a/catalog-ui.js b/catalog-ui.js index 2adf72f..5098819 100644 --- a/catalog-ui.js +++ b/catalog-ui.js @@ -32,7 +32,12 @@ window.CatalogUI = (() => { } function renderLibrary() { const openRows=new Set([...root.querySelectorAll('.detail-row[open]')].map(x=>x.dataset.rowId)); - el('hub-results').innerHTML = state.entries.filter(x => x.kind === kind).map(x => `
${escape(x.file)}${escape(x.role_label)}${size(x.size)}${x.used_by_profiles?.length?`${x.used_by_profiles.length} Profil(e)`:'Nicht zugeordnet'}

Quelle: ${escape(x.repo)}

${x.profile_eligible?'Modelldatei · über ein Profil verwenden':'Zusatzdatei · wird einem Modellprofil unter Komponenten zugeordnet'}

Version und Integrität

Revision ${escape(x.revision)}

${x.upstream_hash_verified ? 'SHA-256 mit Quelle geprüft' : 'SHA-256 lokal erfasst; Größe mit Quelle geprüft'}

${executionHTML(x.execution)}${x.used_by_profiles?.length?`

Verwendet von Profil: ${x.used_by_profiles.map(p=>escape(p.name)).join(", ")}. Bitte zuerst das Profil löschen.

`:""}
${x.profile_eligible===true?``:""}
`).join('') || '

Deine Bibliothek ist noch leer

Unter „Entdecken“ kannst du Dateien für diesen Bereich auswählen und herunterladen.

'; + const entries = state.entries.filter(x => x.kind === kind); + const groups = [['model', kind==='chat'?'Sprachmodelle · Hauptgewichte':'Modelle · Hauptgewichte'],['vision_projector','Vision-Projektoren'],['audio_projector','Audio-Projektoren'],['text_encoder','Textencoder'],['vae','VAE · Decoder'],['configuration','Konfigurationen'],['auxiliary','Tokenizer und weitere Zusatzkomponenten']]; + const row = x => `
${escape(x.file)}${escape(x.role_label)}${size(x.size)}${x.used_by_profiles?.length?`${x.used_by_profiles.length} Profil(e)`:'Nicht zugeordnet'}

Quelle: ${escape(x.repo)}

${x.profile_eligible?'Modelldatei · über ein Profil verwenden':'Zusatzdatei · wird einem Modellprofil unter Komponenten zugeordnet'}

Version und Integrität

Revision ${escape(x.revision)}

${x.upstream_hash_verified ? 'SHA-256 mit Quelle geprüft' : 'SHA-256 lokal erfasst; Größe mit Quelle geprüft'}

${executionHTML(x.execution)}${x.used_by_profiles?.length?`

Verwendet von Profil: ${x.used_by_profiles.map(p=>escape(p.name)).join(", ")}. Bitte zuerst das Profil löschen.

`:""}
${x.profile_eligible===true?``:""}
`; + const known = new Set(groups.map(([role])=>role)); + const sections = [...groups, ['other','Weitere Dateien · Zuordnung unbekannt']]; + el('hub-results').innerHTML = sections.map(([role,label])=>{const files=entries.filter(x=>role==='other'?!known.has(x.role):x.role===role);return files.length?`

${escape(label)} (${files.length})

${files.map(row).join('')}
`:'';}).join('') || '

Deine Bibliothek ist noch leer

Unter „Entdecken“ kannst du Dateien für diesen Bereich auswählen und herunterladen.

'; root.querySelectorAll('[data-delete-model]').forEach(b=>b.onclick=async()=>{const entry=state.entries.find(x=>x.id===b.dataset.deleteModel);if(!entry||!confirm(`Datei „${entry.file}“ (${size(entry.size)}) dauerhaft von Athena löschen?`))return;b.disabled=true;try{await api('/delete',{id:entry.id});message('Datei aus der Bibliothek gelöscht.');await refresh();}catch(error){message(error.message);b.disabled=false;}}); } function renderJob() { diff --git a/style.css b/style.css index 616d982..1d9c5a9 100644 --- a/style.css +++ b/style.css @@ -45,3 +45,6 @@ nav a.nav-sub{padding-left:28px;font-size:12px;color:var(--deck-tone-a4bda8, #a4 /* Control is a focused mode chooser; detailed API configuration lives in settings. */ .control-modes{display:flex;gap:12px;margin:24px 0 20px}.control-modes button{min-width:110px;margin:0;font-size:15px}.control-card{max-width:900px}.control-heading{display:flex;align-items:center;justify-content:space-between;gap:16px}.control-heading h2{margin:0;font-size:25px}.control-card>.card-actions{margin-top:18px}.control-api{border-top:1px solid var(--deck-tone-303a37,#303a37);margin-top:24px;padding-top:8px}.control-api h3{font-size:14px}.control-api>div{display:grid;grid-template-columns:130px minmax(0,1fr);gap:14px;margin:12px 0;font-size:13px}.control-api span{color:var(--deck-tone-97a79e,#97a79e)}.control-api code{overflow-wrap:anywhere}.control-details{border-top:1px solid var(--deck-tone-303a37,#303a37);padding-top:16px;margin-top:20px}.control-card .small{font-size:12px}@media(max-width:600px){.control-modes{gap:8px}.control-modes button{min-width:0;flex:1;padding:12px}.control-api>div{grid-template-columns:1fr;gap:4px}} + +.library-group + .library-group { margin-top: 1.5rem; } +.library-group > h3 { margin: .5rem 0 .75rem; }