@saasicat/ui-vue 0.22.2 → 0.24.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/README.md +1 -1
- package/dist/{chunk-LY52T4N4.js → chunk-TQQMKWN6.js} +58 -1
- package/dist/{chunk-XMMFN2WJ.js → chunk-VYMTWCTT.js} +51 -1
- package/dist/client/index.cjs +57 -0
- package/dist/client/index.d.cts +58 -1
- package/dist/client/index.d.ts +58 -1
- package/dist/client/index.js +15 -1
- package/dist/index.cjs +321 -159
- package/dist/index.d.cts +67 -4
- package/dist/index.d.ts +67 -4
- package/dist/index.js +72 -2
- package/dist/quasar/index.cjs +116 -20
- package/dist/quasar/index.d.cts +48 -3
- package/dist/quasar/index.d.ts +48 -3
- package/dist/quasar/index.js +58 -3
- package/dist/{use-super-admin-i18n-CgTuNi8h.d.cts → use-sa-theme-B5t7oXph.d.cts} +51 -1
- package/dist/{use-super-admin-i18n-CHNdsSlm.d.ts → use-sa-theme-OUBlaqgl.d.ts} +51 -1
- package/package.json +5 -2
- package/src/client/identity-accents.ts +129 -0
- package/src/client/index.ts +1 -0
- package/src/components/BundleVersionPublishDialog.vue +17 -17
- package/src/components/KvBlock.vue +6 -6
- package/src/components/MarketingPromotionsTab.vue +84 -80
- package/src/components/MfaPromptDialog.vue +2 -2
- package/src/components/TenantActionConfirmDialog.vue +5 -5
- package/src/components/VersionDiffPreview.vue +18 -18
- package/src/components/bundle-editor/BundleCreatePanel.vue +52 -52
- package/src/components/bundle-editor/BundleFeaturesEditor.vue +20 -20
- package/src/components/bundle-editor/BundlePlanCompatPicker.vue +33 -33
- package/src/components/bundle-editor/BundleQuotasEditor.vue +26 -26
- package/src/components/bundle-editor/BundleStatusBanner.vue +21 -21
- package/src/components/bundle-editor/BundleVersionInlineEditor.vue +49 -49
- package/src/components/bundle-editor/BundleVersionStrip.vue +30 -30
- package/src/components/dialogs/PilotCreateDialog.vue +20 -20
- package/src/components/dialogs/PilotEditDialog.vue +6 -6
- package/src/components/dialogs/PromoCodeCreateDialog.vue +9 -9
- package/src/components/dialogs/PromoCodeDialogFields.vue +64 -63
- package/src/components/dialogs/PromoCodeEditDialog.vue +11 -11
- package/src/components/dialogs/pilot-dialog.css +48 -48
- package/src/components/plan/PlanCycleToggle.vue +9 -16
- package/src/components/plan/PlanGrid.vue +30 -34
- package/src/components/plan/PriceSummary.vue +35 -35
- package/src/components/plan/PromoCodeInput.vue +26 -26
- package/src/components/plan/PublicBundleGrid.vue +32 -28
- package/src/components/plan-create-dialog/PlanCreateDialog.vue +50 -50
- package/src/components/plan-detail/PlanDetail.vue +178 -157
- package/src/components/plan-detail/PlanTitleEdit.vue +11 -11
- package/src/components/plan-list/PlanList.vue +116 -100
- package/src/components/plan-matrix/PlanMatrix.vue +97 -114
- package/src/components/plan-review/PlanReview.vue +61 -57
- package/src/components/plan-version-editor/PlanVersionEditor.vue +246 -203
- package/src/components/wizard-stepper/WizardStepper.vue +17 -17
- package/src/index.ts +1 -0
- package/src/pages-standard/AdminLayout.vue +58 -37
- package/src/pages-standard/AdminManifestErrorPage.vue +6 -6
- package/src/pages-standard/AuditPage.vue +3 -3
- package/src/pages-standard/BundlesPage.vue +37 -37
- package/src/pages-standard/DashboardPage.vue +22 -19
- package/src/pages-standard/DiscoveryPage.vue +55 -49
- package/src/pages-standard/EmailHistoryPage.vue +53 -71
- package/src/pages-standard/MarketingCatalogPage.vue +245 -221
- package/src/pages-standard/PilotsPage.vue +7 -6
- package/src/pages-standard/PlatformEmailPage.vue +18 -18
- package/src/pages-standard/PromoCodeDetailPage.vue +3 -3
- package/src/pages-standard/PromoCodesPage.vue +10 -7
- package/src/pages-standard/SuperAdminLoginPage.vue +39 -25
- package/src/pages-standard/SuperAdminSetupWizard.vue +44 -33
- package/src/pages-standard/TenantDetailPage.vue +7 -7
- package/src/pages-standard/TenantsPage.vue +16 -50
- package/src/pages-standard/bundles-page/BundleAccordionList.vue +13 -13
- package/src/pages-standard/discovery-page/CatalogEntryTransPanel.vue +24 -24
- package/src/pages-standard/discovery-page/DiscoveryCapList.vue +22 -22
- package/src/pages-standard/discovery-page/DiscoveryFeatureCard.vue +39 -39
- package/src/pages-standard/discovery-page/DiscoveryQuotaCard.vue +26 -26
- package/src/pages-standard/discovery-page/DiscoveryStatusControl.vue +1 -1
- package/src/pages-standard/discovery-page/discovery-ui.ts +10 -7
- package/src/pages-standard/marketing-catalog/MarketingCatalogAdmin.vue +2 -5
- package/src/pages-standard/plan-versions/PlanDiffCard.vue +27 -20
- package/src/pages-standard/plan-versions/PlanVersionsDiff.vue +24 -16
- package/src/pages-standard/plan-versions/PlanVersionsTimeline.vue +45 -45
- package/src/pages-standard/plans-page/PlanBundleOverview.vue +21 -15
- package/src/pages-standard/plans-page/PlanPublishDialog.vue +4 -4
- package/src/pages-standard/plans-page/PlansPageToast.vue +6 -6
- package/src/pages-standard/sa-theme.css +9 -687
- package/src/pages-standard/tenants/StatusPill.vue +13 -13
- package/src/pages-standard/tenants/format.ts +11 -12
- package/src/pages-tenant/LimitsRow.vue +4 -4
- package/src/pages-tenant/MySubscriptionBundlesPage.vue +70 -61
- package/src/pages-tenant/OnboardingConfigurator.vue +25 -25
- package/src/pages-tenant/PackageSnapshotPanel.vue +10 -16
- package/src/pages-tenant/PendingVersionBanner.vue +12 -12
- package/src/pages-tenant/PlanChangeWizard.vue +22 -76
- package/src/pages-tenant/TenantPlanSection.vue +19 -69
- package/src/pages-tenant/UsageBar.vue +7 -7
- package/src/pages-tenant/default-i18n.ts +113 -0
- package/src/pages-tenant/tenant-plan-section/BundlePreviewDialog.vue +14 -14
- package/src/pages-tenant/tenant-plan-section/TenantBundleStore.vue +10 -10
- package/src/pages-tenant/tenant-plan-section/TenantFeatureMatrix.vue +2 -2
- package/src/quasar/create-super-admin-app.ts +96 -1
- package/src/quasar/dark-bridge.ts +66 -0
- package/src/quasar/index.ts +1 -0
- package/src/ui/theme/_breakpoints.scss +34 -0
- package/src/ui/theme/base.css +50 -0
- package/src/ui/theme/components/body.css +23 -0
- package/src/ui/theme/components/button.css +158 -0
- package/src/ui/theme/components/card.css +74 -0
- package/src/ui/theme/components/field.css +38 -0
- package/src/ui/theme/components/hero.css +46 -0
- package/src/ui/theme/components/paginator.css +63 -0
- package/src/ui/theme/components/section.css +67 -0
- package/src/ui/theme/components/statistics.css +189 -0
- package/src/ui/theme/components/table.css +60 -0
- package/src/ui/theme/index.css +42 -0
- package/src/ui/theme/tokens.legacy.css +147 -0
- package/src/ui/theme/tokens.primitive.css +112 -0
- package/src/ui/theme/tokens.scale.css +103 -0
- package/src/ui/theme/tokens.semantic.dark.css +185 -0
- package/src/ui/theme/tokens.semantic.light.css +242 -0
- package/src/vue/use-sa-theme.ts +154 -0
|
@@ -47,16 +47,17 @@
|
|
|
47
47
|
>
|
|
48
48
|
<template #row-actions="{ row }">
|
|
49
49
|
<slot name="row-actions" :row="row">
|
|
50
|
-
<
|
|
50
|
+
<button
|
|
51
51
|
v-for="action in visibleActions(row)"
|
|
52
52
|
:key="action.id"
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
:
|
|
53
|
+
type="button"
|
|
54
|
+
class="sa-icon-btn"
|
|
55
|
+
:class="action.color === 'negative' ? 'sa-icon-btn--negative' : ''"
|
|
56
56
|
:title="action.label"
|
|
57
|
-
:color="action.color ?? 'grey-7'"
|
|
58
57
|
@click="action.handler(row)"
|
|
59
|
-
|
|
58
|
+
>
|
|
59
|
+
<q-icon :name="action.icon" size="18px" />
|
|
60
|
+
</button>
|
|
60
61
|
</slot>
|
|
61
62
|
</template>
|
|
62
63
|
</AdminTable>
|
|
@@ -36,30 +36,30 @@
|
|
|
36
36
|
</q-td>
|
|
37
37
|
</template>
|
|
38
38
|
<template #row-actions="{ row }">
|
|
39
|
-
<
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
icon="send"
|
|
43
|
-
color="primary"
|
|
39
|
+
<button
|
|
40
|
+
type="button"
|
|
41
|
+
class="sa-icon-btn"
|
|
44
42
|
:title="msg.provider.sendTestMail"
|
|
45
43
|
@click="openTest(row)"
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
44
|
+
>
|
|
45
|
+
<q-icon name="send" size="18px" />
|
|
46
|
+
</button>
|
|
47
|
+
<button
|
|
48
|
+
type="button"
|
|
49
|
+
class="sa-icon-btn"
|
|
52
50
|
:title="common.edit"
|
|
53
51
|
@click="openEdit(row)"
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
52
|
+
>
|
|
53
|
+
<q-icon name="edit" size="18px" />
|
|
54
|
+
</button>
|
|
55
|
+
<button
|
|
56
|
+
type="button"
|
|
57
|
+
class="sa-icon-btn sa-icon-btn--negative"
|
|
60
58
|
:title="common.delete"
|
|
61
59
|
@click="onDelete(row)"
|
|
62
|
-
|
|
60
|
+
>
|
|
61
|
+
<q-icon name="delete" size="18px" />
|
|
62
|
+
</button>
|
|
63
63
|
</template>
|
|
64
64
|
</AdminTable>
|
|
65
65
|
</AdminSection>
|
|
@@ -297,11 +297,11 @@ const redemptionRows = computed(() => data.value?.redemptions ?? []);
|
|
|
297
297
|
gap: 14px;
|
|
298
298
|
}
|
|
299
299
|
.sa-promo-detail__kv {
|
|
300
|
-
background:
|
|
301
|
-
border: 1px solid var(--sa-border);
|
|
300
|
+
background: var(--sa-color-bg-surface-raised);
|
|
301
|
+
border: 1px solid var(--sa-color-border);
|
|
302
302
|
border-radius: 8px;
|
|
303
303
|
padding: 12px;
|
|
304
|
-
font-size:
|
|
304
|
+
font-size: var(--sa-text-sm);
|
|
305
305
|
margin: 0;
|
|
306
306
|
overflow-x: auto;
|
|
307
307
|
font-family: var(--sa-font-mono);
|
|
@@ -66,16 +66,17 @@
|
|
|
66
66
|
</template>
|
|
67
67
|
<template #row-actions="{ row }">
|
|
68
68
|
<slot name="row-actions" :row="row" :reload="reload">
|
|
69
|
-
<
|
|
69
|
+
<button
|
|
70
70
|
v-for="action in visibleActions(row)"
|
|
71
71
|
:key="action.id"
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
:
|
|
72
|
+
type="button"
|
|
73
|
+
class="sa-icon-btn"
|
|
74
|
+
:class="action.color === 'negative' ? 'sa-icon-btn--negative' : ''"
|
|
75
75
|
:title="action.label"
|
|
76
|
-
:color="action.color ?? 'grey-7'"
|
|
77
76
|
@click="action.handler(row)"
|
|
78
|
-
|
|
77
|
+
>
|
|
78
|
+
<q-icon :name="action.icon" size="18px" />
|
|
79
|
+
</button>
|
|
79
80
|
</slot>
|
|
80
81
|
</template>
|
|
81
82
|
</AdminTable>
|
|
@@ -109,7 +110,9 @@
|
|
|
109
110
|
import AdminTable from '../components/admin-page/AdminTable.vue';
|
|
110
111
|
import type { PromoCodePlanOption } from '../components/dialogs/types.js';
|
|
111
112
|
|
|
112
|
-
|
|
113
|
+
import { IDENTITY_ACCENTS } from '../client/identity-accents.js';
|
|
114
|
+
|
|
115
|
+
const PLAN_COLOR_PALETTE = IDENTITY_ACCENTS;
|
|
113
116
|
|
|
114
117
|
/**
|
|
115
118
|
* Heuristic from a consumer wrapper: assigns each plan a stable color so plan
|
|
@@ -199,7 +199,7 @@ async function handleSubmit(): Promise<void> {
|
|
|
199
199
|
on top of the centered card on short viewports. */
|
|
200
200
|
margin-left: auto;
|
|
201
201
|
align-self: flex-start;
|
|
202
|
-
color: var(--sa-login-tag-color, var(--sa-
|
|
202
|
+
color: var(--sa-login-tag-color, var(--sa-color-fg-secondary));
|
|
203
203
|
}
|
|
204
204
|
.sa-login-wrap {
|
|
205
205
|
min-height: 100vh;
|
|
@@ -208,15 +208,19 @@ async function handleSubmit(): Promise<void> {
|
|
|
208
208
|
align-items: center;
|
|
209
209
|
justify-content: center;
|
|
210
210
|
padding: 24px;
|
|
211
|
-
background: linear-gradient(
|
|
211
|
+
background: linear-gradient(
|
|
212
|
+
180deg,
|
|
213
|
+
var(--sa-color-inverse-bg) 0%,
|
|
214
|
+
var(--sa-color-inverse-surface) 100%
|
|
215
|
+
);
|
|
212
216
|
}
|
|
213
217
|
.sa-login-card {
|
|
214
218
|
width: 420px;
|
|
215
219
|
max-width: 92vw;
|
|
216
|
-
background:
|
|
220
|
+
background: var(--sa-color-bg-surface);
|
|
217
221
|
border-radius: 18px;
|
|
218
222
|
padding: 32px;
|
|
219
|
-
box-shadow: 0 24px 48px
|
|
223
|
+
box-shadow: 0 24px 48px var(--sa-shadow-tint-4);
|
|
220
224
|
}
|
|
221
225
|
.sa-login-brand {
|
|
222
226
|
display: flex;
|
|
@@ -234,10 +238,20 @@ async function handleSubmit(): Promise<void> {
|
|
|
234
238
|
overflow: hidden;
|
|
235
239
|
}
|
|
236
240
|
.sa-login-logo--text {
|
|
237
|
-
background: var(
|
|
238
|
-
|
|
241
|
+
background: var(
|
|
242
|
+
--sa-login-logo-bg,
|
|
243
|
+
linear-gradient(
|
|
244
|
+
135deg,
|
|
245
|
+
var(--sa-color-inverse-surface-soft),
|
|
246
|
+
var(--sa-color-inverse-surface)
|
|
247
|
+
)
|
|
248
|
+
);
|
|
249
|
+
/* The fallback has to match the fallback background above, which is the
|
|
250
|
+
* invariant dark gradient — not the accent. An app that sets its own
|
|
251
|
+
* `--sa-login-logo-bg` sets `--sa-login-logo-color` with it. */
|
|
252
|
+
color: var(--sa-login-logo-color, var(--sa-color-inverse-fg));
|
|
239
253
|
font-weight: 800;
|
|
240
|
-
font-size:
|
|
254
|
+
font-size: var(--sa-text-xl);
|
|
241
255
|
text-transform: uppercase;
|
|
242
256
|
}
|
|
243
257
|
.sa-login-logo--img img {
|
|
@@ -247,26 +261,26 @@ async function handleSubmit(): Promise<void> {
|
|
|
247
261
|
}
|
|
248
262
|
.sa-login-brand__name {
|
|
249
263
|
font-weight: 800;
|
|
250
|
-
font-size:
|
|
251
|
-
color: var(--sa-heading);
|
|
264
|
+
font-size: var(--sa-text-lg);
|
|
265
|
+
color: var(--sa-color-fg-heading);
|
|
252
266
|
line-height: 1.1;
|
|
253
267
|
}
|
|
254
268
|
.sa-login-brand__tag {
|
|
255
|
-
font-size:
|
|
256
|
-
color: var(--sa-login-tag-color, var(--sa-
|
|
269
|
+
font-size: var(--sa-text-sm);
|
|
270
|
+
color: var(--sa-login-tag-color, var(--sa-color-fg-secondary));
|
|
257
271
|
text-transform: uppercase;
|
|
258
272
|
letter-spacing: 0.08em;
|
|
259
273
|
}
|
|
260
274
|
|
|
261
275
|
.sa-login-title {
|
|
262
|
-
font-size:
|
|
276
|
+
font-size: var(--sa-text-2xl);
|
|
263
277
|
font-weight: 800;
|
|
264
|
-
color: var(--sa-heading);
|
|
278
|
+
color: var(--sa-color-fg-heading);
|
|
265
279
|
margin: 0 0 6px;
|
|
266
280
|
}
|
|
267
281
|
.sa-login-subtitle {
|
|
268
|
-
font-size:
|
|
269
|
-
color: var(--sa-
|
|
282
|
+
font-size: var(--sa-text-md);
|
|
283
|
+
color: var(--sa-color-fg-secondary);
|
|
270
284
|
margin: 0 0 20px;
|
|
271
285
|
line-height: 1.5;
|
|
272
286
|
}
|
|
@@ -279,10 +293,10 @@ async function handleSubmit(): Promise<void> {
|
|
|
279
293
|
width: 100%;
|
|
280
294
|
}
|
|
281
295
|
.sa-login-error {
|
|
282
|
-
background:
|
|
283
|
-
border: 1px solid
|
|
284
|
-
color:
|
|
285
|
-
font-size:
|
|
296
|
+
background: var(--sa-color-negative-surface);
|
|
297
|
+
border: 1px solid var(--sa-color-negative-border);
|
|
298
|
+
color: var(--sa-color-negative-fg);
|
|
299
|
+
font-size: var(--sa-text-md);
|
|
286
300
|
margin-top: 4px;
|
|
287
301
|
padding: 8px 12px;
|
|
288
302
|
border-radius: 8px;
|
|
@@ -290,20 +304,20 @@ async function handleSubmit(): Promise<void> {
|
|
|
290
304
|
.sa-login-hint {
|
|
291
305
|
margin-top: 18px;
|
|
292
306
|
padding: 10px 12px;
|
|
293
|
-
background: var(--sa-border-soft);
|
|
307
|
+
background: var(--sa-color-border-soft);
|
|
294
308
|
border-radius: 8px;
|
|
295
|
-
font-size:
|
|
296
|
-
color: var(--sa-
|
|
309
|
+
font-size: var(--sa-text-sm);
|
|
310
|
+
color: var(--sa-color-fg-secondary);
|
|
297
311
|
}
|
|
298
312
|
.sa-login-hint code {
|
|
299
|
-
background: var(--sa-border);
|
|
313
|
+
background: var(--sa-color-border);
|
|
300
314
|
padding: 1px 5px;
|
|
301
315
|
border-radius: 4px;
|
|
302
316
|
}
|
|
303
317
|
.sa-login-env {
|
|
304
318
|
margin-top: 18px;
|
|
305
|
-
color:
|
|
306
|
-
font-size:
|
|
319
|
+
color: var(--sa-color-inverse-fg-muted);
|
|
320
|
+
font-size: var(--sa-text-sm);
|
|
307
321
|
text-transform: uppercase;
|
|
308
322
|
letter-spacing: 0.08em;
|
|
309
323
|
}
|
|
@@ -277,15 +277,19 @@ async function submitConfirm(): Promise<void> {
|
|
|
277
277
|
align-items: center;
|
|
278
278
|
justify-content: center;
|
|
279
279
|
padding: 24px;
|
|
280
|
-
background: linear-gradient(
|
|
280
|
+
background: linear-gradient(
|
|
281
|
+
180deg,
|
|
282
|
+
var(--sa-color-inverse-bg) 0%,
|
|
283
|
+
var(--sa-color-inverse-surface) 100%
|
|
284
|
+
);
|
|
281
285
|
}
|
|
282
286
|
.sa-setup-card {
|
|
283
287
|
width: 460px;
|
|
284
288
|
max-width: 92vw;
|
|
285
|
-
background:
|
|
289
|
+
background: var(--sa-color-bg-surface);
|
|
286
290
|
border-radius: 18px;
|
|
287
291
|
padding: 32px;
|
|
288
|
-
box-shadow: 0 24px 48px
|
|
292
|
+
box-shadow: 0 24px 48px var(--sa-shadow-tint-4);
|
|
289
293
|
}
|
|
290
294
|
.sa-setup-head {
|
|
291
295
|
display: flex;
|
|
@@ -296,7 +300,7 @@ async function submitConfirm(): Promise<void> {
|
|
|
296
300
|
.sa-setup-locale {
|
|
297
301
|
margin-left: auto;
|
|
298
302
|
align-self: flex-start;
|
|
299
|
-
color: var(--sa-
|
|
303
|
+
color: var(--sa-color-fg-secondary);
|
|
300
304
|
}
|
|
301
305
|
.sa-setup-badge {
|
|
302
306
|
width: 44px;
|
|
@@ -305,31 +309,38 @@ async function submitConfirm(): Promise<void> {
|
|
|
305
309
|
display: flex;
|
|
306
310
|
align-items: center;
|
|
307
311
|
justify-content: center;
|
|
308
|
-
background: linear-gradient(
|
|
309
|
-
|
|
312
|
+
background: linear-gradient(
|
|
313
|
+
135deg,
|
|
314
|
+
var(--sa-color-inverse-surface-soft),
|
|
315
|
+
var(--sa-color-inverse-surface)
|
|
316
|
+
);
|
|
317
|
+
/* The gradient never moves, so the text on it must not either.
|
|
318
|
+
* `--sa-color-fg-on-accent` is white today but belongs to the accent, and
|
|
319
|
+
* the design guide tells a light brand to override it to something dark. */
|
|
320
|
+
color: var(--sa-color-inverse-fg);
|
|
310
321
|
font-weight: 800;
|
|
311
|
-
font-size:
|
|
322
|
+
font-size: var(--sa-text-xl);
|
|
312
323
|
text-transform: uppercase;
|
|
313
324
|
}
|
|
314
325
|
.sa-setup-title {
|
|
315
326
|
margin: 0;
|
|
316
327
|
font-weight: 800;
|
|
317
|
-
font-size:
|
|
318
|
-
color: var(--sa-heading);
|
|
328
|
+
font-size: var(--sa-text-xl);
|
|
329
|
+
color: var(--sa-color-fg-heading);
|
|
319
330
|
line-height: 1.1;
|
|
320
331
|
}
|
|
321
332
|
.sa-setup-sub {
|
|
322
|
-
font-size:
|
|
323
|
-
color: var(--sa-
|
|
333
|
+
font-size: var(--sa-text-sm);
|
|
334
|
+
color: var(--sa-color-fg-secondary);
|
|
324
335
|
}
|
|
325
336
|
.sa-setup-hint {
|
|
326
|
-
font-size:
|
|
327
|
-
color: var(--sa-
|
|
337
|
+
font-size: var(--sa-text-md);
|
|
338
|
+
color: var(--sa-color-fg-secondary);
|
|
328
339
|
line-height: 1.5;
|
|
329
340
|
margin: 0 0 16px;
|
|
330
341
|
}
|
|
331
342
|
.sa-setup-hint code {
|
|
332
|
-
background: var(--sa-border);
|
|
343
|
+
background: var(--sa-color-border);
|
|
333
344
|
padding: 1px 5px;
|
|
334
345
|
border-radius: 4px;
|
|
335
346
|
}
|
|
@@ -341,10 +352,10 @@ async function submitConfirm(): Promise<void> {
|
|
|
341
352
|
width: 100%;
|
|
342
353
|
}
|
|
343
354
|
.sa-setup-error {
|
|
344
|
-
background:
|
|
345
|
-
border: 1px solid
|
|
346
|
-
color:
|
|
347
|
-
font-size:
|
|
355
|
+
background: var(--sa-color-negative-surface);
|
|
356
|
+
border: 1px solid var(--sa-color-negative-border);
|
|
357
|
+
color: var(--sa-color-negative-fg);
|
|
358
|
+
font-size: var(--sa-text-md);
|
|
348
359
|
margin-bottom: 16px;
|
|
349
360
|
padding: 8px 12px;
|
|
350
361
|
border-radius: 8px;
|
|
@@ -357,46 +368,46 @@ async function submitConfirm(): Promise<void> {
|
|
|
357
368
|
margin-bottom: 12px;
|
|
358
369
|
}
|
|
359
370
|
.sa-setup-qr img {
|
|
360
|
-
border: 1px solid var(--sa-border);
|
|
371
|
+
border: 1px solid var(--sa-color-border);
|
|
361
372
|
border-radius: 8px;
|
|
362
373
|
padding: 8px;
|
|
363
|
-
background:
|
|
374
|
+
background: var(--sa-color-bg-surface);
|
|
364
375
|
}
|
|
365
376
|
.sa-setup-qr__hint {
|
|
366
|
-
font-size:
|
|
367
|
-
color: var(--sa-muted);
|
|
377
|
+
font-size: var(--sa-text-sm);
|
|
378
|
+
color: var(--sa-color-fg-muted);
|
|
368
379
|
}
|
|
369
380
|
.sa-setup-secret {
|
|
370
|
-
background: var(--sa-border-soft);
|
|
381
|
+
background: var(--sa-color-border-soft);
|
|
371
382
|
border-radius: 8px;
|
|
372
383
|
padding: 10px 12px;
|
|
373
384
|
margin-bottom: 10px;
|
|
374
385
|
}
|
|
375
386
|
.sa-setup-secret__label {
|
|
376
|
-
font-size:
|
|
387
|
+
font-size: var(--sa-text-xs);
|
|
377
388
|
text-transform: uppercase;
|
|
378
389
|
letter-spacing: 0.06em;
|
|
379
|
-
color: var(--sa-muted);
|
|
390
|
+
color: var(--sa-color-fg-muted);
|
|
380
391
|
margin-bottom: 4px;
|
|
381
392
|
}
|
|
382
393
|
.sa-setup-secret__value {
|
|
383
|
-
font-size:
|
|
394
|
+
font-size: var(--sa-text-lg);
|
|
384
395
|
font-weight: 700;
|
|
385
|
-
color: var(--sa-heading);
|
|
396
|
+
color: var(--sa-color-fg-heading);
|
|
386
397
|
word-break: break-all;
|
|
387
398
|
letter-spacing: 0.04em;
|
|
388
399
|
}
|
|
389
400
|
.sa-setup-uri {
|
|
390
401
|
margin: 4px 0 4px;
|
|
391
|
-
font-size:
|
|
392
|
-
color: var(--sa-
|
|
402
|
+
font-size: var(--sa-text-sm);
|
|
403
|
+
color: var(--sa-color-fg-secondary);
|
|
393
404
|
}
|
|
394
405
|
.sa-setup-uri__value {
|
|
395
406
|
display: block;
|
|
396
407
|
margin-top: 6px;
|
|
397
408
|
word-break: break-all;
|
|
398
|
-
color:
|
|
399
|
-
background: var(--sa-bg-
|
|
409
|
+
color: var(--sa-color-fg-body);
|
|
410
|
+
background: var(--sa-color-bg-sunken);
|
|
400
411
|
padding: 6px 8px;
|
|
401
412
|
border-radius: 6px;
|
|
402
413
|
}
|
|
@@ -405,8 +416,8 @@ async function submitConfirm(): Promise<void> {
|
|
|
405
416
|
width: 100%;
|
|
406
417
|
background: none;
|
|
407
418
|
border: none;
|
|
408
|
-
color: var(--sa-muted);
|
|
409
|
-
font-size:
|
|
419
|
+
color: var(--sa-color-fg-muted);
|
|
420
|
+
font-size: var(--sa-text-sm);
|
|
410
421
|
cursor: pointer;
|
|
411
422
|
text-decoration: underline;
|
|
412
423
|
}
|
|
@@ -327,13 +327,13 @@ const defaultUserColumns = computed<QTableColumn[]>(() => [
|
|
|
327
327
|
display: flex;
|
|
328
328
|
justify-content: space-between;
|
|
329
329
|
align-items: center;
|
|
330
|
-
border-bottom: 1px solid var(--sa-border-soft);
|
|
330
|
+
border-bottom: 1px solid var(--sa-color-border-soft);
|
|
331
331
|
padding-bottom: 14px;
|
|
332
332
|
margin-bottom: 16px;
|
|
333
333
|
}
|
|
334
334
|
.sa-tenant-detail__card-sub {
|
|
335
|
-
color: var(--sa-muted);
|
|
336
|
-
font-size:
|
|
335
|
+
color: var(--sa-color-fg-muted);
|
|
336
|
+
font-size: var(--sa-text-md);
|
|
337
337
|
margin: 4px 0 0;
|
|
338
338
|
}
|
|
339
339
|
.sa-tenant-detail__card-actions {
|
|
@@ -343,13 +343,13 @@ const defaultUserColumns = computed<QTableColumn[]>(() => [
|
|
|
343
343
|
align-items: center;
|
|
344
344
|
}
|
|
345
345
|
.sa-tenant-detail__empty {
|
|
346
|
-
color: var(--sa-muted);
|
|
347
|
-
font-size:
|
|
346
|
+
color: var(--sa-color-fg-muted);
|
|
347
|
+
font-size: var(--sa-text-md);
|
|
348
348
|
}
|
|
349
349
|
code {
|
|
350
|
-
background:
|
|
350
|
+
background: var(--sa-color-bg-sunken);
|
|
351
351
|
padding: 1px 6px;
|
|
352
352
|
border-radius: 4px;
|
|
353
|
-
font-size:
|
|
353
|
+
font-size: var(--sa-text-sm);
|
|
354
354
|
}
|
|
355
355
|
</style>
|
|
@@ -119,8 +119,8 @@
|
|
|
119
119
|
v-for="action in visibleActions(row)"
|
|
120
120
|
:key="action.id"
|
|
121
121
|
:href="action.to ? action.to(row) : undefined"
|
|
122
|
-
class="sa-
|
|
123
|
-
:class="action.tone ? `sa-
|
|
122
|
+
class="sa-icon-btn"
|
|
123
|
+
:class="action.tone ? `sa-icon-btn--${action.tone}` : ''"
|
|
124
124
|
:title="action.label"
|
|
125
125
|
@click="action.handler ? action.handler(row) : undefined"
|
|
126
126
|
>
|
|
@@ -176,7 +176,8 @@ import {
|
|
|
176
176
|
import MfaPromptDialog from '../components/MfaPromptDialog.vue';
|
|
177
177
|
import TenantActionConfirmDialog from '../components/TenantActionConfirmDialog.vue';
|
|
178
178
|
import StatusPill, { type PillTone } from './tenants/StatusPill.vue';
|
|
179
|
-
import {
|
|
179
|
+
import { identityChipStyle } from '../client/identity-accents.js';
|
|
180
|
+
import { formatDate, planAccent, tenantInitials } from './tenants/format.js';
|
|
180
181
|
|
|
181
182
|
// Platform standard page: tenant list.
|
|
182
183
|
//
|
|
@@ -323,7 +324,7 @@ const props = withDefaults(
|
|
|
323
324
|
pageSize: 25,
|
|
324
325
|
showPlanColumn: true,
|
|
325
326
|
planLabelField: 'plan',
|
|
326
|
-
planAccents: () =>
|
|
327
|
+
planAccents: () => ({}),
|
|
327
328
|
usageFields: () => [],
|
|
328
329
|
manifest: null,
|
|
329
330
|
},
|
|
@@ -484,8 +485,8 @@ const combinedActions = computed<TenantRowAction[]>(() => {
|
|
|
484
485
|
const hasActions = computed(() => combinedActions.value.length > 0);
|
|
485
486
|
|
|
486
487
|
function avatarStyle(row: TenantRow): Record<string, string> {
|
|
487
|
-
const
|
|
488
|
-
return { background
|
|
488
|
+
const { background, color } = identityChipStyle(planAccentFor(row));
|
|
489
|
+
return { background, color };
|
|
489
490
|
}
|
|
490
491
|
|
|
491
492
|
function planAccentFor(row: TenantRow): string {
|
|
@@ -543,7 +544,7 @@ function visibleActions(row: TenantRow): TenantRowAction[] {
|
|
|
543
544
|
AdminTable, behind a prop. */
|
|
544
545
|
.sa-tenants__mono {
|
|
545
546
|
font-family: var(--sa-font-mono, ui-monospace, monospace);
|
|
546
|
-
font-size:
|
|
547
|
+
font-size: var(--sa-text-sm);
|
|
547
548
|
}
|
|
548
549
|
|
|
549
550
|
.sa-tenants__tenant {
|
|
@@ -556,7 +557,7 @@ function visibleActions(row: TenantRow): TenantRowAction[] {
|
|
|
556
557
|
height: 32px;
|
|
557
558
|
border-radius: 8px;
|
|
558
559
|
font-weight: 800;
|
|
559
|
-
font-size:
|
|
560
|
+
font-size: var(--sa-text-sm);
|
|
560
561
|
font-family: var(--sa-font-head, system-ui, sans-serif);
|
|
561
562
|
display: flex;
|
|
562
563
|
align-items: center;
|
|
@@ -564,13 +565,13 @@ function visibleActions(row: TenantRow): TenantRowAction[] {
|
|
|
564
565
|
flex-shrink: 0;
|
|
565
566
|
}
|
|
566
567
|
.sa-tenants__name {
|
|
567
|
-
font-size:
|
|
568
|
+
font-size: var(--sa-text-md);
|
|
568
569
|
font-weight: 600;
|
|
569
|
-
color: var(--sa-
|
|
570
|
+
color: var(--sa-color-fg-heading);
|
|
570
571
|
}
|
|
571
572
|
.sa-tenants__slug {
|
|
572
|
-
font-size:
|
|
573
|
-
color: var(--sa-
|
|
573
|
+
font-size: var(--sa-text-xs);
|
|
574
|
+
color: var(--sa-color-fg-muted);
|
|
574
575
|
font-family: var(--sa-font-mono, ui-monospace, monospace);
|
|
575
576
|
}
|
|
576
577
|
|
|
@@ -595,46 +596,11 @@ function visibleActions(row: TenantRow): TenantRowAction[] {
|
|
|
595
596
|
display: inline-flex;
|
|
596
597
|
align-items: center;
|
|
597
598
|
gap: 4px;
|
|
598
|
-
font-size:
|
|
599
|
-
color: var(--sa-
|
|
599
|
+
font-size: var(--sa-text-sm);
|
|
600
|
+
color: var(--sa-color-fg-secondary);
|
|
600
601
|
margin-left: 8px;
|
|
601
602
|
}
|
|
602
603
|
.sa-tenants__usage :deep(.q-icon) {
|
|
603
|
-
color: var(--sa-
|
|
604
|
-
}
|
|
605
|
-
|
|
606
|
-
.sa-tenants__icon-btn {
|
|
607
|
-
background: transparent;
|
|
608
|
-
border: none;
|
|
609
|
-
cursor: pointer;
|
|
610
|
-
width: 28px;
|
|
611
|
-
height: 28px;
|
|
612
|
-
border-radius: 6px;
|
|
613
|
-
display: inline-flex;
|
|
614
|
-
align-items: center;
|
|
615
|
-
justify-content: center;
|
|
616
|
-
text-decoration: none;
|
|
617
|
-
color: var(--sa-muted, var(--sa-muted));
|
|
618
|
-
}
|
|
619
|
-
.sa-tenants__icon-btn:hover {
|
|
620
|
-
background: var(--sa-border-soft);
|
|
621
|
-
}
|
|
622
|
-
.sa-tenants__icon-btn :deep(.q-icon) {
|
|
623
|
-
color: inherit;
|
|
624
|
-
}
|
|
625
|
-
.sa-tenants__icon-btn--negative {
|
|
626
|
-
color: var(--sa-negative, #dc2626);
|
|
627
|
-
}
|
|
628
|
-
.sa-tenants__icon-btn--positive {
|
|
629
|
-
color: var(--sa-positive, #047857);
|
|
630
|
-
}
|
|
631
|
-
.sa-tenants__icon-btn--primary {
|
|
632
|
-
color: var(--sa-primary, #3f6bff);
|
|
633
|
-
}
|
|
634
|
-
.sa-tenants__icon-btn--warning {
|
|
635
|
-
color: var(--sa-warning, #d97706);
|
|
636
|
-
}
|
|
637
|
-
.sa-tenants__icon-btn--accent {
|
|
638
|
-
color: var(--sa-accent, #7c3aed);
|
|
604
|
+
color: var(--sa-color-fg-muted);
|
|
639
605
|
}
|
|
640
606
|
</style>
|
|
@@ -100,31 +100,31 @@ function translationCount(bundle: BundleRow): string {
|
|
|
100
100
|
DiscoveryPage.vue would otherwise override .sa-bundle-chip--live (same specificity,
|
|
101
101
|
later source order) and render the "Live" tag grey instead of green. */
|
|
102
102
|
.sa-bundle-chip {
|
|
103
|
-
font-size:
|
|
103
|
+
font-size: var(--sa-text-2xs);
|
|
104
104
|
font-weight: 600;
|
|
105
105
|
padding: 2px 7px;
|
|
106
106
|
border-radius: 6px;
|
|
107
|
-
background: var(--sa-border-soft);
|
|
108
|
-
color: var(--sa-
|
|
107
|
+
background: var(--sa-color-border-soft);
|
|
108
|
+
color: var(--sa-color-fg-secondary);
|
|
109
109
|
}
|
|
110
110
|
.sa-bundle-chip--info {
|
|
111
|
-
background: var(--sa-
|
|
112
|
-
color: var(--sa-
|
|
111
|
+
background: var(--sa-color-accent-surface-strong);
|
|
112
|
+
color: var(--sa-color-accent-strong);
|
|
113
113
|
}
|
|
114
114
|
.sa-bundle-chip--live {
|
|
115
|
-
background:
|
|
116
|
-
color:
|
|
115
|
+
background: var(--sa-color-positive-surface-strong);
|
|
116
|
+
color: var(--sa-color-positive-fg);
|
|
117
117
|
}
|
|
118
118
|
.sa-bundle-chip--draft {
|
|
119
|
-
background:
|
|
120
|
-
color:
|
|
119
|
+
background: var(--sa-color-warning-surface-strong);
|
|
120
|
+
color: var(--sa-color-warning-fg);
|
|
121
121
|
}
|
|
122
122
|
.sa-bundle-chip--supersed {
|
|
123
|
-
background: var(--sa-border);
|
|
124
|
-
color: var(--sa-muted);
|
|
123
|
+
background: var(--sa-color-border);
|
|
124
|
+
color: var(--sa-color-fg-muted);
|
|
125
125
|
}
|
|
126
126
|
.sa-bundle-chip--scheduled {
|
|
127
|
-
background:
|
|
128
|
-
color:
|
|
127
|
+
background: var(--sa-color-warning-surface-strong);
|
|
128
|
+
color: var(--sa-color-warning-fg);
|
|
129
129
|
}
|
|
130
130
|
</style>
|