98 lines
3.8 KiB
HTML
98 lines
3.8 KiB
HTML
{{/* Admin providers — server-rendered provider list with status. */}}
|
|
|
|
{{define "admin-providers"}}
|
|
<div class="admin-page">
|
|
<h2>Providers</h2>
|
|
<p class="section-hint">AI provider configurations. Each provider connects to an API endpoint.</p>
|
|
|
|
<div class="admin-toolbar">
|
|
<button class="btn-small btn-primary" onclick="sb.call('Pages.showProviderForm')">+ Add Provider</button>
|
|
</div>
|
|
|
|
<div id="providerFormWrap" style="display:none;">
|
|
{{template "admin-provider-form" .}}
|
|
</div>
|
|
|
|
{{if .Data.Providers}}
|
|
<table class="admin-table">
|
|
<thead>
|
|
<tr>
|
|
<th>Name</th>
|
|
<th>Type</th>
|
|
<th>Scope</th>
|
|
<th>Models</th>
|
|
<th>Endpoint</th>
|
|
<th></th>
|
|
</tr>
|
|
</thead>
|
|
<tbody>
|
|
{{range .Data.ProviderDetails}}
|
|
<tr>
|
|
<td><strong>{{.Name}}</strong></td>
|
|
<td><span class="admin-badge">{{.Provider}}</span></td>
|
|
<td><span class="admin-badge admin-badge-{{.Scope}}">{{.Scope}}</span></td>
|
|
<td>{{.ModelCount}}</td>
|
|
<td style="max-width:200px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;color:var(--text-secondary);">{{.Endpoint}}</td>
|
|
<td>
|
|
<button class="btn-small" onclick="sb.call('Pages.syncProvider','{{.ID}}')">Sync</button>
|
|
<button class="btn-small" onclick="sb.call('Pages.editProvider','{{.ID}}')">Edit</button>
|
|
</td>
|
|
</tr>
|
|
{{end}}
|
|
</tbody>
|
|
</table>
|
|
{{else}}
|
|
<div class="empty-hint">No providers configured. Add one to get started.</div>
|
|
{{end}}
|
|
</div>
|
|
{{end}}
|
|
|
|
{{define "admin-provider-form"}}
|
|
<div class="admin-inline-form" id="providerForm">
|
|
<h3 style="margin:0 0 12px;font-size:14px;" id="providerFormTitle">Add Provider</h3>
|
|
<input type="hidden" id="providerFormId" value="">
|
|
<div class="form-row">
|
|
<div class="form-group" style="flex:1;min-width:150px;">
|
|
<label>Name</label>
|
|
<input type="text" id="providerFormName" placeholder="My OpenAI">
|
|
</div>
|
|
<div class="form-group" style="flex:1;min-width:150px;">
|
|
<label>Type</label>
|
|
<select id="providerFormType">
|
|
<option value="">— select —</option>
|
|
{{range .Data.ProviderTypes}}
|
|
<option value="{{.ID}}">{{.Name}}</option>
|
|
{{end}}
|
|
</select>
|
|
</div>
|
|
</div>
|
|
<div class="form-row">
|
|
<div class="form-group" style="flex:2;min-width:200px;">
|
|
<label>Endpoint</label>
|
|
<input type="text" id="providerFormEndpoint" placeholder="https://api.openai.com/v1">
|
|
</div>
|
|
<div class="form-group" style="flex:1;min-width:150px;">
|
|
<label>API Key</label>
|
|
<input type="password" id="providerFormKey" placeholder="sk-...">
|
|
</div>
|
|
</div>
|
|
<div class="form-row">
|
|
<div class="form-group" style="flex:1;min-width:150px;">
|
|
<label>Scope</label>
|
|
<select id="providerFormScope">
|
|
<option value="global">Global</option>
|
|
<option value="team">Team</option>
|
|
</select>
|
|
</div>
|
|
<div class="form-group" style="flex:1;min-width:150px;" id="providerFormTeamWrap" style="display:none;">
|
|
<label>Team</label>
|
|
{{template "team-select" (dict "FieldName" "providerFormTeamId" "Label" "" "Teams" .Data.Teams "Selected" "" "AllowEmpty" false)}}
|
|
</div>
|
|
</div>
|
|
<div style="display:flex;gap:8px;margin-top:8px;">
|
|
<button class="btn-small btn-primary" onclick="sb.call('Pages.saveProvider')">Save</button>
|
|
<button class="btn-small" onclick="sb.call('Pages.hideProviderForm')">Cancel</button>
|
|
</div>
|
|
</div>
|
|
{{end}}
|