@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,259 +1,239 @@
|
|
|
1
1
|
<template>
|
|
2
2
|
<div class="pr">
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
<
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
{{ msg.review.subtitleTail }}
|
|
11
|
-
</p>
|
|
12
|
-
</div>
|
|
13
|
-
<div class="pr-head-actions">
|
|
3
|
+
<AdminHero :title="msg.review.title">
|
|
4
|
+
<template #subtitle>
|
|
5
|
+
{{ msg.review.subtitleLead }}
|
|
6
|
+
<code class="pr-mono">{{ plan.planKey }}@v{{ version.version }}</code>
|
|
7
|
+
{{ msg.review.subtitleTail }}
|
|
8
|
+
</template>
|
|
9
|
+
<template #actions>
|
|
14
10
|
<button
|
|
15
|
-
class="
|
|
11
|
+
class="sa-btn"
|
|
16
12
|
type="button"
|
|
17
13
|
:disabled="publishing || saving"
|
|
18
14
|
@click="$emit('back')"
|
|
19
15
|
>
|
|
20
|
-
<
|
|
21
|
-
<svg
|
|
22
|
-
width="14"
|
|
23
|
-
height="14"
|
|
24
|
-
viewBox="0 0 24 24"
|
|
25
|
-
fill="none"
|
|
26
|
-
stroke="currentColor"
|
|
27
|
-
stroke-width="2"
|
|
28
|
-
>
|
|
29
|
-
<path d="M5 12h14M13 5l7 7-7 7" />
|
|
30
|
-
</svg>
|
|
31
|
-
</span>
|
|
16
|
+
<q-icon name="arrow_back" size="16px" />
|
|
32
17
|
<span>{{ common.back }}</span>
|
|
33
18
|
</button>
|
|
34
19
|
<button
|
|
35
|
-
class="
|
|
20
|
+
class="sa-btn"
|
|
36
21
|
type="button"
|
|
37
22
|
:disabled="publishing || saving"
|
|
38
23
|
@click="$emit('saveAndExit')"
|
|
39
24
|
>
|
|
40
|
-
{{ saving ? msg.review.saving : msg.review.saveAsDraft }}
|
|
25
|
+
<span>{{ saving ? msg.review.saving : msg.review.saveAsDraft }}</span>
|
|
41
26
|
</button>
|
|
42
27
|
<button
|
|
43
|
-
class="
|
|
28
|
+
class="sa-btn sa-btn--primary"
|
|
44
29
|
type="button"
|
|
45
30
|
:disabled="!canPublish || publishing || saving"
|
|
46
31
|
:title="canPublish ? undefined : msg.review.publishBlocked"
|
|
47
32
|
@click="onPublish"
|
|
48
33
|
>
|
|
49
|
-
<
|
|
50
|
-
width="14"
|
|
51
|
-
height="14"
|
|
52
|
-
viewBox="0 0 24 24"
|
|
53
|
-
fill="none"
|
|
54
|
-
stroke="currentColor"
|
|
55
|
-
stroke-width="2"
|
|
56
|
-
>
|
|
57
|
-
<path d="M13 2L3 14h9l-1 8 10-12h-9l1-8z" />
|
|
58
|
-
</svg>
|
|
34
|
+
<q-icon name="bolt" size="16px" />
|
|
59
35
|
<span>{{ publishing ? msg.review.publishing : publishLabel }}</span>
|
|
60
36
|
</button>
|
|
61
|
-
</
|
|
62
|
-
</
|
|
63
|
-
|
|
64
|
-
<
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
<div class="pr-
|
|
70
|
-
<
|
|
71
|
-
|
|
72
|
-
<div class="pr-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
<div class="pr-row">
|
|
76
|
-
<div class="pr-label">{{ msg.review.labelDisplayName }}</div>
|
|
77
|
-
<div class="pr-val">{{ plan.label }}</div>
|
|
78
|
-
</div>
|
|
79
|
-
<div class="pr-row">
|
|
80
|
-
<div class="pr-label">{{ common.description }}</div>
|
|
81
|
-
<div class="pr-val">
|
|
82
|
-
<template v-if="plan.description">{{ plan.description }}</template>
|
|
83
|
-
<i v-else class="pr-missing">{{ msg.review.missing }}</i>
|
|
37
|
+
</template>
|
|
38
|
+
</AdminHero>
|
|
39
|
+
|
|
40
|
+
<AdminBody>
|
|
41
|
+
<div v-if="publishError" class="pr-banner">{{ publishError }}</div>
|
|
42
|
+
|
|
43
|
+
<div class="pr-grid">
|
|
44
|
+
<!-- Left column -->
|
|
45
|
+
<div class="pr-col">
|
|
46
|
+
<div class="pr-card">
|
|
47
|
+
<h3 class="pr-card-title">{{ msg.review.cardMasterData }}</h3>
|
|
48
|
+
<div class="pr-row">
|
|
49
|
+
<div class="pr-label">{{ msg.review.labelPlanKey }}</div>
|
|
50
|
+
<div class="pr-val pr-mono">{{ plan.planKey }}</div>
|
|
84
51
|
</div>
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
<div class="pr-card">
|
|
89
|
-
<h3 class="pr-card-title">{{ pricingCardTitle }}</h3>
|
|
90
|
-
<div class="pr-row">
|
|
91
|
-
<div class="pr-label">{{ msg.review.labelValidFrom }}</div>
|
|
92
|
-
<div class="pr-val">
|
|
93
|
-
<template v-if="version.validFrom">{{
|
|
94
|
-
version.validFrom.slice(0, 10)
|
|
95
|
-
}}</template>
|
|
96
|
-
<i v-else class="pr-missing">{{
|
|
97
|
-
msg.review.missingRequiredOnPublish
|
|
98
|
-
}}</i>
|
|
99
|
-
</div>
|
|
100
|
-
</div>
|
|
101
|
-
<div class="pr-row">
|
|
102
|
-
<div class="pr-label">{{ msg.review.labelValidUntil }}</div>
|
|
103
|
-
<div class="pr-val">
|
|
104
|
-
<template v-if="version.validUntil">{{
|
|
105
|
-
version.validUntil.slice(0, 10)
|
|
106
|
-
}}</template>
|
|
107
|
-
<span v-else class="pr-inf">{{ msg.review.unlimited }}</span>
|
|
52
|
+
<div class="pr-row">
|
|
53
|
+
<div class="pr-label">{{ msg.review.labelDisplayName }}</div>
|
|
54
|
+
<div class="pr-val">{{ plan.label }}</div>
|
|
108
55
|
</div>
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
}}</template>
|
|
116
|
-
<i v-else class="pr-missing">{{ msg.review.missing }}</i>
|
|
117
|
-
</div>
|
|
118
|
-
</div>
|
|
119
|
-
<div class="pr-row">
|
|
120
|
-
<div class="pr-label">{{ msg.review.labelYearlyPrice }}</div>
|
|
121
|
-
<div class="pr-val">{{ formatMoney(version.yearlyNet) }}</div>
|
|
122
|
-
</div>
|
|
123
|
-
<div class="pr-row">
|
|
124
|
-
<div class="pr-label">{{ msg.review.labelPublicCatalog }}</div>
|
|
125
|
-
<div class="pr-val">
|
|
126
|
-
<span v-if="version.marketed" class="pr-chip pr-chip--live">{{
|
|
127
|
-
msg.review.visibleInCatalog
|
|
128
|
-
}}</span>
|
|
129
|
-
<span v-else class="pr-chip pr-chip--muted">{{
|
|
130
|
-
msg.review.hiddenFromCatalog
|
|
131
|
-
}}</span>
|
|
56
|
+
<div class="pr-row">
|
|
57
|
+
<div class="pr-label">{{ common.description }}</div>
|
|
58
|
+
<div class="pr-val">
|
|
59
|
+
<template v-if="plan.description">{{ plan.description }}</template>
|
|
60
|
+
<i v-else class="pr-missing">{{ msg.review.missing }}</i>
|
|
61
|
+
</div>
|
|
132
62
|
</div>
|
|
133
63
|
</div>
|
|
134
|
-
</div>
|
|
135
64
|
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
<div class="pr-
|
|
141
|
-
{{
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
<
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
<div v-if="quotaList.length === 0" class="pr-comp-empty">
|
|
148
|
-
{{ msg.review.componentEmpty }}
|
|
65
|
+
<div class="pr-card">
|
|
66
|
+
<h3 class="pr-card-title">{{ pricingCardTitle }}</h3>
|
|
67
|
+
<div class="pr-row">
|
|
68
|
+
<div class="pr-label">{{ msg.review.labelValidFrom }}</div>
|
|
69
|
+
<div class="pr-val">
|
|
70
|
+
<template v-if="version.validFrom">{{
|
|
71
|
+
version.validFrom.slice(0, 10)
|
|
72
|
+
}}</template>
|
|
73
|
+
<i v-else class="pr-missing">{{
|
|
74
|
+
msg.review.missingRequiredOnPublish
|
|
75
|
+
}}</i>
|
|
149
76
|
</div>
|
|
150
77
|
</div>
|
|
151
|
-
<div class="pr-
|
|
152
|
-
<div class="pr-
|
|
153
|
-
|
|
78
|
+
<div class="pr-row">
|
|
79
|
+
<div class="pr-label">{{ msg.review.labelValidUntil }}</div>
|
|
80
|
+
<div class="pr-val">
|
|
81
|
+
<template v-if="version.validUntil">{{
|
|
82
|
+
version.validUntil.slice(0, 10)
|
|
83
|
+
}}</template>
|
|
84
|
+
<span v-else class="pr-inf">{{ msg.review.unlimited }}</span>
|
|
154
85
|
</div>
|
|
155
|
-
|
|
156
|
-
|
|
86
|
+
</div>
|
|
87
|
+
<div class="pr-row">
|
|
88
|
+
<div class="pr-label">{{ msg.review.labelMonthlyPrice }}</div>
|
|
89
|
+
<div class="pr-val">
|
|
90
|
+
<template v-if="hasMonthly">{{
|
|
91
|
+
formatMoney(version.monthlyNet)
|
|
92
|
+
}}</template>
|
|
93
|
+
<i v-else class="pr-missing">{{ msg.review.missing }}</i>
|
|
157
94
|
</div>
|
|
158
|
-
|
|
159
|
-
|
|
95
|
+
</div>
|
|
96
|
+
<div class="pr-row">
|
|
97
|
+
<div class="pr-label">{{ msg.review.labelYearlyPrice }}</div>
|
|
98
|
+
<div class="pr-val">{{ formatMoney(version.yearlyNet) }}</div>
|
|
99
|
+
</div>
|
|
100
|
+
<div class="pr-row">
|
|
101
|
+
<div class="pr-label">{{ msg.review.labelPublicCatalog }}</div>
|
|
102
|
+
<div class="pr-val">
|
|
103
|
+
<span v-if="version.marketed" class="pr-chip pr-chip--live">{{
|
|
104
|
+
msg.review.visibleInCatalog
|
|
105
|
+
}}</span>
|
|
106
|
+
<span v-else class="pr-chip pr-chip--muted">{{
|
|
107
|
+
msg.review.hiddenFromCatalog
|
|
108
|
+
}}</span>
|
|
160
109
|
</div>
|
|
161
110
|
</div>
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
111
|
+
</div>
|
|
112
|
+
|
|
113
|
+
<div class="pr-card">
|
|
114
|
+
<h3 class="pr-card-title">{{ componentsCardTitle }}</h3>
|
|
115
|
+
<div class="pr-components">
|
|
116
|
+
<div class="pr-comp-col">
|
|
117
|
+
<div class="pr-comp-head pr-comp-head--quota">
|
|
118
|
+
{{ quotaSectionTitle }}
|
|
119
|
+
</div>
|
|
120
|
+
<div v-for="q in quotaList" :key="q.key" class="pr-comp-item">
|
|
121
|
+
<span>{{ q.label }}</span>
|
|
122
|
+
<b>{{ q.value }}{{ q.unit ? ' ' + q.unit : '' }}</b>
|
|
123
|
+
</div>
|
|
124
|
+
<div v-if="quotaList.length === 0" class="pr-comp-empty">
|
|
125
|
+
{{ msg.review.componentEmpty }}
|
|
126
|
+
</div>
|
|
165
127
|
</div>
|
|
166
|
-
<div
|
|
167
|
-
<
|
|
128
|
+
<div class="pr-comp-col">
|
|
129
|
+
<div class="pr-comp-head pr-comp-head--feature">
|
|
130
|
+
{{ featureSectionTitle }}
|
|
131
|
+
</div>
|
|
132
|
+
<div v-for="f in featureList" :key="f.key" class="pr-comp-item">
|
|
133
|
+
<span>{{ f.label }}</span>
|
|
134
|
+
</div>
|
|
135
|
+
<div v-if="featureList.length === 0" class="pr-comp-empty">
|
|
136
|
+
{{ msg.review.componentEmpty }}
|
|
137
|
+
</div>
|
|
168
138
|
</div>
|
|
169
|
-
<div
|
|
170
|
-
|
|
139
|
+
<div class="pr-comp-col">
|
|
140
|
+
<div class="pr-comp-head pr-comp-head--bundle">
|
|
141
|
+
{{ bundleSectionTitle }}
|
|
142
|
+
</div>
|
|
143
|
+
<div v-for="b in bundleList" :key="b.key" class="pr-comp-item">
|
|
144
|
+
<span>{{ b.label }}</span>
|
|
145
|
+
</div>
|
|
146
|
+
<div v-if="bundleList.length === 0" class="pr-comp-empty">
|
|
147
|
+
{{ msg.review.componentEmpty }}
|
|
148
|
+
</div>
|
|
171
149
|
</div>
|
|
172
150
|
</div>
|
|
173
151
|
</div>
|
|
174
152
|
</div>
|
|
175
|
-
</div>
|
|
176
153
|
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
154
|
+
<!-- Right column -->
|
|
155
|
+
<div class="pr-col">
|
|
156
|
+
<div class="pr-card">
|
|
157
|
+
<h3 class="pr-card-title">
|
|
158
|
+
{{ msg.review.cardChangeNote }} <span class="pr-req">*</span>
|
|
159
|
+
</h3>
|
|
160
|
+
<p class="pr-card-hint">{{ msg.review.changeNoteHint }}</p>
|
|
161
|
+
<div v-if="version.changeNote" class="pr-note">
|
|
162
|
+
{{ version.changeNote }}
|
|
163
|
+
</div>
|
|
164
|
+
<div v-else class="pr-note pr-note--missing">
|
|
165
|
+
{{ msg.review.changeNoteMissing }}
|
|
166
|
+
</div>
|
|
187
167
|
</div>
|
|
188
|
-
</div>
|
|
189
168
|
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
169
|
+
<div class="pr-card">
|
|
170
|
+
<h3 class="pr-card-title">{{ msg.review.cardChecklist }}</h3>
|
|
171
|
+
<div class="pr-checks">
|
|
172
|
+
<div
|
|
173
|
+
v-for="c in checks"
|
|
174
|
+
:key="c.id"
|
|
175
|
+
class="pr-check"
|
|
176
|
+
:class="c.ok ? 'pr-check--ok' : 'pr-check--warn'"
|
|
177
|
+
>
|
|
178
|
+
<span class="pr-check-mark">
|
|
179
|
+
<svg
|
|
180
|
+
v-if="c.ok"
|
|
181
|
+
width="11"
|
|
182
|
+
height="11"
|
|
183
|
+
viewBox="0 0 24 24"
|
|
184
|
+
fill="none"
|
|
185
|
+
stroke="currentColor"
|
|
186
|
+
stroke-width="3.5"
|
|
187
|
+
>
|
|
188
|
+
<path d="M5 13l4 4L19 7" />
|
|
189
|
+
</svg>
|
|
190
|
+
<svg
|
|
191
|
+
v-else
|
|
192
|
+
width="11"
|
|
193
|
+
height="11"
|
|
194
|
+
viewBox="0 0 24 24"
|
|
195
|
+
fill="none"
|
|
196
|
+
stroke="currentColor"
|
|
197
|
+
stroke-width="2.5"
|
|
198
|
+
>
|
|
199
|
+
<path
|
|
200
|
+
d="M10.29 3.86L1.82 18a2 2 0 001.71 3h16.94a2 2 0 001.71-3L13.71 3.86a2 2 0 00-3.42 0zM12 9v4M12 17h.01"
|
|
201
|
+
/>
|
|
202
|
+
</svg>
|
|
203
|
+
</span>
|
|
204
|
+
<span>{{ c.label }}</span>
|
|
205
|
+
</div>
|
|
226
206
|
</div>
|
|
227
207
|
</div>
|
|
228
|
-
</div>
|
|
229
208
|
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
209
|
+
<div v-if="predecessor" class="pr-card pr-card--regress">
|
|
210
|
+
<h3 class="pr-card-title">{{ msg.review.cardRegression }}</h3>
|
|
211
|
+
<p class="pr-card-hint">{{ msg.review.regressionHint }}</p>
|
|
212
|
+
<label class="pr-toggle">
|
|
213
|
+
<input v-model="forceRegressive" type="checkbox" />
|
|
214
|
+
<span>{{ msg.review.forceRegressive }}</span>
|
|
215
|
+
</label>
|
|
216
|
+
</div>
|
|
238
217
|
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
218
|
+
<div class="pr-card">
|
|
219
|
+
<h3 class="pr-card-title">{{ msg.review.cardZeroPrice }}</h3>
|
|
220
|
+
<p class="pr-card-hint">{{ msg.review.zeroPriceHint }}</p>
|
|
221
|
+
<label class="pr-toggle">
|
|
222
|
+
<input v-model="allowZeroPrice" type="checkbox" />
|
|
223
|
+
<span>{{ msg.review.allowZeroPrice }}</span>
|
|
224
|
+
</label>
|
|
225
|
+
</div>
|
|
247
226
|
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
227
|
+
<div class="pr-card pr-card--impact">
|
|
228
|
+
<h3 class="pr-card-title">{{ msg.review.cardTenantImpact }}</h3>
|
|
229
|
+
<div class="pr-impact">
|
|
230
|
+
<div class="pr-impact-num">{{ tenantImpactCount }}</div>
|
|
231
|
+
<div class="pr-impact-text">{{ impactText }}</div>
|
|
232
|
+
</div>
|
|
253
233
|
</div>
|
|
254
234
|
</div>
|
|
255
235
|
</div>
|
|
256
|
-
</
|
|
236
|
+
</AdminBody>
|
|
257
237
|
</div>
|
|
258
238
|
</template>
|
|
259
239
|
|
|
@@ -263,8 +243,12 @@ import type { PlanRow, PlanVersionRow } from '@saasicat/types';
|
|
|
263
243
|
import { formatMessage } from '../../client/i18n/format.js';
|
|
264
244
|
import { formatCurrency } from '../../client/i18n/currency.js';
|
|
265
245
|
import { useSaMessages, useSuperAdminI18n } from '../../vue/use-super-admin-i18n.js';
|
|
246
|
+
// This view replaces the page hero while it is open: its actions hang on the
|
|
247
|
+
// publish checklist and the force flags below, which live here.
|
|
248
|
+
import AdminBody from '../admin-page/AdminBody.vue';
|
|
249
|
+
import AdminHero from '../admin-page/AdminHero.vue';
|
|
266
250
|
|
|
267
|
-
// PlanReview — step 3 of the plan wizard (
|
|
251
|
+
// PlanReview — step 3 of the plan wizard (plan simulation
|
|
268
252
|
// "Review & Publish"). Shows the saved draft read-only, checks the
|
|
269
253
|
// publish checklist and triggers publish. The draft was already persisted
|
|
270
254
|
// in the editor (step 2); review mutates nothing except publish.
|
|
@@ -401,7 +385,7 @@ const hasMonthly = computed(() => {
|
|
|
401
385
|
});
|
|
402
386
|
|
|
403
387
|
// "Gültig ab" must lie strictly after the "Gültig ab" of the predecessor
|
|
404
|
-
// version
|
|
388
|
+
// version — otherwise the publish endpoint rejects.
|
|
405
389
|
const validFromAfterPredecessor = computed(() => {
|
|
406
390
|
const prev = props.predecessor;
|
|
407
391
|
if (!prev?.validFrom || !props.version.validFrom) return true;
|
|
@@ -468,82 +452,14 @@ function onPublish(): void {
|
|
|
468
452
|
|
|
469
453
|
<style scoped>
|
|
470
454
|
.pr {
|
|
471
|
-
padding: 22px 26px;
|
|
472
|
-
background: var(--sa-bg-app);
|
|
473
455
|
min-height: 100%;
|
|
474
456
|
box-sizing: border-box;
|
|
475
|
-
font-family: var(--sa-font-body);
|
|
476
|
-
color: var(--sa-body);
|
|
477
|
-
}
|
|
478
|
-
.pr * {
|
|
479
|
-
box-sizing: border-box;
|
|
480
457
|
}
|
|
481
458
|
.pr-mono {
|
|
482
459
|
font-family: var(--sa-font-mono);
|
|
483
460
|
font-weight: 600;
|
|
484
461
|
}
|
|
485
462
|
|
|
486
|
-
.pr-head {
|
|
487
|
-
display: flex;
|
|
488
|
-
align-items: flex-end;
|
|
489
|
-
gap: 20px;
|
|
490
|
-
margin-bottom: 16px;
|
|
491
|
-
}
|
|
492
|
-
.pr-head-text {
|
|
493
|
-
flex: 1;
|
|
494
|
-
min-width: 0;
|
|
495
|
-
}
|
|
496
|
-
.pr-title {
|
|
497
|
-
font: 700 22px/1.2 var(--sa-font-head);
|
|
498
|
-
letter-spacing: -0.02em;
|
|
499
|
-
color: var(--sa-heading);
|
|
500
|
-
margin: 0;
|
|
501
|
-
}
|
|
502
|
-
.pr-sub {
|
|
503
|
-
font-size: 12.5px;
|
|
504
|
-
color: var(--sa-muted);
|
|
505
|
-
margin: 4px 0 0;
|
|
506
|
-
}
|
|
507
|
-
.pr-head-actions {
|
|
508
|
-
display: flex;
|
|
509
|
-
gap: 8px;
|
|
510
|
-
}
|
|
511
|
-
|
|
512
|
-
.pr-btn {
|
|
513
|
-
display: inline-flex;
|
|
514
|
-
align-items: center;
|
|
515
|
-
gap: 7px;
|
|
516
|
-
padding: 8px 14px;
|
|
517
|
-
border-radius: 7px;
|
|
518
|
-
font: 500 13px var(--sa-font-body);
|
|
519
|
-
cursor: pointer;
|
|
520
|
-
border: 1px solid var(--sa-border);
|
|
521
|
-
background: var(--sa-bg-surface);
|
|
522
|
-
color: var(--sa-heading);
|
|
523
|
-
transition:
|
|
524
|
-
background 0.12s,
|
|
525
|
-
border-color 0.12s;
|
|
526
|
-
}
|
|
527
|
-
.pr-btn:hover:not(:disabled) {
|
|
528
|
-
background: var(--sa-border-soft);
|
|
529
|
-
}
|
|
530
|
-
.pr-btn:disabled {
|
|
531
|
-
cursor: not-allowed;
|
|
532
|
-
opacity: 0.5;
|
|
533
|
-
}
|
|
534
|
-
.pr-btn--primary {
|
|
535
|
-
background: var(--sa-primary);
|
|
536
|
-
border-color: var(--sa-primary);
|
|
537
|
-
color: #fff;
|
|
538
|
-
}
|
|
539
|
-
.pr-btn--primary:hover:not(:disabled) {
|
|
540
|
-
filter: brightness(0.94);
|
|
541
|
-
}
|
|
542
|
-
.pr-ico--back {
|
|
543
|
-
display: inline-flex;
|
|
544
|
-
transform: rotate(180deg);
|
|
545
|
-
}
|
|
546
|
-
|
|
547
463
|
.pr-banner {
|
|
548
464
|
background: var(--sa-warning-soft);
|
|
549
465
|
border: 1px solid var(--sa-amber-border);
|
|
@@ -8,17 +8,14 @@
|
|
|
8
8
|
<div class="pve-preview-toggle">
|
|
9
9
|
<button
|
|
10
10
|
type="button"
|
|
11
|
-
:class="[
|
|
12
|
-
'pve-btn pve-btn--sm',
|
|
13
|
-
{ 'pve-btn--ghost': previewMode !== 'desktop' },
|
|
14
|
-
]"
|
|
11
|
+
:class="['sa-btn sa-btn--sm', { 'sa-btn--ghost': previewMode !== 'desktop' }]"
|
|
15
12
|
@click="$emit('update:previewMode', 'desktop')"
|
|
16
13
|
>
|
|
17
14
|
{{ msg.catalogPreview.desktop }}
|
|
18
15
|
</button>
|
|
19
16
|
<button
|
|
20
17
|
type="button"
|
|
21
|
-
:class="['
|
|
18
|
+
:class="['sa-btn sa-btn--sm', { 'sa-btn--ghost': previewMode !== 'mobile' }]"
|
|
22
19
|
@click="$emit('update:previewMode', 'mobile')"
|
|
23
20
|
>
|
|
24
21
|
{{ msg.catalogPreview.mobile }}
|
|
@@ -147,6 +144,11 @@
|
|
|
147
144
|
<path d="M12 9v4M12 17h.01" />
|
|
148
145
|
</svg>
|
|
149
146
|
</span>
|
|
147
|
+
<!-- Checklist labels come from the i18n catalog, where one
|
|
148
|
+
entry (`checklistTenantImpact`) emphasises the affected
|
|
149
|
+
tenant count with a bold span. Both interpolated values are
|
|
150
|
+
numbers the platform computed, never request data. -->
|
|
151
|
+
<!-- eslint-disable-next-line vue/no-v-html -->
|
|
150
152
|
<span v-html="item.label" />
|
|
151
153
|
</div>
|
|
152
154
|
</div>
|