@saasicat/ui-vue 0.18.1 → 0.21.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (67) hide show
  1. package/dist/{catalog-JXdKdIqG.d.cts → catalog-BY_t9prv.d.cts} +1 -0
  2. package/dist/{catalog-JXdKdIqG.d.ts → catalog-BY_t9prv.d.ts} +1 -0
  3. package/dist/{chunk-Y5MWMWMD.js → chunk-7IFKVGZV.js} +1 -1
  4. package/dist/{chunk-CC4WK3DC.js → chunk-JN6HZGLV.js} +4 -4
  5. package/dist/{chunk-VRCVJTY4.js → chunk-OTP3OSSW.js} +1 -1
  6. package/dist/client/index.cjs +4 -4
  7. package/dist/client/index.d.cts +2 -2
  8. package/dist/client/index.d.ts +2 -2
  9. package/dist/client/index.js +2 -2
  10. package/dist/index.cjs +6 -6
  11. package/dist/index.d.cts +4 -4
  12. package/dist/index.d.ts +4 -4
  13. package/dist/index.js +3 -3
  14. package/dist/quasar/index.cjs +5 -0
  15. package/dist/quasar/index.d.cts +2 -2
  16. package/dist/quasar/index.d.ts +2 -2
  17. package/dist/quasar/index.js +2 -2
  18. package/dist/{use-super-admin-i18n-1nCOkvgi.d.cts → use-super-admin-i18n-DlJRGIVq.d.cts} +1 -1
  19. package/dist/{use-super-admin-i18n-BlqcD0N7.d.ts → use-super-admin-i18n-c_Eqsu9u.d.ts} +1 -1
  20. package/package.json +2 -2
  21. package/src/client/i18n/format.ts +7 -4
  22. package/src/client/i18n/messages/common.ts +2 -0
  23. package/src/components/admin-page/AdminBody.vue +40 -0
  24. package/src/components/admin-page/AdminHero.vue +32 -0
  25. package/src/components/admin-page/AdminPage.vue +16 -0
  26. package/src/components/admin-page/AdminSection.vue +38 -0
  27. package/src/components/plan-cockpit/PlanCockpit.vue +15 -0
  28. package/src/components/plan-cockpit/PlanCockpitAuditLog.vue +8 -8
  29. package/src/components/plan-cockpit/PlanCockpitDiffPanel.vue +10 -11
  30. package/src/components/plan-cockpit/PlanCockpitImpactPanel.vue +8 -8
  31. package/src/components/plan-cockpit/PlanCockpitVersions.vue +9 -11
  32. package/src/components/plan-detail/PlanAuditLog.vue +7 -8
  33. package/src/components/plan-detail/PlanDetail.vue +14 -1
  34. package/src/components/plan-detail/PlanVersionDiffPanel.vue +5 -8
  35. package/src/components/plan-detail/PlanVersionsPanel.vue +9 -11
  36. package/src/components/plan-list/PlanList.vue +224 -257
  37. package/src/pages-standard/AdminLayout.vue +4 -2
  38. package/src/pages-standard/AuditPage.vue +18 -43
  39. package/src/pages-standard/BundlesPage.vue +17 -34
  40. package/src/pages-standard/DashboardPage.vue +20 -51
  41. package/src/pages-standard/DiscoveryPage.vue +38 -51
  42. package/src/pages-standard/EmailHistoryPage.vue +20 -71
  43. package/src/pages-standard/MarketingCatalogPage.vue +304 -315
  44. package/src/pages-standard/PilotsPage.vue +24 -56
  45. package/src/pages-standard/PlansPage.vue +25 -22
  46. package/src/pages-standard/PlatformEmailPage.vue +19 -51
  47. package/src/pages-standard/PromoCodeDetailPage.vue +39 -50
  48. package/src/pages-standard/PromoCodesPage.vue +8 -15
  49. package/src/pages-standard/SubscriptionsPage.vue +9 -35
  50. package/src/pages-standard/SuperAdminSetupWizard.vue +2 -1
  51. package/src/pages-standard/TenantDetailPage.vue +79 -174
  52. package/src/pages-standard/TenantsPage.vue +8 -33
  53. package/src/pages-standard/UsersPage.vue +21 -54
  54. package/src/pages-standard/bundles-page/BundlesToolbar.vue +67 -0
  55. package/src/pages-standard/marketing-catalog/MarketingCatalogAdmin.vue +111 -73
  56. package/src/pages-standard/marketing-catalog/MarketingCatalogHeader.vue +54 -62
  57. package/src/pages-standard/marketing-catalog/MarketingCatalogPreview.vue +53 -35
  58. package/src/pages-standard/marketing-catalog/MarketingCatalogToolbar.vue +7 -7
  59. package/src/pages-standard/plans-page/PlansPageToast.vue +5 -5
  60. package/src/pages-standard/sa-theme.css +85 -29
  61. package/src/pages-standard/tenant-detail/TenantMasterData.vue +28 -0
  62. package/src/pages-standard/tenant-detail/TenantUsage.vue +31 -0
  63. package/src/pages-standard/tenant-detail/TenantUsers.vue +21 -0
  64. package/src/pages-standard/tenant-detail/types.ts +38 -0
  65. package/src/vue/use-mfa-prompt.ts +72 -0
  66. package/src/pages-standard/bundles-page/BundlesHeader.vue +0 -68
  67. package/src/pages-standard/discovery-page/DiscoveryHeader.vue +0 -34
@@ -391,6 +391,7 @@ declare const commonMessages: Record<SaBuiltinLocale, {
391
391
  loading: string;
392
392
  saving: string;
393
393
  loadingData: string;
394
+ noData: string;
394
395
  error: string;
395
396
  errorLoadFailed: string;
396
397
  errorSaveFailed: string;
@@ -391,6 +391,7 @@ declare const commonMessages: Record<SaBuiltinLocale, {
391
391
  loading: string;
392
392
  saving: string;
393
393
  loadingData: string;
394
+ noData: string;
394
395
  error: string;
395
396
  errorLoadFailed: string;
396
397
  errorSaveFailed: string;
@@ -1,7 +1,7 @@
1
1
  import {
2
2
  createSaCatalog,
3
3
  defaultKvStore
4
- } from "./chunk-CC4WK3DC.js";
4
+ } from "./chunk-JN6HZGLV.js";
5
5
 
6
6
  // src/vue/super-admin-context.ts
7
7
  var SUPER_ADMIN_BRAND_KEY = /* @__PURE__ */ Symbol.for(
@@ -79,11 +79,9 @@ function mergeMessages(base, overrides) {
79
79
  }
80
80
 
81
81
  // src/client/i18n/format.ts
82
+ import { formatErrorMessage } from "@saasicat/types";
82
83
  function formatMessage(template, params) {
83
- return template.replace(/\{(\w+)\}/g, (match, name) => {
84
- const value = params[name];
85
- return value === void 0 ? match : String(value);
86
- });
84
+ return formatErrorMessage(template, params);
87
85
  }
88
86
 
89
87
  // src/client/i18n/currency.ts
@@ -603,6 +601,7 @@ var commonMessages = defineMessages(
603
601
  loading: "Lade \u2026",
604
602
  saving: "Speichere \u2026",
605
603
  loadingData: "Daten werden geladen\u2026",
604
+ noData: "Keine Daten vorhanden",
606
605
  error: "Fehler",
607
606
  errorLoadFailed: "Laden fehlgeschlagen",
608
607
  errorSaveFailed: "Speichern fehlgeschlagen",
@@ -673,6 +672,7 @@ var commonMessages = defineMessages(
673
672
  loading: "Loading \u2026",
674
673
  saving: "Saving \u2026",
675
674
  loadingData: "Loading data\u2026",
675
+ noData: "No data available",
676
676
  error: "Error",
677
677
  errorLoadFailed: "Failed to load",
678
678
  errorSaveFailed: "Failed to save",
@@ -4,7 +4,7 @@ import {
4
4
  defaultKvStore,
5
5
  isSaBuiltinLocale,
6
6
  navMessages
7
- } from "./chunk-CC4WK3DC.js";
7
+ } from "./chunk-JN6HZGLV.js";
8
8
 
9
9
  // src/client/version.ts
10
10
  var ADMIN_UI_VERSION = "1.2.0";
@@ -732,11 +732,9 @@ function queryString(params) {
732
732
  }
733
733
 
734
734
  // src/client/i18n/format.ts
735
+ var import_types4 = require("@saasicat/types");
735
736
  function formatMessage(template, params) {
736
- return template.replace(/\{(\w+)\}/g, (match, name) => {
737
- const value = params[name];
738
- return value === void 0 ? match : String(value);
739
- });
737
+ return (0, import_types4.formatErrorMessage)(template, params);
740
738
  }
741
739
 
742
740
  // src/client/i18n/currency.ts
@@ -1256,6 +1254,7 @@ var commonMessages = defineMessages(
1256
1254
  loading: "Lade \u2026",
1257
1255
  saving: "Speichere \u2026",
1258
1256
  loadingData: "Daten werden geladen\u2026",
1257
+ noData: "Keine Daten vorhanden",
1259
1258
  error: "Fehler",
1260
1259
  errorLoadFailed: "Laden fehlgeschlagen",
1261
1260
  errorSaveFailed: "Speichern fehlgeschlagen",
@@ -1326,6 +1325,7 @@ var commonMessages = defineMessages(
1326
1325
  loading: "Loading \u2026",
1327
1326
  saving: "Saving \u2026",
1328
1327
  loadingData: "Loading data\u2026",
1328
+ noData: "No data available",
1329
1329
  error: "Error",
1330
1330
  errorLoadFailed: "Failed to load",
1331
1331
  errorSaveFailed: "Failed to save",
@@ -1,5 +1,5 @@
1
- import { H as HttpClient, K as KvStore, S as SaLocale, w as SaNavMessages } from '../catalog-JXdKdIqG.cjs';
2
- export { f as ActionDefNotInManifestError, A as ActionHandler, e as ActionRegistry, D as DEFAULT_SA_LOCALE, g as HttpResponse, M as MessageTree, h as MissingHandlerError, P as PartialMessages, R as ResolvedAction, i as SA_INTL_LOCALES, j as SA_LOCALES, k as SA_LOCALE_LABELS, l as SA_MESSAGES, m as SaBuiltinLocale, n as SaCatalog, o as SaCatalogOptions, c as SaLocaleDefinition, b as SaLocaleOption, a as SaMessages, d as SaMessagesOverrides, T as TranslationOf, p as createSaCatalog, q as defaultHttpClient, r as defaultKvStore, s as defineMessages, t as isSaBuiltinLocale, u as mergeMessages, v as resolveMessages } from '../catalog-JXdKdIqG.cjs';
1
+ import { H as HttpClient, K as KvStore, S as SaLocale, w as SaNavMessages } from '../catalog-BY_t9prv.cjs';
2
+ export { f as ActionDefNotInManifestError, A as ActionHandler, e as ActionRegistry, D as DEFAULT_SA_LOCALE, g as HttpResponse, M as MessageTree, h as MissingHandlerError, P as PartialMessages, R as ResolvedAction, i as SA_INTL_LOCALES, j as SA_LOCALES, k as SA_LOCALE_LABELS, l as SA_MESSAGES, m as SaBuiltinLocale, n as SaCatalog, o as SaCatalogOptions, c as SaLocaleDefinition, b as SaLocaleOption, a as SaMessages, d as SaMessagesOverrides, T as TranslationOf, p as createSaCatalog, q as defaultHttpClient, r as defaultKvStore, s as defineMessages, t as isSaBuiltinLocale, u as mergeMessages, v as resolveMessages } from '../catalog-BY_t9prv.cjs';
3
3
  import { PublicBootResponse, AdminManifest, StandardPageKey, TenantColumnDef, PromoCodeRecord, AdminTenantDetail, AdminUserListFilter, AdminUserListRow, AdminAuditListFilter, AuditEntry, AdminSubscriptionListRow } from '@saasicat/types';
4
4
 
5
5
  declare const ADMIN_UI_VERSION = "1.2.0";
@@ -1,5 +1,5 @@
1
- import { H as HttpClient, K as KvStore, S as SaLocale, w as SaNavMessages } from '../catalog-JXdKdIqG.js';
2
- export { f as ActionDefNotInManifestError, A as ActionHandler, e as ActionRegistry, D as DEFAULT_SA_LOCALE, g as HttpResponse, M as MessageTree, h as MissingHandlerError, P as PartialMessages, R as ResolvedAction, i as SA_INTL_LOCALES, j as SA_LOCALES, k as SA_LOCALE_LABELS, l as SA_MESSAGES, m as SaBuiltinLocale, n as SaCatalog, o as SaCatalogOptions, c as SaLocaleDefinition, b as SaLocaleOption, a as SaMessages, d as SaMessagesOverrides, T as TranslationOf, p as createSaCatalog, q as defaultHttpClient, r as defaultKvStore, s as defineMessages, t as isSaBuiltinLocale, u as mergeMessages, v as resolveMessages } from '../catalog-JXdKdIqG.js';
1
+ import { H as HttpClient, K as KvStore, S as SaLocale, w as SaNavMessages } from '../catalog-BY_t9prv.js';
2
+ export { f as ActionDefNotInManifestError, A as ActionHandler, e as ActionRegistry, D as DEFAULT_SA_LOCALE, g as HttpResponse, M as MessageTree, h as MissingHandlerError, P as PartialMessages, R as ResolvedAction, i as SA_INTL_LOCALES, j as SA_LOCALES, k as SA_LOCALE_LABELS, l as SA_MESSAGES, m as SaBuiltinLocale, n as SaCatalog, o as SaCatalogOptions, c as SaLocaleDefinition, b as SaLocaleOption, a as SaMessages, d as SaMessagesOverrides, T as TranslationOf, p as createSaCatalog, q as defaultHttpClient, r as defaultKvStore, s as defineMessages, t as isSaBuiltinLocale, u as mergeMessages, v as resolveMessages } from '../catalog-BY_t9prv.js';
3
3
  import { PublicBootResponse, AdminManifest, StandardPageKey, TenantColumnDef, PromoCodeRecord, AdminTenantDetail, AdminUserListFilter, AdminUserListRow, AdminAuditListFilter, AuditEntry, AdminSubscriptionListRow } from '@saasicat/types';
4
4
 
5
5
  declare const ADMIN_UI_VERSION = "1.2.0";
@@ -21,7 +21,7 @@ import {
21
21
  resolveExtension,
22
22
  resolveLoginBranding,
23
23
  trimTrailingSlashes
24
- } from "../chunk-VRCVJTY4.js";
24
+ } from "../chunk-OTP3OSSW.js";
25
25
  import {
26
26
  DEFAULT_SA_LOCALE,
27
27
  SA_INTL_LOCALES,
@@ -37,7 +37,7 @@ import {
37
37
  isSaBuiltinLocale,
38
38
  mergeMessages,
39
39
  resolveMessages
40
- } from "../chunk-CC4WK3DC.js";
40
+ } from "../chunk-JN6HZGLV.js";
41
41
  export {
42
42
  ADMIN_UI_VERSION,
43
43
  ActionDefNotInManifestError,
package/dist/index.cjs CHANGED
@@ -807,11 +807,9 @@ function queryString(params) {
807
807
  }
808
808
 
809
809
  // src/client/i18n/format.ts
810
+ var import_types4 = require("@saasicat/types");
810
811
  function formatMessage(template, params) {
811
- return template.replace(/\{(\w+)\}/g, (match, name) => {
812
- const value = params[name];
813
- return value === void 0 ? match : String(value);
814
- });
812
+ return (0, import_types4.formatErrorMessage)(template, params);
815
813
  }
816
814
 
817
815
  // src/client/i18n/currency.ts
@@ -1331,6 +1329,7 @@ var commonMessages = defineMessages(
1331
1329
  loading: "Lade \u2026",
1332
1330
  saving: "Speichere \u2026",
1333
1331
  loadingData: "Daten werden geladen\u2026",
1332
+ noData: "Keine Daten vorhanden",
1334
1333
  error: "Fehler",
1335
1334
  errorLoadFailed: "Laden fehlgeschlagen",
1336
1335
  errorSaveFailed: "Speichern fehlgeschlagen",
@@ -1401,6 +1400,7 @@ var commonMessages = defineMessages(
1401
1400
  loading: "Loading \u2026",
1402
1401
  saving: "Saving \u2026",
1403
1402
  loadingData: "Loading data\u2026",
1403
+ noData: "No data available",
1404
1404
  error: "Error",
1405
1405
  errorLoadFailed: "Failed to load",
1406
1406
  errorSaveFailed: "Failed to save",
@@ -4515,7 +4515,7 @@ function useTenantBilling(options = {}) {
4515
4515
 
4516
4516
  // src/vue/use-subscription-draft.ts
4517
4517
  var import_vue12 = require("vue");
4518
- var import_types11 = require("@saasicat/types");
4518
+ var import_types12 = require("@saasicat/types");
4519
4519
  var DEFAULT_YEARLY_FACTOR = 10;
4520
4520
  function unwrap(source) {
4521
4521
  if (source && typeof source === "object" && "value" in source) {
@@ -4555,7 +4555,7 @@ function useSubscriptionDraft(options) {
4555
4555
  const planFeatures = selectedPlan.value?.features ?? [];
4556
4556
  const selected = selectedBundles.value;
4557
4557
  const keptIds = new Set(
4558
- (0, import_types11.selectChargeableBundles)(planFeatures, selected).map((b) => b.bundleVersionId)
4558
+ (0, import_types12.selectChargeableBundles)(planFeatures, selected).map((b) => b.bundleVersionId)
4559
4559
  );
4560
4560
  return selected.filter((b) => keptIds.has(b.bundleVersionId));
4561
4561
  });
package/dist/index.d.cts CHANGED
@@ -1,9 +1,9 @@
1
1
  import { BootLoaderOptions, ManifestLoaderOptions, BuildRouteEntry, SidebarSection, NavBuilderOptions, BatchColumnData, BatchColumnFetcherOptions, BootLoader, ManifestLoader } from './client/index.cjs';
2
2
  export { ADMIN_UI_VERSION, AdminPromoListFilter, AdminPromoListRow, AdminResourceClientOptions, BatchColumnDriftError, BatchColumnFetcher, BatchColumnRow, BatchColumnValue, BootLoadError, CachedManifestEntry, DEFAULT_STANDARD_PAGE_ROUTES, HttpJsonError, LoginBootProject, LoginBrandFallback, LoginBranding, ManifestLoadError, MessageParams, ParamStyle, SidebarItem, buildRoutes, buildSidebar, createAdminResourceClient, defaultSectionOrder, formatCurrency, formatMessage, getJson, isProductionBoot, postJson, resolveExtension, resolveLoginBranding, trimTrailingSlashes } from './client/index.cjs';
3
- import { H as HttpClient, e as ActionRegistry, A as ActionHandler, K as KvStore, S as SaLocale } from './catalog-JXdKdIqG.cjs';
4
- export { f as ActionDefNotInManifestError, D as DEFAULT_SA_LOCALE, g as HttpResponse, M as MessageTree, h as MissingHandlerError, P as PartialMessages, R as ResolvedAction, i as SA_INTL_LOCALES, j as SA_LOCALES, k as SA_LOCALE_LABELS, l as SA_MESSAGES, m as SaBuiltinLocale, n as SaCatalog, o as SaCatalogOptions, c as SaLocaleDefinition, b as SaLocaleOption, a as SaMessages, d as SaMessagesOverrides, T as TranslationOf, p as createSaCatalog, q as defaultHttpClient, r as defaultKvStore, s as defineMessages, t as isSaBuiltinLocale, u as mergeMessages, v as resolveMessages } from './catalog-JXdKdIqG.cjs';
5
- import { A as ActionsMap, a as SuperAdminBrand, b as SuperAdminEndpoints, E as ExtensionsMap, c as SuperAdminLoginAdapter } from './use-super-admin-i18n-1nCOkvgi.cjs';
6
- export { f as ExtensionLoader, I as InstallPlugin, g as SA_LOCALE_STORAGE_KEY, h as SUPER_ADMIN_ACTIONS_KEY, i as SUPER_ADMIN_BRAND_KEY, j as SUPER_ADMIN_ENDPOINTS_KEY, k as SUPER_ADMIN_EXTENSIONS_KEY, l as SUPER_ADMIN_HTTP_KEY, m as SUPER_ADMIN_I18N_KEY, n as SUPER_ADMIN_LOGIN_ADAPTER_KEY, o as SUPER_ADMIN_MANIFEST_KEY, p as SUPER_ADMIN_NOTIFY_KEY, q as SuperAdminAuthGuardOptions, S as SuperAdminGuardOptions, e as SuperAdminI18n, d as SuperAdminI18nOptions, r as SuperAdminLoginResult, s as SuperAdminManifestGuardOptions, U as UiNotify, t as UiNotifyKind, u as UiNotifyOptions, v as buildNavigationGuard, w as createSuperAdminI18n, x as useSaMessages, y as useSuperAdminI18n } from './use-super-admin-i18n-1nCOkvgi.cjs';
3
+ import { H as HttpClient, e as ActionRegistry, A as ActionHandler, K as KvStore, S as SaLocale } from './catalog-BY_t9prv.cjs';
4
+ export { f as ActionDefNotInManifestError, D as DEFAULT_SA_LOCALE, g as HttpResponse, M as MessageTree, h as MissingHandlerError, P as PartialMessages, R as ResolvedAction, i as SA_INTL_LOCALES, j as SA_LOCALES, k as SA_LOCALE_LABELS, l as SA_MESSAGES, m as SaBuiltinLocale, n as SaCatalog, o as SaCatalogOptions, c as SaLocaleDefinition, b as SaLocaleOption, a as SaMessages, d as SaMessagesOverrides, T as TranslationOf, p as createSaCatalog, q as defaultHttpClient, r as defaultKvStore, s as defineMessages, t as isSaBuiltinLocale, u as mergeMessages, v as resolveMessages } from './catalog-BY_t9prv.cjs';
5
+ import { A as ActionsMap, a as SuperAdminBrand, b as SuperAdminEndpoints, E as ExtensionsMap, c as SuperAdminLoginAdapter } from './use-super-admin-i18n-DlJRGIVq.cjs';
6
+ export { f as ExtensionLoader, I as InstallPlugin, g as SA_LOCALE_STORAGE_KEY, h as SUPER_ADMIN_ACTIONS_KEY, i as SUPER_ADMIN_BRAND_KEY, j as SUPER_ADMIN_ENDPOINTS_KEY, k as SUPER_ADMIN_EXTENSIONS_KEY, l as SUPER_ADMIN_HTTP_KEY, m as SUPER_ADMIN_I18N_KEY, n as SUPER_ADMIN_LOGIN_ADAPTER_KEY, o as SUPER_ADMIN_MANIFEST_KEY, p as SUPER_ADMIN_NOTIFY_KEY, q as SuperAdminAuthGuardOptions, S as SuperAdminGuardOptions, e as SuperAdminI18n, d as SuperAdminI18nOptions, r as SuperAdminLoginResult, s as SuperAdminManifestGuardOptions, U as UiNotify, t as UiNotifyKind, u as UiNotifyOptions, v as buildNavigationGuard, w as createSuperAdminI18n, x as useSaMessages, y as useSuperAdminI18n } from './use-super-admin-i18n-DlJRGIVq.cjs';
7
7
  import { AdminManifest, TenantListFilter, TenantDto, AuditQuery, AuditEntry, FeatureUiRegistry, PromoPreviewResponse, OnboardingSelectionRequest, PublicMarketingBundle, FeatureDef, FeatureKey, PublicBootResponse, DiscoverySnapshot, CapabilityCatalogEntryRow, FeatureCatalogEntryRow, QuotaCatalogEntryRow, ReviewCatalogEntryData, CatalogEntryI18n, UpdateCatalogEntryBaseData, SyncDiscoveryResult, BundleVersionRow, CreateBundleVersionDraftData, BundleVersionMutationResult, UpdateBundleVersionDraftData, BundleRow, CreateBundleData, UpdateBundleData, SubscriptionBundleRecord, MarketingProjectionFilter, MarketingProjectionRow, CreateMarketingProjectionData, UpdateMarketingProjectionData, PromotionRow, CreatePromotionData, UpdatePromotionData, PlanVersionRow, CreatePlanVersionDraftData, PlanVersionMutationResult, UpdatePlanVersionDraftData, PlanRow, CreatePlanData, UpdatePlanData, TenantActionDef } from '@saasicat/types';
8
8
  import { RouteRecordRaw, NavigationGuardWithThis } from 'vue-router';
9
9
  import * as vue from 'vue';
package/dist/index.d.ts CHANGED
@@ -1,9 +1,9 @@
1
1
  import { BootLoaderOptions, ManifestLoaderOptions, BuildRouteEntry, SidebarSection, NavBuilderOptions, BatchColumnData, BatchColumnFetcherOptions, BootLoader, ManifestLoader } from './client/index.js';
2
2
  export { ADMIN_UI_VERSION, AdminPromoListFilter, AdminPromoListRow, AdminResourceClientOptions, BatchColumnDriftError, BatchColumnFetcher, BatchColumnRow, BatchColumnValue, BootLoadError, CachedManifestEntry, DEFAULT_STANDARD_PAGE_ROUTES, HttpJsonError, LoginBootProject, LoginBrandFallback, LoginBranding, ManifestLoadError, MessageParams, ParamStyle, SidebarItem, buildRoutes, buildSidebar, createAdminResourceClient, defaultSectionOrder, formatCurrency, formatMessage, getJson, isProductionBoot, postJson, resolveExtension, resolveLoginBranding, trimTrailingSlashes } from './client/index.js';
3
- import { H as HttpClient, e as ActionRegistry, A as ActionHandler, K as KvStore, S as SaLocale } from './catalog-JXdKdIqG.js';
4
- export { f as ActionDefNotInManifestError, D as DEFAULT_SA_LOCALE, g as HttpResponse, M as MessageTree, h as MissingHandlerError, P as PartialMessages, R as ResolvedAction, i as SA_INTL_LOCALES, j as SA_LOCALES, k as SA_LOCALE_LABELS, l as SA_MESSAGES, m as SaBuiltinLocale, n as SaCatalog, o as SaCatalogOptions, c as SaLocaleDefinition, b as SaLocaleOption, a as SaMessages, d as SaMessagesOverrides, T as TranslationOf, p as createSaCatalog, q as defaultHttpClient, r as defaultKvStore, s as defineMessages, t as isSaBuiltinLocale, u as mergeMessages, v as resolveMessages } from './catalog-JXdKdIqG.js';
5
- import { A as ActionsMap, a as SuperAdminBrand, b as SuperAdminEndpoints, E as ExtensionsMap, c as SuperAdminLoginAdapter } from './use-super-admin-i18n-BlqcD0N7.js';
6
- export { f as ExtensionLoader, I as InstallPlugin, g as SA_LOCALE_STORAGE_KEY, h as SUPER_ADMIN_ACTIONS_KEY, i as SUPER_ADMIN_BRAND_KEY, j as SUPER_ADMIN_ENDPOINTS_KEY, k as SUPER_ADMIN_EXTENSIONS_KEY, l as SUPER_ADMIN_HTTP_KEY, m as SUPER_ADMIN_I18N_KEY, n as SUPER_ADMIN_LOGIN_ADAPTER_KEY, o as SUPER_ADMIN_MANIFEST_KEY, p as SUPER_ADMIN_NOTIFY_KEY, q as SuperAdminAuthGuardOptions, S as SuperAdminGuardOptions, e as SuperAdminI18n, d as SuperAdminI18nOptions, r as SuperAdminLoginResult, s as SuperAdminManifestGuardOptions, U as UiNotify, t as UiNotifyKind, u as UiNotifyOptions, v as buildNavigationGuard, w as createSuperAdminI18n, x as useSaMessages, y as useSuperAdminI18n } from './use-super-admin-i18n-BlqcD0N7.js';
3
+ import { H as HttpClient, e as ActionRegistry, A as ActionHandler, K as KvStore, S as SaLocale } from './catalog-BY_t9prv.js';
4
+ export { f as ActionDefNotInManifestError, D as DEFAULT_SA_LOCALE, g as HttpResponse, M as MessageTree, h as MissingHandlerError, P as PartialMessages, R as ResolvedAction, i as SA_INTL_LOCALES, j as SA_LOCALES, k as SA_LOCALE_LABELS, l as SA_MESSAGES, m as SaBuiltinLocale, n as SaCatalog, o as SaCatalogOptions, c as SaLocaleDefinition, b as SaLocaleOption, a as SaMessages, d as SaMessagesOverrides, T as TranslationOf, p as createSaCatalog, q as defaultHttpClient, r as defaultKvStore, s as defineMessages, t as isSaBuiltinLocale, u as mergeMessages, v as resolveMessages } from './catalog-BY_t9prv.js';
5
+ import { A as ActionsMap, a as SuperAdminBrand, b as SuperAdminEndpoints, E as ExtensionsMap, c as SuperAdminLoginAdapter } from './use-super-admin-i18n-c_Eqsu9u.js';
6
+ export { f as ExtensionLoader, I as InstallPlugin, g as SA_LOCALE_STORAGE_KEY, h as SUPER_ADMIN_ACTIONS_KEY, i as SUPER_ADMIN_BRAND_KEY, j as SUPER_ADMIN_ENDPOINTS_KEY, k as SUPER_ADMIN_EXTENSIONS_KEY, l as SUPER_ADMIN_HTTP_KEY, m as SUPER_ADMIN_I18N_KEY, n as SUPER_ADMIN_LOGIN_ADAPTER_KEY, o as SUPER_ADMIN_MANIFEST_KEY, p as SUPER_ADMIN_NOTIFY_KEY, q as SuperAdminAuthGuardOptions, S as SuperAdminGuardOptions, e as SuperAdminI18n, d as SuperAdminI18nOptions, r as SuperAdminLoginResult, s as SuperAdminManifestGuardOptions, U as UiNotify, t as UiNotifyKind, u as UiNotifyOptions, v as buildNavigationGuard, w as createSuperAdminI18n, x as useSaMessages, y as useSuperAdminI18n } from './use-super-admin-i18n-c_Eqsu9u.js';
7
7
  import { AdminManifest, TenantListFilter, TenantDto, AuditQuery, AuditEntry, FeatureUiRegistry, PromoPreviewResponse, OnboardingSelectionRequest, PublicMarketingBundle, FeatureDef, FeatureKey, PublicBootResponse, DiscoverySnapshot, CapabilityCatalogEntryRow, FeatureCatalogEntryRow, QuotaCatalogEntryRow, ReviewCatalogEntryData, CatalogEntryI18n, UpdateCatalogEntryBaseData, SyncDiscoveryResult, BundleVersionRow, CreateBundleVersionDraftData, BundleVersionMutationResult, UpdateBundleVersionDraftData, BundleRow, CreateBundleData, UpdateBundleData, SubscriptionBundleRecord, MarketingProjectionFilter, MarketingProjectionRow, CreateMarketingProjectionData, UpdateMarketingProjectionData, PromotionRow, CreatePromotionData, UpdatePromotionData, PlanVersionRow, CreatePlanVersionDraftData, PlanVersionMutationResult, UpdatePlanVersionDraftData, PlanRow, CreatePlanData, UpdatePlanData, TenantActionDef } from '@saasicat/types';
8
8
  import { RouteRecordRaw, NavigationGuardWithThis } from 'vue-router';
9
9
  import * as vue from 'vue';
package/dist/index.js CHANGED
@@ -21,7 +21,7 @@ import {
21
21
  resolveExtension,
22
22
  resolveLoginBranding,
23
23
  trimTrailingSlashes
24
- } from "./chunk-VRCVJTY4.js";
24
+ } from "./chunk-OTP3OSSW.js";
25
25
  import {
26
26
  SA_LOCALE_STORAGE_KEY,
27
27
  SUPER_ADMIN_ACTIONS_KEY,
@@ -37,7 +37,7 @@ import {
37
37
  createSuperAdminI18n,
38
38
  useSaMessages,
39
39
  useSuperAdminI18n
40
- } from "./chunk-Y5MWMWMD.js";
40
+ } from "./chunk-7IFKVGZV.js";
41
41
  import {
42
42
  DEFAULT_SA_LOCALE,
43
43
  SA_INTL_LOCALES,
@@ -53,7 +53,7 @@ import {
53
53
  isSaBuiltinLocale,
54
54
  mergeMessages,
55
55
  resolveMessages
56
- } from "./chunk-CC4WK3DC.js";
56
+ } from "./chunk-JN6HZGLV.js";
57
57
 
58
58
  // src/vue/use-super-admin-context.ts
59
59
  import { inject } from "vue";
@@ -167,6 +167,9 @@ function mergeMessages(base, overrides) {
167
167
  return result;
168
168
  }
169
169
 
170
+ // src/client/i18n/format.ts
171
+ var import_types = require("@saasicat/types");
172
+
170
173
  // src/client/i18n/messages/audit.ts
171
174
  var auditMessages = defineMessages(
172
175
  {
@@ -661,6 +664,7 @@ var commonMessages = defineMessages(
661
664
  loading: "Lade \u2026",
662
665
  saving: "Speichere \u2026",
663
666
  loadingData: "Daten werden geladen\u2026",
667
+ noData: "Keine Daten vorhanden",
664
668
  error: "Fehler",
665
669
  errorLoadFailed: "Laden fehlgeschlagen",
666
670
  errorSaveFailed: "Speichern fehlgeschlagen",
@@ -731,6 +735,7 @@ var commonMessages = defineMessages(
731
735
  loading: "Loading \u2026",
732
736
  saving: "Saving \u2026",
733
737
  loadingData: "Loading data\u2026",
738
+ noData: "No data available",
734
739
  error: "Error",
735
740
  errorLoadFailed: "Failed to load",
736
741
  errorSaveFailed: "Failed to save",
@@ -2,8 +2,8 @@ import { Component, App } from 'vue';
2
2
  import { QuasarPluginOptions } from 'quasar';
3
3
  import { Pinia } from 'pinia';
4
4
  import { RouteRecordRaw, RouterHistory, Router } from 'vue-router';
5
- import { H as HttpClient } from '../catalog-JXdKdIqG.cjs';
6
- import { S as SuperAdminGuardOptions, a as SuperAdminBrand, b as SuperAdminEndpoints, E as ExtensionsMap, A as ActionsMap, c as SuperAdminLoginAdapter, U as UiNotify, I as InstallPlugin, d as SuperAdminI18nOptions, e as SuperAdminI18n } from '../use-super-admin-i18n-1nCOkvgi.cjs';
5
+ import { H as HttpClient } from '../catalog-BY_t9prv.cjs';
6
+ import { S as SuperAdminGuardOptions, a as SuperAdminBrand, b as SuperAdminEndpoints, E as ExtensionsMap, A as ActionsMap, c as SuperAdminLoginAdapter, U as UiNotify, I as InstallPlugin, d as SuperAdminI18nOptions, e as SuperAdminI18n } from '../use-super-admin-i18n-DlJRGIVq.cjs';
7
7
  import '@saasicat/types';
8
8
 
9
9
  interface CreateSuperAdminAppOptions extends SuperAdminGuardOptions {
@@ -2,8 +2,8 @@ import { Component, App } from 'vue';
2
2
  import { QuasarPluginOptions } from 'quasar';
3
3
  import { Pinia } from 'pinia';
4
4
  import { RouteRecordRaw, RouterHistory, Router } from 'vue-router';
5
- import { H as HttpClient } from '../catalog-JXdKdIqG.js';
6
- import { S as SuperAdminGuardOptions, a as SuperAdminBrand, b as SuperAdminEndpoints, E as ExtensionsMap, A as ActionsMap, c as SuperAdminLoginAdapter, U as UiNotify, I as InstallPlugin, d as SuperAdminI18nOptions, e as SuperAdminI18n } from '../use-super-admin-i18n-BlqcD0N7.js';
5
+ import { H as HttpClient } from '../catalog-BY_t9prv.js';
6
+ import { S as SuperAdminGuardOptions, a as SuperAdminBrand, b as SuperAdminEndpoints, E as ExtensionsMap, A as ActionsMap, c as SuperAdminLoginAdapter, U as UiNotify, I as InstallPlugin, d as SuperAdminI18nOptions, e as SuperAdminI18n } from '../use-super-admin-i18n-c_Eqsu9u.js';
7
7
  import '@saasicat/types';
8
8
 
9
9
  interface CreateSuperAdminAppOptions extends SuperAdminGuardOptions {
@@ -10,10 +10,10 @@ import {
10
10
  SUPER_ADMIN_NOTIFY_KEY,
11
11
  buildNavigationGuard,
12
12
  createSuperAdminI18n
13
- } from "../chunk-Y5MWMWMD.js";
13
+ } from "../chunk-7IFKVGZV.js";
14
14
  import {
15
15
  defaultHttpClient
16
- } from "../chunk-CC4WK3DC.js";
16
+ } from "../chunk-JN6HZGLV.js";
17
17
 
18
18
  // src/quasar/create-super-admin-app.ts
19
19
  import { createApp } from "vue";
@@ -1,7 +1,7 @@
1
1
  import { Component, App, InjectionKey, Ref, ComputedRef } from 'vue';
2
2
  import { NavigationGuardWithThis } from 'vue-router';
3
3
  import { ActionKey, ComponentKey, AdminManifest } from '@saasicat/types';
4
- import { A as ActionHandler, H as HttpClient, S as SaLocale, a as SaMessages, b as SaLocaleOption, c as SaLocaleDefinition, d as SaMessagesOverrides, K as KvStore } from './catalog-JXdKdIqG.cjs';
4
+ import { A as ActionHandler, H as HttpClient, S as SaLocale, a as SaMessages, b as SaLocaleOption, c as SaLocaleDefinition, d as SaMessagesOverrides, K as KvStore } from './catalog-BY_t9prv.cjs';
5
5
 
6
6
  /**
7
7
  * App-specific branding data that the platform `AdminLayout` and other
@@ -1,7 +1,7 @@
1
1
  import { Component, App, InjectionKey, Ref, ComputedRef } from 'vue';
2
2
  import { NavigationGuardWithThis } from 'vue-router';
3
3
  import { ActionKey, ComponentKey, AdminManifest } from '@saasicat/types';
4
- import { A as ActionHandler, H as HttpClient, S as SaLocale, a as SaMessages, b as SaLocaleOption, c as SaLocaleDefinition, d as SaMessagesOverrides, K as KvStore } from './catalog-JXdKdIqG.js';
4
+ import { A as ActionHandler, H as HttpClient, S as SaLocale, a as SaMessages, b as SaLocaleOption, c as SaLocaleDefinition, d as SaMessagesOverrides, K as KvStore } from './catalog-BY_t9prv.js';
5
5
 
6
6
  /**
7
7
  * App-specific branding data that the platform `AdminLayout` and other
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@saasicat/ui-vue",
3
- "version": "0.18.1",
3
+ "version": "0.21.0",
4
4
  "description": "Vue 3 components, resource clients and composables for the SuperAdmin UI shell. Provides boot and manifest loaders, navigation, actions and standard pages.",
5
5
  "type": "module",
6
6
  "main": "./dist/index.cjs",
@@ -53,7 +53,7 @@
53
53
  "src"
54
54
  ],
55
55
  "dependencies": {
56
- "@saasicat/types": "^0.18.1"
56
+ "@saasicat/types": "^0.21.0"
57
57
  },
58
58
  "peerDependencies": {
59
59
  "pinia": "^2.0.0 || ^3.0.0",
@@ -1,12 +1,15 @@
1
1
  // Placeholder interpolation for catalog messages: `{name}` is replaced with
2
2
  // `params.name`. Unknown placeholders stay verbatim so a missing param is
3
3
  // visible in the UI instead of silently disappearing.
4
+ //
5
+ // The implementation lives in `@saasicat/types` because the shipped error-text
6
+ // catalogue needs the same interpolation and must not depend on a UI package.
7
+ // This stays as the name the UI code already imports.
8
+
9
+ import { formatErrorMessage } from '@saasicat/types';
4
10
 
5
11
  export type MessageParams = Record<string, string | number>;
6
12
 
7
13
  export function formatMessage(template: string, params: MessageParams): string {
8
- return template.replace(/\{(\w+)\}/g, (match, name: string) => {
9
- const value = params[name];
10
- return value === undefined ? match : String(value);
11
- });
14
+ return formatErrorMessage(template, params);
12
15
  }
@@ -27,6 +27,7 @@ export const commonMessages = defineMessages(
27
27
  loading: 'Lade …',
28
28
  saving: 'Speichere …',
29
29
  loadingData: 'Daten werden geladen…',
30
+ noData: 'Keine Daten vorhanden',
30
31
  error: 'Fehler',
31
32
  errorLoadFailed: 'Laden fehlgeschlagen',
32
33
  errorSaveFailed: 'Speichern fehlgeschlagen',
@@ -97,6 +98,7 @@ export const commonMessages = defineMessages(
97
98
  loading: 'Loading …',
98
99
  saving: 'Saving …',
99
100
  loadingData: 'Loading data…',
101
+ noData: 'No data available',
100
102
  error: 'Error',
101
103
  errorLoadFailed: 'Failed to load',
102
104
  errorSaveFailed: 'Failed to save',
@@ -0,0 +1,40 @@
1
+ <template>
2
+ <div class="sa-page-body">
3
+ <div v-if="loading" class="sa-page-body__state">
4
+ <slot name="loading">
5
+ <q-spinner size="32px" />
6
+ <span>{{ loadingText ?? common.loadingData }}</span>
7
+ </slot>
8
+ </div>
9
+
10
+ <div v-else-if="empty" class="sa-page-body__state sa-page-body__state--empty">
11
+ <slot name="empty">{{ emptyText ?? common.noData }}</slot>
12
+ </div>
13
+
14
+ <slot v-else />
15
+ </div>
16
+ </template>
17
+
18
+ <script setup lang="ts">
19
+ import { useSaMessages } from '../../vue/use-super-admin-i18n.js';
20
+
21
+ // The page body: everything below the hero, plus the two states that body is
22
+ // almost always in before it has content.
23
+ //
24
+ // Ten of the fifteen standard pages used to spell out their own spinner and
25
+ // their own empty text, each with a private class for the same centred,
26
+ // muted block. The states live here so a page describes *when* it is empty
27
+ // rather than *what* empty looks like.
28
+ //
29
+ // Like AdminPage, this is deliberately not <main>: the landmark belongs to
30
+ // AdminLayout and must appear once per document.
31
+ defineProps<{
32
+ loading?: boolean;
33
+ /** Shown when not loading. The page decides what counts as empty. */
34
+ empty?: boolean;
35
+ loadingText?: string;
36
+ emptyText?: string;
37
+ }>();
38
+
39
+ const common = useSaMessages('common');
40
+ </script>
@@ -0,0 +1,32 @@
1
+ <template>
2
+ <header class="sa-page-head">
3
+ <div>
4
+ <slot name="before-title" />
5
+ <h1 class="sa-page-head__title">{{ title }}</h1>
6
+ <p v-if="subtitle || $slots.subtitle" class="sa-page-head__sub">
7
+ <slot name="subtitle">{{ subtitle }}</slot>
8
+ </p>
9
+ </div>
10
+ <div v-if="$slots.actions" class="sa-page-head__actions">
11
+ <slot name="actions" />
12
+ </div>
13
+ </header>
14
+ </template>
15
+
16
+ <script setup lang="ts">
17
+ // The page hero: the one <h1> a page is allowed to have.
18
+ //
19
+ // `title` is required on purpose. It is the part of the contract that the
20
+ // previous class-name convention could not enforce — a page can forget to add
21
+ // `.sa-page-head`, but it cannot instantiate this component without a title,
22
+ // because vue-tsc rejects it.
23
+ //
24
+ // `subtitle` covers the plain-text case; the matching slot is for the detail
25
+ // pages whose subtitle carries markup (a status badge, a <code> slug).
26
+ // `before-title` holds the back link on detail pages, which sits above the
27
+ // heading rather than beside it.
28
+ defineProps<{
29
+ title: string;
30
+ subtitle?: string;
31
+ }>();
32
+ </script>
@@ -0,0 +1,16 @@
1
+ <template>
2
+ <div class="sa-page">
3
+ <slot />
4
+ </div>
5
+ </template>
6
+
7
+ <script setup lang="ts">
8
+ // Root of every SuperAdmin content page.
9
+ //
10
+ // It owns the page frame — canvas background, min-height and page padding —
11
+ // which eleven pages used to declare verbatim in their own scoped styles.
12
+ //
13
+ // It deliberately does NOT render <main>. The landmark belongs to the layout
14
+ // and must appear exactly once per document; AdminLayout provides it. Quasar's
15
+ // QPage also renders <main>, which is why pages must not use QPage either.
16
+ </script>
@@ -0,0 +1,38 @@
1
+ <template>
2
+ <section class="sa-section" :aria-labelledby="headingId">
3
+ <header class="sa-section__head">
4
+ <div>
5
+ <h2 :id="headingId" class="sa-section__title">{{ title }}</h2>
6
+ <p v-if="subtitle || $slots.subtitle" class="sa-section__sub">
7
+ <slot name="subtitle">{{ subtitle }}</slot>
8
+ </p>
9
+ </div>
10
+ <div v-if="$slots.actions" class="sa-section__actions">
11
+ <slot name="actions" />
12
+ </div>
13
+ </header>
14
+ <slot />
15
+ </section>
16
+ </template>
17
+
18
+ <script setup lang="ts">
19
+ import { useId } from 'vue';
20
+
21
+ // A labelled block within a page, carrying the page's only heading level
22
+ // below the hero's <h1>.
23
+ //
24
+ // The aria-labelledby wiring is the reason this is a component and not a bare
25
+ // <section>: an unnamed <section> is not a landmark at all — assistive
26
+ // technology treats it as a generic container. Pointing it at its own heading
27
+ // is what makes it navigable, and doing that by hand needs a unique id per
28
+ // instance, which is exactly the step a hand-written section forgets.
29
+ //
30
+ // The section is structural, not a surface. A block that should read as a card
31
+ // adds `.sa-card`, which falls through to the root element.
32
+ defineProps<{
33
+ title: string;
34
+ subtitle?: string;
35
+ }>();
36
+
37
+ const headingId = useId();
38
+ </script>
@@ -597,6 +597,21 @@ const diffRows = computed<DiffRow[]>(() => {
597
597
  border-bottom: 0;
598
598
  padding-bottom: 8px;
599
599
  }
600
+ .pc-card .sa-section__head {
601
+ padding: 14px 18px;
602
+ border-bottom: 1px solid var(--pc-border);
603
+ margin-bottom: 0;
604
+ }
605
+ .pc-card--audit-head .sa-section__head {
606
+ border-bottom: 0;
607
+ }
608
+ .pc-card .sa-section__title {
609
+ letter-spacing: -0.01em;
610
+ }
611
+ .pc-card .sa-section__sub {
612
+ font-size: 11.5px;
613
+ margin-top: 2px;
614
+ }
600
615
  .pc-card-head-text {
601
616
  flex: 1;
602
617
  min-width: 0;
@@ -1,11 +1,10 @@
1
1
  <template>
2
- <section v-if="auditRows.length > 0 || loadingAudit" class="pc-card pc-audit-card">
3
- <div class="pc-card-head pc-card-head--audit">
4
- <div class="pc-card-head-text">
5
- <div class="pc-card-title">{{ msg.auditLog.title }}</div>
6
- <div class="pc-card-sub">{{ msg.auditLog.subtitle }}</div>
7
- </div>
8
- </div>
2
+ <AdminSection
3
+ v-if="auditRows.length > 0 || loadingAudit"
4
+ :title="msg.auditLog.title"
5
+ :subtitle="msg.auditLog.subtitle"
6
+ class="pc-card pc-audit-card pc-card--audit-head"
7
+ >
9
8
  <div class="pc-audit">
10
9
  <div v-if="loadingAudit" class="pc-empty pc-empty--inline">
11
10
  {{ msg.auditLog.loading }}
@@ -18,11 +17,12 @@
18
17
  <span class="pc-audit-what">{{ auditLabel(a) }}</span>
19
18
  </div>
20
19
  </div>
21
- </section>
20
+ </AdminSection>
22
21
  </template>
23
22
 
24
23
  <script setup lang="ts">
25
24
  import { formatMessage } from '../../client/i18n/format.js';
25
+ import AdminSection from '../admin-page/AdminSection.vue';
26
26
  import { useSaMessages, useSuperAdminI18n } from '../../vue/use-super-admin-i18n.js';
27
27
  import type { AuditRow } from './types';
28
28
 
@@ -1,13 +1,11 @@
1
1
  <template>
2
- <section class="pc-card">
3
- <div class="pc-card-head">
4
- <div class="pc-card-head-text">
5
- <div class="pc-card-title">{{ panelTitle }}</div>
6
- <div class="pc-card-sub">
7
- {{ diffPair ? msg.diff.subOnPublish : msg.diff.noComparison }}
8
- </div>
9
- </div>
10
- <div v-if="diffPair" class="pc-pillrow">
2
+ <AdminSection
3
+ :title="panelTitle"
4
+ :subtitle="diffPair ? msg.diff.subOnPublish : msg.diff.noComparison"
5
+ class="pc-card"
6
+ >
7
+ <template v-if="diffPair" #actions>
8
+ <div class="pc-pillrow">
11
9
  <span class="pc-pill" style="background: #ecfdf5; color: #047857">
12
10
  +{{ diff.addedFeatures.length }} F
13
11
  </span>
@@ -23,7 +21,7 @@
23
21
  Q
24
22
  </span>
25
23
  </div>
26
- </div>
24
+ </template>
27
25
  <div class="pc-diff-body">
28
26
  <div
29
27
  v-for="d in diffRows"
@@ -72,11 +70,12 @@
72
70
  {{ msg.diff.noChangesDetected }}
73
71
  </div>
74
72
  </div>
75
- </section>
73
+ </AdminSection>
76
74
  </template>
77
75
 
78
76
  <script setup lang="ts">
79
77
  import { computed } from 'vue';
78
+ import AdminSection from '../admin-page/AdminSection.vue';
80
79
  import { formatMessage } from '../../client/i18n/format.js';
81
80
  import { useSaMessages } from '../../vue/use-super-admin-i18n.js';
82
81
  import type { DiffRow, DiffSummary, PlanVersionPair } from './types';