@saasicat/ui-vue 0.19.0 → 0.22.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/{catalog-JXdKdIqG.d.cts → catalog-DJcfm5N2.d.cts} +21 -7
- package/dist/{catalog-JXdKdIqG.d.ts → catalog-DJcfm5N2.d.ts} +21 -7
- package/dist/{chunk-DPTIOQXX.js → chunk-F7NRM6KI.js} +56 -28
- package/dist/{chunk-RVG6LQHL.js → chunk-LY52T4N4.js} +21 -2
- package/dist/{chunk-ORX3ZG47.js → chunk-XMMFN2WJ.js} +74 -3
- package/dist/client/index.cjs +134 -29
- package/dist/client/index.d.cts +53 -3
- package/dist/client/index.d.ts +53 -3
- package/dist/client/index.js +14 -2
- package/dist/index.cjs +321 -162
- package/dist/index.d.cts +30 -8
- package/dist/index.d.ts +30 -8
- package/dist/index.js +176 -133
- package/dist/quasar/index.cjs +78 -29
- package/dist/quasar/index.d.cts +2 -2
- package/dist/quasar/index.d.ts +2 -2
- package/dist/quasar/index.js +6 -2
- package/dist/testing-e2e/admin-pages-suite.d.cts +37 -0
- package/dist/testing-e2e/admin-pages-suite.d.ts +37 -0
- package/dist/{use-super-admin-i18n-BlqcD0N7.d.ts → use-super-admin-i18n-CHNdsSlm.d.ts} +34 -7
- package/dist/{use-super-admin-i18n-1nCOkvgi.d.cts → use-super-admin-i18n-CgTuNi8h.d.cts} +34 -7
- package/package.json +18 -8
- package/src/client/i18n/messages/bundles.ts +0 -2
- package/src/client/i18n/messages/common.ts +24 -0
- package/src/client/i18n/messages/discovery.ts +2 -2
- package/src/client/i18n/messages/marketing.ts +2 -4
- package/src/client/i18n/messages/plan-detail.ts +0 -4
- package/src/client/i18n/messages/plans.ts +20 -8
- package/src/client/i18n/messages/tenants.ts +0 -2
- package/src/client/index.ts +1 -0
- package/src/client/manifest-loader.ts +1 -1
- package/src/client/resolve-plans.ts +144 -0
- package/src/components/BundleVersionPublishDialog.vue +6 -6
- package/src/components/KvBlock.vue +4 -4
- package/src/components/MarketingPromotionsTab.vue +34 -48
- package/src/components/MfaPromptDialog.vue +8 -2
- package/src/components/TenantActionConfirmDialog.vue +4 -4
- package/src/components/VersionDiffPreview.vue +7 -7
- package/src/components/admin-page/AdminBody.vue +40 -0
- package/src/components/admin-page/AdminFilters.vue +12 -0
- package/src/components/admin-page/AdminHero.vue +49 -0
- package/src/components/admin-page/AdminKpi.vue +84 -0
- package/src/components/admin-page/AdminPage.vue +16 -0
- package/src/components/admin-page/AdminPaginator.vue +195 -0
- package/src/components/admin-page/AdminRefreshBtn.vue +39 -0
- package/src/components/admin-page/AdminSection.vue +53 -0
- package/src/components/admin-page/AdminStatistics.vue +40 -0
- package/src/components/admin-page/AdminTable.vue +175 -0
- package/src/components/bundle-editor/BundleCreatePanel.vue +23 -23
- package/src/components/bundle-editor/BundleFeaturesEditor.vue +7 -7
- package/src/components/bundle-editor/BundlePlanCompatPicker.vue +9 -9
- package/src/components/bundle-editor/BundleQuotasEditor.vue +11 -11
- package/src/components/bundle-editor/BundleStatusBanner.vue +6 -6
- package/src/components/bundle-editor/BundleVersionInlineEditor.vue +18 -18
- package/src/components/bundle-editor/BundleVersionStrip.vue +12 -12
- package/src/components/dialogs/PilotCreateDialog.vue +12 -12
- package/src/components/dialogs/PilotEditDialog.vue +7 -7
- package/src/components/dialogs/PromoCodeCreateDialog.vue +8 -8
- package/src/components/dialogs/PromoCodeDialogFields.vue +33 -19
- package/src/components/dialogs/PromoCodeEditDialog.vue +10 -10
- package/src/components/plan/PlanGrid.vue +1 -1
- package/src/components/plan-create-dialog/PlanCreateDialog.vue +34 -46
- package/src/components/plan-detail/PlanAuditLog.vue +7 -8
- package/src/components/plan-detail/PlanDetail.vue +95 -292
- package/src/components/plan-detail/PlanDetailKpis.vue +22 -27
- package/src/components/plan-detail/PlanTitleEdit.vue +133 -0
- package/src/components/plan-detail/PlanVersionDiffPanel.vue +5 -8
- package/src/components/plan-detail/PlanVersionsPanel.vue +9 -11
- package/src/components/plan-list/PlanList.vue +206 -457
- package/src/components/plan-matrix/PlanMatrix.vue +66 -183
- package/src/components/plan-review/PlanReview.vue +191 -275
- package/src/components/plan-version-editor/PlanCatalogPreview.vue +7 -5
- package/src/components/plan-version-editor/PlanVersionEditor.vue +200 -295
- package/src/components/plan-version-editor/PlanVersionEditorHeader.vue +23 -55
- package/src/index.ts +1 -0
- package/src/pages-standard/AdminLayout.vue +38 -12
- package/src/pages-standard/AdminManifestErrorPage.vue +79 -9
- package/src/pages-standard/AuditPage.vue +65 -109
- package/src/pages-standard/BundlesPage.vue +146 -179
- package/src/pages-standard/DashboardPage.vue +59 -154
- package/src/pages-standard/DiscoveryPage.vue +172 -227
- package/src/pages-standard/EmailHistoryPage.vue +118 -159
- package/src/pages-standard/MarketingCatalogPage.vue +399 -440
- package/src/pages-standard/PilotsPage.vue +69 -117
- package/src/pages-standard/PlansPage.vue +240 -112
- package/src/pages-standard/PlatformEmailPage.vue +56 -91
- package/src/pages-standard/PromoCodeDetailPage.vue +49 -74
- package/src/pages-standard/PromoCodesPage.vue +95 -128
- package/src/pages-standard/SubscriptionsPage.vue +19 -52
- package/src/pages-standard/SuperAdminLoginPage.vue +12 -12
- package/src/pages-standard/SuperAdminSetupWizard.vue +22 -18
- package/src/pages-standard/TenantDetailPage.vue +100 -191
- package/src/pages-standard/TenantsPage.vue +190 -295
- package/src/pages-standard/UsersPage.vue +89 -157
- package/src/pages-standard/bundles-page/BundleAccordionList.vue +20 -17
- package/src/pages-standard/bundles-page/BundlesKpis.vue +13 -22
- package/src/pages-standard/bundles-page/BundlesToolbar.vue +63 -0
- package/src/pages-standard/discovery-page/CatalogEntryTransPanel.vue +10 -10
- package/src/pages-standard/discovery-page/DiscoveryCapList.vue +5 -5
- package/src/pages-standard/discovery-page/DiscoveryFeatureCard.vue +16 -16
- package/src/pages-standard/discovery-page/DiscoveryKpis.vue +31 -27
- package/src/pages-standard/discovery-page/DiscoveryQuotaCard.vue +7 -7
- package/src/pages-standard/marketing-catalog/MarketingCatalogAdmin.vue +111 -73
- package/src/pages-standard/marketing-catalog/MarketingCatalogHeader.vue +43 -62
- package/src/pages-standard/marketing-catalog/MarketingCatalogPreview.vue +53 -35
- package/src/pages-standard/marketing-catalog/MarketingCatalogToolbar.vue +7 -7
- package/src/pages-standard/plan-versions/PlanDiffCard.vue +6 -6
- package/src/pages-standard/plan-versions/PlanVersionsDiff.vue +6 -6
- package/src/pages-standard/plan-versions/PlanVersionsTimeline.vue +16 -16
- package/src/pages-standard/plans-page/PlanBundleOverview.vue +14 -29
- package/src/pages-standard/plans-page/PlanPublishDialog.vue +1 -1
- package/src/pages-standard/plans-page/PlansPageToast.vue +6 -6
- package/src/pages-standard/sa-theme.css +552 -86
- package/src/pages-standard/tenant-detail/TenantMasterData.vue +28 -0
- package/src/pages-standard/tenant-detail/TenantUsage.vue +31 -0
- package/src/pages-standard/tenant-detail/TenantUsers.vue +15 -0
- package/src/pages-standard/tenant-detail/types.ts +38 -0
- package/src/pages-standard/tenants/StatusPill.vue +2 -2
- package/src/pages-tenant/MySubscriptionBundlesPage.vue +25 -25
- package/src/pages-tenant/OnboardingConfigurator.vue +1 -5
- package/src/pages-tenant/PackageSnapshotPanel.vue +1 -1
- package/src/pages-tenant/TenantPlanSection.vue +12 -20
- package/src/quasar/create-super-admin-app.ts +4 -0
- package/src/vue/entitlement-provider.ts +0 -1
- package/src/vue/feature-router-guard.ts +0 -1
- package/src/vue/super-admin-context.ts +106 -1
- package/src/vue/use-api-list.ts +2 -1
- package/src/vue/use-mfa-prompt.ts +72 -0
- package/src/vue/use-pagination.ts +63 -0
- package/src/vue/use-plans.ts +1 -2
- package/src/vue/use-sign-out.ts +90 -0
- package/src/vue/use-tenant-billing.ts +1 -1
- package/src/vue/use-tenant-manifest.ts +0 -1
- package/src/components/KpiCard.vue +0 -53
- package/src/components/plan-cockpit/PlanCockpit.vue +0 -1012
- package/src/components/plan-cockpit/PlanCockpitAuditLog.vue +0 -72
- package/src/components/plan-cockpit/PlanCockpitDiffPanel.vue +0 -100
- package/src/components/plan-cockpit/PlanCockpitHeader.vue +0 -101
- package/src/components/plan-cockpit/PlanCockpitImpactPanel.vue +0 -112
- package/src/components/plan-cockpit/PlanCockpitKpis.vue +0 -68
- package/src/components/plan-cockpit/PlanCockpitVersions.vue +0 -251
- package/src/components/plan-cockpit/types.ts +0 -72
- package/src/components/plan-detail/PlanDetailHeader.vue +0 -194
- package/src/pages-standard/bundles-page/BundlesHeader.vue +0 -68
- package/src/pages-standard/discovery-page/DiscoveryHeader.vue +0 -34
|
@@ -1,114 +1,81 @@
|
|
|
1
1
|
<template>
|
|
2
|
-
<
|
|
3
|
-
<
|
|
4
|
-
<
|
|
5
|
-
<
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
2
|
+
<AdminPage class="sa-tenant-detail">
|
|
3
|
+
<AdminHero :title="data?.name ?? labels.title">
|
|
4
|
+
<template v-if="data" #subtitle>
|
|
5
|
+
{{ labels.slug }}: <code>{{ data.slug }}</code>
|
|
6
|
+
</template>
|
|
7
|
+
<!--
|
|
8
|
+
Back first, then the tenant-level actions, then whatever the app
|
|
9
|
+
adds — the same order every other hero uses. Both are plain
|
|
10
|
+
`.sa-btn` buttons: a hero is where a page's own actions live, and
|
|
11
|
+
a detail page's "suspend" is exactly that. It used to sit on the
|
|
12
|
+
master-data section instead, which read as an action on that one
|
|
13
|
+
card rather than on the tenant.
|
|
14
|
+
-->
|
|
15
|
+
<template #actions>
|
|
16
|
+
<button class="sa-btn" type="button" @click="goBack">
|
|
17
|
+
<q-icon name="arrow_back" size="16px" />
|
|
18
|
+
<span>{{ labels.back }}</span>
|
|
19
|
+
</button>
|
|
20
|
+
<button
|
|
21
|
+
v-for="action in manifestActions"
|
|
22
|
+
:key="action.def.id"
|
|
23
|
+
:class="['sa-btn', toneClass(action.def.actionKey)]"
|
|
24
|
+
type="button"
|
|
25
|
+
@click="action.onClick"
|
|
26
|
+
>
|
|
27
|
+
<q-icon :name="iconForActionKey(action.def.actionKey)" size="16px" />
|
|
28
|
+
<span>{{ action.def.label }}</span>
|
|
29
|
+
</button>
|
|
30
|
+
<slot name="header-actions" :data="data" :reload="load" />
|
|
31
|
+
</template>
|
|
32
|
+
</AdminHero>
|
|
33
|
+
|
|
34
|
+
<AdminBody :loading="loading" :empty="!data">
|
|
35
|
+
<template v-if="data">
|
|
27
36
|
<!-- Master data -->
|
|
28
|
-
<
|
|
29
|
-
<
|
|
30
|
-
<
|
|
31
|
-
|
|
32
|
-
<p v-if="stammdatenSub" class="sa-tenant-detail__card-sub">
|
|
33
|
-
{{ stammdatenSub }}
|
|
34
|
-
</p>
|
|
35
|
-
</div>
|
|
36
|
-
<div class="sa-tenant-detail__card-actions">
|
|
37
|
-
<!-- Manifest-driven default actions (Suspend/Reactivate) -->
|
|
38
|
-
<q-btn
|
|
39
|
-
v-for="action in manifestActions"
|
|
40
|
-
:key="action.def.id"
|
|
41
|
-
outline
|
|
42
|
-
:color="toneColor(action.def.actionKey)"
|
|
43
|
-
:icon="iconForActionKey(action.def.actionKey)"
|
|
44
|
-
:label="action.def.label"
|
|
45
|
-
@click="action.onClick"
|
|
46
|
-
/>
|
|
47
|
-
<slot name="card-actions" :data="data" :reload="load" />
|
|
48
|
-
</div>
|
|
49
|
-
</header>
|
|
37
|
+
<AdminSection :title="labels.masterData" :subtitle="stammdatenSub" class="q-mb-md">
|
|
38
|
+
<template #actions>
|
|
39
|
+
<slot name="card-actions" :data="data" :reload="load" />
|
|
40
|
+
</template>
|
|
50
41
|
<slot name="stammdaten" :data="data">
|
|
51
|
-
<
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
:label="labels.pilot"
|
|
59
|
-
:value="data.subscription?.isPilot ? common.yes : common.no"
|
|
60
|
-
/>
|
|
61
|
-
<KvBlock
|
|
62
|
-
:label="labels.trialEnd"
|
|
63
|
-
:value="formatDate(data.subscription?.trialEndsAt)"
|
|
64
|
-
/>
|
|
65
|
-
<KvBlock
|
|
66
|
-
:label="labels.pilotEnd"
|
|
67
|
-
:value="formatDate(data.subscription?.pilotEndsAt)"
|
|
68
|
-
/>
|
|
69
|
-
<KvBlock v-if="data.vatId" :label="labels.vatId" :value="data.vatId" />
|
|
42
|
+
<TenantMasterData
|
|
43
|
+
:data="data"
|
|
44
|
+
:labels="labels"
|
|
45
|
+
:format-date="formatDateResolved"
|
|
46
|
+
:yes="common.yes"
|
|
47
|
+
:no="common.no"
|
|
48
|
+
>
|
|
70
49
|
<slot name="extra-stammdaten" :data="data" />
|
|
71
|
-
</
|
|
50
|
+
</TenantMasterData>
|
|
72
51
|
</slot>
|
|
73
|
-
</
|
|
52
|
+
</AdminSection>
|
|
74
53
|
|
|
75
54
|
<!-- Usage -->
|
|
76
|
-
<
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
:value="resolveVerbrauch(field)"
|
|
84
|
-
/>
|
|
85
|
-
</div>
|
|
86
|
-
</div>
|
|
55
|
+
<AdminSection
|
|
56
|
+
v-if="verbrauchFields.length > 0"
|
|
57
|
+
:title="labels.usage"
|
|
58
|
+
class="q-mb-md"
|
|
59
|
+
>
|
|
60
|
+
<TenantUsage :data="data" :fields="verbrauchFields" />
|
|
61
|
+
</AdminSection>
|
|
87
62
|
|
|
88
63
|
<!-- Users -->
|
|
89
|
-
<
|
|
90
|
-
<
|
|
91
|
-
|
|
92
|
-
flat
|
|
93
|
-
:rows="data.users"
|
|
94
|
-
:columns="userColumns ?? defaultUserColumns"
|
|
95
|
-
row-key="id"
|
|
96
|
-
:pagination="{ rowsPerPage: 0 }"
|
|
97
|
-
hide-pagination
|
|
98
|
-
/>
|
|
99
|
-
</div>
|
|
64
|
+
<AdminSection v-if="showUsers && data.users" :title="labels.users" class="q-mb-md">
|
|
65
|
+
<TenantUsers :users="data.users" :columns="userColumns ?? defaultUserColumns" />
|
|
66
|
+
</AdminSection>
|
|
100
67
|
|
|
101
68
|
<slot name="extra-cards" :data="data" :reload="load" />
|
|
102
69
|
</template>
|
|
103
|
-
</
|
|
70
|
+
</AdminBody>
|
|
104
71
|
|
|
105
72
|
<!-- Manifest-driven action flow dialogs -->
|
|
106
73
|
<MfaPromptDialog
|
|
107
|
-
|
|
108
|
-
:description="
|
|
109
|
-
:error="
|
|
110
|
-
@update:model-value="
|
|
111
|
-
@confirm="
|
|
74
|
+
:model-value="mfa.show.value"
|
|
75
|
+
:description="mfa.description.value"
|
|
76
|
+
:error="mfa.error.value"
|
|
77
|
+
@update:model-value="mfa.onVisibility"
|
|
78
|
+
@confirm="mfa.onConfirm"
|
|
112
79
|
/>
|
|
113
80
|
<TenantActionConfirmDialog
|
|
114
81
|
v-model="confirmState.show"
|
|
@@ -118,47 +85,31 @@
|
|
|
118
85
|
@submit="onConfirmSubmit"
|
|
119
86
|
@cancel="onConfirmCancel"
|
|
120
87
|
/>
|
|
121
|
-
</
|
|
88
|
+
</AdminPage>
|
|
122
89
|
</template>
|
|
123
90
|
|
|
124
91
|
<script setup lang="ts">
|
|
125
92
|
import { computed, onMounted, ref, toRef } from 'vue';
|
|
126
|
-
import
|
|
93
|
+
import AdminBody from '../components/admin-page/AdminBody.vue';
|
|
94
|
+
import { useMfaPrompt } from '../vue/use-mfa-prompt.js';
|
|
95
|
+
import AdminHero from '../components/admin-page/AdminHero.vue';
|
|
96
|
+
import AdminSection from '../components/admin-page/AdminSection.vue';
|
|
97
|
+
import AdminPage from '../components/admin-page/AdminPage.vue';
|
|
98
|
+
import { useRouter, type RouteLocationRaw } from 'vue-router';
|
|
99
|
+
import type { TenantDetailData, VerbrauchField } from './tenant-detail/types.js';
|
|
127
100
|
import type { QTableColumn } from 'quasar';
|
|
128
101
|
import { useSuperAdminNotify } from '../quasar/notify.js';
|
|
129
102
|
import type { AdminManifest, TenantActionDef, TenantDto } from '@saasicat/types';
|
|
130
103
|
import { formatMessage } from '../client/i18n/format.js';
|
|
131
|
-
import
|
|
104
|
+
import TenantMasterData from './tenant-detail/TenantMasterData.vue';
|
|
105
|
+
import TenantUsage from './tenant-detail/TenantUsage.vue';
|
|
106
|
+
import TenantUsers from './tenant-detail/TenantUsers.vue';
|
|
132
107
|
import MfaPromptDialog from '../components/MfaPromptDialog.vue';
|
|
133
108
|
import TenantActionConfirmDialog from '../components/TenantActionConfirmDialog.vue';
|
|
134
109
|
import { useSaMessages } from '../vue/use-super-admin-i18n.js';
|
|
135
110
|
import { useTenantActionFlow } from '../vue/use-tenant-action-flow.js';
|
|
136
111
|
|
|
137
|
-
export
|
|
138
|
-
id: string;
|
|
139
|
-
slug: string;
|
|
140
|
-
name: string;
|
|
141
|
-
isActive: boolean;
|
|
142
|
-
vatId?: string | null;
|
|
143
|
-
subscription?: {
|
|
144
|
-
plan?: string | null;
|
|
145
|
-
status?: string | null;
|
|
146
|
-
isPilot?: boolean | null;
|
|
147
|
-
trialEndsAt?: string | null;
|
|
148
|
-
pilotEndsAt?: string | null;
|
|
149
|
-
} | null;
|
|
150
|
-
users?: Array<Record<string, unknown> & { id: string }>;
|
|
151
|
-
/** Freely selectable usage numbers — the page renders them via `verbrauchFields`. */
|
|
152
|
-
counts?: Record<string, number | string>;
|
|
153
|
-
}
|
|
154
|
-
|
|
155
|
-
export interface VerbrauchField {
|
|
156
|
-
label: string;
|
|
157
|
-
/** Lookup key in `data.counts`. */
|
|
158
|
-
key?: string;
|
|
159
|
-
/** Alternative: custom getter. Takes precedence over `key`. */
|
|
160
|
-
getter?: (data: TenantDetailData) => string | number;
|
|
161
|
-
}
|
|
112
|
+
export type { TenantDetailData, VerbrauchField } from './tenant-detail/types.js';
|
|
162
113
|
|
|
163
114
|
const props = withDefaults(
|
|
164
115
|
defineProps<{
|
|
@@ -232,55 +183,22 @@ function defaultFormatDate(value: string | null | undefined): string {
|
|
|
232
183
|
return String(value).slice(0, 10);
|
|
233
184
|
}
|
|
234
185
|
|
|
235
|
-
function
|
|
186
|
+
function formatDateResolved(value: string | null | undefined): string {
|
|
236
187
|
return props.formatDate ? props.formatDate(value) : defaultFormatDate(value);
|
|
237
188
|
}
|
|
238
189
|
|
|
239
|
-
function resolveVerbrauch(field: VerbrauchField): string {
|
|
240
|
-
if (!data.value) return '—';
|
|
241
|
-
if (field.getter) return String(field.getter(data.value));
|
|
242
|
-
if (field.key) {
|
|
243
|
-
const v = data.value.counts?.[field.key];
|
|
244
|
-
return v === undefined || v === null ? '0' : String(v);
|
|
245
|
-
}
|
|
246
|
-
return '—';
|
|
247
|
-
}
|
|
248
|
-
|
|
249
190
|
// ── Manifest-driven Action Flow (Suspend/Reactivate, Default) ──────────
|
|
250
191
|
const manifestRef = toRef(() => props.manifest);
|
|
251
192
|
|
|
252
|
-
const
|
|
253
|
-
show: false,
|
|
254
|
-
description: '',
|
|
255
|
-
error: '',
|
|
256
|
-
});
|
|
257
|
-
let pendingMfaResolve: ((code: string | null) => void) | null = null;
|
|
193
|
+
const mfa = useMfaPrompt();
|
|
258
194
|
|
|
259
195
|
function showMfaDialog(def: TenantActionDef, ctx: { row: TenantDto }): Promise<string | null> {
|
|
260
|
-
return
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
}),
|
|
267
|
-
error: '',
|
|
268
|
-
};
|
|
269
|
-
pendingMfaResolve = (code) => {
|
|
270
|
-
pendingMfaResolve = null;
|
|
271
|
-
resolve(code);
|
|
272
|
-
};
|
|
273
|
-
});
|
|
274
|
-
}
|
|
275
|
-
|
|
276
|
-
function onMfaConfirm(code: string): void {
|
|
277
|
-
pendingMfaResolve?.(code);
|
|
278
|
-
mfaState.value.show = false;
|
|
279
|
-
}
|
|
280
|
-
|
|
281
|
-
function onMfaDialogVisibility(open: boolean): void {
|
|
282
|
-
mfaState.value.show = open;
|
|
283
|
-
if (!open && pendingMfaResolve) pendingMfaResolve(null);
|
|
196
|
+
return mfa.prompt(
|
|
197
|
+
formatMessage(msg.value.actions.mfaDescription, {
|
|
198
|
+
action: def.label,
|
|
199
|
+
tenant: ctx.row.name,
|
|
200
|
+
}),
|
|
201
|
+
);
|
|
284
202
|
}
|
|
285
203
|
|
|
286
204
|
const confirmState = ref<{
|
|
@@ -348,16 +266,29 @@ const manifestActions = computed(() => {
|
|
|
348
266
|
.map((a) => ({ def: a.def, onClick: () => void a.invoke(row) }));
|
|
349
267
|
});
|
|
350
268
|
|
|
269
|
+
const router = useRouter();
|
|
270
|
+
|
|
271
|
+
/**
|
|
272
|
+
* The hero back button navigates rather than rendering a link.
|
|
273
|
+
*
|
|
274
|
+
* `backRoute` is a `RouteLocationRaw`, not an href, so there is no anchor to
|
|
275
|
+
* build without duplicating the router's resolution — and every other hero in
|
|
276
|
+
* the package uses a button for the same step.
|
|
277
|
+
*/
|
|
278
|
+
function goBack(): void {
|
|
279
|
+
void router.push(props.backRoute);
|
|
280
|
+
}
|
|
281
|
+
|
|
351
282
|
function iconForActionKey(actionKey: string): string {
|
|
352
283
|
if (actionKey.endsWith('.suspend')) return 'block';
|
|
353
284
|
if (actionKey.endsWith('.reactivate')) return 'play_arrow';
|
|
354
285
|
return 'bolt';
|
|
355
286
|
}
|
|
356
287
|
|
|
357
|
-
function
|
|
358
|
-
if (actionKey.endsWith('.suspend')) return '
|
|
359
|
-
if (actionKey.endsWith('.reactivate')) return 'positive';
|
|
360
|
-
return 'primary';
|
|
288
|
+
function toneClass(actionKey: string): string {
|
|
289
|
+
if (actionKey.endsWith('.suspend')) return 'sa-btn--danger';
|
|
290
|
+
if (actionKey.endsWith('.reactivate')) return 'sa-btn--positive';
|
|
291
|
+
return 'sa-btn--primary';
|
|
361
292
|
}
|
|
362
293
|
|
|
363
294
|
const defaultUserColumns = computed<QTableColumn[]>(() => [
|
|
@@ -392,16 +323,6 @@ const defaultUserColumns = computed<QTableColumn[]>(() => [
|
|
|
392
323
|
</script>
|
|
393
324
|
|
|
394
325
|
<style scoped>
|
|
395
|
-
.sa-tenant-detail {
|
|
396
|
-
min-height: calc(100vh - 56px);
|
|
397
|
-
background: var(--sa-bg-app);
|
|
398
|
-
}
|
|
399
|
-
.sa-tenant-detail__back {
|
|
400
|
-
margin-bottom: 6px;
|
|
401
|
-
}
|
|
402
|
-
.sa-tenant-detail__body {
|
|
403
|
-
padding: 12px 28px 28px;
|
|
404
|
-
}
|
|
405
326
|
.sa-tenant-detail__card-head {
|
|
406
327
|
display: flex;
|
|
407
328
|
justify-content: space-between;
|
|
@@ -421,18 +342,6 @@ const defaultUserColumns = computed<QTableColumn[]>(() => [
|
|
|
421
342
|
gap: 8px;
|
|
422
343
|
align-items: center;
|
|
423
344
|
}
|
|
424
|
-
.sa-tenant-detail__grid {
|
|
425
|
-
display: grid;
|
|
426
|
-
grid-template-columns: repeat(auto-fit, minmax(180px, 1fr));
|
|
427
|
-
gap: 12px;
|
|
428
|
-
}
|
|
429
|
-
.sa-tenant-detail__state {
|
|
430
|
-
padding: 32px 0;
|
|
431
|
-
color: var(--sa-muted);
|
|
432
|
-
display: flex;
|
|
433
|
-
align-items: center;
|
|
434
|
-
gap: 12px;
|
|
435
|
-
}
|
|
436
345
|
.sa-tenant-detail__empty {
|
|
437
346
|
color: var(--sa-muted);
|
|
438
347
|
font-size: 13px;
|