Changeset 0.37.5 (#217)
Co-authored-by: gobha <jasafpro@gmail.com> Co-committed-by: gobha <jasafpro@gmail.com>
This commit is contained in:
110
src/js/sw/surfaces/settings/models.js
Normal file
110
src/js/sw/surfaces/settings/models.js
Normal file
@@ -0,0 +1,110 @@
|
||||
/**
|
||||
* ModelsSection — user model list with visibility toggle
|
||||
*/
|
||||
const { html } = window;
|
||||
const { useState, useEffect, useCallback } = hooks;
|
||||
|
||||
function esc(s) { return s == null ? '' : String(s); }
|
||||
|
||||
export function ModelsSection() {
|
||||
const [models, setModels] = useState(null);
|
||||
const [prefs, setPrefs] = useState({});
|
||||
const [search, setSearch] = useState('');
|
||||
const [typeFilter, setTypeFilter] = useState('');
|
||||
const [provFilter, setProvFilter] = useState('');
|
||||
|
||||
useEffect(() => {
|
||||
(async () => {
|
||||
try {
|
||||
const [m, p] = await Promise.all([
|
||||
sw.api.models.enabled(),
|
||||
sw.api.models.preferences(),
|
||||
]);
|
||||
setModels(m?.data || m || []);
|
||||
// Build prefs map: model_id → { hidden }
|
||||
const map = {};
|
||||
(p?.data || p || []).forEach(x => { map[x.model_id] = x; });
|
||||
setPrefs(map);
|
||||
} catch (e) {
|
||||
console.warn('[settings/models]', e.message);
|
||||
setModels([]);
|
||||
}
|
||||
})();
|
||||
}, []);
|
||||
|
||||
const toggleHidden = useCallback(async (model) => {
|
||||
const current = prefs[model.id]?.hidden || false;
|
||||
try {
|
||||
await sw.api.models.setPref(model.id, model.provider_config_id, !current);
|
||||
setPrefs(p => ({ ...p, [model.id]: { ...p[model.id], hidden: !current } }));
|
||||
} catch (e) {
|
||||
sw.emit('toast', { message: e.message, variant: 'error' });
|
||||
}
|
||||
}, [prefs]);
|
||||
|
||||
if (models === null) {
|
||||
return html`<div class="settings-placeholder">Loading models\u2026</div>`;
|
||||
}
|
||||
|
||||
// Derive filter options
|
||||
const types = [...new Set(models.map(m => m.model_type).filter(Boolean))];
|
||||
const providers = [...new Set(models.map(m => m.provider_name || m.provider).filter(Boolean))];
|
||||
|
||||
const filtered = models.filter(m => {
|
||||
const name = (m.display_name || m.model_id || '').toLowerCase();
|
||||
if (search && !name.includes(search.toLowerCase())) return false;
|
||||
if (typeFilter && m.model_type !== typeFilter) return false;
|
||||
if (provFilter && (m.provider_name || m.provider) !== provFilter) return false;
|
||||
return true;
|
||||
});
|
||||
|
||||
return html`
|
||||
<div style="display:flex;gap:8px;margin-bottom:16px;flex-wrap:wrap;">
|
||||
<input type="text" placeholder="Search models\u2026"
|
||||
style="flex:1;min-width:140px;"
|
||||
value=${search} onInput=${e => setSearch(e.target.value)} />
|
||||
${types.length > 1 && html`
|
||||
<select value=${typeFilter} onChange=${e => setTypeFilter(e.target.value)}>
|
||||
<option value="">All types</option>
|
||||
${types.map(t => html`<option value=${t}>${t}</option>`)}
|
||||
</select>
|
||||
`}
|
||||
${providers.length > 1 && html`
|
||||
<select value=${provFilter} onChange=${e => setProvFilter(e.target.value)}>
|
||||
<option value="">All providers</option>
|
||||
${providers.map(p => html`<option value=${p}>${p}</option>`)}
|
||||
</select>
|
||||
`}
|
||||
</div>
|
||||
<table class="admin-table">
|
||||
<thead>
|
||||
<tr><th>Model</th><th>Type</th><th>Provider</th><th style="width:60px;">Visible</th></tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
${filtered.map(m => {
|
||||
const hidden = prefs[m.id]?.hidden || false;
|
||||
return html`
|
||||
<tr style=${hidden ? 'opacity:0.5' : ''}>
|
||||
<td style="font-weight:500;font-size:13px;">
|
||||
${esc(m.display_name || m.model_id)}
|
||||
</td>
|
||||
<td style="font-size:12px;color:var(--text-2);">
|
||||
${esc(m.model_type)}
|
||||
</td>
|
||||
<td style="font-size:12px;color:var(--text-2);">
|
||||
${esc(m.provider_name || m.provider)}
|
||||
</td>
|
||||
<td>
|
||||
<input type="checkbox" checked=${!hidden}
|
||||
onChange=${() => toggleHidden(m)} />
|
||||
</td>
|
||||
</tr>
|
||||
`;
|
||||
})}
|
||||
</tbody>
|
||||
</table>
|
||||
<div style="font-size:12px;color:var(--text-3);margin-top:8px;">
|
||||
${filtered.length} model${filtered.length !== 1 ? 's' : ''}
|
||||
</div>
|
||||
`;
|
||||
}
|
||||
Reference in New Issue
Block a user