@saasicat/ui-vue 0.21.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-BY_t9prv.d.cts → catalog-DJcfm5N2.d.cts} +20 -7
- package/dist/{catalog-BY_t9prv.d.ts → catalog-DJcfm5N2.d.ts} +20 -7
- package/dist/{chunk-JN6HZGLV.js → chunk-F7NRM6KI.js} +54 -28
- package/dist/{chunk-7IFKVGZV.js → chunk-LY52T4N4.js} +21 -2
- package/dist/{chunk-OTP3OSSW.js → chunk-XMMFN2WJ.js} +74 -3
- package/dist/client/index.cjs +132 -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 +319 -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 +76 -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-c_Eqsu9u.d.ts → use-super-admin-i18n-CHNdsSlm.d.ts} +34 -7
- package/dist/{use-super-admin-i18n-DlJRGIVq.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 +22 -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/AdminFilters.vue +12 -0
- package/src/components/admin-page/AdminHero.vue +22 -5
- package/src/components/admin-page/AdminKpi.vue +84 -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 +31 -16
- 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/PlanDetail.vue +92 -302
- package/src/components/plan-detail/PlanDetailKpis.vue +22 -27
- package/src/components/plan-detail/PlanTitleEdit.vue +133 -0
- package/src/components/plan-list/PlanList.vue +72 -290
- 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 +34 -10
- package/src/pages-standard/AdminManifestErrorPage.vue +79 -9
- package/src/pages-standard/AuditPage.vue +53 -72
- package/src/pages-standard/BundlesPage.vue +128 -144
- package/src/pages-standard/DashboardPage.vue +43 -107
- package/src/pages-standard/DiscoveryPage.vue +158 -200
- package/src/pages-standard/EmailHistoryPage.vue +98 -88
- package/src/pages-standard/MarketingCatalogPage.vue +237 -267
- package/src/pages-standard/PilotsPage.vue +44 -60
- package/src/pages-standard/PlansPage.vue +230 -105
- package/src/pages-standard/PlatformEmailPage.vue +37 -40
- package/src/pages-standard/PromoCodeDetailPage.vue +16 -30
- package/src/pages-standard/PromoCodesPage.vue +86 -112
- package/src/pages-standard/SubscriptionsPage.vue +10 -17
- package/src/pages-standard/SuperAdminLoginPage.vue +12 -12
- package/src/pages-standard/SuperAdminSetupWizard.vue +20 -17
- package/src/pages-standard/TenantDetailPage.vue +45 -41
- package/src/pages-standard/TenantsPage.vue +184 -264
- package/src/pages-standard/UsersPage.vue +69 -104
- 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 +6 -10
- 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 +1 -1
- package/src/pages-standard/marketing-catalog/MarketingCatalogHeader.vue +2 -13
- 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 +1 -1
- package/src/pages-standard/sa-theme.css +481 -71
- package/src/pages-standard/tenant-detail/TenantUsers.vue +2 -8
- 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-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 -1027
- package/src/components/plan-cockpit/PlanCockpitAuditLog.vue +0 -72
- package/src/components/plan-cockpit/PlanCockpitDiffPanel.vue +0 -99
- 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 -249
- package/src/components/plan-cockpit/types.ts +0 -72
- package/src/components/plan-detail/PlanDetailHeader.vue +0 -194
|
@@ -1,81 +1,66 @@
|
|
|
1
1
|
<template>
|
|
2
2
|
<AdminPage class="sa-users">
|
|
3
|
-
<AdminHero :title="resolvedTitle" :subtitle="subtitle"
|
|
4
|
-
<template #actions>
|
|
5
|
-
<q-btn
|
|
6
|
-
unelevated
|
|
7
|
-
color="primary"
|
|
8
|
-
icon="search"
|
|
9
|
-
:label="common.search"
|
|
10
|
-
@click="reload"
|
|
11
|
-
/>
|
|
12
|
-
</template>
|
|
13
|
-
</AdminHero>
|
|
3
|
+
<AdminHero :title="resolvedTitle" :subtitle="subtitle" />
|
|
14
4
|
|
|
15
|
-
<
|
|
16
|
-
<
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
</
|
|
29
|
-
</div>
|
|
5
|
+
<AdminBody>
|
|
6
|
+
<AdminSection>
|
|
7
|
+
<AdminStatistics :label="resolvedTitle">
|
|
8
|
+
<AdminKpi
|
|
9
|
+
v-for="tile in statTiles"
|
|
10
|
+
:key="tile.id"
|
|
11
|
+
:label="tile.label"
|
|
12
|
+
:value="tile.count"
|
|
13
|
+
:tone="tile.tone"
|
|
14
|
+
:selected="statusFilter === tile.id"
|
|
15
|
+
:action="() => (statusFilter = tile.id)"
|
|
16
|
+
/>
|
|
17
|
+
</AdminStatistics>
|
|
18
|
+
</AdminSection>
|
|
30
19
|
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
20
|
+
<AdminSection :title="common.results" class="sa-users__card">
|
|
21
|
+
<AdminFilters class="q-mb-lg">
|
|
22
|
+
<q-input
|
|
23
|
+
v-model="filter.q"
|
|
24
|
+
outlined
|
|
25
|
+
dense
|
|
26
|
+
:label="msg.filterQuery"
|
|
27
|
+
clearable
|
|
28
|
+
debounce="250"
|
|
29
|
+
@update:model-value="reload"
|
|
30
|
+
/>
|
|
31
|
+
<q-input
|
|
32
|
+
v-model="filter.tenant"
|
|
33
|
+
outlined
|
|
34
|
+
dense
|
|
35
|
+
:label="msg.filterTenant"
|
|
36
|
+
clearable
|
|
37
|
+
debounce="250"
|
|
38
|
+
@update:model-value="reload"
|
|
39
|
+
/>
|
|
40
|
+
<slot name="filters-extra" />
|
|
41
|
+
</AdminFilters>
|
|
52
42
|
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
/>
|
|
75
|
-
</q-td>
|
|
76
|
-
</template>
|
|
77
|
-
<template #body-cell-actions="{ row }">
|
|
78
|
-
<q-td>
|
|
43
|
+
<AdminTable
|
|
44
|
+
:rows="filteredRows"
|
|
45
|
+
:columns="effectiveColumns"
|
|
46
|
+
:loading="loading"
|
|
47
|
+
storage-key="users"
|
|
48
|
+
>
|
|
49
|
+
<template #body-cell-status="{ row }">
|
|
50
|
+
<q-td>
|
|
51
|
+
<q-badge
|
|
52
|
+
:color="row.isActive ? 'positive' : 'grey'"
|
|
53
|
+
:label="row.isActive ? msg.statusActive : msg.statusDeactivated"
|
|
54
|
+
/>
|
|
55
|
+
<q-badge
|
|
56
|
+
v-if="row.invitationStatus === 'PENDING'"
|
|
57
|
+
color="amber-7"
|
|
58
|
+
:label="msg.badgePending"
|
|
59
|
+
class="q-ml-xs"
|
|
60
|
+
/>
|
|
61
|
+
</q-td>
|
|
62
|
+
</template>
|
|
63
|
+
<template #row-actions="{ row }">
|
|
79
64
|
<slot name="row-actions" :row="row">
|
|
80
65
|
<q-btn
|
|
81
66
|
v-for="action in visibleActions(row)"
|
|
@@ -88,10 +73,10 @@
|
|
|
88
73
|
@click="action.handler(row)"
|
|
89
74
|
/>
|
|
90
75
|
</slot>
|
|
91
|
-
</
|
|
92
|
-
</
|
|
93
|
-
</
|
|
94
|
-
</
|
|
76
|
+
</template>
|
|
77
|
+
</AdminTable>
|
|
78
|
+
</AdminSection>
|
|
79
|
+
</AdminBody>
|
|
95
80
|
|
|
96
81
|
<MfaPromptDialog
|
|
97
82
|
v-if="needsMfaDialog"
|
|
@@ -106,12 +91,18 @@
|
|
|
106
91
|
</template>
|
|
107
92
|
|
|
108
93
|
<script setup lang="ts">
|
|
94
|
+
import AdminTable from '../components/admin-page/AdminTable.vue';
|
|
109
95
|
import { computed, onMounted, reactive, ref } from 'vue';
|
|
110
96
|
import { useMfaPrompt } from '../vue/use-mfa-prompt.js';
|
|
111
97
|
import { useQuasar } from 'quasar';
|
|
112
98
|
import { useSuperAdminNotify } from '../quasar/notify.js';
|
|
99
|
+
import AdminBody from '../components/admin-page/AdminBody.vue';
|
|
100
|
+
import AdminFilters from '../components/admin-page/AdminFilters.vue';
|
|
113
101
|
import AdminHero from '../components/admin-page/AdminHero.vue';
|
|
102
|
+
import AdminKpi from '../components/admin-page/AdminKpi.vue';
|
|
114
103
|
import AdminPage from '../components/admin-page/AdminPage.vue';
|
|
104
|
+
import AdminSection from '../components/admin-page/AdminSection.vue';
|
|
105
|
+
import AdminStatistics from '../components/admin-page/AdminStatistics.vue';
|
|
115
106
|
import MfaPromptDialog from '../components/MfaPromptDialog.vue';
|
|
116
107
|
import { formatMessage } from '../client/i18n/format.js';
|
|
117
108
|
import { useSaMessages, useSuperAdminI18n } from '../vue/use-super-admin-i18n.js';
|
|
@@ -318,14 +309,6 @@ const mergedActions = computed<readonly UserRowAction[]>(() => [
|
|
|
318
309
|
|
|
319
310
|
const effectiveColumns = computed(() => {
|
|
320
311
|
const cols = [...baseColumns.value];
|
|
321
|
-
if (mergedActions.value.length > 0) {
|
|
322
|
-
cols.push({
|
|
323
|
-
name: 'actions',
|
|
324
|
-
label: '',
|
|
325
|
-
field: 'id' as never,
|
|
326
|
-
align: 'right' as 'left',
|
|
327
|
-
});
|
|
328
|
-
}
|
|
329
312
|
return cols;
|
|
330
313
|
});
|
|
331
314
|
|
|
@@ -468,22 +451,4 @@ function onDeactivateClick(row: UserRow): void {
|
|
|
468
451
|
}
|
|
469
452
|
</script>
|
|
470
453
|
|
|
471
|
-
<style scoped>
|
|
472
|
-
.sa-users__filter {
|
|
473
|
-
display: flex;
|
|
474
|
-
gap: 10px;
|
|
475
|
-
margin-bottom: 12px;
|
|
476
|
-
align-items: center;
|
|
477
|
-
flex-wrap: wrap;
|
|
478
|
-
}
|
|
479
|
-
.sa-users__filter > * {
|
|
480
|
-
flex: 1;
|
|
481
|
-
min-width: 200px;
|
|
482
|
-
}
|
|
483
|
-
.sa-users__card {
|
|
484
|
-
background: #fff;
|
|
485
|
-
border: 1px solid var(--sa-border, #e2e8f0);
|
|
486
|
-
border-radius: 12px;
|
|
487
|
-
overflow: hidden;
|
|
488
|
-
}
|
|
489
|
-
</style>
|
|
454
|
+
<style scoped></style>
|
|
@@ -12,13 +12,16 @@
|
|
|
12
12
|
<div class="sa-bd-card__titlerow">
|
|
13
13
|
<span class="sa-bd-card__key">{{ bundle.bundleKey }}</span>
|
|
14
14
|
<span
|
|
15
|
-
class="sa-chip"
|
|
16
|
-
:class="`sa-chip--${statusClass(bundle)}`"
|
|
15
|
+
class="sa-bundle-chip"
|
|
16
|
+
:class="`sa-bundle-chip--${statusClass(bundle)}`"
|
|
17
17
|
:title="statusTooltip(bundle)"
|
|
18
18
|
>
|
|
19
19
|
{{ statusLabel(bundle) }}
|
|
20
20
|
</span>
|
|
21
|
-
<span
|
|
21
|
+
<span
|
|
22
|
+
v-if="i18nLocaleCount(bundle) > 0"
|
|
23
|
+
class="sa-bundle-chip sa-bundle-chip--info"
|
|
24
|
+
>
|
|
22
25
|
{{ translationCount(bundle) }}
|
|
23
26
|
</span>
|
|
24
27
|
</div>
|
|
@@ -93,34 +96,34 @@ function translationCount(bundle: BundleRow): string {
|
|
|
93
96
|
|
|
94
97
|
<style scoped>
|
|
95
98
|
/* Status chips co-located with the markup (analogous to PlanList .pl-chip*).
|
|
96
|
-
Deliberately scoped: the identically named global .sa-chip rule in
|
|
97
|
-
DiscoveryPage.vue would otherwise override .sa-chip--live (same specificity,
|
|
99
|
+
Deliberately scoped: the identically named global .sa-bundle-chip rule in
|
|
100
|
+
DiscoveryPage.vue would otherwise override .sa-bundle-chip--live (same specificity,
|
|
98
101
|
later source order) and render the "Live" tag grey instead of green. */
|
|
99
|
-
.sa-chip {
|
|
102
|
+
.sa-bundle-chip {
|
|
100
103
|
font-size: 10px;
|
|
101
104
|
font-weight: 600;
|
|
102
105
|
padding: 2px 7px;
|
|
103
106
|
border-radius: 6px;
|
|
104
|
-
background:
|
|
105
|
-
color:
|
|
107
|
+
background: var(--sa-border-soft);
|
|
108
|
+
color: var(--sa-muted-dark);
|
|
106
109
|
}
|
|
107
|
-
.sa-chip--info {
|
|
108
|
-
background:
|
|
109
|
-
color:
|
|
110
|
+
.sa-bundle-chip--info {
|
|
111
|
+
background: var(--sa-primary-50);
|
|
112
|
+
color: var(--sa-primary-strong);
|
|
110
113
|
}
|
|
111
|
-
.sa-chip--live {
|
|
114
|
+
.sa-bundle-chip--live {
|
|
112
115
|
background: #dcfce7;
|
|
113
116
|
color: #166534;
|
|
114
117
|
}
|
|
115
|
-
.sa-chip--draft {
|
|
118
|
+
.sa-bundle-chip--draft {
|
|
116
119
|
background: #fef3c7;
|
|
117
120
|
color: #92400e;
|
|
118
121
|
}
|
|
119
|
-
.sa-chip--supersed {
|
|
120
|
-
background:
|
|
121
|
-
color:
|
|
122
|
+
.sa-bundle-chip--supersed {
|
|
123
|
+
background: var(--sa-border);
|
|
124
|
+
color: var(--sa-muted);
|
|
122
125
|
}
|
|
123
|
-
.sa-chip--scheduled {
|
|
126
|
+
.sa-bundle-chip--scheduled {
|
|
124
127
|
background: #fef3c7;
|
|
125
128
|
color: #92400e;
|
|
126
129
|
}
|
|
@@ -1,31 +1,22 @@
|
|
|
1
1
|
<template>
|
|
2
|
-
<
|
|
3
|
-
<
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
</div>
|
|
13
|
-
<div class="sa-bundles__kpi">
|
|
14
|
-
<div class="sa-bundles__kpi-label">{{ msg.kpis.drafts }}</div>
|
|
15
|
-
<div class="sa-bundles__kpi-value">{{ totalDraftVersions }}</div>
|
|
16
|
-
<div class="sa-bundles__kpi-sub">{{ draftsSub }}</div>
|
|
17
|
-
</div>
|
|
18
|
-
<div class="sa-bundles__kpi">
|
|
19
|
-
<div class="sa-bundles__kpi-label">{{ msg.kpis.translated }}</div>
|
|
20
|
-
<div class="sa-bundles__kpi-value">{{ translatedCount }}</div>
|
|
21
|
-
<div class="sa-bundles__kpi-sub">{{ translatedSub }}</div>
|
|
22
|
-
</div>
|
|
23
|
-
</div>
|
|
2
|
+
<AdminStatistics :columns="4">
|
|
3
|
+
<AdminKpi :label="msg.kpis.total" :value="bundlesTotal" :sub="totalSub" />
|
|
4
|
+
<AdminKpi
|
|
5
|
+
:label="msg.kpis.scheduled"
|
|
6
|
+
:value="totalScheduledVersions"
|
|
7
|
+
:sub="msg.kpis.scheduledSub"
|
|
8
|
+
/>
|
|
9
|
+
<AdminKpi :label="msg.kpis.drafts" :value="totalDraftVersions" :sub="draftsSub" />
|
|
10
|
+
<AdminKpi :label="msg.kpis.translated" :value="translatedCount" :sub="translatedSub" />
|
|
11
|
+
</AdminStatistics>
|
|
24
12
|
</template>
|
|
25
13
|
|
|
26
14
|
<script setup lang="ts">
|
|
27
15
|
import { computed } from 'vue';
|
|
28
16
|
|
|
17
|
+
import AdminKpi from '../../components/admin-page/AdminKpi.vue';
|
|
18
|
+
import AdminStatistics from '../../components/admin-page/AdminStatistics.vue';
|
|
19
|
+
|
|
29
20
|
import { formatMessage } from '../../client/i18n/format.js';
|
|
30
21
|
import { useSaMessages } from '../../vue/use-super-admin-i18n.js';
|
|
31
22
|
|
|
@@ -14,16 +14,11 @@
|
|
|
14
14
|
>
|
|
15
15
|
<template #prepend><q-icon name="translate" size="18px" /></template>
|
|
16
16
|
</q-select>
|
|
17
|
-
<
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
@click="emit('create')"
|
|
23
|
-
/>
|
|
24
|
-
<q-btn flat icon="refresh" :loading="loading" @click="emit('refresh')">
|
|
25
|
-
<q-tooltip>{{ msg.header.reload }}</q-tooltip>
|
|
26
|
-
</q-btn>
|
|
17
|
+
<button class="sa-btn sa-btn--primary" type="button" @click="emit('create')">
|
|
18
|
+
<q-icon name="add" size="16px" />
|
|
19
|
+
<span>{{ msg.header.newBundle }}</span>
|
|
20
|
+
</button>
|
|
21
|
+
<AdminRefreshBtn :loading="loading" @refresh="emit('refresh')" />
|
|
27
22
|
</div>
|
|
28
23
|
</template>
|
|
29
24
|
|
|
@@ -31,6 +26,7 @@
|
|
|
31
26
|
import { computed } from 'vue';
|
|
32
27
|
|
|
33
28
|
import { useSaMessages } from '../../vue/use-super-admin-i18n.js';
|
|
29
|
+
import AdminRefreshBtn from '../../components/admin-page/AdminRefreshBtn.vue';
|
|
34
30
|
|
|
35
31
|
// The language selector controls which locale feature/quota labels are resolved
|
|
36
32
|
// on the create form and in the detail view (fallback locale → DE → key). The default is the
|
|
@@ -171,13 +171,13 @@ function copyFromDefault(locale: string): void {
|
|
|
171
171
|
gap: 12px;
|
|
172
172
|
}
|
|
173
173
|
.sa-trans-lang {
|
|
174
|
-
border: 1px solid
|
|
174
|
+
border: 1px solid var(--sa-border);
|
|
175
175
|
border-radius: 10px;
|
|
176
176
|
background: #fff;
|
|
177
177
|
padding: 10px 12px;
|
|
178
178
|
}
|
|
179
179
|
.sa-trans-lang--source {
|
|
180
|
-
background:
|
|
180
|
+
background: var(--sa-bg-surface-2);
|
|
181
181
|
border-color: #cbd5e1;
|
|
182
182
|
}
|
|
183
183
|
.sa-trans-lang__head {
|
|
@@ -189,7 +189,7 @@ function copyFromDefault(locale: string): void {
|
|
|
189
189
|
.sa-trans-lang__code {
|
|
190
190
|
font-size: 10px;
|
|
191
191
|
font-weight: 700;
|
|
192
|
-
background:
|
|
192
|
+
background: var(--sa-heading);
|
|
193
193
|
color: #fff;
|
|
194
194
|
padding: 2px 6px;
|
|
195
195
|
border-radius: 5px;
|
|
@@ -205,13 +205,13 @@ function copyFromDefault(locale: string): void {
|
|
|
205
205
|
font-weight: 700;
|
|
206
206
|
text-transform: uppercase;
|
|
207
207
|
letter-spacing: 0.5px;
|
|
208
|
-
color:
|
|
209
|
-
background:
|
|
208
|
+
color: var(--sa-muted-dark);
|
|
209
|
+
background: var(--sa-border);
|
|
210
210
|
padding: 2px 6px;
|
|
211
211
|
border-radius: 5px;
|
|
212
212
|
}
|
|
213
213
|
.sa-trans-lang__copy {
|
|
214
|
-
color:
|
|
214
|
+
color: var(--sa-muted-dark);
|
|
215
215
|
}
|
|
216
216
|
.sa-trans-fields {
|
|
217
217
|
display: flex;
|
|
@@ -228,12 +228,12 @@ function copyFromDefault(locale: string): void {
|
|
|
228
228
|
font-weight: 600;
|
|
229
229
|
text-transform: uppercase;
|
|
230
230
|
letter-spacing: 0.3px;
|
|
231
|
-
color:
|
|
231
|
+
color: var(--sa-muted-light);
|
|
232
232
|
}
|
|
233
233
|
.sa-trans-locked {
|
|
234
234
|
font-size: 13px;
|
|
235
235
|
color: #334155;
|
|
236
|
-
background:
|
|
236
|
+
background: var(--sa-border-soft);
|
|
237
237
|
border: 1px dashed #cbd5e1;
|
|
238
238
|
border-radius: 6px;
|
|
239
239
|
padding: 6px 10px;
|
|
@@ -243,7 +243,7 @@ function copyFromDefault(locale: string): void {
|
|
|
243
243
|
}
|
|
244
244
|
.sa-trans-locked__hint {
|
|
245
245
|
font-size: 10px;
|
|
246
|
-
color:
|
|
246
|
+
color: var(--sa-muted-light);
|
|
247
247
|
text-transform: uppercase;
|
|
248
248
|
}
|
|
249
249
|
.sa-trans__empty {
|
|
@@ -251,7 +251,7 @@ function copyFromDefault(locale: string): void {
|
|
|
251
251
|
padding: 16px;
|
|
252
252
|
text-align: center;
|
|
253
253
|
font-size: 12px;
|
|
254
|
-
color:
|
|
254
|
+
color: var(--sa-muted-light);
|
|
255
255
|
border: 1px dashed #cbd5e1;
|
|
256
256
|
border-radius: 10px;
|
|
257
257
|
}
|
|
@@ -91,7 +91,7 @@ function isNew(cap: CapabilityCatalogEntryRow): boolean {
|
|
|
91
91
|
gap: 10px;
|
|
92
92
|
align-items: flex-start;
|
|
93
93
|
background: #fff;
|
|
94
|
-
border: 1px solid
|
|
94
|
+
border: 1px solid var(--sa-border);
|
|
95
95
|
border-radius: 8px;
|
|
96
96
|
padding: 8px 10px;
|
|
97
97
|
}
|
|
@@ -142,8 +142,8 @@ function isNew(cap: CapabilityCatalogEntryRow): boolean {
|
|
|
142
142
|
color: #b91c1c;
|
|
143
143
|
}
|
|
144
144
|
.sa-caps-row__flag--gone {
|
|
145
|
-
background:
|
|
146
|
-
color:
|
|
145
|
+
background: var(--sa-border);
|
|
146
|
+
color: var(--sa-muted);
|
|
147
147
|
}
|
|
148
148
|
.sa-caps-row.gone {
|
|
149
149
|
opacity: 0.6;
|
|
@@ -153,7 +153,7 @@ function isNew(cap: CapabilityCatalogEntryRow): boolean {
|
|
|
153
153
|
gap: 12px;
|
|
154
154
|
flex-wrap: wrap;
|
|
155
155
|
font-size: 11px;
|
|
156
|
-
color:
|
|
156
|
+
color: var(--sa-muted-dark);
|
|
157
157
|
margin-top: 1px;
|
|
158
158
|
}
|
|
159
159
|
.sa-caps-row__meta code {
|
|
@@ -165,7 +165,7 @@ function isNew(cap: CapabilityCatalogEntryRow): boolean {
|
|
|
165
165
|
gap: 6px;
|
|
166
166
|
font-size: 11px;
|
|
167
167
|
color: #b45309;
|
|
168
|
-
background:
|
|
168
|
+
background: var(--sa-warning-bg);
|
|
169
169
|
border: 1px dashed #fde68a;
|
|
170
170
|
border-radius: 8px;
|
|
171
171
|
padding: 10px 12px;
|
|
@@ -269,7 +269,7 @@ function coverage(locale: string): number {
|
|
|
269
269
|
|
|
270
270
|
<style scoped>
|
|
271
271
|
.sa-fc {
|
|
272
|
-
border: 1px solid
|
|
272
|
+
border: 1px solid var(--sa-border);
|
|
273
273
|
border-radius: 10px;
|
|
274
274
|
background: #fff;
|
|
275
275
|
overflow: hidden;
|
|
@@ -286,7 +286,7 @@ function coverage(locale: string): number {
|
|
|
286
286
|
cursor: pointer;
|
|
287
287
|
}
|
|
288
288
|
.sa-fc__icon {
|
|
289
|
-
color:
|
|
289
|
+
color: var(--sa-muted-dark);
|
|
290
290
|
flex-shrink: 0;
|
|
291
291
|
}
|
|
292
292
|
.sa-fc__main {
|
|
@@ -302,8 +302,8 @@ function coverage(locale: string): number {
|
|
|
302
302
|
.sa-fc__key {
|
|
303
303
|
font-size: 11px;
|
|
304
304
|
font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
|
|
305
|
-
background:
|
|
306
|
-
color:
|
|
305
|
+
background: var(--sa-border-soft);
|
|
306
|
+
color: var(--sa-muted-dark);
|
|
307
307
|
padding: 2px 6px;
|
|
308
308
|
border-radius: 5px;
|
|
309
309
|
white-space: nowrap;
|
|
@@ -311,7 +311,7 @@ function coverage(locale: string): number {
|
|
|
311
311
|
.sa-fc__label {
|
|
312
312
|
font-size: 13px;
|
|
313
313
|
font-weight: 600;
|
|
314
|
-
color:
|
|
314
|
+
color: var(--sa-heading);
|
|
315
315
|
}
|
|
316
316
|
.sa-fc__flag {
|
|
317
317
|
font-size: 10px;
|
|
@@ -337,7 +337,7 @@ function coverage(locale: string): number {
|
|
|
337
337
|
}
|
|
338
338
|
.sa-fc__sub {
|
|
339
339
|
font-size: 11px;
|
|
340
|
-
color:
|
|
340
|
+
color: var(--sa-muted);
|
|
341
341
|
margin-top: 1px;
|
|
342
342
|
}
|
|
343
343
|
.sa-fc__dot {
|
|
@@ -356,16 +356,16 @@ function coverage(locale: string): number {
|
|
|
356
356
|
flex-shrink: 0;
|
|
357
357
|
}
|
|
358
358
|
.sa-fc__chev {
|
|
359
|
-
color:
|
|
359
|
+
color: var(--sa-muted-light);
|
|
360
360
|
transition: transform 0.15s;
|
|
361
361
|
}
|
|
362
362
|
.sa-fc__chev.open {
|
|
363
363
|
transform: rotate(90deg);
|
|
364
364
|
}
|
|
365
365
|
.sa-fc__body {
|
|
366
|
-
border-top: 1px solid
|
|
366
|
+
border-top: 1px solid var(--sa-border-soft);
|
|
367
367
|
padding: 12px;
|
|
368
|
-
background:
|
|
368
|
+
background: var(--sa-bg-surface-2);
|
|
369
369
|
}
|
|
370
370
|
.sa-fc__banner {
|
|
371
371
|
display: flex;
|
|
@@ -377,18 +377,18 @@ function coverage(locale: string): number {
|
|
|
377
377
|
margin-bottom: 10px;
|
|
378
378
|
}
|
|
379
379
|
.sa-fc__banner.warn {
|
|
380
|
-
background:
|
|
380
|
+
background: var(--sa-warning-bg);
|
|
381
381
|
border: 1px solid #fde68a;
|
|
382
382
|
color: #92400e;
|
|
383
383
|
}
|
|
384
384
|
.sa-fc__banner.mute {
|
|
385
|
-
background:
|
|
386
|
-
border: 1px solid
|
|
387
|
-
color:
|
|
385
|
+
background: var(--sa-border-soft);
|
|
386
|
+
border: 1px solid var(--sa-border);
|
|
387
|
+
color: var(--sa-muted-dark);
|
|
388
388
|
}
|
|
389
389
|
.sa-fc__subtabs {
|
|
390
390
|
margin-bottom: 12px;
|
|
391
|
-
border-bottom: 1px solid
|
|
391
|
+
border-bottom: 1px solid var(--sa-border);
|
|
392
392
|
}
|
|
393
393
|
.sa-fc__split {
|
|
394
394
|
display: grid;
|
|
@@ -400,7 +400,7 @@ function coverage(locale: string): number {
|
|
|
400
400
|
font-weight: 700;
|
|
401
401
|
text-transform: uppercase;
|
|
402
402
|
letter-spacing: 0.5px;
|
|
403
|
-
color:
|
|
403
|
+
color: var(--sa-muted-light);
|
|
404
404
|
margin-bottom: 8px;
|
|
405
405
|
}
|
|
406
406
|
.sa-fc__split-count {
|
|
@@ -424,6 +424,6 @@ function coverage(locale: string): number {
|
|
|
424
424
|
font-size: 11px;
|
|
425
425
|
font-weight: 600;
|
|
426
426
|
text-transform: uppercase;
|
|
427
|
-
color:
|
|
427
|
+
color: var(--sa-muted-light);
|
|
428
428
|
}
|
|
429
429
|
</style>
|
|
@@ -1,36 +1,40 @@
|
|
|
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
|
-
|
|
27
|
-
|
|
28
|
-
|
|
2
|
+
<AdminStatistics :columns="5">
|
|
3
|
+
<AdminKpi :label="msg.kpi.featuresTotal" :value="featuresCount" :sub="featuresTotalSub" />
|
|
4
|
+
<AdminKpi
|
|
5
|
+
:label="msg.kpi.approved"
|
|
6
|
+
:value="approvedCount"
|
|
7
|
+
:sub="msg.kpi.approvedSub"
|
|
8
|
+
tone="positive"
|
|
9
|
+
/>
|
|
10
|
+
<AdminKpi
|
|
11
|
+
:label="msg.kpi.pending"
|
|
12
|
+
:value="pendingCount"
|
|
13
|
+
:sub="msg.kpi.pendingSub"
|
|
14
|
+
:tone="pendingCount > 0 ? 'warn' : 'neutral'"
|
|
15
|
+
emphasis="surface"
|
|
16
|
+
/>
|
|
17
|
+
<AdminKpi
|
|
18
|
+
:label="msg.kpi.outdated"
|
|
19
|
+
:value="outdatedCount + obsoleteCount"
|
|
20
|
+
:sub="outdatedSub"
|
|
21
|
+
/>
|
|
22
|
+
<AdminKpi
|
|
23
|
+
:label="msg.kpi.orphans"
|
|
24
|
+
:value="orphanCount"
|
|
25
|
+
:sub="msg.orphansTitle"
|
|
26
|
+
:tone="orphanCount > 0 ? 'danger' : 'neutral'"
|
|
27
|
+
emphasis="surface"
|
|
28
|
+
/>
|
|
29
|
+
</AdminStatistics>
|
|
29
30
|
</template>
|
|
30
31
|
|
|
31
32
|
<script setup lang="ts">
|
|
32
33
|
import { computed } from 'vue';
|
|
33
34
|
|
|
35
|
+
import AdminKpi from '../../components/admin-page/AdminKpi.vue';
|
|
36
|
+
import AdminStatistics from '../../components/admin-page/AdminStatistics.vue';
|
|
37
|
+
|
|
34
38
|
import { formatMessage } from '../../client/i18n/format.js';
|
|
35
39
|
import { useSaMessages } from '../../vue/use-super-admin-i18n.js';
|
|
36
40
|
|