@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.
Files changed (145) hide show
  1. package/dist/{catalog-JXdKdIqG.d.cts → catalog-DJcfm5N2.d.cts} +21 -7
  2. package/dist/{catalog-JXdKdIqG.d.ts → catalog-DJcfm5N2.d.ts} +21 -7
  3. package/dist/{chunk-DPTIOQXX.js → chunk-F7NRM6KI.js} +56 -28
  4. package/dist/{chunk-RVG6LQHL.js → chunk-LY52T4N4.js} +21 -2
  5. package/dist/{chunk-ORX3ZG47.js → chunk-XMMFN2WJ.js} +74 -3
  6. package/dist/client/index.cjs +134 -29
  7. package/dist/client/index.d.cts +53 -3
  8. package/dist/client/index.d.ts +53 -3
  9. package/dist/client/index.js +14 -2
  10. package/dist/index.cjs +321 -162
  11. package/dist/index.d.cts +30 -8
  12. package/dist/index.d.ts +30 -8
  13. package/dist/index.js +176 -133
  14. package/dist/quasar/index.cjs +78 -29
  15. package/dist/quasar/index.d.cts +2 -2
  16. package/dist/quasar/index.d.ts +2 -2
  17. package/dist/quasar/index.js +6 -2
  18. package/dist/testing-e2e/admin-pages-suite.d.cts +37 -0
  19. package/dist/testing-e2e/admin-pages-suite.d.ts +37 -0
  20. package/dist/{use-super-admin-i18n-BlqcD0N7.d.ts → use-super-admin-i18n-CHNdsSlm.d.ts} +34 -7
  21. package/dist/{use-super-admin-i18n-1nCOkvgi.d.cts → use-super-admin-i18n-CgTuNi8h.d.cts} +34 -7
  22. package/package.json +18 -8
  23. package/src/client/i18n/messages/bundles.ts +0 -2
  24. package/src/client/i18n/messages/common.ts +24 -0
  25. package/src/client/i18n/messages/discovery.ts +2 -2
  26. package/src/client/i18n/messages/marketing.ts +2 -4
  27. package/src/client/i18n/messages/plan-detail.ts +0 -4
  28. package/src/client/i18n/messages/plans.ts +20 -8
  29. package/src/client/i18n/messages/tenants.ts +0 -2
  30. package/src/client/index.ts +1 -0
  31. package/src/client/manifest-loader.ts +1 -1
  32. package/src/client/resolve-plans.ts +144 -0
  33. package/src/components/BundleVersionPublishDialog.vue +6 -6
  34. package/src/components/KvBlock.vue +4 -4
  35. package/src/components/MarketingPromotionsTab.vue +34 -48
  36. package/src/components/MfaPromptDialog.vue +8 -2
  37. package/src/components/TenantActionConfirmDialog.vue +4 -4
  38. package/src/components/VersionDiffPreview.vue +7 -7
  39. package/src/components/admin-page/AdminBody.vue +40 -0
  40. package/src/components/admin-page/AdminFilters.vue +12 -0
  41. package/src/components/admin-page/AdminHero.vue +49 -0
  42. package/src/components/admin-page/AdminKpi.vue +84 -0
  43. package/src/components/admin-page/AdminPage.vue +16 -0
  44. package/src/components/admin-page/AdminPaginator.vue +195 -0
  45. package/src/components/admin-page/AdminRefreshBtn.vue +39 -0
  46. package/src/components/admin-page/AdminSection.vue +53 -0
  47. package/src/components/admin-page/AdminStatistics.vue +40 -0
  48. package/src/components/admin-page/AdminTable.vue +175 -0
  49. package/src/components/bundle-editor/BundleCreatePanel.vue +23 -23
  50. package/src/components/bundle-editor/BundleFeaturesEditor.vue +7 -7
  51. package/src/components/bundle-editor/BundlePlanCompatPicker.vue +9 -9
  52. package/src/components/bundle-editor/BundleQuotasEditor.vue +11 -11
  53. package/src/components/bundle-editor/BundleStatusBanner.vue +6 -6
  54. package/src/components/bundle-editor/BundleVersionInlineEditor.vue +18 -18
  55. package/src/components/bundle-editor/BundleVersionStrip.vue +12 -12
  56. package/src/components/dialogs/PilotCreateDialog.vue +12 -12
  57. package/src/components/dialogs/PilotEditDialog.vue +7 -7
  58. package/src/components/dialogs/PromoCodeCreateDialog.vue +8 -8
  59. package/src/components/dialogs/PromoCodeDialogFields.vue +33 -19
  60. package/src/components/dialogs/PromoCodeEditDialog.vue +10 -10
  61. package/src/components/plan/PlanGrid.vue +1 -1
  62. package/src/components/plan-create-dialog/PlanCreateDialog.vue +34 -46
  63. package/src/components/plan-detail/PlanAuditLog.vue +7 -8
  64. package/src/components/plan-detail/PlanDetail.vue +95 -292
  65. package/src/components/plan-detail/PlanDetailKpis.vue +22 -27
  66. package/src/components/plan-detail/PlanTitleEdit.vue +133 -0
  67. package/src/components/plan-detail/PlanVersionDiffPanel.vue +5 -8
  68. package/src/components/plan-detail/PlanVersionsPanel.vue +9 -11
  69. package/src/components/plan-list/PlanList.vue +206 -457
  70. package/src/components/plan-matrix/PlanMatrix.vue +66 -183
  71. package/src/components/plan-review/PlanReview.vue +191 -275
  72. package/src/components/plan-version-editor/PlanCatalogPreview.vue +7 -5
  73. package/src/components/plan-version-editor/PlanVersionEditor.vue +200 -295
  74. package/src/components/plan-version-editor/PlanVersionEditorHeader.vue +23 -55
  75. package/src/index.ts +1 -0
  76. package/src/pages-standard/AdminLayout.vue +38 -12
  77. package/src/pages-standard/AdminManifestErrorPage.vue +79 -9
  78. package/src/pages-standard/AuditPage.vue +65 -109
  79. package/src/pages-standard/BundlesPage.vue +146 -179
  80. package/src/pages-standard/DashboardPage.vue +59 -154
  81. package/src/pages-standard/DiscoveryPage.vue +172 -227
  82. package/src/pages-standard/EmailHistoryPage.vue +118 -159
  83. package/src/pages-standard/MarketingCatalogPage.vue +399 -440
  84. package/src/pages-standard/PilotsPage.vue +69 -117
  85. package/src/pages-standard/PlansPage.vue +240 -112
  86. package/src/pages-standard/PlatformEmailPage.vue +56 -91
  87. package/src/pages-standard/PromoCodeDetailPage.vue +49 -74
  88. package/src/pages-standard/PromoCodesPage.vue +95 -128
  89. package/src/pages-standard/SubscriptionsPage.vue +19 -52
  90. package/src/pages-standard/SuperAdminLoginPage.vue +12 -12
  91. package/src/pages-standard/SuperAdminSetupWizard.vue +22 -18
  92. package/src/pages-standard/TenantDetailPage.vue +100 -191
  93. package/src/pages-standard/TenantsPage.vue +190 -295
  94. package/src/pages-standard/UsersPage.vue +89 -157
  95. package/src/pages-standard/bundles-page/BundleAccordionList.vue +20 -17
  96. package/src/pages-standard/bundles-page/BundlesKpis.vue +13 -22
  97. package/src/pages-standard/bundles-page/BundlesToolbar.vue +63 -0
  98. package/src/pages-standard/discovery-page/CatalogEntryTransPanel.vue +10 -10
  99. package/src/pages-standard/discovery-page/DiscoveryCapList.vue +5 -5
  100. package/src/pages-standard/discovery-page/DiscoveryFeatureCard.vue +16 -16
  101. package/src/pages-standard/discovery-page/DiscoveryKpis.vue +31 -27
  102. package/src/pages-standard/discovery-page/DiscoveryQuotaCard.vue +7 -7
  103. package/src/pages-standard/marketing-catalog/MarketingCatalogAdmin.vue +111 -73
  104. package/src/pages-standard/marketing-catalog/MarketingCatalogHeader.vue +43 -62
  105. package/src/pages-standard/marketing-catalog/MarketingCatalogPreview.vue +53 -35
  106. package/src/pages-standard/marketing-catalog/MarketingCatalogToolbar.vue +7 -7
  107. package/src/pages-standard/plan-versions/PlanDiffCard.vue +6 -6
  108. package/src/pages-standard/plan-versions/PlanVersionsDiff.vue +6 -6
  109. package/src/pages-standard/plan-versions/PlanVersionsTimeline.vue +16 -16
  110. package/src/pages-standard/plans-page/PlanBundleOverview.vue +14 -29
  111. package/src/pages-standard/plans-page/PlanPublishDialog.vue +1 -1
  112. package/src/pages-standard/plans-page/PlansPageToast.vue +6 -6
  113. package/src/pages-standard/sa-theme.css +552 -86
  114. package/src/pages-standard/tenant-detail/TenantMasterData.vue +28 -0
  115. package/src/pages-standard/tenant-detail/TenantUsage.vue +31 -0
  116. package/src/pages-standard/tenant-detail/TenantUsers.vue +15 -0
  117. package/src/pages-standard/tenant-detail/types.ts +38 -0
  118. package/src/pages-standard/tenants/StatusPill.vue +2 -2
  119. package/src/pages-tenant/MySubscriptionBundlesPage.vue +25 -25
  120. package/src/pages-tenant/OnboardingConfigurator.vue +1 -5
  121. package/src/pages-tenant/PackageSnapshotPanel.vue +1 -1
  122. package/src/pages-tenant/TenantPlanSection.vue +12 -20
  123. package/src/quasar/create-super-admin-app.ts +4 -0
  124. package/src/vue/entitlement-provider.ts +0 -1
  125. package/src/vue/feature-router-guard.ts +0 -1
  126. package/src/vue/super-admin-context.ts +106 -1
  127. package/src/vue/use-api-list.ts +2 -1
  128. package/src/vue/use-mfa-prompt.ts +72 -0
  129. package/src/vue/use-pagination.ts +63 -0
  130. package/src/vue/use-plans.ts +1 -2
  131. package/src/vue/use-sign-out.ts +90 -0
  132. package/src/vue/use-tenant-billing.ts +1 -1
  133. package/src/vue/use-tenant-manifest.ts +0 -1
  134. package/src/components/KpiCard.vue +0 -53
  135. package/src/components/plan-cockpit/PlanCockpit.vue +0 -1012
  136. package/src/components/plan-cockpit/PlanCockpitAuditLog.vue +0 -72
  137. package/src/components/plan-cockpit/PlanCockpitDiffPanel.vue +0 -100
  138. package/src/components/plan-cockpit/PlanCockpitHeader.vue +0 -101
  139. package/src/components/plan-cockpit/PlanCockpitImpactPanel.vue +0 -112
  140. package/src/components/plan-cockpit/PlanCockpitKpis.vue +0 -68
  141. package/src/components/plan-cockpit/PlanCockpitVersions.vue +0 -251
  142. package/src/components/plan-cockpit/types.ts +0 -72
  143. package/src/components/plan-detail/PlanDetailHeader.vue +0 -194
  144. package/src/pages-standard/bundles-page/BundlesHeader.vue +0 -68
  145. package/src/pages-standard/discovery-page/DiscoveryHeader.vue +0 -34
@@ -1,43 +1,38 @@
1
1
  <template>
2
- <div class="pd-kpis">
3
- <div class="pd-kpi">
4
- <div class="pd-kpi-label">{{ msg.kpis.activeVersion }}</div>
5
- <div class="pd-kpi-big">
2
+ <AdminStatistics :columns="4">
3
+ <AdminKpi :label="msg.kpis.activeVersion" :sub="activeVersionSub">
4
+ <template #value>
6
5
  <template v-if="liveVersion">
7
6
  v{{ liveVersion.version }}
8
7
  <span class="chip live dot">live</span>
9
8
  </template>
10
9
  <template v-else>—</template>
11
- </div>
12
- <div class="pd-kpi-sub">{{ activeVersionSub }}</div>
13
- </div>
10
+ </template>
11
+ </AdminKpi>
14
12
 
15
- <div class="pd-kpi">
16
- <div class="pd-kpi-label">{{ msg.kpis.tenantImpact }}</div>
17
- <div class="pd-kpi-big">{{ tenantTotal }}</div>
18
- <div class="pd-kpi-sub">{{ msg.kpis.tenantsOnPlan }}</div>
19
- </div>
13
+ <AdminKpi
14
+ :label="msg.kpis.tenantImpact"
15
+ :value="tenantTotal"
16
+ :sub="msg.kpis.tenantsOnPlan"
17
+ />
20
18
 
21
- <div class="pd-kpi">
22
- <div class="pd-kpi-label">{{ msg.kpis.versions }}</div>
23
- <div class="pd-kpi-big">{{ versionCount }}</div>
24
- <div class="pd-kpi-sub">{{ versionsSummary }}</div>
25
- </div>
19
+ <AdminKpi :label="msg.kpis.versions" :value="versionCount" :sub="versionsSummary" />
26
20
 
27
- <div :class="['pd-kpi', draftVersion ? 'draft' : '']">
28
- <div class="pd-kpi-label">{{ msg.kpis.openDraft }}</div>
29
- <div class="pd-kpi-big" :style="draftVersion ? '' : 'color:#cbd5e1'">
30
- {{ draftVersion ? `v${draftVersion.version}` : '—' }}
31
- </div>
32
- <div class="pd-kpi-sub">
33
- {{ draftVersion ? msg.kpis.readyToEdit : msg.kpis.noOpenDraft }}
34
- </div>
35
- </div>
36
- </div>
21
+ <AdminKpi
22
+ :label="msg.kpis.openDraft"
23
+ :value="draftVersion ? `v${draftVersion.version}` : null"
24
+ :sub="draftVersion ? msg.kpis.readyToEdit : msg.kpis.noOpenDraft"
25
+ :tone="draftVersion ? 'warn' : 'neutral'"
26
+ emphasis="surface"
27
+ />
28
+ </AdminStatistics>
37
29
  </template>
38
30
 
39
31
  <script setup lang="ts">
40
32
  import { computed } from 'vue';
33
+
34
+ import AdminKpi from '../admin-page/AdminKpi.vue';
35
+ import AdminStatistics from '../admin-page/AdminStatistics.vue';
41
36
  import type { PlanVersionRow } from '@saasicat/types';
42
37
  import { formatMessage } from '../../client/i18n/format.js';
43
38
  import { useSaMessages } from '../../vue/use-super-admin-i18n.js';
@@ -0,0 +1,133 @@
1
+ <template>
2
+ <span class="pd-title-edit">
3
+ <template v-if="editing">
4
+ <input
5
+ ref="nameInput"
6
+ v-model="nameDraft"
7
+ class="pd-title-edit__input"
8
+ :aria-label="msg.header.editNameAria"
9
+ @keydown.enter="commit"
10
+ @keydown.escape="cancel"
11
+ @blur="commit"
12
+ />
13
+ <span class="pd-title-edit__hint">{{ msg.header.nameEditHint }}</span>
14
+ </template>
15
+ <template v-else>
16
+ {{ plan.label }}
17
+ <button
18
+ v-if="editable"
19
+ class="pd-title-edit__btn"
20
+ type="button"
21
+ :title="msg.header.editNameTitle"
22
+ :aria-label="msg.header.editNameAria"
23
+ @click="start"
24
+ >
25
+ <q-icon name="edit" size="15px" />
26
+ </button>
27
+ </template>
28
+ </span>
29
+ </template>
30
+
31
+ <script setup lang="ts">
32
+ import { nextTick, ref, watch } from 'vue';
33
+ import type { PlanRow } from '@saasicat/types';
34
+ import { useSaMessages } from '../../vue/use-super-admin-i18n.js';
35
+
36
+ // The plan name as the page heading, renameable in place.
37
+ //
38
+ // It goes into AdminHero's `title` slot rather than carrying a heading of its
39
+ // own: the plan detail used to render a second <h1> below the hero's, which
40
+ // left the page with two top-level headings and a title block that had to
41
+ // restate the hero's type scale to match it. Here the hero owns the element
42
+ // and the size; this only fills it.
43
+ const props = defineProps<{
44
+ plan: PlanRow;
45
+ /** Renaming a plan is only offered while an unpublished draft exists. */
46
+ editable: boolean;
47
+ }>();
48
+
49
+ const emit = defineEmits<{
50
+ (e: 'updatePlan', patch: { label: string }): void;
51
+ }>();
52
+
53
+ const msg = useSaMessages('planDetail');
54
+
55
+ const editing = ref(false);
56
+ const nameDraft = ref(props.plan.label);
57
+ const nameInput = ref<HTMLInputElement | null>(null);
58
+
59
+ watch(
60
+ () => props.plan.label,
61
+ (label) => {
62
+ if (!editing.value) nameDraft.value = label;
63
+ },
64
+ );
65
+
66
+ function start(): void {
67
+ nameDraft.value = props.plan.label;
68
+ editing.value = true;
69
+ void nextTick(() => nameInput.value?.focus());
70
+ }
71
+
72
+ function commit(): void {
73
+ if (!editing.value) return;
74
+ const next = nameDraft.value.trim();
75
+ editing.value = false;
76
+ if (next && next !== props.plan.label) emit('updatePlan', { label: next });
77
+ }
78
+
79
+ function cancel(): void {
80
+ nameDraft.value = props.plan.label;
81
+ editing.value = false;
82
+ }
83
+ </script>
84
+
85
+ <style scoped>
86
+ .pd-title-edit {
87
+ display: inline-flex;
88
+ align-items: center;
89
+ gap: 8px;
90
+ }
91
+ /* `font: inherit` on purpose: the heading's type comes from the hero, so the
92
+ * input keeps matching it when that changes. */
93
+ .pd-title-edit__input {
94
+ font: inherit;
95
+ color: var(--sa-heading);
96
+ border: 0;
97
+ background: var(--sa-warning-bg);
98
+ outline: 2px solid var(--sa-amber-light);
99
+ padding: 2px 8px;
100
+ border-radius: var(--sa-radius-control);
101
+ min-width: 220px;
102
+ }
103
+ .pd-title-edit__hint {
104
+ font-size: 11px;
105
+ font-weight: 500;
106
+ color: var(--sa-warning);
107
+ background: var(--sa-warning-bg);
108
+ border: 1px solid var(--sa-amber-border);
109
+ border-radius: var(--sa-radius-control);
110
+ padding: 3px 8px;
111
+ }
112
+ .pd-title-edit__btn {
113
+ display: inline-flex;
114
+ align-items: center;
115
+ justify-content: center;
116
+ width: 28px;
117
+ height: 28px;
118
+ border-radius: var(--sa-radius-control);
119
+ background: transparent;
120
+ border: 1px solid transparent;
121
+ color: var(--sa-muted-light);
122
+ cursor: pointer;
123
+ transition:
124
+ background 0.12s,
125
+ color 0.12s,
126
+ border-color 0.12s;
127
+ }
128
+ .pd-title-edit__btn:hover {
129
+ background: var(--sa-border-soft);
130
+ color: var(--sa-primary);
131
+ border-color: var(--sa-border);
132
+ }
133
+ </style>
@@ -1,10 +1,6 @@
1
1
  <template>
2
- <section class="pd-panel">
3
- <div class="pd-panel-head">
4
- <div style="min-width: 0">
5
- <h3 class="pd-panel-title">{{ panelTitle }}</h3>
6
- <div class="pd-panel-sub">{{ panelSubtitle }}</div>
7
- </div>
2
+ <AdminSection :title="panelTitle" :subtitle="panelSubtitle" class="pd-panel">
3
+ <template #actions>
8
4
  <div class="pd-panel-head-right pd-diff-chips">
9
5
  <template v-if="predecessor">
10
6
  <span class="pd-diff-chip add">+{{ diff.featuresAdded.length }} F</span>
@@ -16,7 +12,7 @@
16
12
  <span class="pd-diff-chip mod">{{ quotaCount(selectedVersion) }} Q</span>
17
13
  </template>
18
14
  </div>
19
- </div>
15
+ </template>
20
16
 
21
17
  <div v-if="predecessor" class="pd-diff-list">
22
18
  <div v-for="d in diffRows" :key="d.id" :class="['pd-diff-row', d.kind]">
@@ -123,11 +119,12 @@
123
119
  </div>
124
120
  </template>
125
121
  </div>
126
- </section>
122
+ </AdminSection>
127
123
  </template>
128
124
 
129
125
  <script setup lang="ts">
130
126
  import { computed } from 'vue';
127
+ import AdminSection from '../admin-page/AdminSection.vue';
131
128
  import type { PlanVersionRow } from '@saasicat/types';
132
129
  import { formatMessage } from '../../client/i18n/format.js';
133
130
  import { useSaMessages } from '../../vue/use-super-admin-i18n.js';
@@ -1,13 +1,10 @@
1
1
  <template>
2
- <section class="pd-panel">
3
- <div class="pd-panel-head">
4
- <div style="min-width: 0">
5
- <h3 class="pd-panel-title">{{ msg.versions.title }}</h3>
6
- <div class="pd-panel-sub">
7
- {{ msg.versions.subtitle }}
8
- <code class="pd-code">supersededAt</code>
9
- </div>
10
- </div>
2
+ <AdminSection :title="msg.versions.title" class="pd-panel">
3
+ <template #subtitle>
4
+ {{ msg.versions.subtitle }}
5
+ <code class="pd-code">supersededAt</code>
6
+ </template>
7
+ <template #actions>
11
8
  <div class="pd-panel-head-right">
12
9
  <button
13
10
  v-if="!draftVersion"
@@ -28,7 +25,7 @@
28
25
  <span>{{ newDraftButtonLabel }}</span>
29
26
  </button>
30
27
  </div>
31
- </div>
28
+ </template>
32
29
 
33
30
  <div v-if="chronological.length > 0" class="pd-timeline">
34
31
  <div class="pd-timeline-hint">
@@ -227,11 +224,12 @@
227
224
  </div>
228
225
  </div>
229
226
  </div>
230
- </section>
227
+ </AdminSection>
231
228
  </template>
232
229
 
233
230
  <script setup lang="ts">
234
231
  import { computed } from 'vue';
232
+ import AdminSection from '../admin-page/AdminSection.vue';
235
233
  import type { PlanVersionRow } from '@saasicat/types';
236
234
  import { formatMessage } from '../../client/i18n/format.js';
237
235
  import { useSaMessages } from '../../vue/use-super-admin-i18n.js';