@saasicat/ui-vue 0.4.0 → 0.6.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +64 -4
- package/dist/chunk-A3W2N26K.js +714 -0
- package/dist/chunk-QZOSDCNP.js +98 -0
- package/dist/chunk-X5SQ5HMB.js +3231 -0
- package/dist/client/index.cjs +3988 -0
- package/dist/client/index.d.cts +321 -0
- package/dist/client/index.d.ts +321 -0
- package/dist/client/index.js +70 -0
- package/dist/index.cjs +4446 -1249
- package/dist/index.d.cts +297 -888
- package/dist/index.d.ts +297 -888
- package/dist/index.js +609 -1348
- package/dist/messages-7b0P8W75.d.cts +1652 -0
- package/dist/messages-7b0P8W75.d.ts +1652 -0
- package/dist/quasar/index.cjs +3340 -0
- package/dist/quasar/index.d.cts +95 -0
- package/dist/quasar/index.d.ts +95 -0
- package/dist/quasar/index.js +96 -0
- package/dist/testing-e2e/admin-pages-suite.cjs +14 -11
- package/dist/testing-e2e/admin-pages-suite.js +14 -11
- package/dist/use-super-admin-i18n-B3v3-SWZ.d.ts +210 -0
- package/dist/use-super-admin-i18n-DMktRVEt.d.cts +210 -0
- package/package.json +23 -3
- package/src/{action-registry.ts → client/action-registry.ts} +4 -4
- package/src/{batch-column-fetcher.ts → client/batch-column-fetcher.ts} +4 -4
- package/src/{boot-loader.ts → client/boot-loader.ts} +3 -3
- package/src/client/i18n/currency.ts +42 -0
- package/src/client/i18n/define.ts +59 -0
- package/src/client/i18n/format.ts +12 -0
- package/src/client/i18n/index.ts +14 -0
- package/src/client/i18n/locale.ts +15 -0
- package/src/client/i18n/messages/audit.ts +42 -0
- package/src/client/i18n/messages/bundles.ts +459 -0
- package/src/client/i18n/messages/common.ts +147 -0
- package/src/client/i18n/messages/dashboard.ts +16 -0
- package/src/client/i18n/messages/discovery.ts +229 -0
- package/src/client/i18n/messages/email.ts +125 -0
- package/src/client/i18n/messages/marketing.ts +270 -0
- package/src/client/i18n/messages/nav.ts +72 -0
- package/src/client/i18n/messages/pilots.ts +192 -0
- package/src/client/i18n/messages/plan-detail.ts +266 -0
- package/src/client/i18n/messages/plan-editor.ts +177 -0
- package/src/client/i18n/messages/plan-versions.ts +251 -0
- package/src/client/i18n/messages/plans.ts +503 -0
- package/src/client/i18n/messages/promos.ts +202 -0
- package/src/client/i18n/messages/shell.ts +145 -0
- package/src/client/i18n/messages/tenants.ts +104 -0
- package/src/client/i18n/messages/users.ts +78 -0
- package/src/client/i18n/messages.ts +84 -0
- package/src/client/index.ts +27 -0
- package/src/{manifest-loader.ts → client/manifest-loader.ts} +4 -4
- package/src/{nav-builder.ts → client/nav-builder.ts} +44 -51
- package/src/{plan-versions-catalog.ts → client/plan-versions-catalog.ts} +42 -30
- package/src/components/BundleVersionPublishDialog.vue +35 -24
- package/src/components/FeatureGate.vue +1 -1
- package/src/components/MarketingPromotionsTab.vue +112 -59
- package/src/components/MfaPromptDialog.vue +11 -11
- package/src/components/TenantActionConfirmDialog.vue +19 -17
- package/src/components/VersionDiffPreview.vue +72 -43
- package/src/components/bundle-editor/BundleCreatePanel.vue +76 -63
- package/src/components/bundle-editor/BundleFeaturesEditor.vue +13 -6
- package/src/components/bundle-editor/BundlePlanCompatPicker.vue +19 -14
- package/src/components/bundle-editor/BundleQuotasEditor.vue +7 -4
- package/src/components/bundle-editor/BundleStatusBanner.vue +36 -19
- package/src/components/bundle-editor/BundleVersionInlineEditor.vue +51 -35
- package/src/components/bundle-editor/BundleVersionStrip.vue +24 -12
- package/src/components/bundle-editor/bundle-version-status.ts +29 -29
- package/src/components/dialogs/PilotCreateDialog.vue +58 -63
- package/src/components/dialogs/PilotEditDialog.vue +40 -34
- package/src/components/dialogs/PromoCodeCreateDialog.vue +89 -63
- package/src/components/dialogs/PromoCodeEditDialog.vue +98 -66
- package/src/components/dialogs/types.ts +3 -13
- package/src/components/plan/PlanCycleToggle.vue +21 -10
- package/src/components/plan/PlanGrid.vue +2 -2
- package/src/components/plan/PriceSummary.vue +1 -1
- package/src/components/plan/PromoCodeInput.vue +1 -1
- package/src/components/plan/PublicBundleGrid.vue +1 -1
- package/src/components/plan-cockpit/PlanCockpit.vue +34 -15
- package/src/components/plan-cockpit/PlanCockpitAuditLog.vue +13 -6
- package/src/components/plan-cockpit/PlanCockpitDiffPanel.vue +18 -9
- package/src/components/plan-cockpit/PlanCockpitHeader.vue +9 -6
- package/src/components/plan-cockpit/PlanCockpitImpactPanel.vue +24 -11
- package/src/components/plan-cockpit/PlanCockpitKpis.vue +28 -17
- package/src/components/plan-cockpit/PlanCockpitVersions.vue +50 -25
- package/src/components/plan-create-dialog/PlanCreateDialog.vue +45 -35
- package/src/components/plan-detail/PlanAuditLog.vue +11 -6
- package/src/components/plan-detail/PlanDetail.vue +21 -23
- package/src/components/plan-detail/PlanDetailHeader.vue +20 -11
- package/src/components/plan-detail/PlanDetailKpis.vue +30 -17
- package/src/components/plan-detail/PlanTerminateDialog.vue +22 -9
- package/src/components/plan-detail/PlanVersionDiffPanel.vue +61 -27
- package/src/components/plan-detail/PlanVersionsPanel.vue +71 -36
- package/src/components/plan-list/PlanList.vue +99 -57
- package/src/components/plan-matrix/PlanMatrix.vue +85 -38
- package/src/components/plan-review/PlanReview.vue +105 -80
- package/src/components/plan-version-editor/PlanCatalogPreview.vue +43 -20
- package/src/components/plan-version-editor/PlanComponentPool.vue +15 -7
- package/src/components/plan-version-editor/PlanVersionBasket.vue +45 -24
- package/src/components/plan-version-editor/PlanVersionDiffDialog.vue +8 -7
- package/src/components/plan-version-editor/PlanVersionEditor.vue +74 -40
- package/src/components/plan-version-editor/PlanVersionEditorHeader.vue +24 -12
- package/src/index.ts +82 -79
- package/src/pages-standard/AdminLayout.vue +43 -18
- package/src/pages-standard/AdminManifestErrorPage.vue +10 -10
- package/src/pages-standard/AuditPage.vue +58 -19
- package/src/pages-standard/BundlesPage.vue +29 -18
- package/src/pages-standard/DashboardPage.vue +31 -17
- package/src/pages-standard/DiscoveryPage.vue +40 -28
- package/src/pages-standard/EmailHistoryPage.vue +98 -69
- package/src/pages-standard/MarketingCatalogPage.vue +40 -21
- package/src/pages-standard/PilotsPage.vue +64 -52
- package/src/pages-standard/PlanVersionsPage.vue +9 -5
- package/src/pages-standard/PlansPage.vue +91 -59
- package/src/pages-standard/PlatformEmailPage.vue +120 -53
- package/src/pages-standard/PromoCodeDetailPage.vue +66 -63
- package/src/pages-standard/PromoCodesPage.vue +51 -54
- package/src/pages-standard/SubscriptionsPage.vue +14 -9
- package/src/pages-standard/SuperAdminLoginPage.vue +19 -16
- package/src/pages-standard/SuperAdminSetupWizard.vue +53 -49
- package/src/pages-standard/TenantDetailPage.vue +54 -40
- package/src/pages-standard/TenantsPage.vue +57 -44
- package/src/pages-standard/UsersPage.vue +70 -52
- package/src/pages-standard/bundles-page/BundleAccordionList.vue +20 -8
- package/src/pages-standard/bundles-page/BundleDetailPanel.vue +28 -18
- package/src/pages-standard/bundles-page/BundlesFilterBar.vue +4 -1
- package/src/pages-standard/bundles-page/BundlesHeader.vue +9 -8
- package/src/pages-standard/bundles-page/BundlesKpis.vue +29 -11
- package/src/pages-standard/discovery-page/CatalogEntryTransPanel.vue +20 -8
- package/src/pages-standard/discovery-page/DiscoveryCapList.vue +5 -3
- package/src/pages-standard/discovery-page/DiscoveryFeatureCard.vue +43 -24
- package/src/pages-standard/discovery-page/DiscoveryHeader.vue +7 -4
- package/src/pages-standard/discovery-page/DiscoveryKpis.vue +28 -15
- package/src/pages-standard/discovery-page/DiscoveryQuotaCard.vue +20 -10
- package/src/pages-standard/discovery-page/DiscoveryStatusControl.vue +9 -6
- package/src/pages-standard/discovery-page/discovery-ui.ts +40 -52
- package/src/pages-standard/marketing-catalog/MarketingCatalogAdmin.vue +81 -49
- package/src/pages-standard/marketing-catalog/MarketingCatalogHeader.vue +13 -10
- package/src/pages-standard/marketing-catalog/MarketingCatalogPreview.vue +24 -20
- package/src/pages-standard/marketing-catalog/MarketingCatalogToolbar.vue +6 -3
- package/src/pages-standard/plan-versions/PlanDiffCard.vue +16 -6
- package/src/pages-standard/plan-versions/PlanVersionHeader.vue +42 -26
- package/src/pages-standard/plan-versions/PlanVersionsAudit.vue +46 -27
- package/src/pages-standard/plan-versions/PlanVersionsDiff.vue +8 -6
- package/src/pages-standard/plan-versions/PlanVersionsList.vue +40 -17
- package/src/pages-standard/plan-versions/PlanVersionsMatrix.vue +1 -1
- package/src/pages-standard/plan-versions/PlanVersionsTimeline.vue +25 -13
- package/src/pages-standard/plan-versions/format.ts +33 -17
- package/src/pages-standard/plans-page/PlanArchiveDialog.vue +12 -8
- package/src/pages-standard/plans-page/PlanBundleOverview.vue +15 -6
- package/src/pages-standard/plans-page/PlanDiscardDraftDialog.vue +18 -7
- package/src/pages-standard/plans-page/PlanPublishDialog.vue +23 -12
- package/src/pages-standard/tenants/format.ts +3 -2
- package/src/pages-tenant/MySubscriptionBundlesPage.vue +73 -38
- package/src/pages-tenant/OnboardingConfigurator.vue +3 -3
- package/src/pages-tenant/PackageSnapshotPanel.vue +1 -1
- package/src/pages-tenant/PlanChangeWizard.vue +10 -6
- package/src/pages-tenant/TenantPlanSection.vue +20 -16
- package/src/pages-tenant/default-i18n.ts +217 -1
- package/src/pages-tenant/tenant-plan-section/BundlePreviewDialog.vue +9 -7
- package/src/pages-tenant/tenant-plan-section/TenantBundleStore.vue +11 -12
- package/src/pages-tenant/tenant-plan-section/TenantFeatureMatrix.vue +4 -1
- package/src/pages-tenant/tenant-plan-section/TenantPlanCardHeader.vue +1 -1
- package/src/pages-tenant/tenant-plan-section/TenantUsageGrid.vue +1 -1
- package/src/quasar/create-super-admin-app.ts +192 -0
- package/src/quasar/index.ts +11 -0
- package/src/quasar/notify.ts +30 -0
- package/src/testing-e2e/admin-pages-suite.ts +14 -11
- package/src/{manifest-store-factory.ts → vue/manifest-store-factory.ts} +1 -1
- package/src/{platform-loaders.ts → vue/platform-loaders.ts} +4 -4
- package/src/{project-page-host.ts → vue/project-page-host.ts} +6 -4
- package/src/{create-super-admin-app.ts → vue/super-admin-context.ts} +20 -139
- package/src/vue/ui-notify.ts +30 -0
- package/src/{use-actions.ts → vue/use-actions.ts} +1 -1
- package/src/{use-api-list.ts → vue/use-api-list.ts} +1 -1
- package/src/{use-audit-entries.ts → vue/use-audit-entries.ts} +3 -3
- package/src/{use-batch-columns.ts → vue/use-batch-columns.ts} +1 -1
- package/src/{use-bulk-publish.ts → vue/use-bulk-publish.ts} +7 -5
- package/src/{use-bundle-versions-map.ts → vue/use-bundle-versions-map.ts} +7 -5
- package/src/{use-bundles.ts → vue/use-bundles.ts} +14 -14
- package/src/{use-catalog-entries.ts → vue/use-catalog-entries.ts} +14 -11
- package/src/{use-discovery.ts → vue/use-discovery.ts} +9 -6
- package/src/{use-entitlement.ts → vue/use-entitlement.ts} +4 -4
- package/src/{use-live-plan-versions.ts → vue/use-live-plan-versions.ts} +5 -5
- package/src/{use-manifest.ts → vue/use-manifest.ts} +1 -1
- package/src/{use-marketing-projections.ts → vue/use-marketing-projections.ts} +10 -7
- package/src/{use-nav.ts → vue/use-nav.ts} +9 -3
- package/src/{use-plan-editor.ts → vue/use-plan-editor.ts} +2 -2
- package/src/{use-plan-versions.ts → vue/use-plan-versions.ts} +3 -3
- package/src/{use-plans.ts → vue/use-plans.ts} +13 -13
- package/src/{use-platform-tenant-actions.ts → vue/use-platform-tenant-actions.ts} +9 -6
- package/src/{use-promotions.ts → vue/use-promotions.ts} +10 -11
- package/src/{use-public-boot.ts → vue/use-public-boot.ts} +1 -1
- package/src/{use-subscription-draft.ts → vue/use-subscription-draft.ts} +2 -3
- package/src/{use-super-admin-context.ts → vue/use-super-admin-context.ts} +5 -5
- package/src/vue/use-super-admin-i18n.ts +82 -0
- package/src/{use-tenant-action-flow.ts → vue/use-tenant-action-flow.ts} +12 -7
- package/src/{use-tenant-billing-catalog.ts → vue/use-tenant-billing-catalog.ts} +2 -2
- package/src/{use-tenant-billing.ts → vue/use-tenant-billing.ts} +2 -2
- package/src/{use-tenant-manifest.ts → vue/use-tenant-manifest.ts} +2 -4
- package/src/{use-tenant-subscription-bundles.ts → vue/use-tenant-subscription-bundles.ts} +5 -5
- package/src/{use-tenants.ts → vue/use-tenants.ts} +3 -3
- package/dist/testing-e2e/admin-pages-suite.d.cts +0 -37
- package/dist/testing-e2e/admin-pages-suite.d.ts +0 -37
- package/src/components/BusinessTypeVersionEditorDialog.vue +0 -417
- package/src/components/BusinessTypeVersionPublishDialog.vue +0 -258
- package/src/pages-standard/BusinessTypesPage.vue +0 -662
- package/src/pages-standard/plan-versions/VersionDiffPreview.vue +0 -167
- package/src/use-business-types.ts +0 -269
- /package/src/{http-json.ts → client/http-json.ts} +0 -0
- /package/src/{types.ts → client/types.ts} +0 -0
- /package/src/{version.ts → client/version.ts} +0 -0
- /package/src/{create-admin-routes.ts → vue/create-admin-routes.ts} +0 -0
- /package/src/{entitlement-provider.ts → vue/entitlement-provider.ts} +0 -0
- /package/src/{feature-router-guard.ts → vue/feature-router-guard.ts} +0 -0
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
// Reactive i18n context for the SuperAdmin shell. `createSuperAdminApp()`
|
|
2
|
+
// provides one instance; pages, components and composables read it via
|
|
3
|
+
// `useSuperAdminI18n()` or the namespace-focused `useSaMessages()`.
|
|
4
|
+
//
|
|
5
|
+
// Design: no vue-i18n dependency. The platform ships complete typed catalogs
|
|
6
|
+
// (`SA_MESSAGES`, German reference + English translation) and consumers switch
|
|
7
|
+
// the locale or override individual strings through the bootstrap option.
|
|
8
|
+
// Without a provider the composables fall back to a shared German instance, so
|
|
9
|
+
// isolated mounts and unit tests need no setup.
|
|
10
|
+
|
|
11
|
+
import { computed, inject, isRef, ref, type ComputedRef, type InjectionKey, type Ref } from 'vue';
|
|
12
|
+
|
|
13
|
+
import {
|
|
14
|
+
DEFAULT_SA_LOCALE,
|
|
15
|
+
SA_INTL_LOCALES,
|
|
16
|
+
resolveMessages,
|
|
17
|
+
type SaLocale,
|
|
18
|
+
type SaMessages,
|
|
19
|
+
type SaMessagesOverrides,
|
|
20
|
+
} from '../client/i18n/index.js';
|
|
21
|
+
|
|
22
|
+
export interface SuperAdminI18n {
|
|
23
|
+
/** Active UI locale — mutable; switching re-renders all catalog texts. */
|
|
24
|
+
locale: Ref<SaLocale>;
|
|
25
|
+
/** Resolved catalog for the active locale (platform + app overrides). */
|
|
26
|
+
messages: ComputedRef<SaMessages>;
|
|
27
|
+
/** BCP-47 tag for `Intl`/`toLocaleString` formatting in the active locale. */
|
|
28
|
+
intlLocale: ComputedRef<string>;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
export interface SuperAdminI18nOptions {
|
|
32
|
+
/**
|
|
33
|
+
* Initial UI locale, default `'de'`. Pass a `Ref` when the app wants to
|
|
34
|
+
* keep control (e.g. a user-profile setting or a header switcher).
|
|
35
|
+
*/
|
|
36
|
+
locale?: SaLocale | Ref<SaLocale>;
|
|
37
|
+
/** Per-locale string overrides layered over the platform catalog. */
|
|
38
|
+
overrides?: Partial<Record<SaLocale, SaMessagesOverrides>>;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
// `Symbol.for` — see super-admin-context.ts: dist- and src-imported module
|
|
42
|
+
// instances must resolve to the same injection key.
|
|
43
|
+
export const SUPER_ADMIN_I18N_KEY: InjectionKey<SuperAdminI18n> = Symbol.for(
|
|
44
|
+
'@saasicat/ui-vue/SUPER_ADMIN_I18N',
|
|
45
|
+
);
|
|
46
|
+
|
|
47
|
+
export function createSuperAdminI18n(options: SuperAdminI18nOptions = {}): SuperAdminI18n {
|
|
48
|
+
const locale = isRef(options.locale)
|
|
49
|
+
? options.locale
|
|
50
|
+
: ref(options.locale ?? DEFAULT_SA_LOCALE);
|
|
51
|
+
const messages = computed(() =>
|
|
52
|
+
resolveMessages(locale.value, options.overrides?.[locale.value]),
|
|
53
|
+
);
|
|
54
|
+
const intlLocale = computed(() => SA_INTL_LOCALES[locale.value]);
|
|
55
|
+
return { locale, messages, intlLocale };
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
let fallbackI18n: SuperAdminI18n | null = null;
|
|
59
|
+
|
|
60
|
+
/**
|
|
61
|
+
* Returns the i18n context provided by `createSuperAdminApp()`. Outside a
|
|
62
|
+
* shell (isolated mounts, tests) a shared German default instance is returned
|
|
63
|
+
* so callers never have to guard for a missing context.
|
|
64
|
+
*/
|
|
65
|
+
export function useSuperAdminI18n(): SuperAdminI18n {
|
|
66
|
+
const injected = inject(SUPER_ADMIN_I18N_KEY, null);
|
|
67
|
+
if (injected) return injected;
|
|
68
|
+
fallbackI18n ??= createSuperAdminI18n();
|
|
69
|
+
return fallbackI18n;
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
/**
|
|
73
|
+
* Focused accessor for one catalog namespace:
|
|
74
|
+
* `const msg = useSaMessages('plans')` → `msg.value.title` /
|
|
75
|
+
* template `msg.title`.
|
|
76
|
+
*/
|
|
77
|
+
export function useSaMessages<K extends keyof SaMessages>(
|
|
78
|
+
namespace: K,
|
|
79
|
+
): ComputedRef<SaMessages[K]> {
|
|
80
|
+
const { messages } = useSuperAdminI18n();
|
|
81
|
+
return computed(() => messages.value[namespace]);
|
|
82
|
+
}
|
|
@@ -13,8 +13,10 @@
|
|
|
13
13
|
|
|
14
14
|
import { computed, type ComputedRef, type Ref } from 'vue';
|
|
15
15
|
import type { AdminManifest, TenantActionDef, TenantDto } from '@saasicat/types';
|
|
16
|
-
import { ActionRegistry } from '
|
|
16
|
+
import { ActionRegistry } from '../client/action-registry.js';
|
|
17
|
+
import { formatMessage } from '../client/i18n/format.js';
|
|
17
18
|
import { useSuperAdminActions } from './use-super-admin-context.js';
|
|
19
|
+
import { useSaMessages } from './use-super-admin-i18n.js';
|
|
18
20
|
|
|
19
21
|
/**
|
|
20
22
|
* Input the app-side handler receives. `mfaCode` is populated when
|
|
@@ -125,6 +127,7 @@ export function useTenantActionFlow<TRow extends TenantDto = TenantDto>(
|
|
|
125
127
|
providers: TenantActionFlowProviders<TRow> = {},
|
|
126
128
|
): UseTenantActionFlowResult<TRow> {
|
|
127
129
|
const handlers = useSuperAdminActions();
|
|
130
|
+
const msg = useSaMessages('tenants');
|
|
128
131
|
const registry = computed<ActionRegistry | null>(() => {
|
|
129
132
|
if (!manifest.value) return null;
|
|
130
133
|
return new ActionRegistry(manifest.value, handlers);
|
|
@@ -151,7 +154,8 @@ export function useTenantActionFlow<TRow extends TenantDto = TenantDto>(
|
|
|
151
154
|
.filter((def) => !providers.visibleForRow || providers.visibleForRow(def, row))
|
|
152
155
|
.map((def) => ({
|
|
153
156
|
def,
|
|
154
|
-
invoke: (r: TRow) =>
|
|
157
|
+
invoke: (r: TRow) =>
|
|
158
|
+
runFlow(def, r ?? row, reg, providers, msg.value.actions.successNotify),
|
|
155
159
|
}));
|
|
156
160
|
}
|
|
157
161
|
|
|
@@ -184,6 +188,7 @@ async function runFlow<TRow extends TenantDto>(
|
|
|
184
188
|
row: TRow,
|
|
185
189
|
registry: ActionRegistry,
|
|
186
190
|
providers: TenantActionFlowProviders<TRow>,
|
|
191
|
+
successTemplate: string,
|
|
187
192
|
): Promise<unknown> {
|
|
188
193
|
let reason: string | null = null;
|
|
189
194
|
let extras: Record<string, unknown> = {};
|
|
@@ -191,8 +196,8 @@ async function runFlow<TRow extends TenantDto>(
|
|
|
191
196
|
if (def.confirmType && def.confirmType !== 'none') {
|
|
192
197
|
if (!providers.confirm) {
|
|
193
198
|
throw new Error(
|
|
194
|
-
`useTenantActionFlow:
|
|
195
|
-
`
|
|
199
|
+
`useTenantActionFlow: action "${def.id}" requires confirmType="${def.confirmType}", ` +
|
|
200
|
+
`but no \`confirm\` provider was supplied.`,
|
|
196
201
|
);
|
|
197
202
|
}
|
|
198
203
|
const c = await providers.confirm(def, { row });
|
|
@@ -205,8 +210,8 @@ async function runFlow<TRow extends TenantDto>(
|
|
|
205
210
|
if (def.requiresMfa) {
|
|
206
211
|
if (!providers.mfa) {
|
|
207
212
|
throw new Error(
|
|
208
|
-
`useTenantActionFlow:
|
|
209
|
-
`\`mfa
|
|
213
|
+
`useTenantActionFlow: action "${def.id}" requires MFA, but no ` +
|
|
214
|
+
`\`mfa\` provider was supplied.`,
|
|
210
215
|
);
|
|
211
216
|
}
|
|
212
217
|
mfaCode = await providers.mfa(def, { row });
|
|
@@ -225,7 +230,7 @@ async function runFlow<TRow extends TenantDto>(
|
|
|
225
230
|
try {
|
|
226
231
|
const input: TenantActionInput<TRow> = { row, mfaCode, reason, extras };
|
|
227
232
|
const result = await resolved.handler(input);
|
|
228
|
-
providers.notify?.('positive',
|
|
233
|
+
providers.notify?.('positive', formatMessage(successTemplate, { action: def.label }));
|
|
229
234
|
providers.onSuccess?.(def, { row });
|
|
230
235
|
return result;
|
|
231
236
|
} catch (err) {
|
|
@@ -8,8 +8,8 @@
|
|
|
8
8
|
|
|
9
9
|
import { ref, type Ref } from 'vue';
|
|
10
10
|
import type { FeatureUiRegistry } from '@saasicat/types';
|
|
11
|
-
import { defaultHttpClient, type HttpClient } from '
|
|
12
|
-
import { trimTrailingSlashes } from '
|
|
11
|
+
import { defaultHttpClient, type HttpClient } from '../client/types.js';
|
|
12
|
+
import { trimTrailingSlashes } from '../client/http-json.js';
|
|
13
13
|
|
|
14
14
|
export interface CatalogPlan {
|
|
15
15
|
id: string;
|
|
@@ -11,8 +11,8 @@
|
|
|
11
11
|
// has `/api` as its baseURL — the result would be `/api/api/billing/...` (404).
|
|
12
12
|
|
|
13
13
|
import { ref, type Ref } from 'vue';
|
|
14
|
-
import { defaultHttpClient, type HttpClient } from '
|
|
15
|
-
import { trimTrailingSlashes } from '
|
|
14
|
+
import { defaultHttpClient, type HttpClient } from '../client/types.js';
|
|
15
|
+
import { trimTrailingSlashes } from '../client/http-json.js';
|
|
16
16
|
|
|
17
17
|
export type BillingCycleStr = 'MONTHLY' | 'YEARLY';
|
|
18
18
|
|
|
@@ -8,7 +8,7 @@
|
|
|
8
8
|
// Spec: handoff/superadmin/QUICKSTART_SIMPLIFICATIONS.md §P14.
|
|
9
9
|
|
|
10
10
|
import { ref, type Ref } from 'vue';
|
|
11
|
-
import { defaultHttpClient, type HttpClient } from '
|
|
11
|
+
import { defaultHttpClient, type HttpClient } from '../client/types.js';
|
|
12
12
|
|
|
13
13
|
export interface TenantManifestNavItem {
|
|
14
14
|
id: string;
|
|
@@ -48,9 +48,7 @@ export interface UseTenantManifestResult {
|
|
|
48
48
|
|
|
49
49
|
export function useTenantManifest(options: UseTenantManifestOptions): UseTenantManifestResult {
|
|
50
50
|
if (!options?.endpoint) {
|
|
51
|
-
throw new Error(
|
|
52
|
-
'useTenantManifest: `endpoint` ist Pflicht (z. B. "/api/tenant/manifest").',
|
|
53
|
-
);
|
|
51
|
+
throw new Error('useTenantManifest: `endpoint` is required (e.g. "/api/tenant/manifest").');
|
|
54
52
|
}
|
|
55
53
|
const http = options.http ?? defaultHttpClient();
|
|
56
54
|
const manifest = ref<TenantManifestShape | null>(null);
|
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
|
|
6
6
|
import { ref, type Ref } from 'vue';
|
|
7
7
|
import type { SubscriptionBundleRecord } from '@saasicat/types';
|
|
8
|
-
import { defaultHttpClient, type HttpClient } from '
|
|
8
|
+
import { defaultHttpClient, type HttpClient } from '../client/types.js';
|
|
9
9
|
|
|
10
10
|
export interface UseTenantSubscriptionBundlesOptions {
|
|
11
11
|
/** App-global API prefix incl. `/billing` (e.g. `/api/v1`). */
|
|
@@ -48,7 +48,7 @@ export function useTenantSubscriptionBundles(
|
|
|
48
48
|
): UseTenantSubscriptionBundlesResult {
|
|
49
49
|
if (!options?.billingEndpoint) {
|
|
50
50
|
throw new Error(
|
|
51
|
-
'useTenantSubscriptionBundles: `billingEndpoint`
|
|
51
|
+
'useTenantSubscriptionBundles: `billingEndpoint` is required (e.g. "/api/v1").',
|
|
52
52
|
);
|
|
53
53
|
}
|
|
54
54
|
const http = options.http ?? defaultHttpClient();
|
|
@@ -75,7 +75,7 @@ export function useTenantSubscriptionBundles(
|
|
|
75
75
|
throw new TenantSubscriptionBundlesApiError(
|
|
76
76
|
res.status,
|
|
77
77
|
body,
|
|
78
|
-
`SubscriptionBundle
|
|
78
|
+
`SubscriptionBundle API responded with HTTP ${res.status}`,
|
|
79
79
|
);
|
|
80
80
|
}
|
|
81
81
|
return body as T;
|
|
@@ -103,7 +103,7 @@ export function useTenantSubscriptionBundles(
|
|
|
103
103
|
body: JSON.stringify(data),
|
|
104
104
|
});
|
|
105
105
|
if (!result) {
|
|
106
|
-
throw new TenantSubscriptionBundlesApiError(0, null, 'add
|
|
106
|
+
throw new TenantSubscriptionBundlesApiError(0, null, 'add returned no body');
|
|
107
107
|
}
|
|
108
108
|
const hydrated = rehydrateDates(result);
|
|
109
109
|
bundles.value = [hydrated, ...bundles.value];
|
|
@@ -119,7 +119,7 @@ export function useTenantSubscriptionBundles(
|
|
|
119
119
|
{ method: 'DELETE', body: JSON.stringify(opts) },
|
|
120
120
|
);
|
|
121
121
|
if (!result) {
|
|
122
|
-
throw new TenantSubscriptionBundlesApiError(0, null, 'cancel
|
|
122
|
+
throw new TenantSubscriptionBundlesApiError(0, null, 'cancel returned no body');
|
|
123
123
|
}
|
|
124
124
|
const hydrated = rehydrateDates(result);
|
|
125
125
|
bundles.value = bundles.value.map((b) => (b.id === subscriptionBundleId ? hydrated : b));
|
|
@@ -44,9 +44,9 @@ export function useTenants<T extends TenantDto = TenantDto>(
|
|
|
44
44
|
): UseTenantsResult<T> {
|
|
45
45
|
if (!options?.endpoint) {
|
|
46
46
|
throw new Error(
|
|
47
|
-
'useTenants: `endpoint`
|
|
48
|
-
'"/api/admin/tenants").
|
|
49
|
-
'
|
|
47
|
+
'useTenants: `endpoint` is required (e.g. "/api/v1/admin/tenants" or ' +
|
|
48
|
+
'"/api/admin/tenants"). The platform has no default because apps ' +
|
|
49
|
+
'use different globalPrefix conventions.',
|
|
50
50
|
);
|
|
51
51
|
}
|
|
52
52
|
const filter = options.filter ?? ref<TenantListFilter>({});
|
|
@@ -1,37 +0,0 @@
|
|
|
1
|
-
import { test, expect } from '@playwright/test';
|
|
2
|
-
|
|
3
|
-
interface AdminPagesSuiteConfig {
|
|
4
|
-
/** Display name, e.g. 'demoapp' / 'clubapp'. */
|
|
5
|
-
appName: string;
|
|
6
|
-
/** URL of the login page (full). */
|
|
7
|
-
loginUrl: string;
|
|
8
|
-
/** Test account. */
|
|
9
|
-
email: string;
|
|
10
|
-
password: string;
|
|
11
|
-
/** Paths the smoke test should click through. */
|
|
12
|
-
pages: ReadonlyArray<{
|
|
13
|
-
/** Display name in the test description. */
|
|
14
|
-
name: string;
|
|
15
|
-
/** Path relative to the origin (e.g. '/admin/tenants'). */
|
|
16
|
-
path: string;
|
|
17
|
-
/** Optional: if set, check that this selector exists. */
|
|
18
|
-
expectVisible?: string;
|
|
19
|
-
/** Optional: HTTP patterns that are OK as 4xx/5xx (e.g. missing backend endpoints). */
|
|
20
|
-
allowedFailures?: readonly RegExp[];
|
|
21
|
-
}>;
|
|
22
|
-
/** Expected KPI card labels on the dashboard page. */
|
|
23
|
-
expectedKpiLabels: readonly string[];
|
|
24
|
-
/** Expected distribution section titles. */
|
|
25
|
-
expectedDistributionTitles?: readonly string[];
|
|
26
|
-
/** Expected shortcut titles on the dashboard. */
|
|
27
|
-
expectedShortcutTitles: readonly string[];
|
|
28
|
-
/** Shortcuts that must NOT appear (e.g. "Dashboard"). */
|
|
29
|
-
forbiddenShortcutTitles?: readonly string[];
|
|
30
|
-
/** Console error patterns that should be ignored. */
|
|
31
|
-
consoleErrorAllowlist?: readonly RegExp[];
|
|
32
|
-
/** Path to the dashboard page (default `/admin/`). */
|
|
33
|
-
dashboardPath?: string;
|
|
34
|
-
}
|
|
35
|
-
declare function runAdminPagesSuite(test: typeof test, expect: typeof expect, config: AdminPagesSuiteConfig): void;
|
|
36
|
-
|
|
37
|
-
export { type AdminPagesSuiteConfig, runAdminPagesSuite };
|
|
@@ -1,37 +0,0 @@
|
|
|
1
|
-
import { test, expect } from '@playwright/test';
|
|
2
|
-
|
|
3
|
-
interface AdminPagesSuiteConfig {
|
|
4
|
-
/** Display name, e.g. 'demoapp' / 'clubapp'. */
|
|
5
|
-
appName: string;
|
|
6
|
-
/** URL of the login page (full). */
|
|
7
|
-
loginUrl: string;
|
|
8
|
-
/** Test account. */
|
|
9
|
-
email: string;
|
|
10
|
-
password: string;
|
|
11
|
-
/** Paths the smoke test should click through. */
|
|
12
|
-
pages: ReadonlyArray<{
|
|
13
|
-
/** Display name in the test description. */
|
|
14
|
-
name: string;
|
|
15
|
-
/** Path relative to the origin (e.g. '/admin/tenants'). */
|
|
16
|
-
path: string;
|
|
17
|
-
/** Optional: if set, check that this selector exists. */
|
|
18
|
-
expectVisible?: string;
|
|
19
|
-
/** Optional: HTTP patterns that are OK as 4xx/5xx (e.g. missing backend endpoints). */
|
|
20
|
-
allowedFailures?: readonly RegExp[];
|
|
21
|
-
}>;
|
|
22
|
-
/** Expected KPI card labels on the dashboard page. */
|
|
23
|
-
expectedKpiLabels: readonly string[];
|
|
24
|
-
/** Expected distribution section titles. */
|
|
25
|
-
expectedDistributionTitles?: readonly string[];
|
|
26
|
-
/** Expected shortcut titles on the dashboard. */
|
|
27
|
-
expectedShortcutTitles: readonly string[];
|
|
28
|
-
/** Shortcuts that must NOT appear (e.g. "Dashboard"). */
|
|
29
|
-
forbiddenShortcutTitles?: readonly string[];
|
|
30
|
-
/** Console error patterns that should be ignored. */
|
|
31
|
-
consoleErrorAllowlist?: readonly RegExp[];
|
|
32
|
-
/** Path to the dashboard page (default `/admin/`). */
|
|
33
|
-
dashboardPath?: string;
|
|
34
|
-
}
|
|
35
|
-
declare function runAdminPagesSuite(test: typeof test, expect: typeof expect, config: AdminPagesSuiteConfig): void;
|
|
36
|
-
|
|
37
|
-
export { type AdminPagesSuiteConfig, runAdminPagesSuite };
|