Changeset 0.37.7 (#219)
Co-authored-by: gobha <jasafpro@gmail.com> Co-committed-by: gobha <jasafpro@gmail.com>
This commit is contained in:
106
src/js/sw/surfaces/team-admin/personas.js
Normal file
106
src/js/sw/surfaces/team-admin/personas.js
Normal file
@@ -0,0 +1,106 @@
|
||||
/**
|
||||
* Team Admin > Personas
|
||||
*/
|
||||
const { html } = window;
|
||||
const { useState, useEffect, useCallback } = hooks;
|
||||
|
||||
export default function PersonasSection({ teamId }) {
|
||||
const [personas, setPersonas] = useState([]);
|
||||
const [loading, setLoading] = useState(true);
|
||||
const [editing, setEditing] = useState(null); // null | 'new' | persona object
|
||||
|
||||
const load = useCallback(async () => {
|
||||
try {
|
||||
const data = await sw.api.teams.personas(teamId);
|
||||
setPersonas(Array.isArray(data) ? data : data.data || []);
|
||||
} catch (e) { sw.toast(e.message, 'error'); }
|
||||
finally { setLoading(false); }
|
||||
}, [teamId]);
|
||||
|
||||
useEffect(() => { load(); }, [load]);
|
||||
|
||||
async function savePersona(e) {
|
||||
e.preventDefault();
|
||||
const form = e.target;
|
||||
const data = {
|
||||
name: form.pname.value.trim(),
|
||||
description: form.description.value.trim(),
|
||||
system_prompt: form.system_prompt.value,
|
||||
};
|
||||
try {
|
||||
if (editing === 'new') {
|
||||
await sw.api.teams.createPersona(teamId, data);
|
||||
sw.toast('Persona created', 'success');
|
||||
} else {
|
||||
await sw.api.teams.updatePersona(teamId, editing.id, data);
|
||||
sw.toast('Persona updated', 'success');
|
||||
}
|
||||
setEditing(null);
|
||||
load();
|
||||
} catch (e) { sw.toast(e.message, 'error'); }
|
||||
}
|
||||
|
||||
async function deletePersona(pid) {
|
||||
const ok = await sw.confirm('Delete this persona?', true);
|
||||
if (!ok) return;
|
||||
try {
|
||||
await sw.api.teams.deletePersona(teamId, pid);
|
||||
sw.toast('Persona deleted', 'success');
|
||||
load();
|
||||
} catch (e) { sw.toast(e.message, 'error'); }
|
||||
}
|
||||
|
||||
if (loading) return html`<div class="settings-placeholder">Loading\u2026</div>`;
|
||||
|
||||
if (editing) {
|
||||
const isNew = editing === 'new';
|
||||
const p = isNew ? {} : editing;
|
||||
return html`
|
||||
<form onSubmit=${savePersona}>
|
||||
<div style="display:flex;align-items:center;gap:8px;margin-bottom:12px;">
|
||||
<button type="button" class="btn-small" onClick=${() => setEditing(null)}>\u2190 Back</button>
|
||||
<h4 style="margin:0;">${isNew ? 'Create Persona' : `Edit: ${p.name}`}</h4>
|
||||
</div>
|
||||
<div class="form-group"><label>Name</label>
|
||||
<input name="pname" value=${p.name || ''} placeholder="Code Reviewer" />
|
||||
</div>
|
||||
<div class="form-group"><label>Description</label>
|
||||
<input name="description" value=${p.description || ''} placeholder="Optional description" />
|
||||
</div>
|
||||
<div class="form-group"><label>System Prompt</label>
|
||||
<textarea name="system_prompt" rows="6" placeholder="System prompt\u2026">${p.system_prompt || ''}</textarea>
|
||||
</div>
|
||||
<div class="form-row" style="margin-top:12px;gap:8px;">
|
||||
<button type="submit" class="btn-small btn-primary">${isNew ? 'Create' : 'Save'}</button>
|
||||
<button type="button" class="btn-small" onClick=${() => setEditing(null)}>Cancel</button>
|
||||
</div>
|
||||
</form>
|
||||
`;
|
||||
}
|
||||
|
||||
return html`
|
||||
<div>
|
||||
<div style="display:flex;align-items:center;gap:8px;margin-bottom:12px;">
|
||||
<div style="flex:1"></div>
|
||||
<button class="btn-md btn-primary" onClick=${() => setEditing('new')}>+ Add</button>
|
||||
</div>
|
||||
|
||||
<div class="admin-list">
|
||||
${personas.length === 0 && html`<div class="empty-hint">No personas</div>`}
|
||||
${personas.map(p => html`
|
||||
<div class="admin-surface-row" key=${p.id}>
|
||||
<div style="flex:1;min-width:0;">
|
||||
<strong>${p.name}</strong>
|
||||
${p.description && html`<span class="text-muted" style="margin-left:8px;font-size:11px;">${p.description.substring(0, 60)}${p.description.length > 60 ? '\u2026' : ''}</span>`}
|
||||
</div>
|
||||
<span class="text-muted" style="font-size:11px;">${p.kb_count || 0} KBs</span>
|
||||
<div class="admin-actions-cell">
|
||||
<button class="btn-small" onClick=${() => setEditing(p)}>Edit</button>
|
||||
<button class="btn-small btn-danger" onClick=${() => deletePersona(p.id)}>Delete</button>
|
||||
</div>
|
||||
</div>
|
||||
`)}
|
||||
</div>
|
||||
</div>
|
||||
`;
|
||||
}
|
||||
Reference in New Issue
Block a user