@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
|
@@ -1,6 +1,10 @@
|
|
|
1
1
|
// Default i18n map for the tenant plan section. Consumers override individual
|
|
2
2
|
// keys via the `i18n` prop or pass their own map through (build a vue-i18n
|
|
3
|
-
// resolver on top of this shape).
|
|
3
|
+
// resolver on top of this shape). The map that a component falls back to is
|
|
4
|
+
// picked from the active SuperAdmin locale via
|
|
5
|
+
// `defaultTenantPlanSectionI18n()`.
|
|
6
|
+
|
|
7
|
+
import type { SaLocale } from '../client/i18n/locale.js';
|
|
4
8
|
|
|
5
9
|
export interface TenantPlanSectionI18n {
|
|
6
10
|
sectionTitle: string;
|
|
@@ -139,6 +143,29 @@ export interface TenantPlanSectionI18n {
|
|
|
139
143
|
packageSnapshotNone: string;
|
|
140
144
|
packageSnapshotShowRaw: string;
|
|
141
145
|
packageSnapshotHideRaw: string;
|
|
146
|
+
/** Inline error prefix (`Fehler: …`). */
|
|
147
|
+
errorLabel: string;
|
|
148
|
+
/** Tenant self-service page "Meine Bundles" (MySubscriptionBundlesPage). */
|
|
149
|
+
myBundlesTitle: string;
|
|
150
|
+
myBundlesSubtitle: string;
|
|
151
|
+
myBundlesEmptyPrefix: string;
|
|
152
|
+
myBundlesEmptySuffix: string;
|
|
153
|
+
myBundlesBookedSince: string;
|
|
154
|
+
myBundlesCanceledAt: string;
|
|
155
|
+
myBundlesRunsUntil: string;
|
|
156
|
+
myBundlesCancelInProgress: string;
|
|
157
|
+
myBundlesBookInProgress: string;
|
|
158
|
+
myBundlesCancelConfirm: string;
|
|
159
|
+
myBundlesStatusCanceledPending: string;
|
|
160
|
+
myBundlesStatusEnded: string;
|
|
161
|
+
myBundlesAddBundleLabel: string;
|
|
162
|
+
myBundlesAddSelectPlaceholder: string;
|
|
163
|
+
myBundlesPricePerMonthShort: string;
|
|
164
|
+
myBundlesHiddenIncompatible: string;
|
|
165
|
+
myBundlesBundleVersionIdLabel: string;
|
|
166
|
+
myBundlesBundleVersionIdPlaceholder: string;
|
|
167
|
+
myBundlesMinimumTermLabel: string;
|
|
168
|
+
myBundlesMinimumTermPlaceholder: string;
|
|
142
169
|
}
|
|
143
170
|
|
|
144
171
|
/** German default strings — apps can override them selectively. */
|
|
@@ -277,4 +304,193 @@ export const DEFAULT_I18N_DE: TenantPlanSectionI18n = {
|
|
|
277
304
|
packageSnapshotNone: 'Diese Subscription wurde nicht über ein Webseiten-Angebot abgeschlossen.',
|
|
278
305
|
packageSnapshotShowRaw: 'Rohdaten anzeigen',
|
|
279
306
|
packageSnapshotHideRaw: 'Rohdaten ausblenden',
|
|
307
|
+
errorLabel: 'Fehler',
|
|
308
|
+
myBundlesTitle: 'Meine Bundles',
|
|
309
|
+
myBundlesSubtitle:
|
|
310
|
+
'Eigenständig gebuchte Add-On-Pakete zu deinem Plan. Mindestlaufzeit + Kündigungs- Termin pro Bundle.',
|
|
311
|
+
myBundlesEmptyPrefix: 'Du hast noch kein Bundle gebucht. Über',
|
|
312
|
+
myBundlesEmptySuffix: 'kannst du dein Paket um zusätzliche Features & Quotas erweitern.',
|
|
313
|
+
myBundlesBookedSince: 'Gebucht seit',
|
|
314
|
+
myBundlesCanceledAt: 'Gekündigt am',
|
|
315
|
+
myBundlesRunsUntil: 'läuft bis',
|
|
316
|
+
myBundlesCancelInProgress: 'Kündige …',
|
|
317
|
+
myBundlesBookInProgress: 'Buche …',
|
|
318
|
+
myBundlesCancelConfirm:
|
|
319
|
+
'Bundle wirklich kündigen? Die Kündigung wird zum nächstmöglichen Termin wirksam.',
|
|
320
|
+
myBundlesStatusCanceledPending: 'Kündigung wirksam ab …',
|
|
321
|
+
myBundlesStatusEnded: 'Beendet',
|
|
322
|
+
myBundlesAddBundleLabel: 'Bundle',
|
|
323
|
+
myBundlesAddSelectPlaceholder: '— bitte wählen —',
|
|
324
|
+
myBundlesPricePerMonthShort: '€ / Mo',
|
|
325
|
+
myBundlesHiddenIncompatible: 'weitere Bundle(s) ausgeblendet — nicht kompatibel mit Plan',
|
|
326
|
+
myBundlesBundleVersionIdLabel: 'BundleVersion-ID',
|
|
327
|
+
myBundlesBundleVersionIdPlaceholder: 'UUID der gewünschten Bundle-Version',
|
|
328
|
+
myBundlesMinimumTermLabel: 'Mindestlaufzeit (Monate, optional)',
|
|
329
|
+
myBundlesMinimumTermPlaceholder: 'Default: 12',
|
|
280
330
|
};
|
|
331
|
+
|
|
332
|
+
/** English default strings — mirror of {@link DEFAULT_I18N_DE}. */
|
|
333
|
+
export const DEFAULT_I18N_EN: TenantPlanSectionI18n = {
|
|
334
|
+
sectionTitle: 'Plan & usage',
|
|
335
|
+
sectionSubtitle: 'Current plan, usage and bundles.',
|
|
336
|
+
loading: 'Loading …',
|
|
337
|
+
noSubscription: 'No subscription found for this tenant.',
|
|
338
|
+
activePlan: 'Current plan',
|
|
339
|
+
cycleMonthly: 'Monthly',
|
|
340
|
+
cycleYearly: 'Yearly',
|
|
341
|
+
statusActive: 'Active',
|
|
342
|
+
statusTrial: 'Trial',
|
|
343
|
+
statusPastDue: 'Payment overdue',
|
|
344
|
+
statusCanceled: 'Canceled',
|
|
345
|
+
statusPendingSales: 'Sales review',
|
|
346
|
+
trialEndsAt: 'Trial ends on',
|
|
347
|
+
pilotEndsAt: 'Pilot ends on',
|
|
348
|
+
nextBillingDate: 'Next billing date',
|
|
349
|
+
pendingChange: 'Pending plan change',
|
|
350
|
+
changeFromTo: 'Change to',
|
|
351
|
+
changeEffectiveAt: 'effective as of',
|
|
352
|
+
changePlanButton: 'Change plan',
|
|
353
|
+
cancelSubscriptionButton: 'Cancel subscription',
|
|
354
|
+
usageTitle: 'Usage',
|
|
355
|
+
featuresOverviewTitle: 'Features',
|
|
356
|
+
featuresActive: 'Included',
|
|
357
|
+
featuresLocked: 'Not included',
|
|
358
|
+
bundlesStoreTitle: 'Bundles',
|
|
359
|
+
bundlesBookedTitle: 'Booked bundles',
|
|
360
|
+
bundlesAvailableTitle: 'Available bundles',
|
|
361
|
+
bundlesAvailableEmpty: 'There are currently no additional bundles available.',
|
|
362
|
+
bundlesPerMonth: 'net/month',
|
|
363
|
+
bundleBookAction: 'Book bundle',
|
|
364
|
+
bundleBookInProgress: 'Booking …',
|
|
365
|
+
bundleCancelAction: 'Cancel',
|
|
366
|
+
bundleReactivateAction: 'Reactivate',
|
|
367
|
+
bundleReactivateConfirmTitle: 'Reactivate bundle',
|
|
368
|
+
bundleReactivateConfirmBody:
|
|
369
|
+
'The cancellation will be reverted. The bundle stays booked, continues to run normally and will be billed again.',
|
|
370
|
+
bundleCanceledAt: 'Canceled effective',
|
|
371
|
+
bundleMinimumTermUntil: 'Minimum term until',
|
|
372
|
+
bundleIncludesLabel: 'Includes',
|
|
373
|
+
bundleAlreadyBooked: 'Already booked',
|
|
374
|
+
bundleIncompatible: 'Not compatible with the current plan',
|
|
375
|
+
bundleMissingRequires: 'Requires',
|
|
376
|
+
bundlePreviewAddTitle: 'Book bundle',
|
|
377
|
+
bundlePreviewCancelTitle: 'Cancel bundle',
|
|
378
|
+
bundlePreviewLoading: 'Calculating preview …',
|
|
379
|
+
bundlePreviewProrationTitle: 'Prorated billing',
|
|
380
|
+
bundlePreviewProratedNow: 'Prorated amount due today',
|
|
381
|
+
bundlePreviewProrationDays: 'days',
|
|
382
|
+
bundlePreviewNextPeriod: 'Regular price from the next period',
|
|
383
|
+
bundlePreviewTrialNote:
|
|
384
|
+
'Nothing is charged during the trial — billing starts with the first paid period.',
|
|
385
|
+
bundlePreviewNoPrice: 'No list price is configured for the current billing cycle.',
|
|
386
|
+
bundlePreviewMinimumTermLabel: 'Minimum term',
|
|
387
|
+
bundlePreviewMinimumTermMonths: 'months, until',
|
|
388
|
+
bundlePreviewMinimumTermNone: 'No minimum term',
|
|
389
|
+
bundlePreviewRedundantTitle: 'Features already included (would be paid for twice)',
|
|
390
|
+
bundlePreviewRedundantCoveredByPlan: 'already in the plan',
|
|
391
|
+
bundlePreviewRedundantCoveredByBundle: 'already in bundle',
|
|
392
|
+
bundlePreviewMissingRequiresTitle: 'Missing prerequisites',
|
|
393
|
+
bundlePreviewBlockersTitle: 'Booking not possible',
|
|
394
|
+
bundlePreviewWarningsTitle: 'Notes',
|
|
395
|
+
bundlePreviewEffectiveAt: 'Cancellation effective as of',
|
|
396
|
+
bundlePreviewSavings: 'Savings per period once effective',
|
|
397
|
+
bundlePreviewConfirmAdd: 'Book (chargeable)',
|
|
398
|
+
bundlePreviewConfirmCancel: 'Confirm cancellation',
|
|
399
|
+
bundlePreviewInProgress: 'Processing …',
|
|
400
|
+
bundlePreviewClose: 'Cancel',
|
|
401
|
+
pendingVersionTitle: 'Upcoming plan change',
|
|
402
|
+
pendingVersionChipNonRegressive: 'Improvement',
|
|
403
|
+
pendingVersionChipRegressive: 'Confirmation required',
|
|
404
|
+
pendingVersionEffectiveAt: 'Effective as of',
|
|
405
|
+
pendingVersionAcceptAction: 'Accept changes',
|
|
406
|
+
pendingVersionAcceptInProgress: 'Accepting …',
|
|
407
|
+
pendingVersionAcceptedAt: 'Accepted on',
|
|
408
|
+
wizardTitle: 'Change plan',
|
|
409
|
+
wizardClose: 'Close',
|
|
410
|
+
wizardCurrent: 'Current',
|
|
411
|
+
wizardBadgeCurrent: 'active',
|
|
412
|
+
wizardBadgePopular: 'popular',
|
|
413
|
+
wizardPriceUnitMonthly: 'net/month',
|
|
414
|
+
wizardPriceUnitYearly: 'net/year',
|
|
415
|
+
wizardPriceOnRequest: 'on request',
|
|
416
|
+
wizardStepChoose: 'Choose plan',
|
|
417
|
+
wizardStepChooseIntro:
|
|
418
|
+
'Choose your target plan and the billing cycle. In the next step we show the usage check and the feature diff.',
|
|
419
|
+
wizardStepPreview: 'Preview',
|
|
420
|
+
wizardStepConfirm: 'Confirm',
|
|
421
|
+
wizardNext: 'Next',
|
|
422
|
+
wizardBack: 'Back',
|
|
423
|
+
wizardPreviewLoading: 'Calculating preview …',
|
|
424
|
+
wizardEffectiveAtLabel: 'Effective as of',
|
|
425
|
+
wizardEffectiveImmediate: 'Effective immediately',
|
|
426
|
+
wizardProrationTitle: 'Prorated billing',
|
|
427
|
+
wizardProrationLine: 'Additional amount until the end of the period:',
|
|
428
|
+
wizardProrationDays: 'days',
|
|
429
|
+
wizardLimitsTitle: 'Limit comparison',
|
|
430
|
+
wizardLimitsUsed: 'Usage',
|
|
431
|
+
wizardLimitsCurrent: 'Current',
|
|
432
|
+
wizardLimitsTarget: 'Target',
|
|
433
|
+
wizardFeaturesGained: 'Newly unlocked',
|
|
434
|
+
wizardFeaturesLost: 'Features you lose',
|
|
435
|
+
wizardBlockersTitle: 'Blockers',
|
|
436
|
+
wizardConfirmImmediate: 'The change takes effect immediately.',
|
|
437
|
+
wizardConfirmScheduled: 'The change takes effect on',
|
|
438
|
+
wizardConfirmAction: 'Confirm change',
|
|
439
|
+
wizardConfirmInProgress: 'Changing …',
|
|
440
|
+
wizardConfirmPriceTitle: 'Price overview',
|
|
441
|
+
wizardConfirmProratedNow: 'Prorated amount due today',
|
|
442
|
+
wizardConfirmRecurringNext: 'Regular price from the next period',
|
|
443
|
+
wizardConfirmRecurringFrom: 'Regular price due from',
|
|
444
|
+
wizardConfirmPerCycleMonthly: 'per month',
|
|
445
|
+
wizardConfirmPerCycleYearly: 'per year',
|
|
446
|
+
wizardConfirmTrialNote: 'Nothing is charged during the trial.',
|
|
447
|
+
wizardConfirmRecurringTrialEnd: 'Regular price from the end of the trial',
|
|
448
|
+
wizardChangeTypeUpgrade: 'Upgrade',
|
|
449
|
+
wizardChangeTypeDowngrade: 'Downgrade',
|
|
450
|
+
wizardChangeTypeCycle: 'Cycle change',
|
|
451
|
+
wizardChangeTypeNoop: 'No change',
|
|
452
|
+
packageSnapshotTitle: 'Booked plan (snapshot)',
|
|
453
|
+
packageSnapshotSubtitle:
|
|
454
|
+
'Read-only copy of the plan as it was marketed at the time of purchase.',
|
|
455
|
+
packageSnapshotCapturedAt: 'Captured on',
|
|
456
|
+
packageSnapshotOfferRef: 'Offer reference',
|
|
457
|
+
packageSnapshotPlanLabel: 'Plan',
|
|
458
|
+
packageSnapshotPlanVersionLabel: 'Plan version',
|
|
459
|
+
packageSnapshotCycleLabel: 'Billing cycle',
|
|
460
|
+
packageSnapshotBundlesLabel: 'Included bundles',
|
|
461
|
+
packageSnapshotBundlesEmpty: 'No bundles in the plan.',
|
|
462
|
+
packageSnapshotPriceMonthly: 'Monthly price',
|
|
463
|
+
packageSnapshotPriceYearly: 'Yearly price',
|
|
464
|
+
packageSnapshotPriceTotal: 'Total price',
|
|
465
|
+
packageSnapshotNone: 'This subscription was not created through a website offer.',
|
|
466
|
+
packageSnapshotShowRaw: 'Show raw data',
|
|
467
|
+
packageSnapshotHideRaw: 'Hide raw data',
|
|
468
|
+
errorLabel: 'Error',
|
|
469
|
+
myBundlesTitle: 'My bundles',
|
|
470
|
+
myBundlesSubtitle:
|
|
471
|
+
'Add-on packages booked independently on top of your plan. Minimum term + cancellation date per bundle.',
|
|
472
|
+
myBundlesEmptyPrefix: 'You have not booked a bundle yet. Use',
|
|
473
|
+
myBundlesEmptySuffix: 'to extend your plan with additional features & quotas.',
|
|
474
|
+
myBundlesBookedSince: 'Booked since',
|
|
475
|
+
myBundlesCanceledAt: 'Canceled on',
|
|
476
|
+
myBundlesRunsUntil: 'runs until',
|
|
477
|
+
myBundlesCancelInProgress: 'Canceling …',
|
|
478
|
+
myBundlesBookInProgress: 'Booking …',
|
|
479
|
+
myBundlesCancelConfirm:
|
|
480
|
+
'Really cancel this bundle? The cancellation takes effect on the next possible date.',
|
|
481
|
+
myBundlesStatusCanceledPending: 'Cancellation effective as of …',
|
|
482
|
+
myBundlesStatusEnded: 'Ended',
|
|
483
|
+
myBundlesAddBundleLabel: 'Bundle',
|
|
484
|
+
myBundlesAddSelectPlaceholder: '— please select —',
|
|
485
|
+
myBundlesPricePerMonthShort: '€ / mo',
|
|
486
|
+
myBundlesHiddenIncompatible: 'more bundle(s) hidden — not compatible with plan',
|
|
487
|
+
myBundlesBundleVersionIdLabel: 'BundleVersion ID',
|
|
488
|
+
myBundlesBundleVersionIdPlaceholder: 'UUID of the desired bundle version',
|
|
489
|
+
myBundlesMinimumTermLabel: 'Minimum term (months, optional)',
|
|
490
|
+
myBundlesMinimumTermPlaceholder: 'Default: 12',
|
|
491
|
+
};
|
|
492
|
+
|
|
493
|
+
/** Default map for the given UI locale — fallback layer under the `i18n` prop. */
|
|
494
|
+
export function defaultTenantPlanSectionI18n(locale: SaLocale): TenantPlanSectionI18n {
|
|
495
|
+
return locale === 'en' ? DEFAULT_I18N_EN : DEFAULT_I18N_DE;
|
|
496
|
+
}
|
|
@@ -23,7 +23,10 @@
|
|
|
23
23
|
|
|
24
24
|
<template v-else-if="preview">
|
|
25
25
|
<!-- Blocker: booking/cancellation not possible -->
|
|
26
|
-
<q-card-section
|
|
26
|
+
<q-card-section
|
|
27
|
+
v-if="preview.blockers.length > 0"
|
|
28
|
+
class="sp-bundle-preview__blockers"
|
|
29
|
+
>
|
|
27
30
|
<div class="sp-bundle-preview__block-title">
|
|
28
31
|
{{ i18n.bundlePreviewBlockersTitle }}
|
|
29
32
|
</div>
|
|
@@ -77,7 +80,9 @@
|
|
|
77
80
|
</div>
|
|
78
81
|
<div class="sp-bundle-preview__price-row">
|
|
79
82
|
<span>{{ i18n.bundlePreviewMinimumTermLabel }}</span>
|
|
80
|
-
<span
|
|
83
|
+
<span
|
|
84
|
+
v-if="addPreview.minimumTermMonths > 0 && addPreview.minimumTermEndsAt"
|
|
85
|
+
>
|
|
81
86
|
{{ addPreview.minimumTermMonths }}
|
|
82
87
|
{{ i18n.bundlePreviewMinimumTermMonths }}
|
|
83
88
|
{{ formatDate(addPreview.minimumTermEndsAt) }}
|
|
@@ -123,10 +128,7 @@
|
|
|
123
128
|
</q-card-section>
|
|
124
129
|
|
|
125
130
|
<!-- Warnings (e.g. MINIMUM_TERM_BINDS) -->
|
|
126
|
-
<q-card-section
|
|
127
|
-
v-if="otherWarnings.length > 0"
|
|
128
|
-
class="sp-bundle-preview__warnings"
|
|
129
|
-
>
|
|
131
|
+
<q-card-section v-if="otherWarnings.length > 0" class="sp-bundle-preview__warnings">
|
|
130
132
|
<div class="sp-bundle-preview__block-title">
|
|
131
133
|
{{ i18n.bundlePreviewWarningsTitle }}
|
|
132
134
|
</div>
|
|
@@ -168,7 +170,7 @@ import type {
|
|
|
168
170
|
BundleAddPreviewShape,
|
|
169
171
|
BundleCancelPreviewShape,
|
|
170
172
|
BundlePreviewShape,
|
|
171
|
-
} from '../../use-tenant-billing.js';
|
|
173
|
+
} from '../../vue/use-tenant-billing.js';
|
|
172
174
|
|
|
173
175
|
// BundlePreviewDialog (#37/#61) — preview BEFORE bundle add/cancel in the
|
|
174
176
|
// tenant self-service: proration until period end, next-period price,
|
|
@@ -9,18 +9,13 @@
|
|
|
9
9
|
<li v-for="row in bookedRows" :key="row.id" class="sp-plan-section__item">
|
|
10
10
|
<div>
|
|
11
11
|
<span class="sp-plan-section__item-label">{{ row.label }}</span>
|
|
12
|
-
<span
|
|
13
|
-
v-if="row.canceledAt"
|
|
14
|
-
class="sp-plan-section__item-canceled"
|
|
15
|
-
>
|
|
12
|
+
<span v-if="row.canceledAt" class="sp-plan-section__item-canceled">
|
|
16
13
|
{{ i18n.bundleCanceledAt }}
|
|
17
14
|
{{ formatDate(row.canceledEffectiveAt ?? row.canceledAt) }}
|
|
18
15
|
</span>
|
|
19
|
-
<span
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
>
|
|
23
|
-
{{ i18n.bundleMinimumTermUntil }} {{ formatDate(row.minimumTermEndsAt) }}
|
|
16
|
+
<span v-else-if="row.minimumTermEndsAt" class="sp-plan-section__item-price">
|
|
17
|
+
{{ i18n.bundleMinimumTermUntil }}
|
|
18
|
+
{{ formatDate(row.minimumTermEndsAt) }}
|
|
24
19
|
</span>
|
|
25
20
|
</div>
|
|
26
21
|
<div class="sp-bundle-store__booked-actions">
|
|
@@ -114,7 +109,11 @@
|
|
|
114
109
|
color="primary"
|
|
115
110
|
unelevated
|
|
116
111
|
class="sp-bundle-store__card-action"
|
|
117
|
-
:label="
|
|
112
|
+
:label="
|
|
113
|
+
buyingId === row.bundle.bundleVersionId
|
|
114
|
+
? i18n.bundleBookInProgress
|
|
115
|
+
: i18n.bundleBookAction
|
|
116
|
+
"
|
|
118
117
|
:loading="buyingId === row.bundle.bundleVersionId"
|
|
119
118
|
:disable="buyingId !== null"
|
|
120
119
|
@click="emit('buy', row.bundle.bundleVersionId)"
|
|
@@ -131,8 +130,8 @@
|
|
|
131
130
|
import { computed } from 'vue';
|
|
132
131
|
import { missingRequiresFor } from '@saasicat/types';
|
|
133
132
|
import type { TenantPlanSectionI18n } from '../default-i18n.js';
|
|
134
|
-
import type { CatalogBundle } from '../../use-tenant-billing-catalog.js';
|
|
135
|
-
import type { SubscriptionBundleShape } from '../../use-tenant-billing.js';
|
|
133
|
+
import type { CatalogBundle } from '../../vue/use-tenant-billing-catalog.js';
|
|
134
|
+
import type { SubscriptionBundleShape } from '../../vue/use-tenant-billing.js';
|
|
136
135
|
|
|
137
136
|
// TenantBundleStore — bundle sales on "Paket & Verbrauch" (#15):
|
|
138
137
|
// lists booked (cancelable) and available (bookable) catalog bundles.
|
|
@@ -38,6 +38,7 @@
|
|
|
38
38
|
<script setup lang="ts">
|
|
39
39
|
import { computed } from 'vue';
|
|
40
40
|
import type { FeatureUiRegistry } from '@saasicat/types';
|
|
41
|
+
import { useSuperAdminI18n } from '../../vue/use-super-admin-i18n.js';
|
|
41
42
|
import type { TenantPlanSectionI18n } from '../default-i18n.js';
|
|
42
43
|
|
|
43
44
|
// TenantFeatureMatrix — complete feature-scope overview (#18):
|
|
@@ -54,6 +55,8 @@ const props = defineProps<{
|
|
|
54
55
|
i18n: TenantPlanSectionI18n;
|
|
55
56
|
}>();
|
|
56
57
|
|
|
58
|
+
const { intlLocale } = useSuperAdminI18n();
|
|
59
|
+
|
|
57
60
|
interface FeatureRow {
|
|
58
61
|
key: string;
|
|
59
62
|
active: boolean;
|
|
@@ -81,7 +84,7 @@ const features = computed<FeatureRow[]>(() => {
|
|
|
81
84
|
// Included first, then alphabetically by label.
|
|
82
85
|
return rows.sort((a, b) => {
|
|
83
86
|
if (a.active !== b.active) return a.active ? -1 : 1;
|
|
84
|
-
return a.label.localeCompare(b.label,
|
|
87
|
+
return a.label.localeCompare(b.label, intlLocale.value);
|
|
85
88
|
});
|
|
86
89
|
});
|
|
87
90
|
</script>
|
|
@@ -45,7 +45,7 @@
|
|
|
45
45
|
|
|
46
46
|
<script setup lang="ts">
|
|
47
47
|
import type { TenantPlanSectionI18n } from '../default-i18n.js';
|
|
48
|
-
import type { UsageSnapshotShape } from '../../use-tenant-billing.js';
|
|
48
|
+
import type { UsageSnapshotShape } from '../../vue/use-tenant-billing.js';
|
|
49
49
|
|
|
50
50
|
defineProps<{
|
|
51
51
|
usage: UsageSnapshotShape;
|
|
@@ -17,7 +17,7 @@
|
|
|
17
17
|
|
|
18
18
|
<script setup lang="ts">
|
|
19
19
|
import type { TenantPlanSectionI18n } from '../default-i18n.js';
|
|
20
|
-
import type { UsageSnapshotShape } from '../../use-tenant-billing.js';
|
|
20
|
+
import type { UsageSnapshotShape } from '../../vue/use-tenant-billing.js';
|
|
21
21
|
import UsageBar from '../UsageBar.vue';
|
|
22
22
|
|
|
23
23
|
defineProps<{
|
|
@@ -0,0 +1,192 @@
|
|
|
1
|
+
// createSuperAdminApp — universal bootstrap helper for SuperAdmin Vue apps.
|
|
2
|
+
// Bundles the Quasar/Pinia/Router setup that every consumer app rebuilds itself
|
|
3
|
+
// today, and exposes the platform contract maps (`extensions:`, `actions:`)
|
|
4
|
+
// via `provide()`.
|
|
5
|
+
//
|
|
6
|
+
// This module is the Quasar layer entry (`@saasicat/ui-vue/quasar`) — the only
|
|
7
|
+
// non-page module in the package that imports `quasar`. The injection keys,
|
|
8
|
+
// option types and the navigation guard live in the Vue layer
|
|
9
|
+
// (`super-admin-context.ts`) so the main entry stays Quasar-free.
|
|
10
|
+
//
|
|
11
|
+
// What the helper does NOT do:
|
|
12
|
+
// - Auth stores, login flows, JWT refresh — app-specific.
|
|
13
|
+
// - CSS imports (Quasar CSS, Material Icons, app theme) — these stay in the
|
|
14
|
+
// app's own `main.ts`, because tsup does not bundle CSS.
|
|
15
|
+
|
|
16
|
+
import { createApp, type App, type Component } from 'vue';
|
|
17
|
+
import { Quasar, Notify, Dialog, Loading, type QuasarPluginOptions } from 'quasar';
|
|
18
|
+
import { createPinia, type Pinia } from 'pinia';
|
|
19
|
+
import {
|
|
20
|
+
createRouter,
|
|
21
|
+
createWebHistory,
|
|
22
|
+
type RouteRecordRaw,
|
|
23
|
+
type Router,
|
|
24
|
+
type RouterHistory,
|
|
25
|
+
} from 'vue-router';
|
|
26
|
+
|
|
27
|
+
import { defaultHttpClient, type HttpClient } from '../client/types.js';
|
|
28
|
+
import {
|
|
29
|
+
SUPER_ADMIN_ACTIONS_KEY,
|
|
30
|
+
SUPER_ADMIN_BRAND_KEY,
|
|
31
|
+
SUPER_ADMIN_ENDPOINTS_KEY,
|
|
32
|
+
SUPER_ADMIN_EXTENSIONS_KEY,
|
|
33
|
+
SUPER_ADMIN_HTTP_KEY,
|
|
34
|
+
SUPER_ADMIN_LOGIN_ADAPTER_KEY,
|
|
35
|
+
SUPER_ADMIN_MANIFEST_KEY,
|
|
36
|
+
buildNavigationGuard,
|
|
37
|
+
type ActionsMap,
|
|
38
|
+
type ExtensionsMap,
|
|
39
|
+
type InstallPlugin,
|
|
40
|
+
type SuperAdminBrand,
|
|
41
|
+
type SuperAdminEndpoints,
|
|
42
|
+
type SuperAdminGuardOptions,
|
|
43
|
+
type SuperAdminLoginAdapter,
|
|
44
|
+
} from '../vue/super-admin-context.js';
|
|
45
|
+
import { SUPER_ADMIN_NOTIFY_KEY, type UiNotify } from '../vue/ui-notify.js';
|
|
46
|
+
import {
|
|
47
|
+
SUPER_ADMIN_I18N_KEY,
|
|
48
|
+
createSuperAdminI18n,
|
|
49
|
+
type SuperAdminI18n,
|
|
50
|
+
type SuperAdminI18nOptions,
|
|
51
|
+
} from '../vue/use-super-admin-i18n.js';
|
|
52
|
+
import { quasarNotify } from './notify.js';
|
|
53
|
+
|
|
54
|
+
export interface CreateSuperAdminAppOptions extends SuperAdminGuardOptions {
|
|
55
|
+
/** App root component (`App.vue`). */
|
|
56
|
+
rootComponent: Component;
|
|
57
|
+
/** App branding (logo, name). */
|
|
58
|
+
brand: SuperAdminBrand;
|
|
59
|
+
/** Endpoint configuration. */
|
|
60
|
+
endpoints: SuperAdminEndpoints;
|
|
61
|
+
/** App's own routes (login, standard pages, bundle pages, …). */
|
|
62
|
+
appRoutes: RouteRecordRaw[];
|
|
63
|
+
/**
|
|
64
|
+
* Static `extensions:` map. Manifest `projectPages[].componentKey` is
|
|
65
|
+
* looked up in it (see Spec §4.4).
|
|
66
|
+
*/
|
|
67
|
+
extensions?: ExtensionsMap;
|
|
68
|
+
/**
|
|
69
|
+
* Static `actions:` map. Manifest `tenants.actions[].actionKey` is looked
|
|
70
|
+
* up in it.
|
|
71
|
+
*/
|
|
72
|
+
actions?: ActionsMap;
|
|
73
|
+
/**
|
|
74
|
+
* Optional: login adapter. When set, it is exposed via `provide()` for the
|
|
75
|
+
* shared `<SuperAdminLoginPage>` (from `pages-standard/`) — the app no
|
|
76
|
+
* longer needs to hold its own LoginPage Vue component.
|
|
77
|
+
*/
|
|
78
|
+
loginAdapter?: SuperAdminLoginAdapter;
|
|
79
|
+
/**
|
|
80
|
+
* Optional: router history variant, default `createWebHistory()`.
|
|
81
|
+
* Apps with a subpath mount override this.
|
|
82
|
+
*/
|
|
83
|
+
routerHistory?: RouterHistory;
|
|
84
|
+
/**
|
|
85
|
+
* Optional: Quasar configuration. Default loads `Notify`/`Dialog`/`Loading`
|
|
86
|
+
* with the established consumer convention (`top-right`, 3 s).
|
|
87
|
+
*/
|
|
88
|
+
quasarOptions?: Partial<QuasarPluginOptions>;
|
|
89
|
+
/**
|
|
90
|
+
* Optional: notify port for the standard pages' toasts. Default is the
|
|
91
|
+
* Quasar `Notify` implementation — apps with their own notification
|
|
92
|
+
* center replace it here without touching the pages.
|
|
93
|
+
*/
|
|
94
|
+
notify?: UiNotify;
|
|
95
|
+
/**
|
|
96
|
+
* Optional: additional Vue plugins (e.g. an app's own NotificationCenter)
|
|
97
|
+
* that are installed after the platform setup, before the mount.
|
|
98
|
+
*/
|
|
99
|
+
installPlugins?: InstallPlugin[];
|
|
100
|
+
/**
|
|
101
|
+
* Optional: `HttpClient` for all pre-login calls (boot, first-run setup).
|
|
102
|
+
* Default `defaultHttpClient()` (= `fetch`). Consumers pass their own
|
|
103
|
+
* variant through (auth header, baseURL, retry) — it then applies uniformly,
|
|
104
|
+
* including for the setup wizard. Consumed via `useSuperAdminHttp()`.
|
|
105
|
+
*/
|
|
106
|
+
http?: HttpClient;
|
|
107
|
+
/**
|
|
108
|
+
* Optional: UI locale + string overrides. Default is German. The created
|
|
109
|
+
* context is returned on the handle (`handle.i18n`) — set
|
|
110
|
+
* `handle.i18n.locale.value = 'en'` (or pass a `Ref` here) to switch at
|
|
111
|
+
* runtime. Consumed via `useSuperAdminI18n()` / `useSaMessages()`.
|
|
112
|
+
*/
|
|
113
|
+
i18n?: SuperAdminI18nOptions;
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
export interface SuperAdminAppHandle {
|
|
117
|
+
app: App;
|
|
118
|
+
router: Router;
|
|
119
|
+
pinia: Pinia;
|
|
120
|
+
/** i18n context of the shell — switch locale via `i18n.locale.value`. */
|
|
121
|
+
i18n: SuperAdminI18n;
|
|
122
|
+
/** Mounts the app on a selector. Returns the root component instance. */
|
|
123
|
+
mount: (selector: string | Element) => ReturnType<App['mount']>;
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
const DEFAULT_QUASAR_OPTIONS: QuasarPluginOptions = {
|
|
127
|
+
plugins: { Notify, Dialog, Loading },
|
|
128
|
+
config: { notify: { position: 'top-right', timeout: 3000 } },
|
|
129
|
+
};
|
|
130
|
+
|
|
131
|
+
/**
|
|
132
|
+
* Universal bootstrap function for SuperAdmin apps. Replaces the `main.ts`
|
|
133
|
+
* boilerplate duplicated per app today (Quasar + Pinia + Router + manifest
|
|
134
|
+
* guard) and exposes the platform maps via `provide()` for downstream
|
|
135
|
+
* components.
|
|
136
|
+
*/
|
|
137
|
+
export function createSuperAdminApp(options: CreateSuperAdminAppOptions): SuperAdminAppHandle {
|
|
138
|
+
const app = createApp(options.rootComponent);
|
|
139
|
+
|
|
140
|
+
app.use(Quasar, options.quasarOptions ?? DEFAULT_QUASAR_OPTIONS);
|
|
141
|
+
|
|
142
|
+
const pinia = createPinia();
|
|
143
|
+
app.use(pinia);
|
|
144
|
+
|
|
145
|
+
const router = createRouter({
|
|
146
|
+
history: options.routerHistory ?? createWebHistory(),
|
|
147
|
+
routes: options.appRoutes,
|
|
148
|
+
});
|
|
149
|
+
|
|
150
|
+
const navGuard = buildNavigationGuard(options);
|
|
151
|
+
if (navGuard) {
|
|
152
|
+
router.beforeEach(navGuard);
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
app.use(router);
|
|
156
|
+
|
|
157
|
+
const endpoints: Required<SuperAdminEndpoints> = {
|
|
158
|
+
apiBase: options.endpoints.apiBase,
|
|
159
|
+
publicBootEndpoint:
|
|
160
|
+
options.endpoints.publicBootEndpoint ?? `${options.endpoints.apiBase}/boot`,
|
|
161
|
+
manifestEndpoint:
|
|
162
|
+
options.endpoints.manifestEndpoint ?? `${options.endpoints.apiBase}/manifest`,
|
|
163
|
+
};
|
|
164
|
+
|
|
165
|
+
const i18n = createSuperAdminI18n(options.i18n);
|
|
166
|
+
|
|
167
|
+
app.provide(SUPER_ADMIN_BRAND_KEY, { tag: 'SuperAdmin', ...options.brand });
|
|
168
|
+
app.provide(SUPER_ADMIN_I18N_KEY, i18n);
|
|
169
|
+
app.provide(SUPER_ADMIN_ENDPOINTS_KEY, endpoints);
|
|
170
|
+
app.provide(SUPER_ADMIN_EXTENSIONS_KEY, options.extensions ?? {});
|
|
171
|
+
app.provide(SUPER_ADMIN_ACTIONS_KEY, options.actions ?? {});
|
|
172
|
+
app.provide(SUPER_ADMIN_NOTIFY_KEY, options.notify ?? quasarNotify);
|
|
173
|
+
if (options.manifestGuard?.getManifest) {
|
|
174
|
+
app.provide(SUPER_ADMIN_MANIFEST_KEY, options.manifestGuard.getManifest);
|
|
175
|
+
}
|
|
176
|
+
if (options.loginAdapter) {
|
|
177
|
+
app.provide(SUPER_ADMIN_LOGIN_ADAPTER_KEY, options.loginAdapter);
|
|
178
|
+
}
|
|
179
|
+
app.provide(SUPER_ADMIN_HTTP_KEY, options.http ?? defaultHttpClient());
|
|
180
|
+
|
|
181
|
+
for (const plugin of options.installPlugins ?? []) {
|
|
182
|
+
plugin(app);
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
return {
|
|
186
|
+
app,
|
|
187
|
+
router,
|
|
188
|
+
pinia,
|
|
189
|
+
i18n,
|
|
190
|
+
mount: (selector) => app.mount(selector),
|
|
191
|
+
};
|
|
192
|
+
}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
// @saasicat/ui-vue/quasar — the Quasar layer entry: everything that installs
|
|
2
|
+
// or calls Quasar from TypeScript. Kept out of the main entry so that
|
|
3
|
+
// `import ... from '@saasicat/ui-vue'` never executes a `quasar` import
|
|
4
|
+
// (Quasar is an optional peer dependency).
|
|
5
|
+
//
|
|
6
|
+
// The Quasar standard pages themselves are consumed as raw SFCs via the
|
|
7
|
+
// `./pages-standard/*`, `./pages-tenant/*` and `./components/*` subpath
|
|
8
|
+
// exports, not through this bundle (tsup ignores `.vue`).
|
|
9
|
+
|
|
10
|
+
export * from './create-super-admin-app.js';
|
|
11
|
+
export * from './notify.js';
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
// Quasar implementation of the UI notify port.
|
|
2
|
+
//
|
|
3
|
+
// Standard pages resolve the port via `useSuperAdminNotify()`: the app-provided
|
|
4
|
+
// port wins, otherwise the Quasar default below. The fallback keeps apps
|
|
5
|
+
// working that mount the standard pages without `createSuperAdminApp()`
|
|
6
|
+
// (their own `main.ts` installs the Quasar Notify plugin, as before).
|
|
7
|
+
|
|
8
|
+
import { inject } from 'vue';
|
|
9
|
+
import { Notify } from 'quasar';
|
|
10
|
+
|
|
11
|
+
import { SUPER_ADMIN_NOTIFY_KEY, type UiNotify } from '../vue/ui-notify.js';
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* Quasar-backed notify port: `position: 'top'` matches the convention the
|
|
15
|
+
* standard pages used with their previous direct `$q.notify` calls.
|
|
16
|
+
*/
|
|
17
|
+
export const quasarNotify: UiNotify = (kind, message, options) => {
|
|
18
|
+
Notify.create({
|
|
19
|
+
type: kind,
|
|
20
|
+
message,
|
|
21
|
+
position: 'top',
|
|
22
|
+
caption: options?.caption,
|
|
23
|
+
timeout: options?.timeoutMs,
|
|
24
|
+
});
|
|
25
|
+
};
|
|
26
|
+
|
|
27
|
+
/** Returns the app-provided notify port, falling back to the Quasar default. */
|
|
28
|
+
export function useSuperAdminNotify(): UiNotify {
|
|
29
|
+
return inject(SUPER_ADMIN_NOTIFY_KEY, quasarNotify);
|
|
30
|
+
}
|