aimeat 1.16.2 → 1.18.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/.env.example +6 -1
- package/dist/locales/en.json +166 -4
- package/dist/locales/fi.json +166 -4
- package/dist/public/components/Card.js +17 -3
- package/dist/public/components/Collapsible.js +39 -0
- package/dist/public/components/CopyButton.js +55 -24
- package/dist/public/components/DataTable.js +57 -0
- package/dist/public/components/EmptyState.js +28 -0
- package/dist/public/components/KeyValueRow.js +37 -0
- package/dist/public/components/Modal.js +22 -5
- package/dist/public/components/Pagination.js +70 -0
- package/dist/public/components/SearchBar.js +44 -0
- package/dist/public/components/StatusDot.js +29 -0
- package/dist/public/components/TagList.js +53 -0
- package/dist/public/components/ToggleSwitch.js +28 -0
- package/dist/public/components/index.js +41 -1
- package/dist/public/css/components/tags.css +24 -0
- package/dist/public/css/style-testbed.css +135 -0
- package/dist/public/css/theme.css +556 -34
- package/dist/public/css/views/admin-agent-integration.css +2 -33
- package/dist/public/css/views/admin.css +730 -686
- package/dist/public/css/views/agents-detail.css +402 -14
- package/dist/public/css/views/help.css +2 -1
- package/dist/public/css/views/hobbies.css +53 -33
- package/dist/public/css/views/marketplace.css +73 -60
- package/dist/public/css/views/openclaw.css +12 -6
- package/dist/public/css/views/portal-classic.css +34 -26
- package/dist/public/css/views/portal-dev.css +41 -32
- package/dist/public/css/views/portal.css +14 -18
- package/dist/public/css/views/profile.css +252 -164
- package/dist/public/css/views/public-knowledge-viewer.css +18 -6
- package/dist/public/css/views/scheduler.css +100 -0
- package/dist/public/js/format.js +41 -0
- package/dist/public/js/services/agent-tasks.js +14 -1
- package/dist/public/js/services/generator-spec-validate.js +5 -1
- package/dist/public/js/services/schedules.js +53 -0
- package/dist/public/js/style-testbed.js +170 -0
- package/dist/public/js/theme.js +114 -0
- package/dist/public/spa.html +74 -16
- package/dist/public/style-testbed.html +420 -0
- package/dist/public/views/admin/agent-integration-tab.js +23 -38
- package/dist/public/views/admin/agent-tasks-tab.js +14 -21
- package/dist/public/views/admin/chat-instances-tab.js +1 -1
- package/dist/public/views/admin/config-tab.js +7 -2
- package/dist/public/views/admin/cortex-tab.js +20 -14
- package/dist/public/views/admin/csm-tab.js +22 -18
- package/dist/public/views/admin/directory-tab.js +3 -3
- package/dist/public/views/admin/email-tab.js +23 -28
- package/dist/public/views/admin/federation-tab.js +15 -5
- package/dist/public/views/admin/generator-debug-tab.js +10 -8
- package/dist/public/views/admin/genesis-tab.js +4 -4
- package/dist/public/views/admin/ghii-tab.js +3 -3
- package/dist/public/views/admin/knowledge-tab.js +15 -5
- package/dist/public/views/admin/matching-tab.js +3 -3
- package/dist/public/views/admin/memory-tab.js +16 -20
- package/dist/public/views/admin/msm-tab.js +30 -17
- package/dist/public/views/admin/overview-tab.js +7 -7
- package/dist/public/views/admin/packages-tab.js +10 -9
- package/dist/public/views/admin/portal-tab.js +14 -4
- package/dist/public/views/admin/prompts-tab.js +5 -5
- package/dist/public/views/admin/push-tab.js +15 -4
- package/dist/public/views/admin/realtime-tab.js +3 -3
- package/dist/public/views/admin/services-tab.js +18 -27
- package/dist/public/views/admin/shared.js +48 -58
- package/dist/public/views/admin/sharing-groups-tab.js +5 -10
- package/dist/public/views/admin/stats-tab.js +3 -3
- package/dist/public/views/guides.js +9 -13
- package/dist/public/views/help.js +3 -24
- package/dist/public/views/hobbies.js +47 -41
- package/dist/public/views/marketplace.js +42 -34
- package/dist/public/views/openclaw.js +0 -1
- package/dist/public/views/portal-classic.js +4 -15
- package/dist/public/views/portal-dev.js +28 -30
- package/dist/public/views/portal.js +16 -21
- package/dist/public/views/portfolio.js +11 -12
- package/dist/public/views/profile/access-tab.js +250 -1
- package/dist/public/views/profile/agents/agent-card.js +75 -4
- package/dist/public/views/profile/agents/tab-activity.js +15 -13
- package/dist/public/views/profile/agents/tab-agent-config.js +60 -6
- package/dist/public/views/profile/agents/tab-integration.js +37 -60
- package/dist/public/views/profile/agents/tab-messages.js +10 -1
- package/dist/public/views/profile/agents/tab-quality.js +25 -19
- package/dist/public/views/profile/agents/tab-schedules.js +110 -0
- package/dist/public/views/profile/agents-activity-subtab.js +4 -4
- package/dist/public/views/profile/agents-services-subtab.js +5 -4
- package/dist/public/views/profile/agents-tab.js +141 -37
- package/dist/public/views/profile/agents-tasks-subtab.js +221 -26
- package/dist/public/views/profile/calibrator-batch.js +5 -11
- package/dist/public/views/profile/calibrator-tab.js +4 -9
- package/dist/public/views/profile/chat-sessions-tab.js +9 -5
- package/dist/public/views/profile/email-tab.js +2 -2
- package/dist/public/views/profile/extensions-tab.js +27 -22
- package/dist/public/views/profile/federation-tab.js +4 -1
- package/dist/public/views/profile/foundry-detail.js +22 -23
- package/dist/public/views/profile/foundry-tab.js +12 -13
- package/dist/public/views/profile/generator-dashboard/DebugPanel.js +4 -7
- package/dist/public/views/profile/generator-dashboard/use-dashboard-core.js +4 -1
- package/dist/public/views/profile/generator-dashboard/use-edit-mode.js +3 -2
- package/dist/public/views/profile/generator-detail.js +26 -30
- package/dist/public/views/profile/generator-tab.js +5 -5
- package/dist/public/views/profile/knowledge-tab.js +12 -12
- package/dist/public/views/profile/landing-page.js +100 -149
- package/dist/public/views/profile/memory-tab.js +15 -11
- package/dist/public/views/profile/node-stats-tab.js +3 -3
- package/dist/public/views/profile/nodes-tab.js +10 -3
- package/dist/public/views/profile/notifications-tab.js +3 -3
- package/dist/public/views/profile/packages-tab.js +14 -14
- package/dist/public/views/profile/scheduler-tab.js +340 -0
- package/dist/public/views/profile/services-tab.js +1 -1
- package/dist/public/views/profile/shared.js +16 -12
- package/dist/public/views/profile/wallet-tab.js +27 -50
- package/dist/public/views/profile/work-tab.js +29 -31
- package/dist/public/views/profile.js +24 -0
- package/dist/public/views/public-knowledge-viewer.js +9 -18
- package/dist/src/auth/middleware.d.ts +3 -2
- package/dist/src/auth/middleware.d.ts.map +1 -1
- package/dist/src/auth/middleware.js +78 -3
- package/dist/src/auth/middleware.js.map +1 -1
- package/dist/src/cli/init-wizard.d.ts.map +1 -1
- package/dist/src/cli/init-wizard.js +13 -1
- package/dist/src/cli/init-wizard.js.map +1 -1
- package/dist/src/config.d.ts +6 -0
- package/dist/src/config.d.ts.map +1 -1
- package/dist/src/config.js +12 -1
- package/dist/src/config.js.map +1 -1
- package/dist/src/generated/api-types.d.ts +708 -8
- package/dist/src/generated/api-types.d.ts.map +1 -1
- package/dist/src/mcp/agent-schedules.d.ts +23 -0
- package/dist/src/mcp/agent-schedules.d.ts.map +1 -0
- package/dist/src/mcp/agent-schedules.js +175 -0
- package/dist/src/mcp/agent-schedules.js.map +1 -0
- package/dist/src/mcp/annotations.d.ts.map +1 -1
- package/dist/src/mcp/annotations.js +6 -0
- package/dist/src/mcp/annotations.js.map +1 -1
- package/dist/src/mcp/catalog/definitions.d.ts.map +1 -1
- package/dist/src/mcp/catalog/definitions.js +55 -0
- package/dist/src/mcp/catalog/definitions.js.map +1 -1
- package/dist/src/mcp/catalog/scopes.d.ts.map +1 -1
- package/dist/src/mcp/catalog/scopes.js +12 -0
- package/dist/src/mcp/catalog/scopes.js.map +1 -1
- package/dist/src/mcp/catalog/surfaces.d.ts.map +1 -1
- package/dist/src/mcp/catalog/surfaces.js +2 -0
- package/dist/src/mcp/catalog/surfaces.js.map +1 -1
- package/dist/src/mcp/index.d.ts.map +1 -1
- package/dist/src/mcp/index.js +2 -0
- package/dist/src/mcp/index.js.map +1 -1
- package/dist/src/models/agent-task-schemas.d.ts +6 -0
- package/dist/src/models/agent-task-schemas.d.ts.map +1 -1
- package/dist/src/models/agent-task-schemas.js +6 -0
- package/dist/src/models/agent-task-schemas.js.map +1 -1
- package/dist/src/models/schemas.d.ts +1 -0
- package/dist/src/models/schemas.d.ts.map +1 -1
- package/dist/src/models/schemas.js +4 -0
- package/dist/src/models/schemas.js.map +1 -1
- package/dist/src/routes/access-tokens.d.ts +17 -0
- package/dist/src/routes/access-tokens.d.ts.map +1 -0
- package/dist/src/routes/access-tokens.js +164 -0
- package/dist/src/routes/access-tokens.js.map +1 -0
- package/dist/src/routes/agent-tasks.d.ts +2 -0
- package/dist/src/routes/agent-tasks.d.ts.map +1 -1
- package/dist/src/routes/agent-tasks.js +118 -23
- package/dist/src/routes/agent-tasks.js.map +1 -1
- package/dist/src/routes/agents.d.ts.map +1 -1
- package/dist/src/routes/agents.js +46 -0
- package/dist/src/routes/agents.js.map +1 -1
- package/dist/src/routes/ai.d.ts +6 -9
- package/dist/src/routes/ai.d.ts.map +1 -1
- package/dist/src/routes/ai.js +26 -175
- package/dist/src/routes/ai.js.map +1 -1
- package/dist/src/routes/apps.d.ts.map +1 -1
- package/dist/src/routes/apps.js +104 -34
- package/dist/src/routes/apps.js.map +1 -1
- package/dist/src/routes/auth.d.ts.map +1 -1
- package/dist/src/routes/auth.js +77 -4
- package/dist/src/routes/auth.js.map +1 -1
- package/dist/src/routes/cortex.d.ts +2 -1
- package/dist/src/routes/cortex.d.ts.map +1 -1
- package/dist/src/routes/cortex.js +13 -8
- package/dist/src/routes/cortex.js.map +1 -1
- package/dist/src/routes/extensions.d.ts.map +1 -1
- package/dist/src/routes/extensions.js +85 -51
- package/dist/src/routes/extensions.js.map +1 -1
- package/dist/src/routes/generator.d.ts.map +1 -1
- package/dist/src/routes/generator.js +109 -43
- package/dist/src/routes/generator.js.map +1 -1
- package/dist/src/routes/ghii.d.ts.map +1 -1
- package/dist/src/routes/ghii.js +34 -13
- package/dist/src/routes/ghii.js.map +1 -1
- package/dist/src/routes/libs.d.ts +15 -0
- package/dist/src/routes/libs.d.ts.map +1 -1
- package/dist/src/routes/libs.js +178 -55
- package/dist/src/routes/libs.js.map +1 -1
- package/dist/src/routes/portal.d.ts.map +1 -1
- package/dist/src/routes/portal.js +1 -0
- package/dist/src/routes/portal.js.map +1 -1
- package/dist/src/routes/schedules.d.ts +33 -0
- package/dist/src/routes/schedules.d.ts.map +1 -0
- package/dist/src/routes/schedules.js +380 -0
- package/dist/src/routes/schedules.js.map +1 -0
- package/dist/src/server-bootstrap/config-init.js +2 -2
- package/dist/src/server-bootstrap/config-init.js.map +1 -1
- package/dist/src/server-bootstrap/routes-loader.d.ts.map +1 -1
- package/dist/src/server-bootstrap/routes-loader.js +7 -0
- package/dist/src/server-bootstrap/routes-loader.js.map +1 -1
- package/dist/src/server-bootstrap/service-init.d.ts.map +1 -1
- package/dist/src/server-bootstrap/service-init.js +2 -1
- package/dist/src/server-bootstrap/service-init.js.map +1 -1
- package/dist/src/services/access-token.d.ts +28 -0
- package/dist/src/services/access-token.d.ts.map +1 -0
- package/dist/src/services/access-token.js +37 -0
- package/dist/src/services/access-token.js.map +1 -0
- package/dist/src/services/ai-completion.d.ts +83 -0
- package/dist/src/services/ai-completion.d.ts.map +1 -0
- package/dist/src/services/ai-completion.js +187 -0
- package/dist/src/services/ai-completion.js.map +1 -0
- package/dist/src/services/config-schema.d.ts.map +1 -1
- package/dist/src/services/config-schema.js +3 -0
- package/dist/src/services/config-schema.js.map +1 -1
- package/dist/src/services/generator-prompt-seeds.d.ts.map +1 -1
- package/dist/src/services/generator-prompt-seeds.js +6 -3
- package/dist/src/services/generator-prompt-seeds.js.map +1 -1
- package/dist/src/services/generator-prompts/spec-validate.d.ts.map +1 -1
- package/dist/src/services/generator-prompts/spec-validate.js +6 -2
- package/dist/src/services/generator-prompts/spec-validate.js.map +1 -1
- package/dist/src/services/generator-registration.d.ts +12 -4
- package/dist/src/services/generator-registration.d.ts.map +1 -1
- package/dist/src/services/generator-registration.js +71 -0
- package/dist/src/services/generator-registration.js.map +1 -1
- package/dist/src/services/generator-validate.d.ts +10 -0
- package/dist/src/services/generator-validate.d.ts.map +1 -1
- package/dist/src/services/generator-validate.js +180 -36
- package/dist/src/services/generator-validate.js.map +1 -1
- package/dist/src/services/owner-session.d.ts +43 -0
- package/dist/src/services/owner-session.d.ts.map +1 -0
- package/dist/src/services/owner-session.js +175 -0
- package/dist/src/services/owner-session.js.map +1 -0
- package/dist/src/services/schedule-constraints.d.ts +65 -0
- package/dist/src/services/schedule-constraints.d.ts.map +1 -0
- package/dist/src/services/schedule-constraints.js +106 -0
- package/dist/src/services/schedule-constraints.js.map +1 -0
- package/dist/src/services/scheduler.d.ts +34 -0
- package/dist/src/services/scheduler.d.ts.map +1 -1
- package/dist/src/services/scheduler.js +266 -22
- package/dist/src/services/scheduler.js.map +1 -1
- package/dist/src/services/skill-bundle/generator.js +19 -0
- package/dist/src/services/skill-bundle/generator.js.map +1 -1
- package/dist/src/storage/interface.d.ts +48 -4
- package/dist/src/storage/interface.d.ts.map +1 -1
- package/dist/src/storage/interface.js.map +1 -1
- package/dist/src/storage/providers/mongodb/index.d.ts +31 -0
- package/dist/src/storage/providers/mongodb/index.d.ts.map +1 -1
- package/dist/src/storage/providers/mongodb/index.js +187 -9
- package/dist/src/storage/providers/mongodb/index.js.map +1 -1
- package/dist/src/storage/providers/sqlite/index.d.ts +31 -0
- package/dist/src/storage/providers/sqlite/index.d.ts.map +1 -1
- package/dist/src/storage/providers/sqlite/index.js +131 -8
- package/dist/src/storage/providers/sqlite/index.js.map +1 -1
- package/dist/src/storage/providers/sqlite/repos/agent-task.d.ts.map +1 -1
- package/dist/src/storage/providers/sqlite/repos/agent-task.js +6 -4
- package/dist/src/storage/providers/sqlite/repos/agent-task.js.map +1 -1
- package/dist/src/storage/providers/sqlite/schema.d.ts.map +1 -1
- package/dist/src/storage/providers/sqlite/schema.js +79 -8
- package/dist/src/storage/providers/sqlite/schema.js.map +1 -1
- package/dist/src/storage/repositories/pat.repository.d.ts +40 -0
- package/dist/src/storage/repositories/pat.repository.d.ts.map +1 -0
- package/dist/src/storage/repositories/pat.repository.js +14 -0
- package/dist/src/storage/repositories/pat.repository.js.map +1 -0
- package/dist/src/storage/repositories/scheduler.repository.d.ts +2 -0
- package/dist/src/storage/repositories/scheduler.repository.d.ts.map +1 -1
- package/dist/src/storage/repositories/session.repository.d.ts +51 -0
- package/dist/src/storage/repositories/session.repository.d.ts.map +1 -1
- package/dist/src/storage/repositories/session.repository.js +12 -0
- package/dist/src/storage/repositories/session.repository.js.map +1 -1
- package/dist/src/utils/env-config.d.ts.map +1 -1
- package/dist/src/utils/env-config.js +25 -1
- package/dist/src/utils/env-config.js.map +1 -1
- package/dist/src/utils/env-validator.d.ts.map +1 -1
- package/dist/src/utils/env-validator.js +4 -0
- package/dist/src/utils/env-validator.js.map +1 -1
- package/package.json +1 -1
- package/prisma/schema.prisma +48 -0
|
@@ -7,6 +7,9 @@
|
|
|
7
7
|
* v1.0.0 -- 2026-05-24 -- Initial creation for Governance Phase C
|
|
8
8
|
* v1.1.0 -- 2026-05-24 -- Fix M8 M9 F19 F20 F21 audit findings
|
|
9
9
|
* v1.2.0 -- 2026-05-24 -- Move readiness into onboarding, add bundle templates, add notify button
|
|
10
|
+
* v1.3.0 -- 2026-06-02 -- Admin design unification: main btn-* classes → adm-btn /
|
|
11
|
+
* adm-btn-action; the bespoke adm-agi-stat-card stat rows → canonical <StatsGrid>
|
|
12
|
+
* (tones success→green, accent→indigo). adm-agi-mono-sm retained (table cells).
|
|
10
13
|
*/
|
|
11
14
|
import { h } from 'preact';
|
|
12
15
|
import { useState, useEffect, useCallback } from 'preact/hooks';
|
|
@@ -14,7 +17,7 @@ import htm from 'htm';
|
|
|
14
17
|
const html = htm.bind(h);
|
|
15
18
|
import { t } from '/js/i18n.js';
|
|
16
19
|
import { useViewCSS } from '/components/useViewCSS.js';
|
|
17
|
-
import { num, dt, Empty } from './shared.js';
|
|
20
|
+
import { num, dt, Empty, StatsGrid } from './shared.js';
|
|
18
21
|
import * as api from '/js/services/admin-agent-integration.js';
|
|
19
22
|
|
|
20
23
|
|
|
@@ -113,7 +116,7 @@ function renderPlatformRegistry(platforms, totalAgents, session, loadData) {
|
|
|
113
116
|
}
|
|
114
117
|
${showForm
|
|
115
118
|
? html`<${AddPlatformForm} session=${session} onDone=${() => { setShowForm(false); loadData(); }} onCancel=${() => setShowForm(false)} />`
|
|
116
|
-
: html`<button class="btn-
|
|
119
|
+
: html`<button class="adm-btn-action adm-agi-add-btn" onClick=${() => setShowForm(true)}>
|
|
117
120
|
${t('admin.agentIntegration.addPlatform')}
|
|
118
121
|
</button>`
|
|
119
122
|
}
|
|
@@ -163,10 +166,10 @@ function AddPlatformForm({ session, onDone, onCancel }) {
|
|
|
163
166
|
<input class="adm-agi-add-form-input" value=${pattern} onInput=${e => setPattern(e.target.value)} placeholder=${t('admin.agentIntegration.placeholders.regex')} />
|
|
164
167
|
</div>
|
|
165
168
|
<div class="adm-agi-add-form-actions">
|
|
166
|
-
<button class="btn
|
|
169
|
+
<button class="adm-btn" onClick=${handleSubmit} disabled=${submitting || !name.trim() || !id.trim()}>
|
|
167
170
|
${submitting ? t('common.loading') : t('common.add')}
|
|
168
171
|
</button>
|
|
169
|
-
<button class="btn-
|
|
172
|
+
<button class="adm-btn-action" onClick=${onCancel}>${t('common.cancel')}</button>
|
|
170
173
|
</div>
|
|
171
174
|
</div>
|
|
172
175
|
`;
|
|
@@ -183,20 +186,11 @@ function renderOnboardingOverview(onboarding, readiness, session, loadData) {
|
|
|
183
186
|
return html`
|
|
184
187
|
<div class="adm-agi-section">
|
|
185
188
|
<div class="adm-agi-section-title">${t('admin.agentIntegration.onboardingOverview')}</div>
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
<div class="adm-agi-stat-card">
|
|
192
|
-
<div class="adm-agi-stat-value adm-agi-stat-value--accent">${num(onboarding.in_progress)}</div>
|
|
193
|
-
<div class="adm-agi-stat-label">${t('admin.agentIntegration.inProgress')}</div>
|
|
194
|
-
</div>
|
|
195
|
-
<div class="adm-agi-stat-card">
|
|
196
|
-
<div class="adm-agi-stat-value">${num(notStarted)}</div>
|
|
197
|
-
<div class="adm-agi-stat-label">${t('admin.agentIntegration.notStarted')}</div>
|
|
198
|
-
</div>
|
|
199
|
-
</div>
|
|
189
|
+
<${StatsGrid} items=${[
|
|
190
|
+
{ label: t('admin.agentIntegration.completed'), value: onboarding.completed, tone: 'green' },
|
|
191
|
+
{ label: t('admin.agentIntegration.inProgress'), value: onboarding.in_progress, tone: 'indigo' },
|
|
192
|
+
{ label: t('admin.agentIntegration.notStarted'), value: notStarted },
|
|
193
|
+
]} />
|
|
200
194
|
${stuck.length > 0 ? html`
|
|
201
195
|
<div class="adm-agi-stuck-title">${t('admin.agentIntegration.stuckAgents')}</div>
|
|
202
196
|
<div class="adm-agi-stuck">
|
|
@@ -246,10 +240,10 @@ function StuckAgentRow({ agent, session, onAction }) {
|
|
|
246
240
|
<div class="adm-agi-stuck-suggestion">${suggestion}</div>
|
|
247
241
|
</div>
|
|
248
242
|
<div class="adm-agi-stuck-actions">
|
|
249
|
-
<button class="btn-
|
|
243
|
+
<button class="adm-btn-action adm-agi-stuck-btn" onClick=${handleRemind} disabled=${acting}>
|
|
250
244
|
${t('admin.agentIntegration.sendReminder')}
|
|
251
245
|
</button>
|
|
252
|
-
<button class="btn-
|
|
246
|
+
<button class="adm-btn-action adm-agi-stuck-btn" onClick=${handleSkip} disabled=${acting}>
|
|
253
247
|
${t('admin.agentIntegration.skipStep')}
|
|
254
248
|
</button>
|
|
255
249
|
</div>
|
|
@@ -337,7 +331,7 @@ function renderSkillBundles(bundles, onRegenerate, regenerating, session) {
|
|
|
337
331
|
: html`<span class="adm-agi-zero">0</span>`
|
|
338
332
|
}</td>
|
|
339
333
|
<td>${info.outdated > 0 ? html`
|
|
340
|
-
<button class="btn-
|
|
334
|
+
<button class="adm-btn-action adm-agi-notify-btn" onClick=${() => handleNotify(platform)}>
|
|
341
335
|
${t('admin.agentIntegration.notifyOutdated')}
|
|
342
336
|
</button>
|
|
343
337
|
` : ''}</td>
|
|
@@ -347,7 +341,7 @@ function renderSkillBundles(bundles, onRegenerate, regenerating, session) {
|
|
|
347
341
|
</table>
|
|
348
342
|
`
|
|
349
343
|
}
|
|
350
|
-
<button class="btn-
|
|
344
|
+
<button class="adm-btn-action adm-agi-regen-btn" onClick=${onRegenerate} disabled=${regenerating}>
|
|
351
345
|
${regenerating ? t('common.loading') : t('admin.agentIntegration.regenerateAll')}
|
|
352
346
|
</button>
|
|
353
347
|
</div>
|
|
@@ -363,25 +357,16 @@ function renderBundleTemplates() {
|
|
|
363
357
|
return html`
|
|
364
358
|
<div class="adm-agi-section">
|
|
365
359
|
<div class="adm-agi-section-title">${t('admin.agentIntegration.bundleTemplates')}</div>
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
<div class="adm-agi-stat-card">
|
|
372
|
-
<div class="adm-agi-stat-value">0</div>
|
|
373
|
-
<div class="adm-agi-stat-label">${t('admin.agentIntegration.customScripts')}</div>
|
|
374
|
-
</div>
|
|
375
|
-
<div class="adm-agi-stat-card">
|
|
376
|
-
<div class="adm-agi-stat-value adm-agi-mono-sm">--</div>
|
|
377
|
-
<div class="adm-agi-stat-label">${t('admin.agentIntegration.lastGenerated')}</div>
|
|
378
|
-
</div>
|
|
379
|
-
</div>
|
|
360
|
+
<${StatsGrid} items=${[
|
|
361
|
+
{ label: t('admin.agentIntegration.customReferences'), value: 0 },
|
|
362
|
+
{ label: t('admin.agentIntegration.customScripts'), value: 0 },
|
|
363
|
+
{ label: t('admin.agentIntegration.lastGenerated'), value: '--' },
|
|
364
|
+
]} />
|
|
380
365
|
<div class="adm-agi-btn-row">
|
|
381
|
-
<button class="btn-
|
|
366
|
+
<button class="adm-btn-action" onClick=${handleComingSoon}>
|
|
382
367
|
${t('admin.agentIntegration.customizeBundle')}
|
|
383
368
|
</button>
|
|
384
|
-
<button class="btn-
|
|
369
|
+
<button class="adm-btn-action" onClick=${handleComingSoon}>
|
|
385
370
|
${t('admin.agentIntegration.previewBundle')}
|
|
386
371
|
</button>
|
|
387
372
|
</div>
|
|
@@ -3,6 +3,9 @@
|
|
|
3
3
|
* @description Admin dashboard tab for browsing all agent tasks across all owners.
|
|
4
4
|
* Provides status filtering, pagination, and TODO progress display.
|
|
5
5
|
* @version-history
|
|
6
|
+
* v1.1.0 -- 2026-06-02 -- Component unification (#16): replace inline hex status
|
|
7
|
+
* colors with tokenized .tag--status-* classes (admin.css) so status tags flip
|
|
8
|
+
* correctly in dark mode.
|
|
6
9
|
* v1.0.0 -- 2026-05-21 -- Initial creation for Agent Dashboard Phase 1
|
|
7
10
|
*/
|
|
8
11
|
import { h } from 'preact';
|
|
@@ -11,7 +14,7 @@ import htm from 'htm';
|
|
|
11
14
|
const html = htm.bind(h);
|
|
12
15
|
import { t } from '/js/i18n.js';
|
|
13
16
|
import { escHtml } from '/js/utils.js';
|
|
14
|
-
import {
|
|
17
|
+
import { dt, Empty, Badge, StatsGrid } from './shared.js';
|
|
15
18
|
import { apiGet } from '/js/api.js';
|
|
16
19
|
|
|
17
20
|
const PAGE_SIZE = 20;
|
|
@@ -25,8 +28,8 @@ export default function AgentTasksTab({ data, reload, session }) {
|
|
|
25
28
|
const [loading, setLoading] = useState(false);
|
|
26
29
|
const [statusFilter, setStatusFilter] = useState('');
|
|
27
30
|
|
|
28
|
-
const loadTasks = useCallback(async (p = 1) => {
|
|
29
|
-
setLoading(true);
|
|
31
|
+
const loadTasks = useCallback(async (p = 1, { showSpinner = true } = {}) => {
|
|
32
|
+
if (showSpinner) setLoading(true);
|
|
30
33
|
try {
|
|
31
34
|
const params = new URLSearchParams();
|
|
32
35
|
params.set('page', String(p));
|
|
@@ -48,7 +51,7 @@ export default function AgentTasksTab({ data, reload, session }) {
|
|
|
48
51
|
|
|
49
52
|
// Listen for live updates
|
|
50
53
|
useEffect(() => {
|
|
51
|
-
const handler = () => { loadTasks(page); };
|
|
54
|
+
const handler = () => { loadTasks(page, { showSpinner: false }); }; // silent: no flash
|
|
52
55
|
window.addEventListener('aimeat-live-update', handler);
|
|
53
56
|
return () => window.removeEventListener('aimeat-live-update', handler);
|
|
54
57
|
}, [loadTasks, page]);
|
|
@@ -57,16 +60,11 @@ export default function AgentTasksTab({ data, reload, session }) {
|
|
|
57
60
|
setStatusFilter(e.target.value);
|
|
58
61
|
}
|
|
59
62
|
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
case 'stalled': return '#eab308';
|
|
66
|
-
case 'queued': return '#a855f7';
|
|
67
|
-
case 'draft': return 'var(--text-dim)';
|
|
68
|
-
default: return 'var(--text-dim)';
|
|
69
|
-
}
|
|
63
|
+
// Map a task status to a tokenized status-tag class (colors live in admin.css,
|
|
64
|
+
// tag--status-* — replaces the former inline hex colors so chips flip in dark mode).
|
|
65
|
+
function statusTagClass(status) {
|
|
66
|
+
const known = ['active', 'done', 'failed', 'stalled', 'queued', 'draft'];
|
|
67
|
+
return known.includes(status) ? `tag tag--status-${status}` : 'tag tag--status-draft';
|
|
70
68
|
}
|
|
71
69
|
|
|
72
70
|
const totalPages = Math.ceil(total / PAGE_SIZE);
|
|
@@ -87,12 +85,7 @@ export default function AgentTasksTab({ data, reload, session }) {
|
|
|
87
85
|
</div>
|
|
88
86
|
|
|
89
87
|
<!-- Stats summary -->
|
|
90
|
-
|
|
91
|
-
<div class="adm-mem-stat">
|
|
92
|
-
<span class="adm-mem-stat-value">${num(total)}</span>
|
|
93
|
-
<span class="adm-mem-stat-label">${t('dashboard.agentTasksTotal')}</span>
|
|
94
|
-
</div>
|
|
95
|
-
</div>
|
|
88
|
+
<${StatsGrid} items=${[{ label: t('dashboard.agentTasksTotal'), value: total }]} />
|
|
96
89
|
|
|
97
90
|
<!-- Table -->
|
|
98
91
|
${tasks.length === 0 && !loading && html`<${Empty} text=${t('dashboard.agentTasksEmpty')} />`}
|
|
@@ -115,7 +108,7 @@ export default function AgentTasksTab({ data, reload, session }) {
|
|
|
115
108
|
<td class="mono" style="font-size:.8rem">${escHtml(task.agent_gaii)}</td>
|
|
116
109
|
<td>${escHtml(task.title)}</td>
|
|
117
110
|
<td>
|
|
118
|
-
<span class
|
|
111
|
+
<span class=${statusTagClass(task.status)}>
|
|
119
112
|
${task.status}
|
|
120
113
|
</span>
|
|
121
114
|
</td>
|
|
@@ -176,7 +176,7 @@ export default function ChatInstancesTab({ data, reload }) {
|
|
|
176
176
|
|
|
177
177
|
<!-- AI Chat Instances -->
|
|
178
178
|
<${StatsGrid} items=${[
|
|
179
|
-
{ label: t('dashboard.totalSessions'), value: sessions.length,
|
|
179
|
+
{ label: t('dashboard.totalSessions'), value: sessions.length, tone: 'cyan' },
|
|
180
180
|
]} />
|
|
181
181
|
|
|
182
182
|
${!sessions.length
|
|
@@ -10,6 +10,9 @@
|
|
|
10
10
|
* v1.2.0 -- 2026-05-31 -- Fix: inputs were bound to the saved value, not the
|
|
11
11
|
* pending edit, so toggling a checkbox / typing snapped straight back on
|
|
12
12
|
* re-render (looked un-editable). All inputs now reflect pending[path].
|
|
13
|
+
* v1.3.0 -- 2026-06-02 -- Admin design unification: inline error <div>
|
|
14
|
+
* replaced with shared <ErrorBox>; success message moved to the
|
|
15
|
+
* adm-config-result-ok class (no inline color/background styles).
|
|
13
16
|
*/
|
|
14
17
|
import { h } from 'preact';
|
|
15
18
|
import { useState } from 'preact/hooks';
|
|
@@ -17,7 +20,7 @@ import htm from 'htm';
|
|
|
17
20
|
const html = htm.bind(h);
|
|
18
21
|
import { t } from '/js/i18n.js';
|
|
19
22
|
import { escHtml } from '/js/utils.js';
|
|
20
|
-
import { Badge, Empty, ExpandableHelp } from './shared.js';
|
|
23
|
+
import { Badge, Empty, ExpandableHelp, ErrorBox } from './shared.js';
|
|
21
24
|
import { saveConfig, deleteConfig } from '/js/services/admin.js';
|
|
22
25
|
|
|
23
26
|
// Map config source to Badge type for visual distinction
|
|
@@ -113,7 +116,9 @@ export default function ConfigTab({ data, reload }) {
|
|
|
113
116
|
</div>
|
|
114
117
|
`}
|
|
115
118
|
|
|
116
|
-
${result &&
|
|
119
|
+
${result && (result.ok
|
|
120
|
+
? html`<div class="adm-config-result-ok adm-mb-md adm-text-base">${escHtml(result.msg)}</div>`
|
|
121
|
+
: html`<div class="adm-mb-md"><${ErrorBox} message=${result.msg} /></div>`)}
|
|
117
122
|
|
|
118
123
|
<!-- Pending changes banner -->
|
|
119
124
|
${editable && pendingKeys.length > 0 && html`
|
|
@@ -5,6 +5,11 @@
|
|
|
5
5
|
* and shows component breakdowns.
|
|
6
6
|
* @version-history
|
|
7
7
|
* v1.0.0 — 2026-03-17 — Initial admin cortex management tab
|
|
8
|
+
* v1.1.0 — 2026-06-02 — Admin design unification: fix the broken useToast wiring
|
|
9
|
+
* (object-destructured the array-returning hook, and passed wrong props to
|
|
10
|
+
* <Toast> — toasts never rendered); now uses the canonical [msg,showErr,showOk,
|
|
11
|
+
* clear] API with a showToast adapter + correct <Toast type text onDismiss>.
|
|
12
|
+
* Main btn-* classes → adm-btn / adm-btn-action / adm-btn adm-btn-danger-solid.
|
|
8
13
|
*/
|
|
9
14
|
import { h } from 'preact';
|
|
10
15
|
import { useState, useEffect, useCallback } from 'preact/hooks';
|
|
@@ -19,24 +24,25 @@ import * as cortexService from '/js/services/cortex.js';
|
|
|
19
24
|
const COMP_ICONS = { schema: '\u{1F4D0}', prompt: '\u{1F4AC}', action: '\u26A1', 'board-template': '\u{1F4CC}', ontology: '\u{1F9EC}', 'seed-data': '\u{1F331}', lib: '\u{1F4E6}' };
|
|
20
25
|
|
|
21
26
|
export default function CortexTab({ data, reload, session }) {
|
|
22
|
-
const
|
|
27
|
+
const [toast, showErr, showOk, clearToast] = useToast();
|
|
28
|
+
const showToast = (text, isError) => isError ? showErr(text) : showOk(text);
|
|
23
29
|
const { confirm, ConfirmUI } = useConfirm();
|
|
24
30
|
const [extensions, setExtensions] = useState([]);
|
|
25
31
|
const [loading, setLoading] = useState(true);
|
|
26
32
|
const [detail, setDetail] = useState(null);
|
|
27
33
|
|
|
28
|
-
const loadData = useCallback(async () => {
|
|
29
|
-
setLoading(true);
|
|
34
|
+
const loadData = useCallback(async ({ showSpinner = true } = {}) => {
|
|
35
|
+
if (showSpinner) setLoading(true);
|
|
30
36
|
try {
|
|
31
37
|
const resp = await cortexService.listExtensions();
|
|
32
38
|
setExtensions(resp?.extensions || []);
|
|
33
|
-
} catch { setExtensions([]); }
|
|
39
|
+
} catch { if (showSpinner) setExtensions([]); }
|
|
34
40
|
setLoading(false);
|
|
35
41
|
}, []);
|
|
36
42
|
|
|
37
43
|
useEffect(() => { loadData(); }, [loadData]);
|
|
38
44
|
useEffect(() => {
|
|
39
|
-
const handler = () => { loadData(); };
|
|
45
|
+
const handler = () => { loadData({ showSpinner: false }); }; // silent: no flash
|
|
40
46
|
window.addEventListener('aimeat-live-update', handler);
|
|
41
47
|
return () => window.removeEventListener('aimeat-live-update', handler);
|
|
42
48
|
}, [loadData]);
|
|
@@ -92,9 +98,9 @@ export default function CortexTab({ data, reload, session }) {
|
|
|
92
98
|
const isActive = ext.status === 'active';
|
|
93
99
|
const vis = ext.visibility || 'private';
|
|
94
100
|
return html`<div>
|
|
95
|
-
|
|
101
|
+
${toast && html`<${Toast} type=${toast.type} text=${toast.text} onDismiss=${clearToast} />`}
|
|
96
102
|
<${ConfirmUI} />
|
|
97
|
-
<button class="btn-
|
|
103
|
+
<button class="adm-btn-action" onClick=${() => setDetail(null)}>${t('dashboard.cortex.back')}</button>
|
|
98
104
|
<h3 class="adm-section-title" style="margin-top:1rem">${escHtml(ext.name)} <span class="adm-text-dim adm-text-sm">v${ext.version || '?'}</span></h3>
|
|
99
105
|
<p class="adm-text-dim">${escHtml(ext.description || '')}</p>
|
|
100
106
|
<div class="adm-meta-row">
|
|
@@ -113,18 +119,18 @@ export default function CortexTab({ data, reload, session }) {
|
|
|
113
119
|
|
|
114
120
|
<div class="adm-actions-row" style="margin-top:1.5rem">
|
|
115
121
|
${isActive
|
|
116
|
-
? html`<button class="btn-
|
|
117
|
-
: html`<button class="btn
|
|
118
|
-
<button class="btn-
|
|
122
|
+
? html`<button class="adm-btn-action" onClick=${() => handleDeactivate(ext.name)}>${t('dashboard.cortex.deactivate')}</button>`
|
|
123
|
+
: html`<button class="adm-btn" onClick=${() => handleActivate(ext.name)}>${t('dashboard.cortex.activate')}</button>`}
|
|
124
|
+
<button class="adm-btn-action" onClick=${() => handleVisibility(ext.name, vis)}>
|
|
119
125
|
${vis === 'public' ? t('dashboard.cortex.makePrivate') : t('dashboard.cortex.makePublic')}
|
|
120
126
|
</button>
|
|
121
|
-
<button class="btn-danger-solid" onClick=${() => handleUninstall(ext.name)}>${t('dashboard.cortex.uninstall')}</button>
|
|
127
|
+
<button class="adm-btn adm-btn-danger-solid" onClick=${() => handleUninstall(ext.name)}>${t('dashboard.cortex.uninstall')}</button>
|
|
122
128
|
</div>
|
|
123
129
|
</div>`;
|
|
124
130
|
}
|
|
125
131
|
|
|
126
132
|
return html`<div>
|
|
127
|
-
|
|
133
|
+
${toast && html`<${Toast} type=${toast.type} text=${toast.text} onDismiss=${clearToast} />`}
|
|
128
134
|
<${ConfirmUI} />
|
|
129
135
|
<${StatsGrid} items=${[
|
|
130
136
|
{ label: t('dashboard.cortex.total'), value: extensions.length },
|
|
@@ -158,8 +164,8 @@ export default function CortexTab({ data, reload, session }) {
|
|
|
158
164
|
<td class="adm-text-dim">${types.join(', ')}</td>
|
|
159
165
|
<td>
|
|
160
166
|
${isActive
|
|
161
|
-
? html`<button class="
|
|
162
|
-
: html`<button class="
|
|
167
|
+
? html`<button class="adm-btn-action" onClick=${() => handleDeactivate(ext.name)}>${t('dashboard.cortex.deactivate')}</button>`
|
|
168
|
+
: html`<button class="adm-btn" onClick=${() => handleActivate(ext.name)}>${t('dashboard.cortex.activate')}</button>`}
|
|
163
169
|
</td>
|
|
164
170
|
</tr>`;
|
|
165
171
|
})}
|
|
@@ -1,11 +1,23 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @file csm-tab.js
|
|
3
|
+
* @description Admin dashboard CSM (Community Service Manifest) tab — list,
|
|
4
|
+
* detail, create and delete of registered CSM templates, plus an AI builder
|
|
5
|
+
* prompt view.
|
|
6
|
+
* @structure default export CsmTab({ data, reload }); list/detail/create/prompt views.
|
|
7
|
+
* @usage Mounted by the admin dashboard tab router.
|
|
8
|
+
* @version-history
|
|
9
|
+
* v1.1.0 — 2026-06-02 — Admin design unification: inline danger styles → adm-btn-danger
|
|
10
|
+
* (2 delete buttons), raw textarea → adm-textarea adm-input-full, error div → <ErrorBox>.
|
|
11
|
+
*/
|
|
1
12
|
import { h } from 'preact';
|
|
2
13
|
import { useState } from 'preact/hooks';
|
|
3
14
|
import htm from 'htm';
|
|
4
15
|
const html = htm.bind(h);
|
|
5
16
|
import { t } from '/js/i18n.js';
|
|
6
17
|
import { escHtml } from '/js/utils.js';
|
|
7
|
-
import { dt, Empty, ExpandableHelp, useToast, Toast } from './shared.js';
|
|
18
|
+
import { dt, Empty, ExpandableHelp, ErrorBox, useToast, Toast } from './shared.js';
|
|
8
19
|
import { useConfirm } from '/components/Modal.js';
|
|
20
|
+
import { CopyButton } from '/components/CopyButton.js';
|
|
9
21
|
import { getCsmDetail, deleteCsm, createCsm, getCsmFileTemplates, getCsmFileTemplate, getCsmBuilderPrompt } from '/js/services/admin.js';
|
|
10
22
|
|
|
11
23
|
export default function CsmTab({ data, reload }) {
|
|
@@ -17,7 +29,6 @@ export default function CsmTab({ data, reload }) {
|
|
|
17
29
|
const [loading, setLoading] = useState(false);
|
|
18
30
|
const [err, setErr] = useState('');
|
|
19
31
|
const [prompt, setPrompt] = useState('');
|
|
20
|
-
const [copied, setCopied] = useState(false);
|
|
21
32
|
const [toast, showErr, showOk, clearToast] = useToast();
|
|
22
33
|
const { confirm, ConfirmUI } = useConfirm();
|
|
23
34
|
|
|
@@ -89,15 +100,7 @@ export default function CsmTab({ data, reload }) {
|
|
|
89
100
|
setLoading(false);
|
|
90
101
|
}
|
|
91
102
|
|
|
92
|
-
|
|
93
|
-
try {
|
|
94
|
-
await navigator.clipboard.writeText(prompt);
|
|
95
|
-
setCopied(true);
|
|
96
|
-
setTimeout(() => setCopied(false), 2000);
|
|
97
|
-
} catch { /* fallback — select text */ }
|
|
98
|
-
}
|
|
99
|
-
|
|
100
|
-
function backToList() { setView('list'); setDetail(null); setErr(''); setCopied(false); }
|
|
103
|
+
function backToList() { setView('list'); setDetail(null); setErr(''); }
|
|
101
104
|
|
|
102
105
|
// ── Detail view ──
|
|
103
106
|
if (view === 'detail' && detail) {
|
|
@@ -110,7 +113,7 @@ export default function CsmTab({ data, reload }) {
|
|
|
110
113
|
<div class="adm-card adm-mt-md">
|
|
111
114
|
<div class="adm-flex-between">
|
|
112
115
|
<h4 style="margin:0">${escHtml(detail.name)}</h4>
|
|
113
|
-
<button class="adm-btn-sm
|
|
116
|
+
<button class="adm-btn-sm adm-btn-danger" onClick=${() => doDelete(detail.name)}>
|
|
114
117
|
${t('dashboard.delete')}
|
|
115
118
|
</button>
|
|
116
119
|
</div>
|
|
@@ -149,9 +152,10 @@ export default function CsmTab({ data, reload }) {
|
|
|
149
152
|
|
|
150
153
|
<div style="position:relative">
|
|
151
154
|
<pre style="background:var(--bg-deep,#0f172a);padding:16px;border-radius:8px;overflow:auto;font-size:.8rem;max-height:500px;white-space:pre-wrap;line-height:1.5;border:1px solid var(--glass-border,#334155)">${prompt}</pre>
|
|
152
|
-
<
|
|
153
|
-
|
|
154
|
-
|
|
155
|
+
<span style="position:absolute;top:8px;right:8px">
|
|
156
|
+
<${CopyButton} text=${prompt} className="adm-btn"
|
|
157
|
+
label=${t('dashboard.copy')} copiedLabel=${t('dashboard.copied')} />
|
|
158
|
+
</span>
|
|
155
159
|
</div>
|
|
156
160
|
|
|
157
161
|
<div class="adm-mt-lg">
|
|
@@ -190,13 +194,13 @@ export default function CsmTab({ data, reload }) {
|
|
|
190
194
|
<label class="adm-text-base adm-text-dim" style="display:block;margin-bottom:4px">${t('dashboard.csmDefinition')}</label>
|
|
191
195
|
<textarea
|
|
192
196
|
rows="16"
|
|
193
|
-
|
|
197
|
+
class="adm-textarea adm-input-full"
|
|
194
198
|
placeholder=${t('dashboard.csmYamlPlaceholder')}
|
|
195
199
|
value=${yaml}
|
|
196
200
|
onInput=${e => setYaml(e.target.value)}
|
|
197
201
|
/>
|
|
198
202
|
|
|
199
|
-
${err && html`<div class="
|
|
203
|
+
${err && html`<div class="adm-mt-sm"><${ErrorBox} message=${err} /></div>`}
|
|
200
204
|
|
|
201
205
|
<div class="adm-flex adm-mt-md">
|
|
202
206
|
<button class="adm-btn" onClick=${doCreate} disabled=${loading || !yaml.trim()}>
|
|
@@ -246,7 +250,7 @@ export default function CsmTab({ data, reload }) {
|
|
|
246
250
|
<td style="white-space:nowrap">
|
|
247
251
|
<button class="adm-btn-sm" onClick=${() => showDetail(c.name)}>${t('dashboard.details')}</button>
|
|
248
252
|
${' '}
|
|
249
|
-
<button class="adm-btn-sm
|
|
253
|
+
<button class="adm-btn-sm adm-btn-danger" onClick=${() => doDelete(c.name)}>
|
|
250
254
|
${t('dashboard.delete')}
|
|
251
255
|
</button>
|
|
252
256
|
</td>
|
|
@@ -28,9 +28,9 @@ export default function DirectoryTab({ data }) {
|
|
|
28
28
|
<${ExpandableHelp} title=${t('dashboard.directoryHelpTitle')}>${t('dashboard.directoryHelpDetail')}</${ExpandableHelp}>
|
|
29
29
|
|
|
30
30
|
<${StatsGrid} items=${[
|
|
31
|
-
{ label: t('dashboard.totalEntries'), value: dir?.total || 0,
|
|
32
|
-
{ label: t('dashboard.cities'), value: dir?.cities || 0,
|
|
33
|
-
{ label: t('dashboard.categories'), value: dir?.categories || 0,
|
|
31
|
+
{ label: t('dashboard.totalEntries'), value: dir?.total || 0, tone: 'cyan' },
|
|
32
|
+
{ label: t('dashboard.cities'), value: dir?.cities || 0, tone: 'green' },
|
|
33
|
+
{ label: t('dashboard.categories'), value: dir?.categories || 0, tone: 'amber' },
|
|
34
34
|
]} />
|
|
35
35
|
|
|
36
36
|
<div class="adm-card" style="margin-top:12px">
|
|
@@ -1,3 +1,13 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @file email-tab.js
|
|
3
|
+
* @description Admin dashboard Email tab — SMTP config view, test-send, group
|
|
4
|
+
* broadcast, and per-locale email template editor with AI-prompt generation.
|
|
5
|
+
* @structure EmailTab (default), TemplateEditor, buildAiPrompt
|
|
6
|
+
* @usage Mounted by the admin dashboard tab router.
|
|
7
|
+
* @version-history
|
|
8
|
+
* v1.1.0 — 2026-06-02 — Admin design unification: raw textareas → adm-textarea
|
|
9
|
+
* adm-input-full; inline button color styles → adm-btn-success/adm-btn-danger.
|
|
10
|
+
*/
|
|
1
11
|
import { h } from 'preact';
|
|
2
12
|
import { useState, useEffect } from 'preact/hooks';
|
|
3
13
|
import htm from 'htm';
|
|
@@ -5,6 +15,7 @@ const html = htm.bind(h);
|
|
|
5
15
|
import { t } from '/js/i18n.js';
|
|
6
16
|
import { EconRow, Empty, ExpandableHelp } from './shared.js';
|
|
7
17
|
import { useConfirm } from '/components/Modal.js';
|
|
18
|
+
import { CopyButton } from '/components/CopyButton.js';
|
|
8
19
|
import { sendTestEmail, getEmailTemplates, sendGroupEmail, saveEmailTemplate, resetEmailTemplate, seedEmailTemplates, resetAllEmailTemplates, saveConfig } from '/js/services/admin.js';
|
|
9
20
|
|
|
10
21
|
const TEMPLATE_IDS = ['notification', 'verification', 'magic_link', 'match_suggestion'];
|
|
@@ -107,23 +118,6 @@ function TemplateEditor({ tpl, locale, onSave, onReset }) {
|
|
|
107
118
|
}, { danger: true });
|
|
108
119
|
}
|
|
109
120
|
|
|
110
|
-
async function copyAiPrompt() {
|
|
111
|
-
const prompt = buildAiPrompt(tpl, locale);
|
|
112
|
-
try {
|
|
113
|
-
await navigator.clipboard.writeText(prompt);
|
|
114
|
-
setMsg({ ok: true, text: t('dashboard.emailTplAiPromptCopied') });
|
|
115
|
-
} catch {
|
|
116
|
-
// Fallback: select textarea
|
|
117
|
-
const ta = document.createElement('textarea');
|
|
118
|
-
ta.value = prompt;
|
|
119
|
-
document.body.appendChild(ta);
|
|
120
|
-
ta.select();
|
|
121
|
-
document.execCommand('copy');
|
|
122
|
-
document.body.removeChild(ta);
|
|
123
|
-
setMsg({ ok: true, text: t('dashboard.emailTplAiPromptCopied') });
|
|
124
|
-
}
|
|
125
|
-
}
|
|
126
|
-
|
|
127
121
|
const hasChanges = editHtml !== (tpl.preview || '') || editText !== (tpl.text || '');
|
|
128
122
|
|
|
129
123
|
const tabStyle = (active) => `
|
|
@@ -167,17 +161,19 @@ function TemplateEditor({ tpl, locale, onSave, onReset }) {
|
|
|
167
161
|
`}
|
|
168
162
|
${view === 'html' && html`
|
|
169
163
|
<textarea
|
|
164
|
+
class="adm-textarea adm-input-full"
|
|
170
165
|
value=${editHtml}
|
|
171
166
|
onInput=${e => setEditHtml(e.target.value)}
|
|
172
|
-
style="
|
|
167
|
+
style="height:420px;font-size:12px;border-top:none;border-radius:0 0 6px 6px"
|
|
173
168
|
spellcheck="false"
|
|
174
169
|
/>
|
|
175
170
|
`}
|
|
176
171
|
${view === 'text' && html`
|
|
177
172
|
<textarea
|
|
173
|
+
class="adm-textarea adm-input-full"
|
|
178
174
|
value=${editText}
|
|
179
175
|
onInput=${e => setEditText(e.target.value)}
|
|
180
|
-
style="
|
|
176
|
+
style="height:300px;font-size:13px;border-top:none;border-radius:0 0 6px 6px"
|
|
181
177
|
spellcheck="false"
|
|
182
178
|
/>
|
|
183
179
|
`}
|
|
@@ -186,11 +182,11 @@ function TemplateEditor({ tpl, locale, onSave, onReset }) {
|
|
|
186
182
|
<div class="adm-flex-center" style="flex-wrap:wrap;margin-top:10px">
|
|
187
183
|
<button class="adm-btn-action adm-text-sm" onClick=${doSave} disabled=${saving || !hasChanges}>
|
|
188
184
|
${saving ? '...' : t('dashboard.emailTplSave')}</button>
|
|
189
|
-
|
|
190
|
-
|
|
185
|
+
<${CopyButton} text=${buildAiPrompt(tpl, locale)} className="adm-btn-action adm-text-sm"
|
|
186
|
+
label=${t('dashboard.emailTplAiPrompt')} copiedLabel=${t('dashboard.emailTplAiPrompt')}
|
|
187
|
+
onCopied=${() => setMsg({ ok: true, text: t('dashboard.emailTplAiPromptCopied') })} />
|
|
191
188
|
${tpl.isCustom && html`
|
|
192
|
-
<button class="adm-btn-action adm-text-sm" onClick=${doReset} disabled=${saving}
|
|
193
|
-
style="color:#ef4444;border-color:rgba(239,68,68,0.3)">${t('dashboard.emailTplReset')}</button>
|
|
189
|
+
<button class="adm-btn-action adm-btn-danger adm-text-sm" onClick=${doReset} disabled=${saving}>${t('dashboard.emailTplReset')}</button>
|
|
194
190
|
`}
|
|
195
191
|
${msg && html`<span class="adm-text-sm" style="color:${msg.ok ? '#22c55e' : '#ef4444'}">${msg.text}</span>`}
|
|
196
192
|
</div>
|
|
@@ -385,11 +381,10 @@ export default function EmailTab({ data, reload, locale }) {
|
|
|
385
381
|
<input type="text" class="adm-input adm-input-full adm-mb-sm" value=${grpSubject}
|
|
386
382
|
onInput=${e => setGrpSubject(e.target.value)}
|
|
387
383
|
placeholder=${t('dashboard.emailGroupSubject')} />
|
|
388
|
-
<textarea class="adm-
|
|
384
|
+
<textarea class="adm-textarea adm-input-full" value=${grpBody}
|
|
389
385
|
onInput=${e => setGrpBody(e.target.value)}
|
|
390
386
|
placeholder=${t('dashboard.emailGroupBody')}
|
|
391
|
-
rows="4"
|
|
392
|
-
style="resize:vertical;font-family:inherit" />
|
|
387
|
+
rows="4" />
|
|
393
388
|
<div class="adm-mt-sm">
|
|
394
389
|
<button class="adm-btn" onClick=${doGroupSend} disabled=${grpSending || !grpSubject || !grpBody}>
|
|
395
390
|
${grpSending ? '...' : t('dashboard.emailGroupSend')}
|
|
@@ -414,12 +409,12 @@ export default function EmailTab({ data, reload, locale }) {
|
|
|
414
409
|
<!-- Seed / Reset All buttons -->
|
|
415
410
|
<div class="adm-flex-center" style="flex-wrap:wrap;margin-bottom:14px;padding:10px 12px;border-radius:6px;background:rgba(255,255,255,0.02);border:1px solid var(--glass-border)">
|
|
416
411
|
${!seeded && html`
|
|
417
|
-
<button class="adm-btn-action adm-text-sm"
|
|
412
|
+
<button class="adm-btn-action adm-btn-success adm-text-sm"
|
|
418
413
|
onClick=${doSeedDefaults}>${t('dashboard.emailTplSeedDefaults')}</button>
|
|
419
414
|
<span style="font-size:.78rem" class="adm-text-dim">${t('dashboard.emailTplSeedExplain')}</span>
|
|
420
415
|
`}
|
|
421
416
|
${seeded && html`
|
|
422
|
-
<button class="adm-btn-action adm-text-sm"
|
|
417
|
+
<button class="adm-btn-action adm-btn-danger adm-text-sm"
|
|
423
418
|
onClick=${doResetAll}>${t('dashboard.emailTplResetAll')}</button>
|
|
424
419
|
<button class="adm-btn-action adm-text-sm"
|
|
425
420
|
onClick=${doSeedDefaults}>${t('dashboard.emailTplReseed')}</button>
|
|
@@ -1,3 +1,13 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @file federation-tab.js
|
|
3
|
+
* @description Admin dashboard Federation tab — peer management, peering
|
|
4
|
+
* requests, network directory, auth policy, and federation bus overview.
|
|
5
|
+
* @structure FederationTab (default)
|
|
6
|
+
* @usage Mounted by the admin dashboard tab router.
|
|
7
|
+
* @version-history
|
|
8
|
+
* v1.1.0 — 2026-06-02 — Admin design unification: inline button color style
|
|
9
|
+
* on the approve action → adm-btn-success.
|
|
10
|
+
*/
|
|
1
11
|
import { h } from 'preact';
|
|
2
12
|
import { useState, useEffect, useCallback, useRef } from 'preact/hooks';
|
|
3
13
|
import htm from 'htm';
|
|
@@ -245,10 +255,10 @@ export default function FederationTab({ data, reload }) {
|
|
|
245
255
|
|
|
246
256
|
<!-- ═══ Stats Overview ═══ -->
|
|
247
257
|
<${StatsGrid} items=${[
|
|
248
|
-
{ label: t('dashboard.fedActivePeers'), value: activePeers.length,
|
|
249
|
-
{ label: t('dashboard.fedDegradedPeers'), value: degradedPeers.length,
|
|
250
|
-
{ label: t('dashboard.fedOfflinePeers'), value: offlinePeers.length,
|
|
251
|
-
{ label: t('dashboard.fedPendingRequests'), value: pendingRequests.length,
|
|
258
|
+
{ label: t('dashboard.fedActivePeers'), value: activePeers.length, tone: 'green' },
|
|
259
|
+
{ label: t('dashboard.fedDegradedPeers'), value: degradedPeers.length, tone: 'amber' },
|
|
260
|
+
{ label: t('dashboard.fedOfflinePeers'), value: offlinePeers.length, tone: 'red' },
|
|
261
|
+
{ label: t('dashboard.fedPendingRequests'), value: pendingRequests.length, tone: 'cyan' },
|
|
252
262
|
]} />
|
|
253
263
|
|
|
254
264
|
<!-- ═══ Federation Auth Policy ═══ -->
|
|
@@ -331,7 +341,7 @@ export default function FederationTab({ data, reload }) {
|
|
|
331
341
|
<td style="max-width:200px;overflow:hidden;text-overflow:ellipsis">${escHtml(r.message || '\u2014')}</td>
|
|
332
342
|
<td class="adm-text-dim">${dt(r.created_at)}</td>
|
|
333
343
|
<td style="display:flex;gap:4px">
|
|
334
|
-
<button class="adm-btn-sm
|
|
344
|
+
<button class="adm-btn-sm adm-btn-success" onClick=${() => doApprove(r.id)}>\u2714 ${t('dashboard.approve')}</button>
|
|
335
345
|
<button class="adm-btn-sm adm-text-error" onClick=${() => doReject(r.id)}>\u2718 ${t('dashboard.fedReject')}</button>
|
|
336
346
|
</td>
|
|
337
347
|
</tr>`)}
|