@saasicat/ui-vue 0.7.0 → 0.8.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/{chunk-A3W2N26K.js → chunk-7N3CJTOA.js} +7 -227
- package/dist/{chunk-X5SQ5HMB.js → chunk-TBLXKSTR.js} +0 -137
- package/dist/{chunk-QZOSDCNP.js → chunk-TY2WYKME.js} +1 -1
- package/dist/client/index.cjs +112 -467
- package/dist/client/index.d.cts +4 -62
- package/dist/client/index.d.ts +4 -62
- package/dist/client/index.js +2 -6
- package/dist/index.cjs +204 -583
- package/dist/index.d.cts +10 -55
- package/dist/index.d.ts +10 -55
- package/dist/index.js +74 -101
- package/dist/{messages-7b0P8W75.d.ts → messages-BIYw32u1.d.cts} +0 -67
- package/dist/{messages-7b0P8W75.d.cts → messages-BIYw32u1.d.ts} +0 -67
- package/dist/quasar/index.cjs +0 -136
- package/dist/quasar/index.d.cts +2 -2
- package/dist/quasar/index.d.ts +2 -2
- package/dist/quasar/index.js +2 -2
- package/dist/{use-super-admin-i18n-B3v3-SWZ.d.ts → use-super-admin-i18n-CWNu_W3u.d.ts} +1 -1
- package/dist/{use-super-admin-i18n-DMktRVEt.d.cts → use-super-admin-i18n-DL_qI1BY.d.cts} +1 -1
- package/package.json +2 -2
- package/src/client/i18n/messages/nav.ts +0 -2
- package/src/client/i18n/messages/plan-versions.ts +0 -143
- package/src/client/index.ts +0 -2
- package/src/client/nav-builder.ts +9 -4
- package/src/index.ts +0 -1
- package/src/pages-standard/AdminLayout.vue +1 -1
- package/src/pages-standard/plan-versions/PlanVersionsDiff.vue +1 -1
- package/src/pages-standard/plan-versions/PlanVersionsTimeline.vue +1 -1
- package/src/pages-standard/plan-versions/catalog-history.types.ts +37 -0
- package/src/pages-standard/plan-versions/format.ts +2 -38
- package/src/client/plan-versions-catalog.ts +0 -380
- package/src/pages-standard/PlanVersionsPage.vue +0 -220
- package/src/pages-standard/plan-versions/PlanVersionHeader.vue +0 -309
- package/src/pages-standard/plan-versions/PlanVersionStatusBadge.vue +0 -48
- package/src/pages-standard/plan-versions/PlanVersionsAudit.vue +0 -326
- package/src/pages-standard/plan-versions/PlanVersionsKpi.vue +0 -65
- package/src/pages-standard/plan-versions/PlanVersionsList.vue +0 -315
- package/src/pages-standard/plan-versions/PlanVersionsMatrix.vue +0 -261
- package/src/pages-standard/plan-versions/types.ts +0 -33
- package/src/vue/use-plan-versions.ts +0 -83
package/dist/client/index.cjs
CHANGED
|
@@ -38,7 +38,6 @@ __export(client_exports, {
|
|
|
38
38
|
SA_MESSAGES: () => SA_MESSAGES,
|
|
39
39
|
buildRoutes: () => buildRoutes,
|
|
40
40
|
buildSidebar: () => buildSidebar,
|
|
41
|
-
buildSnapshots: () => buildSnapshots,
|
|
42
41
|
defaultHttpClient: () => defaultHttpClient,
|
|
43
42
|
defaultKvStore: () => defaultKvStore,
|
|
44
43
|
defaultSectionOrder: () => defaultSectionOrder,
|
|
@@ -46,7 +45,6 @@ __export(client_exports, {
|
|
|
46
45
|
formatCurrency: () => formatCurrency,
|
|
47
46
|
formatMessage: () => formatMessage,
|
|
48
47
|
getJson: () => getJson,
|
|
49
|
-
listOpenDrafts: () => listOpenDrafts,
|
|
50
48
|
mergeMessages: () => mergeMessages,
|
|
51
49
|
postJson: () => postJson,
|
|
52
50
|
resolveExtension: () => resolveExtension,
|
|
@@ -274,7 +272,6 @@ var navMessages = defineMessages(
|
|
|
274
272
|
subscriptions: "Abonnements",
|
|
275
273
|
promoCodes: "Promo-Codes",
|
|
276
274
|
plans: "Pl\xE4ne & Versionen",
|
|
277
|
-
planVersions: "Plan-Versionen",
|
|
278
275
|
audit: "Audit-Log",
|
|
279
276
|
users: "Benutzer",
|
|
280
277
|
pilots: "Piloten",
|
|
@@ -298,7 +295,6 @@ var navMessages = defineMessages(
|
|
|
298
295
|
subscriptions: "Subscriptions",
|
|
299
296
|
promoCodes: "Promo codes",
|
|
300
297
|
plans: "Plans & versions",
|
|
301
|
-
planVersions: "Plan versions",
|
|
302
298
|
audit: "Audit log",
|
|
303
299
|
users: "Users",
|
|
304
300
|
pilots: "Pilots",
|
|
@@ -324,7 +320,6 @@ var DEFAULT_STANDARD_PAGE_ROUTES = {
|
|
|
324
320
|
subscriptions: "/admin/subscriptions",
|
|
325
321
|
promoCodes: "/admin/promo-codes",
|
|
326
322
|
plans: "/admin/plans",
|
|
327
|
-
planVersions: "/admin/plan-versions",
|
|
328
323
|
audit: "/admin/audit",
|
|
329
324
|
users: "/admin/users",
|
|
330
325
|
pilots: "/admin/pilots",
|
|
@@ -334,13 +329,15 @@ var DEFAULT_STANDARD_PAGE_ROUTES = {
|
|
|
334
329
|
platformEmail: "/admin/platform-email",
|
|
335
330
|
platformEmailHistory: "/admin/platform-email-history"
|
|
336
331
|
};
|
|
332
|
+
function isSupportedStandardPageKey(key) {
|
|
333
|
+
return Object.hasOwn(DEFAULT_STANDARD_PAGE_ROUTES, key);
|
|
334
|
+
}
|
|
337
335
|
var DEFAULT_ICONS = {
|
|
338
336
|
dashboard: "dashboard",
|
|
339
337
|
tenants: "business",
|
|
340
338
|
subscriptions: "card_membership",
|
|
341
339
|
promoCodes: "local_activity",
|
|
342
340
|
plans: "workspace_premium",
|
|
343
|
-
planVersions: "history_edu",
|
|
344
341
|
audit: "history",
|
|
345
342
|
users: "people",
|
|
346
343
|
pilots: "flight_takeoff",
|
|
@@ -355,7 +352,6 @@ var PAGE_SECTIONS = {
|
|
|
355
352
|
discovery: "catalog",
|
|
356
353
|
bundles: "catalog",
|
|
357
354
|
plans: "catalog",
|
|
358
|
-
planVersions: "catalog",
|
|
359
355
|
marketingCatalog: "catalog",
|
|
360
356
|
promoCodes: "catalog",
|
|
361
357
|
tenants: "customers",
|
|
@@ -383,6 +379,7 @@ function buildRoutes(manifest, options = {}) {
|
|
|
383
379
|
const overrideIcons = { ...DEFAULT_ICONS, ...options.standardPageIcons };
|
|
384
380
|
const overrideNavSection = { ...defaultNavSections, ...options.standardPageNavSection };
|
|
385
381
|
for (const key of Object.keys(standard)) {
|
|
382
|
+
if (!isSupportedStandardPageKey(key)) continue;
|
|
386
383
|
const def = standard[key];
|
|
387
384
|
if (!def?.enabled) continue;
|
|
388
385
|
const cap = def.requiredCapability ?? null;
|
|
@@ -631,464 +628,6 @@ function formatMessage(template, params) {
|
|
|
631
628
|
});
|
|
632
629
|
}
|
|
633
630
|
|
|
634
|
-
// src/client/i18n/messages/plan-versions.ts
|
|
635
|
-
var planVersionsMessages = defineMessages(
|
|
636
|
-
{
|
|
637
|
-
compareEnd: "Vergleich beenden",
|
|
638
|
-
page: {
|
|
639
|
-
loadingCatalog: "Catalog wird geladen\u2026",
|
|
640
|
-
noAuditLoader: "Kein Audit-Loader konfiguriert."
|
|
641
|
-
},
|
|
642
|
-
header: {
|
|
643
|
-
modeList: "Plan-Liste",
|
|
644
|
-
modeMatrix: "Feature-Matrix",
|
|
645
|
-
modeAudit: "Aktivit\xE4t",
|
|
646
|
-
publishedOn: "Publiziert {date}",
|
|
647
|
-
openDrafts: "offene Drafts",
|
|
648
|
-
regressionOne: "Regression",
|
|
649
|
-
regressionMany: "Regressionen",
|
|
650
|
-
startPublishFlow: "Publish-Flow starten",
|
|
651
|
-
compareModeHint: "Vergleichsmodus aktiv \u2014 andere Ansichten deaktiviert"
|
|
652
|
-
},
|
|
653
|
-
status: {
|
|
654
|
-
draft: "DRAFT",
|
|
655
|
-
active: "AKTIV",
|
|
656
|
-
archived: "ARCHIV"
|
|
657
|
-
},
|
|
658
|
-
timeline: {
|
|
659
|
-
title: "Plan-Catalog",
|
|
660
|
-
snapshotCount: "{count} Snapshots",
|
|
661
|
-
noOpenDrafts: "keine offenen Drafts",
|
|
662
|
-
openCount: "{count} offen",
|
|
663
|
-
unknown: "unbekannt",
|
|
664
|
-
compareHint: "Rechtsklick auf Snapshot \u2192 vergleichen"
|
|
665
|
-
},
|
|
666
|
-
list: {
|
|
667
|
-
kpiPlans: "Pakete",
|
|
668
|
-
kpiSelfService: "Self-Service",
|
|
669
|
-
kpiOfTotal: "von {count}",
|
|
670
|
-
kpiFeaturesTotal: "Features gesamt",
|
|
671
|
-
missingPlansLabel: "Fehlende Pakete:",
|
|
672
|
-
missingPlansHint: "\u2014 keine Live-Version in diesem Snapshot.",
|
|
673
|
-
createDraftFor: "Draft f\xFCr {planId}",
|
|
674
|
-
colPlan: "Paket",
|
|
675
|
-
colPriceNet: "Preis (netto)",
|
|
676
|
-
colFeatures: "Features",
|
|
677
|
-
draftHintLabel: "Arbeitsstand:",
|
|
678
|
-
draftHintBefore: "Drafts oben in der Liste. Limits, Preise und Features per Klick auf",
|
|
679
|
-
draftHintEditButton: '\u201EBearbeiten"',
|
|
680
|
-
draftHintMiddle: "\xE4ndern (ohne MFA). Erst",
|
|
681
|
-
draftHintPublishFlow: "Publish-Flow",
|
|
682
|
-
draftHintAfter: "(Validate \u2192 Diff-Review \u2192 MFA \u2192 Apply) macht sie f\xFCr k\xFCnftige Renewals wirksam."
|
|
683
|
-
},
|
|
684
|
-
matrix: {
|
|
685
|
-
colFeature: "Feature",
|
|
686
|
-
perMonthShort: "/Mo",
|
|
687
|
-
fallbackGroup: "Sonstige"
|
|
688
|
-
},
|
|
689
|
-
diff: {
|
|
690
|
-
legend: "Vergleich",
|
|
691
|
-
plansChanged: "Pakete ge\xE4ndert",
|
|
692
|
-
regressions: "Regressionen",
|
|
693
|
-
sectionPlans: "Pakete",
|
|
694
|
-
changeCountOne: "{count} \xC4nderung",
|
|
695
|
-
changeCountMany: "{count} \xC4nderungen"
|
|
696
|
-
},
|
|
697
|
-
diffPreview: {
|
|
698
|
-
empty: "Keine \xC4nderungen gegen\xFCber der Vorg\xE4ngerversion.",
|
|
699
|
-
improvement: "Verbesserung",
|
|
700
|
-
regression: "Verschlechterung",
|
|
701
|
-
neutral: "Neutral"
|
|
702
|
-
},
|
|
703
|
-
diffFields: {
|
|
704
|
-
featuresAdded: "Hinzugef\xFCgte Features",
|
|
705
|
-
featuresRemoved: "Entfernte Features",
|
|
706
|
-
maxUsers: "Max. Benutzer",
|
|
707
|
-
maxStorageGb: "Speicher (GB)",
|
|
708
|
-
monthlyNet: "Preis monatlich (netto)",
|
|
709
|
-
yearlyNet: "Preis j\xE4hrlich (netto)",
|
|
710
|
-
unitSize: "Einheitsgr\xF6\xDFe"
|
|
711
|
-
},
|
|
712
|
-
audit: {
|
|
713
|
-
title: "Aktivit\xE4t",
|
|
714
|
-
eventCount: "{count} Events",
|
|
715
|
-
loading: "Audit-Trail wird geladen\u2026",
|
|
716
|
-
empty: "Keine Plan-/Add-on-Events im Audit-Log gefunden.",
|
|
717
|
-
actionPlanPublished: "Plan publiziert",
|
|
718
|
-
actionPlanDraftCreated: "Plan-Draft angelegt",
|
|
719
|
-
actionPlanDraftUpdated: "Plan-Draft ge\xE4ndert",
|
|
720
|
-
actionPlanDraftDeleted: "Plan-Draft gel\xF6scht",
|
|
721
|
-
actionCatalogPublished: "Catalog publiziert",
|
|
722
|
-
detailRegression: "Mit mindestens einer Verschlechterung publiziert.",
|
|
723
|
-
detailFieldsChanged: "{count} Felder ge\xE4ndert."
|
|
724
|
-
},
|
|
725
|
-
bulkPublish: {
|
|
726
|
-
changeNoteRequired: "changeNote ist Pflicht beim Publish."
|
|
727
|
-
},
|
|
728
|
-
format: {
|
|
729
|
-
priceIndividual: "individuell",
|
|
730
|
-
today: "heute",
|
|
731
|
-
yesterday: "gestern",
|
|
732
|
-
daysAgo: "vor {count} Tagen",
|
|
733
|
-
weeksAgoOne: "vor {count} Woche",
|
|
734
|
-
weeksAgoMany: "vor {count} Wochen",
|
|
735
|
-
monthsAgo: "vor {count} Monaten",
|
|
736
|
-
yearsAgoOne: "vor {count} Jahr",
|
|
737
|
-
yearsAgoMany: "vor {count} Jahren"
|
|
738
|
-
},
|
|
739
|
-
catalog: {
|
|
740
|
-
draftsLabel: "Arbeitsstand",
|
|
741
|
-
draftsTitleEmpty: "Keine offenen Drafts",
|
|
742
|
-
draftsTitleOne: "{count} offener Draft bereit f\xFCr Publish",
|
|
743
|
-
draftsTitleMany: "{count} offene Drafts bereit f\xFCr Publish",
|
|
744
|
-
draftsDescriptionEmpty: "Lege einen Draft an, um Limits, Preise oder Features zu \xE4ndern. Drafts sind ohne MFA editierbar und werden erst beim Publish wirksam.",
|
|
745
|
-
draftsDescription: "Diese Tabelle zeigt, wie der Catalog nach Publish aller Drafts aussehen w\xFCrde. Bestehende Mandanten bleiben auf der vorherigen Version, bis sie aktiv migriert werden.",
|
|
746
|
-
activeLabel: "Aktuell",
|
|
747
|
-
activeTitle: "Live-Catalog",
|
|
748
|
-
activeDescription: "Diese Plan-Versionen sind aktuell f\xFCr neue Onboardings und f\xFCr Renewals nach Stichtag aktiv.",
|
|
749
|
-
publishEvent: "Publish-Event",
|
|
750
|
-
publishEventSingle: "{planId} v{version} publiziert",
|
|
751
|
-
publishEventMultiple: "{count} Versionen publiziert",
|
|
752
|
-
reconstructedSnapshot: "Snapshot rekonstruiert aus per-Entity-Versionen."
|
|
753
|
-
}
|
|
754
|
-
},
|
|
755
|
-
{
|
|
756
|
-
compareEnd: "End comparison",
|
|
757
|
-
page: {
|
|
758
|
-
loadingCatalog: "Loading catalog\u2026",
|
|
759
|
-
noAuditLoader: "No audit loader configured."
|
|
760
|
-
},
|
|
761
|
-
header: {
|
|
762
|
-
modeList: "Plan list",
|
|
763
|
-
modeMatrix: "Feature matrix",
|
|
764
|
-
modeAudit: "Activity",
|
|
765
|
-
publishedOn: "Published {date}",
|
|
766
|
-
openDrafts: "open drafts",
|
|
767
|
-
regressionOne: "regression",
|
|
768
|
-
regressionMany: "regressions",
|
|
769
|
-
startPublishFlow: "Start publish flow",
|
|
770
|
-
compareModeHint: "Comparison mode active \u2014 other views disabled"
|
|
771
|
-
},
|
|
772
|
-
status: {
|
|
773
|
-
draft: "DRAFT",
|
|
774
|
-
active: "ACTIVE",
|
|
775
|
-
archived: "ARCHIVED"
|
|
776
|
-
},
|
|
777
|
-
timeline: {
|
|
778
|
-
title: "Plan catalog",
|
|
779
|
-
snapshotCount: "{count} snapshots",
|
|
780
|
-
noOpenDrafts: "no open drafts",
|
|
781
|
-
openCount: "{count} open",
|
|
782
|
-
unknown: "unknown",
|
|
783
|
-
compareHint: "Right-click a snapshot \u2192 compare"
|
|
784
|
-
},
|
|
785
|
-
list: {
|
|
786
|
-
kpiPlans: "Plans",
|
|
787
|
-
kpiSelfService: "Self-service",
|
|
788
|
-
kpiOfTotal: "of {count}",
|
|
789
|
-
kpiFeaturesTotal: "Features total",
|
|
790
|
-
missingPlansLabel: "Missing plans:",
|
|
791
|
-
missingPlansHint: "\u2014 no live version in this snapshot.",
|
|
792
|
-
createDraftFor: "Draft for {planId}",
|
|
793
|
-
colPlan: "Plan",
|
|
794
|
-
colPriceNet: "Price (net)",
|
|
795
|
-
colFeatures: "Features",
|
|
796
|
-
draftHintLabel: "Working state:",
|
|
797
|
-
draftHintBefore: "Drafts at the top of the list. Change limits, prices and features by clicking",
|
|
798
|
-
draftHintEditButton: '"Edit"',
|
|
799
|
-
draftHintMiddle: "(without MFA). Only the",
|
|
800
|
-
draftHintPublishFlow: "publish flow",
|
|
801
|
-
draftHintAfter: "(validate \u2192 diff review \u2192 MFA \u2192 apply) makes them effective for future renewals."
|
|
802
|
-
},
|
|
803
|
-
matrix: {
|
|
804
|
-
colFeature: "Feature",
|
|
805
|
-
perMonthShort: "/mo",
|
|
806
|
-
fallbackGroup: "Other"
|
|
807
|
-
},
|
|
808
|
-
diff: {
|
|
809
|
-
legend: "Comparison",
|
|
810
|
-
plansChanged: "Plans changed",
|
|
811
|
-
regressions: "Regressions",
|
|
812
|
-
sectionPlans: "Plans",
|
|
813
|
-
changeCountOne: "{count} change",
|
|
814
|
-
changeCountMany: "{count} changes"
|
|
815
|
-
},
|
|
816
|
-
diffPreview: {
|
|
817
|
-
empty: "No changes compared to the previous version.",
|
|
818
|
-
improvement: "Improvement",
|
|
819
|
-
regression: "Regression",
|
|
820
|
-
neutral: "Neutral"
|
|
821
|
-
},
|
|
822
|
-
diffFields: {
|
|
823
|
-
featuresAdded: "Added features",
|
|
824
|
-
featuresRemoved: "Removed features",
|
|
825
|
-
maxUsers: "Max. users",
|
|
826
|
-
maxStorageGb: "Storage (GB)",
|
|
827
|
-
monthlyNet: "Price monthly (net)",
|
|
828
|
-
yearlyNet: "Price yearly (net)",
|
|
829
|
-
unitSize: "Unit size"
|
|
830
|
-
},
|
|
831
|
-
audit: {
|
|
832
|
-
title: "Activity",
|
|
833
|
-
eventCount: "{count} events",
|
|
834
|
-
loading: "Loading audit trail\u2026",
|
|
835
|
-
empty: "No plan/add-on events found in the audit log.",
|
|
836
|
-
actionPlanPublished: "Plan published",
|
|
837
|
-
actionPlanDraftCreated: "Plan draft created",
|
|
838
|
-
actionPlanDraftUpdated: "Plan draft changed",
|
|
839
|
-
actionPlanDraftDeleted: "Plan draft deleted",
|
|
840
|
-
actionCatalogPublished: "Catalog published",
|
|
841
|
-
detailRegression: "Published with at least one regression.",
|
|
842
|
-
detailFieldsChanged: "{count} fields changed."
|
|
843
|
-
},
|
|
844
|
-
bulkPublish: {
|
|
845
|
-
changeNoteRequired: "changeNote is required when publishing."
|
|
846
|
-
},
|
|
847
|
-
format: {
|
|
848
|
-
priceIndividual: "custom",
|
|
849
|
-
today: "today",
|
|
850
|
-
yesterday: "yesterday",
|
|
851
|
-
daysAgo: "{count} days ago",
|
|
852
|
-
weeksAgoOne: "{count} week ago",
|
|
853
|
-
weeksAgoMany: "{count} weeks ago",
|
|
854
|
-
monthsAgo: "{count} months ago",
|
|
855
|
-
yearsAgoOne: "{count} year ago",
|
|
856
|
-
yearsAgoMany: "{count} years ago"
|
|
857
|
-
},
|
|
858
|
-
catalog: {
|
|
859
|
-
draftsLabel: "Working state",
|
|
860
|
-
draftsTitleEmpty: "No open drafts",
|
|
861
|
-
draftsTitleOne: "{count} open draft ready to publish",
|
|
862
|
-
draftsTitleMany: "{count} open drafts ready to publish",
|
|
863
|
-
draftsDescriptionEmpty: "Create a draft to change limits, prices or features. Drafts are editable without MFA and only take effect when published.",
|
|
864
|
-
draftsDescription: "This table shows what the catalog would look like after publishing all drafts. Existing tenants stay on the previous version until they are actively migrated.",
|
|
865
|
-
activeLabel: "Current",
|
|
866
|
-
activeTitle: "Live catalog",
|
|
867
|
-
activeDescription: "These plan versions are currently active for new onboardings and for renewals after the effective date.",
|
|
868
|
-
publishEvent: "Publish event",
|
|
869
|
-
publishEventSingle: "{planId} v{version} published",
|
|
870
|
-
publishEventMultiple: "{count} versions published",
|
|
871
|
-
reconstructedSnapshot: "Snapshot reconstructed from per-entity versions."
|
|
872
|
-
}
|
|
873
|
-
}
|
|
874
|
-
);
|
|
875
|
-
|
|
876
|
-
// src/client/plan-versions-catalog.ts
|
|
877
|
-
var dec = (s) => Number(s);
|
|
878
|
-
function extractQuotas(p) {
|
|
879
|
-
if (p.quotas && Object.keys(p.quotas).length > 0) {
|
|
880
|
-
return { ...p.quotas };
|
|
881
|
-
}
|
|
882
|
-
const out = {};
|
|
883
|
-
if (typeof p.maxUsers === "number") out.users = p.maxUsers;
|
|
884
|
-
if (typeof p.maxVehicles === "number") out.vehicles = p.maxVehicles;
|
|
885
|
-
if (typeof p.maxStorageGb === "number") out.storageGb = p.maxStorageGb;
|
|
886
|
-
return out;
|
|
887
|
-
}
|
|
888
|
-
var sortByPublishedDesc = (rows) => [...rows].sort((a, b) => {
|
|
889
|
-
const at = a.publishedAt ? Date.parse(a.publishedAt) : Number.POSITIVE_INFINITY;
|
|
890
|
-
const bt = b.publishedAt ? Date.parse(b.publishedAt) : Number.POSITIVE_INFINITY;
|
|
891
|
-
if (at !== bt) return bt - at;
|
|
892
|
-
return b.version - a.version;
|
|
893
|
-
});
|
|
894
|
-
function findLiveAt(rows, asOfMs) {
|
|
895
|
-
const candidates = rows.filter((r) => {
|
|
896
|
-
if (r.publishedAt === null) return false;
|
|
897
|
-
if (Date.parse(r.publishedAt) > asOfMs) return false;
|
|
898
|
-
if (r.supersededAt !== null && Date.parse(r.supersededAt) <= asOfMs) return false;
|
|
899
|
-
return true;
|
|
900
|
-
});
|
|
901
|
-
if (candidates.length === 0) return null;
|
|
902
|
-
return [...candidates].sort((a, b) => b.version - a.version)[0] ?? null;
|
|
903
|
-
}
|
|
904
|
-
function findCurrentLive(rows) {
|
|
905
|
-
return rows.find((r) => r.publishedAt !== null && r.supersededAt === null) ?? null;
|
|
906
|
-
}
|
|
907
|
-
function findDraft(rows) {
|
|
908
|
-
return rows.find((r) => r.publishedAt === null) ?? null;
|
|
909
|
-
}
|
|
910
|
-
function groupBy(rows, keyOf) {
|
|
911
|
-
const out = /* @__PURE__ */ new Map();
|
|
912
|
-
for (const r of rows) {
|
|
913
|
-
const k = keyOf(r);
|
|
914
|
-
const list = out.get(k) ?? [];
|
|
915
|
-
list.push(r);
|
|
916
|
-
out.set(k, list);
|
|
917
|
-
}
|
|
918
|
-
return out;
|
|
919
|
-
}
|
|
920
|
-
function resolvePlan(source, liveBase) {
|
|
921
|
-
const quotas = extractQuotas(source);
|
|
922
|
-
return {
|
|
923
|
-
source,
|
|
924
|
-
liveBase,
|
|
925
|
-
isDraft: source.publishedAt === null,
|
|
926
|
-
planId: source.planId,
|
|
927
|
-
features: source.features,
|
|
928
|
-
quotas,
|
|
929
|
-
monthlyNet: dec(source.monthlyNet),
|
|
930
|
-
yearlyNet: dec(source.yearlyNet),
|
|
931
|
-
marketed: source.marketed,
|
|
932
|
-
version: source.version,
|
|
933
|
-
maxUsers: quotas.users,
|
|
934
|
-
maxVehicles: quotas.vehicles,
|
|
935
|
-
maxStorageGb: quotas.storageGb
|
|
936
|
-
};
|
|
937
|
-
}
|
|
938
|
-
function draftsTitle(draftCount, msg) {
|
|
939
|
-
if (draftCount === 0) return msg.draftsTitleEmpty;
|
|
940
|
-
const template = draftCount === 1 ? msg.draftsTitleOne : msg.draftsTitleMany;
|
|
941
|
-
return formatMessage(template, { count: draftCount });
|
|
942
|
-
}
|
|
943
|
-
function dateLabel(iso, locale) {
|
|
944
|
-
return new Date(iso).toLocaleDateString(SA_INTL_LOCALES[locale], {
|
|
945
|
-
day: "2-digit",
|
|
946
|
-
month: "short",
|
|
947
|
-
year: "numeric"
|
|
948
|
-
});
|
|
949
|
-
}
|
|
950
|
-
function buildDraftsSnapshot(data, sortPlansFn, locale) {
|
|
951
|
-
const msg = planVersionsMessages[locale].catalog;
|
|
952
|
-
const planByKey = groupBy(data.planVersions, (r) => r.planId);
|
|
953
|
-
const plans = [];
|
|
954
|
-
for (const [, rows] of planByKey) {
|
|
955
|
-
const draft = findDraft(rows);
|
|
956
|
-
const live = findCurrentLive(rows);
|
|
957
|
-
if (draft) plans.push(resolvePlan(draft, live));
|
|
958
|
-
else if (live) plans.push(resolvePlan(live, null));
|
|
959
|
-
}
|
|
960
|
-
const draftCount = plans.filter((p) => p.isDraft).length;
|
|
961
|
-
return {
|
|
962
|
-
id: "drafts",
|
|
963
|
-
kind: "drafts",
|
|
964
|
-
status: "DRAFT",
|
|
965
|
-
label: msg.draftsLabel,
|
|
966
|
-
title: draftsTitle(draftCount, msg),
|
|
967
|
-
description: draftCount === 0 ? msg.draftsDescriptionEmpty : msg.draftsDescription,
|
|
968
|
-
asOf: null,
|
|
969
|
-
createdAt: null,
|
|
970
|
-
publishedAt: null,
|
|
971
|
-
authorEmail: null,
|
|
972
|
-
plans: sortPlansFn(plans),
|
|
973
|
-
draftCount,
|
|
974
|
-
regressionCount: 0
|
|
975
|
-
};
|
|
976
|
-
}
|
|
977
|
-
function buildActiveSnapshot(data, sortPlansFn, locale) {
|
|
978
|
-
const msg = planVersionsMessages[locale].catalog;
|
|
979
|
-
const planByKey = groupBy(data.planVersions, (r) => r.planId);
|
|
980
|
-
const plans = [];
|
|
981
|
-
for (const [, rows] of planByKey) {
|
|
982
|
-
const live = findCurrentLive(rows);
|
|
983
|
-
if (live) plans.push(resolvePlan(live, null));
|
|
984
|
-
}
|
|
985
|
-
if (plans.length === 0) return null;
|
|
986
|
-
const publishedDates = plans.map((p) => p.source.publishedAt).filter((t) => t !== null).sort();
|
|
987
|
-
const latestPublished = publishedDates[publishedDates.length - 1];
|
|
988
|
-
return {
|
|
989
|
-
id: "active",
|
|
990
|
-
kind: "active",
|
|
991
|
-
status: "ACTIVE",
|
|
992
|
-
label: msg.activeLabel,
|
|
993
|
-
title: msg.activeTitle,
|
|
994
|
-
description: msg.activeDescription,
|
|
995
|
-
asOf: latestPublished ?? null,
|
|
996
|
-
createdAt: null,
|
|
997
|
-
publishedAt: latestPublished ?? null,
|
|
998
|
-
authorEmail: null,
|
|
999
|
-
plans: sortPlansFn(plans),
|
|
1000
|
-
draftCount: 0,
|
|
1001
|
-
regressionCount: 0
|
|
1002
|
-
};
|
|
1003
|
-
}
|
|
1004
|
-
function buildHistoricalSnapshots(data, sortPlansFn, locale) {
|
|
1005
|
-
const msg = planVersionsMessages[locale].catalog;
|
|
1006
|
-
const allPublishedAt = /* @__PURE__ */ new Set();
|
|
1007
|
-
for (const r of data.planVersions) if (r.publishedAt) allPublishedAt.add(r.publishedAt);
|
|
1008
|
-
if (allPublishedAt.size === 0) return [];
|
|
1009
|
-
const planByKey = groupBy(data.planVersions, (r) => r.planId);
|
|
1010
|
-
const liveTimestamps = /* @__PURE__ */ new Set();
|
|
1011
|
-
for (const rows of planByKey.values()) {
|
|
1012
|
-
const live = findCurrentLive(rows);
|
|
1013
|
-
if (live?.publishedAt) liveTimestamps.add(live.publishedAt);
|
|
1014
|
-
}
|
|
1015
|
-
const liveSorted = [...liveTimestamps].sort();
|
|
1016
|
-
const latestLive = liveSorted[liveSorted.length - 1];
|
|
1017
|
-
const sortedDesc = [...allPublishedAt].sort((a, b) => Date.parse(b) - Date.parse(a));
|
|
1018
|
-
const out = [];
|
|
1019
|
-
for (const ts of sortedDesc) {
|
|
1020
|
-
if (latestLive && Date.parse(ts) >= Date.parse(latestLive)) continue;
|
|
1021
|
-
const tMs = Date.parse(ts) + 1;
|
|
1022
|
-
const plans = [];
|
|
1023
|
-
for (const [, rows] of planByKey) {
|
|
1024
|
-
const live = findLiveAt(rows, tMs);
|
|
1025
|
-
if (live) plans.push(resolvePlan(live, null));
|
|
1026
|
-
}
|
|
1027
|
-
if (plans.length === 0) continue;
|
|
1028
|
-
const publishedAtThisEvent = data.planVersions.filter((r) => r.publishedAt === ts);
|
|
1029
|
-
const regressionCount = publishedAtThisEvent.filter((r) => !r.nonRegressive).length;
|
|
1030
|
-
const author = publishedAtThisEvent[0]?.publishedByUserId ?? null;
|
|
1031
|
-
out.push({
|
|
1032
|
-
id: `hist-${ts}`,
|
|
1033
|
-
kind: "historical",
|
|
1034
|
-
status: "ARCHIVED",
|
|
1035
|
-
label: dateLabel(ts, locale),
|
|
1036
|
-
title: summarizeEvent(publishedAtThisEvent, msg),
|
|
1037
|
-
description: detailEvent(publishedAtThisEvent, msg),
|
|
1038
|
-
asOf: ts,
|
|
1039
|
-
createdAt: ts,
|
|
1040
|
-
publishedAt: ts,
|
|
1041
|
-
authorEmail: author,
|
|
1042
|
-
plans: sortPlansFn(plans),
|
|
1043
|
-
draftCount: 0,
|
|
1044
|
-
regressionCount
|
|
1045
|
-
});
|
|
1046
|
-
}
|
|
1047
|
-
return out;
|
|
1048
|
-
}
|
|
1049
|
-
function summarizeEvent(rows, msg) {
|
|
1050
|
-
if (rows.length === 0) return msg.publishEvent;
|
|
1051
|
-
if (rows.length === 1) {
|
|
1052
|
-
const r = rows[0];
|
|
1053
|
-
return formatMessage(msg.publishEventSingle, { planId: r.planId, version: r.version });
|
|
1054
|
-
}
|
|
1055
|
-
return formatMessage(msg.publishEventMultiple, { count: rows.length });
|
|
1056
|
-
}
|
|
1057
|
-
function detailEvent(rows, msg) {
|
|
1058
|
-
if (rows.length === 0) return "";
|
|
1059
|
-
const note = rows[0]?.changeNote ?? "";
|
|
1060
|
-
return note.length > 0 ? note : msg.reconstructedSnapshot;
|
|
1061
|
-
}
|
|
1062
|
-
function sortPlansBy(order) {
|
|
1063
|
-
if (!order || order.length === 0) {
|
|
1064
|
-
return (rows) => [...rows].sort((a, b) => a.planId.localeCompare(b.planId));
|
|
1065
|
-
}
|
|
1066
|
-
const idx = {};
|
|
1067
|
-
for (let i = 0; i < order.length; i++) idx[order[i]] = i;
|
|
1068
|
-
return (rows) => [...rows].sort((a, b) => {
|
|
1069
|
-
const ai = idx[a.planId] ?? Number.POSITIVE_INFINITY;
|
|
1070
|
-
const bi = idx[b.planId] ?? Number.POSITIVE_INFINITY;
|
|
1071
|
-
if (ai !== bi) return ai - bi;
|
|
1072
|
-
return a.planId.localeCompare(b.planId);
|
|
1073
|
-
});
|
|
1074
|
-
}
|
|
1075
|
-
function buildSnapshots(data, options = {}) {
|
|
1076
|
-
const locale = options.locale ?? DEFAULT_SA_LOCALE;
|
|
1077
|
-
const sortPlansFn = sortPlansBy(options.planSortOrder);
|
|
1078
|
-
const drafts = buildDraftsSnapshot(data, sortPlansFn, locale);
|
|
1079
|
-
const active = buildActiveSnapshot(data, sortPlansFn, locale);
|
|
1080
|
-
const historical = buildHistoricalSnapshots(data, sortPlansFn, locale);
|
|
1081
|
-
const out = [drafts];
|
|
1082
|
-
if (active) out.push(active);
|
|
1083
|
-
out.push(...historical);
|
|
1084
|
-
return out;
|
|
1085
|
-
}
|
|
1086
|
-
function listOpenDrafts(data) {
|
|
1087
|
-
return {
|
|
1088
|
-
plans: sortByPublishedDesc(data.planVersions).filter((r) => r.publishedAt === null)
|
|
1089
|
-
};
|
|
1090
|
-
}
|
|
1091
|
-
|
|
1092
631
|
// src/client/i18n/currency.ts
|
|
1093
632
|
var DEFAULT_CURRENCY = "EUR";
|
|
1094
633
|
var formatters = /* @__PURE__ */ new Map();
|
|
@@ -2955,6 +2494,114 @@ var planEditorMessages = defineMessages(
|
|
|
2955
2494
|
}
|
|
2956
2495
|
);
|
|
2957
2496
|
|
|
2497
|
+
// src/client/i18n/messages/plan-versions.ts
|
|
2498
|
+
var planVersionsMessages = defineMessages(
|
|
2499
|
+
{
|
|
2500
|
+
compareEnd: "Vergleich beenden",
|
|
2501
|
+
status: {
|
|
2502
|
+
draft: "DRAFT",
|
|
2503
|
+
active: "AKTIV",
|
|
2504
|
+
archived: "ARCHIV"
|
|
2505
|
+
},
|
|
2506
|
+
timeline: {
|
|
2507
|
+
title: "Plan-Catalog",
|
|
2508
|
+
snapshotCount: "{count} Snapshots",
|
|
2509
|
+
noOpenDrafts: "keine offenen Drafts",
|
|
2510
|
+
openCount: "{count} offen",
|
|
2511
|
+
unknown: "unbekannt",
|
|
2512
|
+
compareHint: "Rechtsklick auf Snapshot \u2192 vergleichen"
|
|
2513
|
+
},
|
|
2514
|
+
diff: {
|
|
2515
|
+
legend: "Vergleich",
|
|
2516
|
+
plansChanged: "Pakete ge\xE4ndert",
|
|
2517
|
+
regressions: "Regressionen",
|
|
2518
|
+
sectionPlans: "Pakete",
|
|
2519
|
+
changeCountOne: "{count} \xC4nderung",
|
|
2520
|
+
changeCountMany: "{count} \xC4nderungen"
|
|
2521
|
+
},
|
|
2522
|
+
diffPreview: {
|
|
2523
|
+
empty: "Keine \xC4nderungen gegen\xFCber der Vorg\xE4ngerversion.",
|
|
2524
|
+
improvement: "Verbesserung",
|
|
2525
|
+
regression: "Verschlechterung",
|
|
2526
|
+
neutral: "Neutral"
|
|
2527
|
+
},
|
|
2528
|
+
diffFields: {
|
|
2529
|
+
featuresAdded: "Hinzugef\xFCgte Features",
|
|
2530
|
+
featuresRemoved: "Entfernte Features",
|
|
2531
|
+
maxUsers: "Max. Benutzer",
|
|
2532
|
+
maxStorageGb: "Speicher (GB)",
|
|
2533
|
+
monthlyNet: "Preis monatlich (netto)",
|
|
2534
|
+
yearlyNet: "Preis j\xE4hrlich (netto)",
|
|
2535
|
+
unitSize: "Einheitsgr\xF6\xDFe"
|
|
2536
|
+
},
|
|
2537
|
+
bulkPublish: {
|
|
2538
|
+
changeNoteRequired: "changeNote ist Pflicht beim Publish."
|
|
2539
|
+
},
|
|
2540
|
+
format: {
|
|
2541
|
+
today: "heute",
|
|
2542
|
+
yesterday: "gestern",
|
|
2543
|
+
daysAgo: "vor {count} Tagen",
|
|
2544
|
+
weeksAgoOne: "vor {count} Woche",
|
|
2545
|
+
weeksAgoMany: "vor {count} Wochen",
|
|
2546
|
+
monthsAgo: "vor {count} Monaten",
|
|
2547
|
+
yearsAgoOne: "vor {count} Jahr",
|
|
2548
|
+
yearsAgoMany: "vor {count} Jahren"
|
|
2549
|
+
}
|
|
2550
|
+
},
|
|
2551
|
+
{
|
|
2552
|
+
compareEnd: "End comparison",
|
|
2553
|
+
status: {
|
|
2554
|
+
draft: "DRAFT",
|
|
2555
|
+
active: "ACTIVE",
|
|
2556
|
+
archived: "ARCHIVED"
|
|
2557
|
+
},
|
|
2558
|
+
timeline: {
|
|
2559
|
+
title: "Plan catalog",
|
|
2560
|
+
snapshotCount: "{count} snapshots",
|
|
2561
|
+
noOpenDrafts: "no open drafts",
|
|
2562
|
+
openCount: "{count} open",
|
|
2563
|
+
unknown: "unknown",
|
|
2564
|
+
compareHint: "Right-click a snapshot \u2192 compare"
|
|
2565
|
+
},
|
|
2566
|
+
diff: {
|
|
2567
|
+
legend: "Comparison",
|
|
2568
|
+
plansChanged: "Plans changed",
|
|
2569
|
+
regressions: "Regressions",
|
|
2570
|
+
sectionPlans: "Plans",
|
|
2571
|
+
changeCountOne: "{count} change",
|
|
2572
|
+
changeCountMany: "{count} changes"
|
|
2573
|
+
},
|
|
2574
|
+
diffPreview: {
|
|
2575
|
+
empty: "No changes compared to the previous version.",
|
|
2576
|
+
improvement: "Improvement",
|
|
2577
|
+
regression: "Regression",
|
|
2578
|
+
neutral: "Neutral"
|
|
2579
|
+
},
|
|
2580
|
+
diffFields: {
|
|
2581
|
+
featuresAdded: "Added features",
|
|
2582
|
+
featuresRemoved: "Removed features",
|
|
2583
|
+
maxUsers: "Max. users",
|
|
2584
|
+
maxStorageGb: "Storage (GB)",
|
|
2585
|
+
monthlyNet: "Price monthly (net)",
|
|
2586
|
+
yearlyNet: "Price yearly (net)",
|
|
2587
|
+
unitSize: "Unit size"
|
|
2588
|
+
},
|
|
2589
|
+
bulkPublish: {
|
|
2590
|
+
changeNoteRequired: "changeNote is required when publishing."
|
|
2591
|
+
},
|
|
2592
|
+
format: {
|
|
2593
|
+
today: "today",
|
|
2594
|
+
yesterday: "yesterday",
|
|
2595
|
+
daysAgo: "{count} days ago",
|
|
2596
|
+
weeksAgoOne: "{count} week ago",
|
|
2597
|
+
weeksAgoMany: "{count} weeks ago",
|
|
2598
|
+
monthsAgo: "{count} months ago",
|
|
2599
|
+
yearsAgoOne: "{count} year ago",
|
|
2600
|
+
yearsAgoMany: "{count} years ago"
|
|
2601
|
+
}
|
|
2602
|
+
}
|
|
2603
|
+
);
|
|
2604
|
+
|
|
2958
2605
|
// src/client/i18n/messages/plans.ts
|
|
2959
2606
|
var plansMessages = defineMessages(
|
|
2960
2607
|
{
|
|
@@ -3971,7 +3618,6 @@ function resolveMessages(locale, overrides) {
|
|
|
3971
3618
|
SA_MESSAGES,
|
|
3972
3619
|
buildRoutes,
|
|
3973
3620
|
buildSidebar,
|
|
3974
|
-
buildSnapshots,
|
|
3975
3621
|
defaultHttpClient,
|
|
3976
3622
|
defaultKvStore,
|
|
3977
3623
|
defaultSectionOrder,
|
|
@@ -3979,7 +3625,6 @@ function resolveMessages(locale, overrides) {
|
|
|
3979
3625
|
formatCurrency,
|
|
3980
3626
|
formatMessage,
|
|
3981
3627
|
getJson,
|
|
3982
|
-
listOpenDrafts,
|
|
3983
3628
|
mergeMessages,
|
|
3984
3629
|
postJson,
|
|
3985
3630
|
resolveExtension,
|