@saasicat/ui-vue 0.21.0 → 0.22.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (132) hide show
  1. package/dist/{catalog-BY_t9prv.d.cts → catalog-DJcfm5N2.d.cts} +20 -7
  2. package/dist/{catalog-BY_t9prv.d.ts → catalog-DJcfm5N2.d.ts} +20 -7
  3. package/dist/{chunk-JN6HZGLV.js → chunk-F7NRM6KI.js} +54 -28
  4. package/dist/{chunk-7IFKVGZV.js → chunk-LY52T4N4.js} +21 -2
  5. package/dist/{chunk-OTP3OSSW.js → chunk-XMMFN2WJ.js} +74 -3
  6. package/dist/client/index.cjs +132 -29
  7. package/dist/client/index.d.cts +53 -3
  8. package/dist/client/index.d.ts +53 -3
  9. package/dist/client/index.js +14 -2
  10. package/dist/index.cjs +319 -162
  11. package/dist/index.d.cts +30 -8
  12. package/dist/index.d.ts +30 -8
  13. package/dist/index.js +176 -133
  14. package/dist/quasar/index.cjs +76 -29
  15. package/dist/quasar/index.d.cts +2 -2
  16. package/dist/quasar/index.d.ts +2 -2
  17. package/dist/quasar/index.js +6 -2
  18. package/dist/testing-e2e/admin-pages-suite.d.cts +37 -0
  19. package/dist/testing-e2e/admin-pages-suite.d.ts +37 -0
  20. package/dist/{use-super-admin-i18n-c_Eqsu9u.d.ts → use-super-admin-i18n-CHNdsSlm.d.ts} +34 -7
  21. package/dist/{use-super-admin-i18n-DlJRGIVq.d.cts → use-super-admin-i18n-CgTuNi8h.d.cts} +34 -7
  22. package/package.json +18 -8
  23. package/src/client/i18n/messages/bundles.ts +0 -2
  24. package/src/client/i18n/messages/common.ts +22 -0
  25. package/src/client/i18n/messages/discovery.ts +2 -2
  26. package/src/client/i18n/messages/marketing.ts +2 -4
  27. package/src/client/i18n/messages/plan-detail.ts +0 -4
  28. package/src/client/i18n/messages/plans.ts +20 -8
  29. package/src/client/i18n/messages/tenants.ts +0 -2
  30. package/src/client/index.ts +1 -0
  31. package/src/client/manifest-loader.ts +1 -1
  32. package/src/client/resolve-plans.ts +144 -0
  33. package/src/components/BundleVersionPublishDialog.vue +6 -6
  34. package/src/components/KvBlock.vue +4 -4
  35. package/src/components/MarketingPromotionsTab.vue +34 -48
  36. package/src/components/MfaPromptDialog.vue +8 -2
  37. package/src/components/TenantActionConfirmDialog.vue +4 -4
  38. package/src/components/VersionDiffPreview.vue +7 -7
  39. package/src/components/admin-page/AdminFilters.vue +12 -0
  40. package/src/components/admin-page/AdminHero.vue +22 -5
  41. package/src/components/admin-page/AdminKpi.vue +84 -0
  42. package/src/components/admin-page/AdminPaginator.vue +195 -0
  43. package/src/components/admin-page/AdminRefreshBtn.vue +39 -0
  44. package/src/components/admin-page/AdminSection.vue +31 -16
  45. package/src/components/admin-page/AdminStatistics.vue +40 -0
  46. package/src/components/admin-page/AdminTable.vue +175 -0
  47. package/src/components/bundle-editor/BundleCreatePanel.vue +23 -23
  48. package/src/components/bundle-editor/BundleFeaturesEditor.vue +7 -7
  49. package/src/components/bundle-editor/BundlePlanCompatPicker.vue +9 -9
  50. package/src/components/bundle-editor/BundleQuotasEditor.vue +11 -11
  51. package/src/components/bundle-editor/BundleStatusBanner.vue +6 -6
  52. package/src/components/bundle-editor/BundleVersionInlineEditor.vue +18 -18
  53. package/src/components/bundle-editor/BundleVersionStrip.vue +12 -12
  54. package/src/components/dialogs/PilotCreateDialog.vue +12 -12
  55. package/src/components/dialogs/PilotEditDialog.vue +7 -7
  56. package/src/components/dialogs/PromoCodeCreateDialog.vue +8 -8
  57. package/src/components/dialogs/PromoCodeDialogFields.vue +33 -19
  58. package/src/components/dialogs/PromoCodeEditDialog.vue +10 -10
  59. package/src/components/plan/PlanGrid.vue +1 -1
  60. package/src/components/plan-create-dialog/PlanCreateDialog.vue +34 -46
  61. package/src/components/plan-detail/PlanDetail.vue +92 -302
  62. package/src/components/plan-detail/PlanDetailKpis.vue +22 -27
  63. package/src/components/plan-detail/PlanTitleEdit.vue +133 -0
  64. package/src/components/plan-list/PlanList.vue +72 -290
  65. package/src/components/plan-matrix/PlanMatrix.vue +66 -183
  66. package/src/components/plan-review/PlanReview.vue +191 -275
  67. package/src/components/plan-version-editor/PlanCatalogPreview.vue +7 -5
  68. package/src/components/plan-version-editor/PlanVersionEditor.vue +200 -295
  69. package/src/components/plan-version-editor/PlanVersionEditorHeader.vue +23 -55
  70. package/src/index.ts +1 -0
  71. package/src/pages-standard/AdminLayout.vue +34 -10
  72. package/src/pages-standard/AdminManifestErrorPage.vue +79 -9
  73. package/src/pages-standard/AuditPage.vue +53 -72
  74. package/src/pages-standard/BundlesPage.vue +128 -144
  75. package/src/pages-standard/DashboardPage.vue +43 -107
  76. package/src/pages-standard/DiscoveryPage.vue +158 -200
  77. package/src/pages-standard/EmailHistoryPage.vue +98 -88
  78. package/src/pages-standard/MarketingCatalogPage.vue +237 -267
  79. package/src/pages-standard/PilotsPage.vue +44 -60
  80. package/src/pages-standard/PlansPage.vue +230 -105
  81. package/src/pages-standard/PlatformEmailPage.vue +37 -40
  82. package/src/pages-standard/PromoCodeDetailPage.vue +16 -30
  83. package/src/pages-standard/PromoCodesPage.vue +86 -112
  84. package/src/pages-standard/SubscriptionsPage.vue +10 -17
  85. package/src/pages-standard/SuperAdminLoginPage.vue +12 -12
  86. package/src/pages-standard/SuperAdminSetupWizard.vue +20 -17
  87. package/src/pages-standard/TenantDetailPage.vue +45 -41
  88. package/src/pages-standard/TenantsPage.vue +184 -264
  89. package/src/pages-standard/UsersPage.vue +69 -104
  90. package/src/pages-standard/bundles-page/BundleAccordionList.vue +20 -17
  91. package/src/pages-standard/bundles-page/BundlesKpis.vue +13 -22
  92. package/src/pages-standard/bundles-page/BundlesToolbar.vue +6 -10
  93. package/src/pages-standard/discovery-page/CatalogEntryTransPanel.vue +10 -10
  94. package/src/pages-standard/discovery-page/DiscoveryCapList.vue +5 -5
  95. package/src/pages-standard/discovery-page/DiscoveryFeatureCard.vue +16 -16
  96. package/src/pages-standard/discovery-page/DiscoveryKpis.vue +31 -27
  97. package/src/pages-standard/discovery-page/DiscoveryQuotaCard.vue +7 -7
  98. package/src/pages-standard/marketing-catalog/MarketingCatalogAdmin.vue +1 -1
  99. package/src/pages-standard/marketing-catalog/MarketingCatalogHeader.vue +2 -13
  100. package/src/pages-standard/plan-versions/PlanDiffCard.vue +6 -6
  101. package/src/pages-standard/plan-versions/PlanVersionsDiff.vue +6 -6
  102. package/src/pages-standard/plan-versions/PlanVersionsTimeline.vue +16 -16
  103. package/src/pages-standard/plans-page/PlanBundleOverview.vue +14 -29
  104. package/src/pages-standard/plans-page/PlanPublishDialog.vue +1 -1
  105. package/src/pages-standard/plans-page/PlansPageToast.vue +1 -1
  106. package/src/pages-standard/sa-theme.css +481 -71
  107. package/src/pages-standard/tenant-detail/TenantUsers.vue +2 -8
  108. package/src/pages-standard/tenants/StatusPill.vue +2 -2
  109. package/src/pages-tenant/MySubscriptionBundlesPage.vue +25 -25
  110. package/src/pages-tenant/OnboardingConfigurator.vue +1 -5
  111. package/src/pages-tenant/PackageSnapshotPanel.vue +1 -1
  112. package/src/pages-tenant/TenantPlanSection.vue +12 -20
  113. package/src/quasar/create-super-admin-app.ts +4 -0
  114. package/src/vue/entitlement-provider.ts +0 -1
  115. package/src/vue/feature-router-guard.ts +0 -1
  116. package/src/vue/super-admin-context.ts +106 -1
  117. package/src/vue/use-api-list.ts +2 -1
  118. package/src/vue/use-pagination.ts +63 -0
  119. package/src/vue/use-plans.ts +1 -2
  120. package/src/vue/use-sign-out.ts +90 -0
  121. package/src/vue/use-tenant-billing.ts +1 -1
  122. package/src/vue/use-tenant-manifest.ts +0 -1
  123. package/src/components/KpiCard.vue +0 -53
  124. package/src/components/plan-cockpit/PlanCockpit.vue +0 -1027
  125. package/src/components/plan-cockpit/PlanCockpitAuditLog.vue +0 -72
  126. package/src/components/plan-cockpit/PlanCockpitDiffPanel.vue +0 -99
  127. package/src/components/plan-cockpit/PlanCockpitHeader.vue +0 -101
  128. package/src/components/plan-cockpit/PlanCockpitImpactPanel.vue +0 -112
  129. package/src/components/plan-cockpit/PlanCockpitKpis.vue +0 -68
  130. package/src/components/plan-cockpit/PlanCockpitVersions.vue +0 -249
  131. package/src/components/plan-cockpit/types.ts +0 -72
  132. package/src/components/plan-detail/PlanDetailHeader.vue +0 -194
@@ -195,7 +195,6 @@ declare const bundlesMessages: Record<SaBuiltinLocale, {
195
195
  subtitle: string;
196
196
  displayLocale: string;
197
197
  newBundle: string;
198
- reload: string;
199
198
  };
200
199
  filter: {
201
200
  all: string;
@@ -392,6 +391,8 @@ declare const commonMessages: Record<SaBuiltinLocale, {
392
391
  saving: string;
393
392
  loadingData: string;
394
393
  noData: string;
394
+ filters: string;
395
+ results: string;
395
396
  error: string;
396
397
  errorLoadFailed: string;
397
398
  errorSaveFailed: string;
@@ -438,6 +439,15 @@ declare const commonMessages: Record<SaBuiltinLocale, {
438
439
  both: string;
439
440
  createFailed: string;
440
441
  noChanges: string;
442
+ paginator: {
443
+ label: string;
444
+ rowsPerPage: string;
445
+ all: string;
446
+ page: string;
447
+ pageInput: string;
448
+ previous: string;
449
+ next: string;
450
+ };
441
451
  }>;
442
452
 
443
453
  declare const dashboardMessages: Record<SaBuiltinLocale, {
@@ -626,7 +636,6 @@ declare const marketingMessages: Record<SaBuiltinLocale, {
626
636
  defaultLocale: string;
627
637
  deactivateLocale: string;
628
638
  addLocale: string;
629
- refresh: string;
630
639
  };
631
640
  page: {
632
641
  loading: string;
@@ -860,10 +869,8 @@ declare const planDetailMessages: Record<SaBuiltinLocale, {
860
869
  versionsSummary: string;
861
870
  versionsSummaryWithDrafts: string;
862
871
  openDraft: string;
863
- noDraft: string;
864
872
  readyToEdit: string;
865
873
  noOpenDraft: string;
866
- createNewDraft: string;
867
874
  };
868
875
  versions: {
869
876
  title: string;
@@ -1103,6 +1110,7 @@ declare const planVersionsMessages: Record<SaBuiltinLocale, {
1103
1110
 
1104
1111
  declare const plansMessages: Record<SaBuiltinLocale, {
1105
1112
  page: {
1113
+ subtitle: string;
1106
1114
  loading: string;
1107
1115
  toastPlanCreated: string;
1108
1116
  toastDraftSaved: string;
@@ -1147,7 +1155,10 @@ declare const plansMessages: Record<SaBuiltinLocale, {
1147
1155
  };
1148
1156
  list: {
1149
1157
  title: string;
1150
- summary: string;
1158
+ statPlans: string;
1159
+ statLive: string;
1160
+ statDrafts: string;
1161
+ statTenants: string;
1151
1162
  matrixView: string;
1152
1163
  newPlan: string;
1153
1164
  searchPlaceholder: string;
@@ -1184,7 +1195,10 @@ declare const plansMessages: Record<SaBuiltinLocale, {
1184
1195
  };
1185
1196
  matrix: {
1186
1197
  title: string;
1187
- summary: string;
1198
+ statPlans: string;
1199
+ statFeatures: string;
1200
+ statQuotas: string;
1201
+ statBundles: string;
1188
1202
  catalogPreview: string;
1189
1203
  createPlan: string;
1190
1204
  createPlanSub: string;
@@ -1497,7 +1511,6 @@ declare const tenantsMessages: Record<SaBuiltinLocale, {
1497
1511
  columnCreatedAt: string;
1498
1512
  suspended: string;
1499
1513
  empty: string;
1500
- pagination: string;
1501
1514
  };
1502
1515
  detail: {
1503
1516
  backToList: string;
@@ -195,7 +195,6 @@ declare const bundlesMessages: Record<SaBuiltinLocale, {
195
195
  subtitle: string;
196
196
  displayLocale: string;
197
197
  newBundle: string;
198
- reload: string;
199
198
  };
200
199
  filter: {
201
200
  all: string;
@@ -392,6 +391,8 @@ declare const commonMessages: Record<SaBuiltinLocale, {
392
391
  saving: string;
393
392
  loadingData: string;
394
393
  noData: string;
394
+ filters: string;
395
+ results: string;
395
396
  error: string;
396
397
  errorLoadFailed: string;
397
398
  errorSaveFailed: string;
@@ -438,6 +439,15 @@ declare const commonMessages: Record<SaBuiltinLocale, {
438
439
  both: string;
439
440
  createFailed: string;
440
441
  noChanges: string;
442
+ paginator: {
443
+ label: string;
444
+ rowsPerPage: string;
445
+ all: string;
446
+ page: string;
447
+ pageInput: string;
448
+ previous: string;
449
+ next: string;
450
+ };
441
451
  }>;
442
452
 
443
453
  declare const dashboardMessages: Record<SaBuiltinLocale, {
@@ -626,7 +636,6 @@ declare const marketingMessages: Record<SaBuiltinLocale, {
626
636
  defaultLocale: string;
627
637
  deactivateLocale: string;
628
638
  addLocale: string;
629
- refresh: string;
630
639
  };
631
640
  page: {
632
641
  loading: string;
@@ -860,10 +869,8 @@ declare const planDetailMessages: Record<SaBuiltinLocale, {
860
869
  versionsSummary: string;
861
870
  versionsSummaryWithDrafts: string;
862
871
  openDraft: string;
863
- noDraft: string;
864
872
  readyToEdit: string;
865
873
  noOpenDraft: string;
866
- createNewDraft: string;
867
874
  };
868
875
  versions: {
869
876
  title: string;
@@ -1103,6 +1110,7 @@ declare const planVersionsMessages: Record<SaBuiltinLocale, {
1103
1110
 
1104
1111
  declare const plansMessages: Record<SaBuiltinLocale, {
1105
1112
  page: {
1113
+ subtitle: string;
1106
1114
  loading: string;
1107
1115
  toastPlanCreated: string;
1108
1116
  toastDraftSaved: string;
@@ -1147,7 +1155,10 @@ declare const plansMessages: Record<SaBuiltinLocale, {
1147
1155
  };
1148
1156
  list: {
1149
1157
  title: string;
1150
- summary: string;
1158
+ statPlans: string;
1159
+ statLive: string;
1160
+ statDrafts: string;
1161
+ statTenants: string;
1151
1162
  matrixView: string;
1152
1163
  newPlan: string;
1153
1164
  searchPlaceholder: string;
@@ -1184,7 +1195,10 @@ declare const plansMessages: Record<SaBuiltinLocale, {
1184
1195
  };
1185
1196
  matrix: {
1186
1197
  title: string;
1187
- summary: string;
1198
+ statPlans: string;
1199
+ statFeatures: string;
1200
+ statQuotas: string;
1201
+ statBundles: string;
1188
1202
  catalogPreview: string;
1189
1203
  createPlan: string;
1190
1204
  createPlanSub: string;
@@ -1497,7 +1511,6 @@ declare const tenantsMessages: Record<SaBuiltinLocale, {
1497
1511
  columnCreatedAt: string;
1498
1512
  suspended: string;
1499
1513
  empty: string;
1500
- pagination: string;
1501
1514
  };
1502
1515
  detail: {
1503
1516
  backToList: string;
@@ -186,8 +186,7 @@ var bundlesMessages = defineMessages(
186
186
  title: "Bundles",
187
187
  subtitle: "Produktgruppen aus Features & Quotas \u2014 verwendet in Pl\xE4nen. Bundles werden im SuperAdmin kuratiert.",
188
188
  displayLocale: "Anzeige-Sprache",
189
- newBundle: "Neues Bundle",
190
- reload: "Liste neu laden"
189
+ newBundle: "Neues Bundle"
191
190
  },
192
191
  filter: {
193
192
  all: "Alle Status",
@@ -401,8 +400,7 @@ var bundlesMessages = defineMessages(
401
400
  title: "Bundles",
402
401
  subtitle: "Product groups made of features & quotas \u2014 used in plans. Bundles are curated in the SuperAdmin.",
403
402
  displayLocale: "Display language",
404
- newBundle: "New bundle",
405
- reload: "Reload list"
403
+ newBundle: "New bundle"
406
404
  },
407
405
  filter: {
408
406
  all: "All statuses",
@@ -602,6 +600,8 @@ var commonMessages = defineMessages(
602
600
  saving: "Speichere \u2026",
603
601
  loadingData: "Daten werden geladen\u2026",
604
602
  noData: "Keine Daten vorhanden",
603
+ filters: "Filter",
604
+ results: "Ergebnisse",
605
605
  error: "Fehler",
606
606
  errorLoadFailed: "Laden fehlgeschlagen",
607
607
  errorSaveFailed: "Speichern fehlgeschlagen",
@@ -647,7 +647,16 @@ var commonMessages = defineMessages(
647
647
  unlimited: "unbegrenzt",
648
648
  both: "Beide",
649
649
  createFailed: "Anlegen fehlgeschlagen",
650
- noChanges: "Keine \xC4nderungen"
650
+ noChanges: "Keine \xC4nderungen",
651
+ paginator: {
652
+ label: "Seitennavigation",
653
+ rowsPerPage: "Zeilen pro Seite",
654
+ all: "Alle",
655
+ page: "Seite {page}/{pages}",
656
+ pageInput: "Seite, 1 bis {pages}",
657
+ previous: "Vorherige Seite",
658
+ next: "N\xE4chste Seite"
659
+ }
651
660
  },
652
661
  {
653
662
  save: "Save",
@@ -673,6 +682,8 @@ var commonMessages = defineMessages(
673
682
  saving: "Saving \u2026",
674
683
  loadingData: "Loading data\u2026",
675
684
  noData: "No data available",
685
+ filters: "Filters",
686
+ results: "Results",
676
687
  error: "Error",
677
688
  errorLoadFailed: "Failed to load",
678
689
  errorSaveFailed: "Failed to save",
@@ -718,7 +729,16 @@ var commonMessages = defineMessages(
718
729
  unlimited: "unlimited",
719
730
  both: "Both",
720
731
  createFailed: "Creation failed",
721
- noChanges: "No changes"
732
+ noChanges: "No changes",
733
+ paginator: {
734
+ label: "Pagination",
735
+ rowsPerPage: "Rows per page",
736
+ all: "All",
737
+ page: "Page {page}/{pages}",
738
+ pageInput: "Page, 1 to {pages}",
739
+ previous: "Previous page",
740
+ next: "Next page"
741
+ }
722
742
  }
723
743
  );
724
744
 
@@ -823,7 +843,7 @@ var discoveryMessages = defineMessages(
823
843
  quota: {
824
844
  usageProvider: "UsageProvider",
825
845
  usageProviderMissing: "fehlt",
826
- noUsageProviderWarning: "Eine harte Quota ohne UsageProvider ist nicht deploy-f\xE4hig (Preflight, SPEC_V2 \xA76.3).",
846
+ noUsageProviderWarning: "Eine harte Quota ohne UsageProvider ist nicht deploy-f\xE4hig (Preflight).",
827
847
  outdatedBanner: "Die code-abgeleiteten Quota-Fakten (Einheit/Enforcement/Provider) haben sich seit der letzten Freigabe ge\xE4ndert \u2014 bitte pr\xFCfen und"
828
848
  },
829
849
  caps: {
@@ -927,7 +947,7 @@ var discoveryMessages = defineMessages(
927
947
  quota: {
928
948
  usageProvider: "UsageProvider",
929
949
  usageProviderMissing: "missing",
930
- noUsageProviderWarning: "A hard quota without a UsageProvider is not deployable (preflight, SPEC_V2 \xA76.3).",
950
+ noUsageProviderWarning: "A hard quota without a UsageProvider is not deployable (preflight).",
931
951
  outdatedBanner: "The code-derived quota facts (unit/enforcement/provider) have changed since the last approval \u2014 please review and"
932
952
  },
933
953
  caps: {
@@ -1087,8 +1107,7 @@ var marketingMessages = defineMessages(
1087
1107
  localesLabel: "Sprachen:",
1088
1108
  defaultLocale: "Default-Sprache",
1089
1109
  deactivateLocale: "Sprache deaktivieren",
1090
- addLocale: "+ Sprache",
1091
- refresh: "Aktualisieren"
1110
+ addLocale: "+ Sprache"
1092
1111
  },
1093
1112
  page: {
1094
1113
  loading: "Lade Marketing-Catalog \u2026",
@@ -1156,7 +1175,7 @@ var marketingMessages = defineMessages(
1156
1175
  },
1157
1176
  promotionsTab: {
1158
1177
  title: "Aktionen & Rabatte",
1159
- subtitle: "Zeitlich begrenzte Preis-Aktionen \u2014 \xFCberschreiben den regul\xE4ren Preis auf der Pricing-Page (SPEC_V2 \xA79a).",
1178
+ subtitle: "Zeitlich begrenzte Preis-Aktionen \u2014 \xFCberschreiben den regul\xE4ren Preis auf der Pricing-Page.",
1160
1179
  add: "+ Aktion anlegen",
1161
1180
  timelineHead: "Aktions-Timeline \xB7 gestrichelt = heute",
1162
1181
  today: "heute",
@@ -1215,8 +1234,7 @@ var marketingMessages = defineMessages(
1215
1234
  localesLabel: "Languages:",
1216
1235
  defaultLocale: "Default language",
1217
1236
  deactivateLocale: "Deactivate language",
1218
- addLocale: "+ Language",
1219
- refresh: "Refresh"
1237
+ addLocale: "+ Language"
1220
1238
  },
1221
1239
  page: {
1222
1240
  loading: "Loading marketing catalog \u2026",
@@ -1284,7 +1302,7 @@ var marketingMessages = defineMessages(
1284
1302
  },
1285
1303
  promotionsTab: {
1286
1304
  title: "Promotions & discounts",
1287
- subtitle: "Time-limited price promotions \u2014 they override the regular price on the pricing page (SPEC_V2 \xA79a).",
1305
+ subtitle: "Time-limited price promotions \u2014 they override the regular price on the pricing page.",
1288
1306
  add: "+ Create promotion",
1289
1307
  timelineHead: "Promotion timeline \xB7 dashed = today",
1290
1308
  today: "today",
@@ -1599,10 +1617,8 @@ var planDetailMessages = defineMessages(
1599
1617
  versionsSummary: "{published} live/superseded",
1600
1618
  versionsSummaryWithDrafts: "{published} live/superseded \xB7 {drafts} Draft",
1601
1619
  openDraft: "Offener Draft",
1602
- noDraft: "Kein Draft",
1603
1620
  readyToEdit: "Bereit zum Bearbeiten",
1604
- noOpenDraft: "Keine Draft-Version offen",
1605
- createNewDraft: "Neue Draft anlegen"
1621
+ noOpenDraft: "Keine Draft-Version offen"
1606
1622
  },
1607
1623
  versions: {
1608
1624
  title: "Versionen",
@@ -1726,10 +1742,8 @@ var planDetailMessages = defineMessages(
1726
1742
  versionsSummary: "{published} live/superseded",
1727
1743
  versionsSummaryWithDrafts: "{published} live/superseded \xB7 {drafts} draft",
1728
1744
  openDraft: "Open draft",
1729
- noDraft: "No draft",
1730
1745
  readyToEdit: "Ready to edit",
1731
- noOpenDraft: "No draft version open",
1732
- createNewDraft: "Create a new draft"
1746
+ noOpenDraft: "No draft version open"
1733
1747
  },
1734
1748
  versions: {
1735
1749
  title: "Versions",
@@ -2116,6 +2130,7 @@ var plansMessages = defineMessages(
2116
2130
  // PlansPage — shell of the plan area: loading state, toasts and the
2117
2131
  // error texts of the draft/publish/archive/discard actions.
2118
2132
  page: {
2133
+ subtitle: "Pl\xE4ne b\xFCndeln Features & Quotas zu einem Angebot. Jede \xC4nderung wird als neue Version ver\xF6ffentlicht \u2014 Live-Versionen bleiben unangetastet.",
2119
2134
  loading: "Pl\xE4ne werden geladen\u2026",
2120
2135
  toastPlanCreated: "Plan {planKey} angelegt \u2014 jetzt die erste Version zusammenstellen.",
2121
2136
  toastDraftSaved: "Draft v{version} von {planKey} gespeichert.",
@@ -2162,7 +2177,10 @@ var plansMessages = defineMessages(
2162
2177
  // PlanList — default plan overview with one row per plan.
2163
2178
  list: {
2164
2179
  title: "Alle Pl\xE4ne",
2165
- summary: "{plans} Pl\xE4ne \xB7 {live} live \xB7 {drafts} offene Drafts \xB7 {tenants} Mandanten zugeordnet",
2180
+ statPlans: "Pl\xE4ne",
2181
+ statLive: "Live",
2182
+ statDrafts: "Offene Drafts",
2183
+ statTenants: "Mandanten",
2166
2184
  matrixView: "Matrix-Ansicht",
2167
2185
  newPlan: "Neuer Plan",
2168
2186
  searchPlaceholder: "Plan suchen\u2026",
@@ -2200,7 +2218,10 @@ var plansMessages = defineMessages(
2200
2218
  // PlanMatrix — all plans side by side, components as rows.
2201
2219
  matrix: {
2202
2220
  title: "Pl\xE4ne \xB7 Matrix-Vergleich",
2203
- summary: "Alle Pl\xE4ne nebeneinander \xB7 {plans} Pl\xE4ne \xB7 {features} Features \xB7 {quotas} Quotas \xB7 {bundles} Bundles",
2221
+ statPlans: "Pl\xE4ne",
2222
+ statFeatures: "Features",
2223
+ statQuotas: "Quotas",
2224
+ statBundles: "Bundles",
2204
2225
  catalogPreview: "Catalog-Vorschau",
2205
2226
  createPlan: "Plan anlegen",
2206
2227
  createPlanSub: "oder Klon erstellen",
@@ -2341,6 +2362,7 @@ var plansMessages = defineMessages(
2341
2362
  },
2342
2363
  {
2343
2364
  page: {
2365
+ subtitle: "Plans bundle features & quotas into an offering. Every change ships as a new version \u2014 live versions stay untouched.",
2344
2366
  loading: "Loading plans\u2026",
2345
2367
  toastPlanCreated: "Plan {planKey} created \u2014 now assemble the first version.",
2346
2368
  toastDraftSaved: "Draft v{version} of {planKey} saved.",
@@ -2385,7 +2407,10 @@ var plansMessages = defineMessages(
2385
2407
  },
2386
2408
  list: {
2387
2409
  title: "All plans",
2388
- summary: "{plans} plans \xB7 {live} live \xB7 {drafts} open drafts \xB7 {tenants} tenants assigned",
2410
+ statPlans: "Plans",
2411
+ statLive: "Live",
2412
+ statDrafts: "Open drafts",
2413
+ statTenants: "Tenants",
2389
2414
  matrixView: "Matrix view",
2390
2415
  newPlan: "New plan",
2391
2416
  searchPlaceholder: "Search plan\u2026",
@@ -2422,7 +2447,10 @@ var plansMessages = defineMessages(
2422
2447
  },
2423
2448
  matrix: {
2424
2449
  title: "Plans \xB7 matrix comparison",
2425
- summary: "All plans side by side \xB7 {plans} plans \xB7 {features} features \xB7 {quotas} quotas \xB7 {bundles} bundles",
2450
+ statPlans: "Plans",
2451
+ statFeatures: "Features",
2452
+ statQuotas: "Quotas",
2453
+ statBundles: "Bundles",
2426
2454
  catalogPreview: "Catalog preview",
2427
2455
  createPlan: "Create plan",
2428
2456
  createPlanSub: "or create a clone",
@@ -2911,8 +2939,7 @@ var tenantsMessages = defineMessages(
2911
2939
  columnUsage: "Verbrauch",
2912
2940
  columnCreatedAt: "Angelegt",
2913
2941
  suspended: "Suspendiert",
2914
- empty: "Keine Mandanten mit diesen Filtern.",
2915
- pagination: "{total} Mandanten \xB7 Seite {page} / {pages}"
2942
+ empty: "Keine Mandanten mit diesen Filtern."
2916
2943
  },
2917
2944
  detail: {
2918
2945
  backToList: "Mandanten-Liste",
@@ -2960,8 +2987,7 @@ var tenantsMessages = defineMessages(
2960
2987
  columnUsage: "Usage",
2961
2988
  columnCreatedAt: "Created",
2962
2989
  suspended: "Suspended",
2963
- empty: "No tenants match these filters.",
2964
- pagination: "{total} tenants \xB7 Page {page} / {pages}"
2990
+ empty: "No tenants match these filters."
2965
2991
  },
2966
2992
  detail: {
2967
2993
  backToList: "Tenant list",
@@ -1,7 +1,7 @@
1
1
  import {
2
2
  createSaCatalog,
3
3
  defaultKvStore
4
- } from "./chunk-JN6HZGLV.js";
4
+ } from "./chunk-F7NRM6KI.js";
5
5
 
6
6
  // src/vue/super-admin-context.ts
7
7
  var SUPER_ADMIN_BRAND_KEY = /* @__PURE__ */ Symbol.for(
@@ -19,17 +19,27 @@ var SUPER_ADMIN_ACTIONS_KEY = /* @__PURE__ */ Symbol.for(
19
19
  var SUPER_ADMIN_MANIFEST_KEY = /* @__PURE__ */ Symbol.for(
20
20
  "@saasicat/ui-vue/SUPER_ADMIN_MANIFEST"
21
21
  );
22
+ var SUPER_ADMIN_MANIFEST_CLEAR_CACHE_KEY = /* @__PURE__ */ Symbol.for("@saasicat/ui-vue/SUPER_ADMIN_MANIFEST_CLEAR_CACHE");
22
23
  var SUPER_ADMIN_LOGIN_ADAPTER_KEY = /* @__PURE__ */ Symbol.for(
23
24
  "@saasicat/ui-vue/SUPER_ADMIN_LOGIN_ADAPTER"
24
25
  );
25
26
  var SUPER_ADMIN_HTTP_KEY = /* @__PURE__ */ Symbol.for(
26
27
  "@saasicat/ui-vue/SUPER_ADMIN_HTTP"
27
28
  );
29
+ function isUnauthorizedError(err) {
30
+ const status = err?.status;
31
+ return status === 401 || status === 403;
32
+ }
28
33
  function buildNavigationGuard(options) {
29
34
  const { authGuard, manifestGuard } = options;
30
35
  if (!authGuard && !manifestGuard) return null;
36
+ let redirectedForUnauthorized = false;
37
+ let reachedLoginAfterRedirect = false;
31
38
  return async (to) => {
32
- if (to.meta?.public === true) return true;
39
+ if (to.meta?.public === true) {
40
+ if (redirectedForUnauthorized) reachedLoginAfterRedirect = true;
41
+ return true;
42
+ }
33
43
  if (authGuard) {
34
44
  if (!authGuard.isAuthenticated()) return authGuard.onUnauthenticated();
35
45
  if (authGuard.isSuperAdmin && !authGuard.isSuperAdmin()) {
@@ -39,7 +49,15 @@ function buildNavigationGuard(options) {
39
49
  if (manifestGuard) {
40
50
  try {
41
51
  await manifestGuard.ensureLoaded();
52
+ redirectedForUnauthorized = false;
53
+ reachedLoginAfterRedirect = false;
42
54
  } catch (err) {
55
+ if (authGuard && isUnauthorizedError(err)) {
56
+ if (!redirectedForUnauthorized || !reachedLoginAfterRedirect) {
57
+ redirectedForUnauthorized = true;
58
+ return authGuard.onUnauthenticated();
59
+ }
60
+ }
43
61
  if (manifestGuard.errorRoute && to.path !== manifestGuard.errorRoute) {
44
62
  return manifestGuard.errorRoute;
45
63
  }
@@ -113,6 +131,7 @@ export {
113
131
  SUPER_ADMIN_EXTENSIONS_KEY,
114
132
  SUPER_ADMIN_ACTIONS_KEY,
115
133
  SUPER_ADMIN_MANIFEST_KEY,
134
+ SUPER_ADMIN_MANIFEST_CLEAR_CACHE_KEY,
116
135
  SUPER_ADMIN_LOGIN_ADAPTER_KEY,
117
136
  SUPER_ADMIN_HTTP_KEY,
118
137
  buildNavigationGuard,
@@ -4,7 +4,7 @@ import {
4
4
  defaultKvStore,
5
5
  isSaBuiltinLocale,
6
6
  navMessages
7
- } from "./chunk-JN6HZGLV.js";
7
+ } from "./chunk-F7NRM6KI.js";
8
8
 
9
9
  // src/client/version.ts
10
10
  var ADMIN_UI_VERSION = "1.2.0";
@@ -136,7 +136,7 @@ var ManifestLoader = class {
136
136
  if (res.status !== 200) {
137
137
  throw new ManifestLoadError(
138
138
  res.status,
139
- `Manifest-Endpunkt antwortete HTTP ${res.status}`
139
+ `Manifest endpoint responded with HTTP ${res.status}`
140
140
  );
141
141
  }
142
142
  const body = await res.json();
@@ -565,6 +565,71 @@ function isProductionBoot(boot) {
565
565
  return boot?.project?.environment === "production";
566
566
  }
567
567
 
568
+ // src/client/resolve-plans.ts
569
+ function todayIsoDate() {
570
+ return (/* @__PURE__ */ new Date()).toISOString().slice(0, 10);
571
+ }
572
+ function isCurrentlyValid(v, today) {
573
+ if (!v.publishedAt) return false;
574
+ if (v.validFrom && v.validFrom.slice(0, 10) > today) return false;
575
+ if (v.validUntil && v.validUntil.slice(0, 10) < today) return false;
576
+ return true;
577
+ }
578
+ function isFutureScheduled(v, today) {
579
+ if (!v.publishedAt) return false;
580
+ if (!v.validFrom) return false;
581
+ return v.validFrom.slice(0, 10) > today;
582
+ }
583
+ function isExpired(v, today) {
584
+ if (!v.publishedAt) return false;
585
+ if (!v.validUntil) return false;
586
+ return v.validUntil.slice(0, 10) < today;
587
+ }
588
+ function resolvePlans({
589
+ plans,
590
+ versionsByPlanId,
591
+ tenantCountsByPlanKey,
592
+ today = todayIsoDate()
593
+ }) {
594
+ return [...plans].sort((a, b) => a.sortOrder - b.sortOrder || a.planKey.localeCompare(b.planKey)).map((plan) => {
595
+ const versions = versionsByPlanId[plan.id] ?? [];
596
+ const drafts = versions.filter((v) => !v.publishedAt);
597
+ const published = versions.filter((v) => Boolean(v.publishedAt));
598
+ const currentLive = published.find((v) => isCurrentlyValid(v, today)) ?? null;
599
+ const futureScheduled = published.filter((v) => isFutureScheduled(v, today)).sort((a, b) => (a.validFrom ?? "").localeCompare(b.validFrom ?? ""));
600
+ const primary = currentLive ?? futureScheduled[0] ?? null;
601
+ const seen = /* @__PURE__ */ new Set();
602
+ if (primary) seen.add(primary.id);
603
+ const subRows = [];
604
+ for (const v of [...futureScheduled, ...drafts]) {
605
+ if (seen.has(v.id)) continue;
606
+ subRows.push(v);
607
+ seen.add(v.id);
608
+ }
609
+ return {
610
+ plan,
611
+ planKey: plan.planKey,
612
+ label: plan.label,
613
+ description: plan.description ?? null,
614
+ currentLive,
615
+ primary,
616
+ subRows,
617
+ hasAnyVersion: versions.length > 0,
618
+ allExpired: versions.length > 0 && drafts.length === 0 && futureScheduled.length === 0 && published.every((v) => isExpired(v, today)),
619
+ draft: drafts[0] ?? null,
620
+ tenantCount: tenantCountsByPlanKey[plan.planKey] ?? 0
621
+ };
622
+ });
623
+ }
624
+ function countPlans(resolved) {
625
+ return {
626
+ plans: resolved.length,
627
+ live: resolved.filter((p) => p.currentLive !== null).length,
628
+ drafts: resolved.filter((p) => p.draft !== null).length,
629
+ tenants: resolved.reduce((sum, p) => sum + p.tenantCount, 0)
630
+ };
631
+ }
632
+
568
633
  export {
569
634
  ADMIN_UI_VERSION,
570
635
  HttpJsonError,
@@ -587,5 +652,11 @@ export {
587
652
  BatchColumnFetcher,
588
653
  createAdminResourceClient,
589
654
  resolveLoginBranding,
590
- isProductionBoot
655
+ isProductionBoot,
656
+ todayIsoDate,
657
+ isCurrentlyValid,
658
+ isFutureScheduled,
659
+ isExpired,
660
+ resolvePlans,
661
+ countPlans
591
662
  };