@replicated/portal-components 0.0.25 → 0.0.27

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 (172) hide show
  1. package/components/metadata/registry.json +2 -2
  2. package/components/metadata/registry.md +2 -2
  3. package/dist/actions/branding-actions.js +6 -4
  4. package/dist/actions/branding-actions.js.map +1 -1
  5. package/dist/actions/change-team.js +1 -0
  6. package/dist/actions/change-team.js.map +1 -1
  7. package/dist/actions/index.d.mts +1 -1
  8. package/dist/actions/index.d.ts +1 -1
  9. package/dist/actions/index.js +1 -50
  10. package/dist/actions/index.js.map +1 -1
  11. package/dist/actions/install-actions.d.mts +1 -1
  12. package/dist/actions/install-actions.d.ts +1 -1
  13. package/dist/actions/install-actions.js +1 -0
  14. package/dist/actions/install-actions.js.map +1 -1
  15. package/dist/actions/invite-actions.js +6 -5
  16. package/dist/actions/invite-actions.js.map +1 -1
  17. package/dist/actions/magic-link-actions.js +6 -5
  18. package/dist/actions/magic-link-actions.js.map +1 -1
  19. package/dist/actions/service-account.d.mts +1 -1
  20. package/dist/actions/service-account.d.ts +1 -1
  21. package/dist/actions/service-account.js +1 -0
  22. package/dist/actions/service-account.js.map +1 -1
  23. package/dist/actions/support-bundles.d.mts +1 -1
  24. package/dist/actions/support-bundles.d.ts +1 -1
  25. package/dist/actions/support-bundles.js +1 -50
  26. package/dist/actions/support-bundles.js.map +1 -1
  27. package/dist/actions/team-settings.d.mts +1 -1
  28. package/dist/actions/team-settings.d.ts +1 -1
  29. package/dist/actions/team-settings.js +1 -0
  30. package/dist/actions/team-settings.js.map +1 -1
  31. package/dist/actions/trial-signup-actions.js +6 -5
  32. package/dist/actions/trial-signup-actions.js.map +1 -1
  33. package/dist/actions/trial-signup.js +6 -5
  34. package/dist/actions/trial-signup.js.map +1 -1
  35. package/dist/actions/user-settings.d.mts +1 -1
  36. package/dist/actions/user-settings.d.ts +1 -1
  37. package/dist/actions/user-settings.js +1 -0
  38. package/dist/actions/user-settings.js.map +1 -1
  39. package/dist/airgap-instances.d.mts +1 -1
  40. package/dist/airgap-instances.d.ts +1 -1
  41. package/dist/airgap-instances.js +25 -25
  42. package/dist/airgap-instances.js.map +1 -1
  43. package/dist/{saml-handlers.d.mts → api/saml.d.mts} +2 -2
  44. package/dist/{saml-handlers.d.ts → api/saml.d.ts} +2 -2
  45. package/dist/{saml-handlers.js → api/saml.js} +4 -3
  46. package/dist/api/saml.js.map +1 -0
  47. package/dist/api/support-bundles.d.mts +22 -0
  48. package/dist/api/support-bundles.d.ts +22 -0
  49. package/dist/api/support-bundles.js +245 -0
  50. package/dist/api/support-bundles.js.map +1 -0
  51. package/dist/{branding-BsMSywts.d.mts → branding-DmsrDTNE.d.mts} +2 -1
  52. package/dist/{branding-BsMSywts.d.ts → branding-DmsrDTNE.d.ts} +2 -1
  53. package/dist/esm/actions/branding-actions.js +6 -4
  54. package/dist/esm/actions/branding-actions.js.map +1 -1
  55. package/dist/esm/actions/change-team.js +1 -0
  56. package/dist/esm/actions/change-team.js.map +1 -1
  57. package/dist/esm/actions/index.js +2 -50
  58. package/dist/esm/actions/index.js.map +1 -1
  59. package/dist/esm/actions/install-actions.js +1 -0
  60. package/dist/esm/actions/install-actions.js.map +1 -1
  61. package/dist/esm/actions/invite-actions.js +6 -5
  62. package/dist/esm/actions/invite-actions.js.map +1 -1
  63. package/dist/esm/actions/magic-link-actions.js +6 -5
  64. package/dist/esm/actions/magic-link-actions.js.map +1 -1
  65. package/dist/esm/actions/service-account.js +1 -0
  66. package/dist/esm/actions/service-account.js.map +1 -1
  67. package/dist/esm/actions/support-bundles.js +2 -50
  68. package/dist/esm/actions/support-bundles.js.map +1 -1
  69. package/dist/esm/actions/team-settings.js +1 -0
  70. package/dist/esm/actions/team-settings.js.map +1 -1
  71. package/dist/esm/actions/trial-signup-actions.js +6 -5
  72. package/dist/esm/actions/trial-signup-actions.js.map +1 -1
  73. package/dist/esm/actions/trial-signup.js +6 -5
  74. package/dist/esm/actions/trial-signup.js.map +1 -1
  75. package/dist/esm/actions/user-settings.js +1 -0
  76. package/dist/esm/actions/user-settings.js.map +1 -1
  77. package/dist/esm/airgap-instances.js +25 -25
  78. package/dist/esm/airgap-instances.js.map +1 -1
  79. package/dist/esm/{saml-handlers.js → api/saml.js} +4 -3
  80. package/dist/esm/api/saml.js.map +1 -0
  81. package/dist/esm/api/support-bundles.js +243 -0
  82. package/dist/esm/api/support-bundles.js.map +1 -0
  83. package/dist/esm/helm-install-wizard.js +1 -0
  84. package/dist/esm/helm-install-wizard.js.map +1 -1
  85. package/dist/esm/index.js +262 -215
  86. package/dist/esm/index.js.map +1 -1
  87. package/dist/esm/install-actions.js +1 -0
  88. package/dist/esm/install-actions.js.map +1 -1
  89. package/dist/esm/instance-card.js +25 -25
  90. package/dist/esm/instance-card.js.map +1 -1
  91. package/dist/esm/license-details.js +1 -0
  92. package/dist/esm/license-details.js.map +1 -1
  93. package/dist/esm/linux-install-wizard.js +1 -0
  94. package/dist/esm/linux-install-wizard.js.map +1 -1
  95. package/dist/esm/online-instance-list.js +25 -25
  96. package/dist/esm/online-instance-list.js.map +1 -1
  97. package/dist/esm/saml-callback-client.js.map +1 -1
  98. package/dist/esm/security-card.js +39 -24
  99. package/dist/esm/security-card.js.map +1 -1
  100. package/dist/esm/support-card.js +1 -0
  101. package/dist/esm/support-card.js.map +1 -1
  102. package/dist/esm/top-nav.js +82 -79
  103. package/dist/esm/top-nav.js.map +1 -1
  104. package/dist/esm/update-layout.js +82 -79
  105. package/dist/esm/update-layout.js.map +1 -1
  106. package/dist/esm/upload-support-bundle-modal.js +46 -16
  107. package/dist/esm/upload-support-bundle-modal.js.map +1 -1
  108. package/dist/esm/utils/index.js +48 -1
  109. package/dist/esm/utils/index.js.map +1 -1
  110. package/dist/helm-install-wizard.d.mts +2 -2
  111. package/dist/helm-install-wizard.d.ts +2 -2
  112. package/dist/helm-install-wizard.js +1 -0
  113. package/dist/helm-install-wizard.js.map +1 -1
  114. package/dist/{index-DXy7RxOX.d.ts → index-Bcp17Mf3.d.ts} +1 -16
  115. package/dist/{index-JX9-CIMA.d.mts → index-DaH1bSuO.d.mts} +1 -16
  116. package/dist/index.d.mts +5 -4
  117. package/dist/index.d.ts +5 -4
  118. package/dist/index.js +262 -214
  119. package/dist/index.js.map +1 -1
  120. package/dist/install-actions.d.mts +2 -2
  121. package/dist/install-actions.d.ts +2 -2
  122. package/dist/install-actions.js +1 -0
  123. package/dist/install-actions.js.map +1 -1
  124. package/dist/instance-card.d.mts +1 -1
  125. package/dist/instance-card.d.ts +1 -1
  126. package/dist/instance-card.js +25 -25
  127. package/dist/instance-card.js.map +1 -1
  128. package/dist/license-details.js +1 -0
  129. package/dist/license-details.js.map +1 -1
  130. package/dist/linux-install-wizard.d.mts +2 -2
  131. package/dist/linux-install-wizard.d.ts +2 -2
  132. package/dist/linux-install-wizard.js +1 -0
  133. package/dist/linux-install-wizard.js.map +1 -1
  134. package/dist/online-instance-list.d.mts +1 -1
  135. package/dist/online-instance-list.d.ts +1 -1
  136. package/dist/online-instance-list.js +25 -25
  137. package/dist/online-instance-list.js.map +1 -1
  138. package/dist/pending-installations.d.mts +1 -1
  139. package/dist/pending-installations.d.ts +1 -1
  140. package/dist/saml-callback-client.d.mts +1 -1
  141. package/dist/saml-callback-client.d.ts +1 -1
  142. package/dist/saml-callback-client.js.map +1 -1
  143. package/dist/security-card.d.mts +1 -1
  144. package/dist/security-card.d.ts +1 -1
  145. package/dist/security-card.js +43 -24
  146. package/dist/security-card.js.map +1 -1
  147. package/dist/styles.css +4 -12
  148. package/dist/support-bundles-card.d.mts +1 -1
  149. package/dist/support-bundles-card.d.ts +1 -1
  150. package/dist/support-card.js +1 -0
  151. package/dist/support-card.js.map +1 -1
  152. package/dist/{top-nav-CEqw0KpO.d.ts → top-nav-8f2U69MF.d.ts} +1 -1
  153. package/dist/{top-nav-BUQAGoG1.d.mts → top-nav-B2yA3PC7.d.mts} +1 -1
  154. package/dist/top-nav.d.mts +2 -2
  155. package/dist/top-nav.d.ts +2 -2
  156. package/dist/top-nav.js +82 -79
  157. package/dist/top-nav.js.map +1 -1
  158. package/dist/update-layout.js +82 -79
  159. package/dist/update-layout.js.map +1 -1
  160. package/dist/upload-support-bundle-modal.d.mts +9 -9
  161. package/dist/upload-support-bundle-modal.d.ts +9 -9
  162. package/dist/upload-support-bundle-modal.js +46 -16
  163. package/dist/upload-support-bundle-modal.js.map +1 -1
  164. package/dist/upload-with-progress-D760HthX.d.mts +35 -0
  165. package/dist/upload-with-progress-D760HthX.d.ts +35 -0
  166. package/dist/utils/index.d.mts +3 -2
  167. package/dist/utils/index.d.ts +3 -2
  168. package/dist/utils/index.js +48 -0
  169. package/dist/utils/index.js.map +1 -1
  170. package/package.json +10 -5
  171. package/dist/esm/saml-handlers.js.map +0 -1
  172. package/dist/saml-handlers.js.map +0 -1
package/dist/index.js CHANGED
@@ -127,7 +127,7 @@ var init_tracer = __esm({
127
127
 
128
128
  // package.json
129
129
  var package_default = {
130
- version: "0.0.25"};
130
+ version: "0.0.27"};
131
131
 
132
132
  // src/tokens/index.ts
133
133
  var baseTokens = {
@@ -450,218 +450,6 @@ async function fetchLicenseCore() {
450
450
  var fetchLicenseImpl = react.cache(fetchLicenseCore);
451
451
  var fetchLicense = fetchLicenseImpl;
452
452
 
453
- // src/utils/constants.ts
454
- var DEFAULT_FAVICON = "data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%239ca3af' stroke-width='1.5'%3E%3Ccircle cx='12' cy='12' r='10'/%3E%3Cellipse cx='12' cy='12' rx='4' ry='10'/%3E%3Cpath d='M2 12h20'/%3E%3C/svg%3E";
455
- var DEFAULT_PRIMARY_COLOR = "#4f46e5";
456
- var DEFAULT_SECONDARY_COLOR = "#6366f1";
457
- var isHttpApiOrigin = () => {
458
- return process.env.REPLICATED_APP_ORIGIN?.startsWith("http://") || false;
459
- };
460
-
461
- // src/utils/branding.ts
462
- var normalizeColor = (color) => {
463
- if (!color || typeof color !== "string") {
464
- return void 0;
465
- }
466
- const trimmed = color.trim();
467
- if (/^#?[0-9a-fA-F]{3}([0-9a-fA-F]{3})?$/.test(trimmed)) {
468
- return trimmed.startsWith("#") ? trimmed : `#${trimmed}`;
469
- }
470
- console.debug("[portal-components] Invalid color format rejected (only hex supported):", trimmed);
471
- return void 0;
472
- };
473
- var sanitizeUrlForCss = (url) => {
474
- if (!url || typeof url !== "string") {
475
- return void 0;
476
- }
477
- const trimmed = url.trim();
478
- try {
479
- const urlObj = new URL(trimmed);
480
- if (!["http:", "https:", "data:"].includes(urlObj.protocol)) {
481
- console.debug("[portal-components] Invalid URL protocol for background image:", urlObj.protocol);
482
- return void 0;
483
- }
484
- } catch {
485
- console.debug("[portal-components] Invalid URL format for background image:", trimmed);
486
- return void 0;
487
- }
488
- const escaped = trimmed.replace(/\\/g, "\\\\").replace(/\)/g, "\\)").replace(/"/g, '\\"').replace(/'/g, "\\'").replace(/[\x00-\x1F\x7F]/g, "");
489
- return escaped;
490
- };
491
- var decodeBranding = ({ brandingData }) => {
492
- if (!brandingData || typeof brandingData !== "string") {
493
- return {
494
- primaryColor: DEFAULT_PRIMARY_COLOR,
495
- secondaryColor: DEFAULT_SECONDARY_COLOR
496
- };
497
- }
498
- try {
499
- const decoded = buffer.Buffer.from(brandingData, "base64").toString("utf-8");
500
- const parsed = JSON.parse(decoded);
501
- const logo = typeof parsed.logo === "string" ? parsed.logo : void 0;
502
- const titleRaw = typeof parsed.title === "string" ? parsed.title.trim() : "";
503
- const title = titleRaw ? titleRaw : void 0;
504
- const favicon = typeof parsed.favicon === "string" ? parsed.favicon : void 0;
505
- const primaryColorRaw = parsed.primaryColor ?? parsed.primary_color;
506
- const secondaryColorRaw = parsed.secondaryColor ?? parsed.secondary_color;
507
- const primaryColor = normalizeColor(primaryColorRaw);
508
- const secondaryColor = normalizeColor(secondaryColorRaw);
509
- const supportPortalLink = typeof parsed.supportPortalLink === "string" ? parsed.supportPortalLink : void 0;
510
- const backgroundRaw = parsed.background;
511
- const background = backgroundRaw === "minimal" || backgroundRaw === "custom" || backgroundRaw === "image" ? backgroundRaw : void 0;
512
- const backgroundImage = sanitizeUrlForCss(parsed.backgroundImage);
513
- const backgroundGradientStart = normalizeColor(parsed.customColor1);
514
- const backgroundGradientEnd = normalizeColor(parsed.customColor2);
515
- return {
516
- logo,
517
- title,
518
- favicon,
519
- primaryColor: primaryColor || DEFAULT_PRIMARY_COLOR,
520
- secondaryColor: secondaryColor || DEFAULT_SECONDARY_COLOR,
521
- supportPortalLink,
522
- background,
523
- backgroundImage,
524
- backgroundGradientStart,
525
- backgroundGradientEnd
526
- };
527
- } catch (error) {
528
- console.debug("[portal-components] unable to parse branding JSON", error);
529
- return {
530
- primaryColor: DEFAULT_PRIMARY_COLOR,
531
- secondaryColor: DEFAULT_SECONDARY_COLOR
532
- };
533
- }
534
- };
535
-
536
- // src/utils/session.ts
537
- async function validateSession(token) {
538
- if (!token || typeof token !== "string" || !token.trim()) {
539
- return false;
540
- }
541
- const endpoint = `${getApiOrigin()}/enterprise-portal/user`;
542
- const response = await fetch(endpoint, {
543
- method: "GET",
544
- headers: {
545
- authorization: `Bearer ${token}`
546
- },
547
- // Short timeout for validation
548
- signal: AbortSignal.timeout(5e3)
549
- });
550
- if (response.status === 401) {
551
- return false;
552
- }
553
- if (!response.ok) {
554
- throw new Error(`Session validation failed with status ${response.status}`);
555
- }
556
- return true;
557
- }
558
-
559
- // src/utils/format.ts
560
- function formatBytes(bytes, decimals = 1) {
561
- if (bytes === 0) return "0 Bytes";
562
- const k = 1024;
563
- const dm = decimals < 0 ? 0 : decimals;
564
- const sizes = ["Bytes", "KB", "MB", "GB", "TB"];
565
- const i = Math.floor(Math.log(bytes) / Math.log(k));
566
- return `${parseFloat((bytes / Math.pow(k, i)).toFixed(dm))} ${sizes[i]}`;
567
- }
568
- function formatDateShort(dateString) {
569
- if (!dateString) return "Never";
570
- const date = new Date(dateString);
571
- if (isNaN(date.getTime())) {
572
- return dateString;
573
- }
574
- return date.toLocaleDateString("en-US", {
575
- year: "numeric",
576
- month: "2-digit",
577
- day: "2-digit"
578
- });
579
- }
580
- function formatDate(dateString) {
581
- if (!dateString) return "Never";
582
- const date = new Date(dateString);
583
- if (isNaN(date.getTime())) {
584
- return dateString;
585
- }
586
- return date.toLocaleDateString("en-US", {
587
- month: "short",
588
- day: "numeric",
589
- year: "numeric",
590
- hour: "numeric",
591
- minute: "2-digit",
592
- hour12: true
593
- });
594
- }
595
- function formatDateTime(dateString) {
596
- const date = new Date(dateString);
597
- if (isNaN(date.getTime())) {
598
- return dateString;
599
- }
600
- return date.toLocaleString("en-US", {
601
- timeZone: "UTC",
602
- year: "numeric",
603
- month: "2-digit",
604
- day: "2-digit",
605
- hour: "2-digit",
606
- minute: "2-digit",
607
- second: "2-digit",
608
- hour12: false
609
- }) + " UTC";
610
- }
611
- function formatDateTimeLocal(dateString) {
612
- if (!dateString) return "N/A";
613
- try {
614
- const date = new Date(dateString);
615
- if (isNaN(date.getTime())) {
616
- return dateString;
617
- }
618
- return date.toLocaleDateString("en-US", {
619
- month: "numeric",
620
- day: "numeric",
621
- year: "numeric",
622
- hour: "numeric",
623
- minute: "2-digit",
624
- hour12: true
625
- });
626
- } catch {
627
- return "N/A";
628
- }
629
- }
630
-
631
- // src/utils/release-helpers.ts
632
- function convertToReleaseEntry(release, channelName, options) {
633
- const sections = [];
634
- if (release.release_notes && release.release_notes.trim().length > 0) {
635
- if (options.releaseNotesMode === "markdown") {
636
- sections.push({
637
- title: "Release Notes",
638
- description: release.release_notes
639
- });
640
- } else {
641
- const releaseNotesItems = release.release_notes.split(/\r?\n/).map((line) => line.trim()).filter((line) => line.length > 0);
642
- sections.push({
643
- title: "Release Notes",
644
- description: releaseNotesItems.length === 0 ? release.release_notes : void 0,
645
- items: releaseNotesItems.length > 0 ? releaseNotesItems : void 0
646
- });
647
- }
648
- }
649
- const charts = release.helm_charts ? release.helm_charts.filter((chart) => !chart.is_kots_installer_only).map((chart) => `${chart.name} v${chart.version}`) : [];
650
- if (charts.length > 0) {
651
- sections.push({
652
- title: "Helm Charts",
653
- items: charts,
654
- description: "Latest chart versions included in this release."
655
- });
656
- }
657
- return {
658
- version: release.label || `Release ${release.release_sequence}`,
659
- channel: channelName || `Channel ${release.channel_sequence}`,
660
- releasedAt: release.release_date,
661
- sections
662
- };
663
- }
664
-
665
453
  // src/actions/index.ts
666
454
  var getApiOrigin = () => {
667
455
  return (process.env.REPLICATED_APP_ORIGIN || "https://replicated.app").replace(/\/+$/, "");
@@ -804,6 +592,7 @@ var fetchCustomBrandingImpl = async () => {
804
592
  title: payload.title,
805
593
  primaryColor: payload.primaryColor,
806
594
  secondaryColor: payload.secondaryColor,
595
+ contact: payload.contact,
807
596
  favicon: payload.faviconUrl,
808
597
  supportPortalLink: payload.supportPortalLink || "",
809
598
  background: payload.background,
@@ -1746,6 +1535,91 @@ var LicenseDetails = async ({
1746
1535
  ] })
1747
1536
  ] });
1748
1537
  };
1538
+
1539
+ // src/utils/constants.ts
1540
+ var DEFAULT_FAVICON = "data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%239ca3af' stroke-width='1.5'%3E%3Ccircle cx='12' cy='12' r='10'/%3E%3Cellipse cx='12' cy='12' rx='4' ry='10'/%3E%3Cpath d='M2 12h20'/%3E%3C/svg%3E";
1541
+ var DEFAULT_PRIMARY_COLOR = "#4f46e5";
1542
+ var DEFAULT_SECONDARY_COLOR = "#6366f1";
1543
+ var isHttpApiOrigin = () => {
1544
+ return process.env.REPLICATED_APP_ORIGIN?.startsWith("http://") || false;
1545
+ };
1546
+
1547
+ // src/utils/branding.ts
1548
+ var normalizeColor = (color) => {
1549
+ if (!color || typeof color !== "string") {
1550
+ return void 0;
1551
+ }
1552
+ const trimmed = color.trim();
1553
+ if (/^#?[0-9a-fA-F]{3}([0-9a-fA-F]{3})?$/.test(trimmed)) {
1554
+ return trimmed.startsWith("#") ? trimmed : `#${trimmed}`;
1555
+ }
1556
+ console.debug("[portal-components] Invalid color format rejected (only hex supported):", trimmed);
1557
+ return void 0;
1558
+ };
1559
+ var sanitizeUrlForCss = (url) => {
1560
+ if (!url || typeof url !== "string") {
1561
+ return void 0;
1562
+ }
1563
+ const trimmed = url.trim();
1564
+ try {
1565
+ const urlObj = new URL(trimmed);
1566
+ if (!["http:", "https:", "data:"].includes(urlObj.protocol)) {
1567
+ console.debug("[portal-components] Invalid URL protocol for background image:", urlObj.protocol);
1568
+ return void 0;
1569
+ }
1570
+ } catch {
1571
+ console.debug("[portal-components] Invalid URL format for background image:", trimmed);
1572
+ return void 0;
1573
+ }
1574
+ const escaped = trimmed.replace(/\\/g, "\\\\").replace(/\)/g, "\\)").replace(/"/g, '\\"').replace(/'/g, "\\'").replace(/[\x00-\x1F\x7F]/g, "");
1575
+ return escaped;
1576
+ };
1577
+ var decodeBranding = ({ brandingData }) => {
1578
+ if (!brandingData || typeof brandingData !== "string") {
1579
+ return {
1580
+ primaryColor: DEFAULT_PRIMARY_COLOR,
1581
+ secondaryColor: DEFAULT_SECONDARY_COLOR
1582
+ };
1583
+ }
1584
+ try {
1585
+ const decoded = buffer.Buffer.from(brandingData, "base64").toString("utf-8");
1586
+ const parsed = JSON.parse(decoded);
1587
+ const logo = typeof parsed.logo === "string" ? parsed.logo : void 0;
1588
+ const titleRaw = typeof parsed.title === "string" ? parsed.title.trim() : "";
1589
+ const title = titleRaw ? titleRaw : void 0;
1590
+ const favicon = typeof parsed.favicon === "string" ? parsed.favicon : void 0;
1591
+ const primaryColorRaw = parsed.primaryColor ?? parsed.primary_color;
1592
+ const secondaryColorRaw = parsed.secondaryColor ?? parsed.secondary_color;
1593
+ const primaryColor = normalizeColor(primaryColorRaw);
1594
+ const secondaryColor = normalizeColor(secondaryColorRaw);
1595
+ const contact = typeof parsed.contact === "string" ? parsed.contact : void 0;
1596
+ const supportPortalLink = typeof parsed.supportPortalLink === "string" ? parsed.supportPortalLink : void 0;
1597
+ const backgroundRaw = parsed.background;
1598
+ const background = backgroundRaw === "minimal" || backgroundRaw === "custom" || backgroundRaw === "image" ? backgroundRaw : void 0;
1599
+ const backgroundImage = sanitizeUrlForCss(parsed.backgroundImage);
1600
+ const backgroundGradientStart = normalizeColor(parsed.customColor1);
1601
+ const backgroundGradientEnd = normalizeColor(parsed.customColor2);
1602
+ return {
1603
+ logo,
1604
+ title,
1605
+ favicon,
1606
+ primaryColor: primaryColor || DEFAULT_PRIMARY_COLOR,
1607
+ secondaryColor: secondaryColor || DEFAULT_SECONDARY_COLOR,
1608
+ contact,
1609
+ supportPortalLink,
1610
+ background,
1611
+ backgroundImage,
1612
+ backgroundGradientStart,
1613
+ backgroundGradientEnd
1614
+ };
1615
+ } catch (error) {
1616
+ console.debug("[portal-components] unable to parse branding JSON", error);
1617
+ return {
1618
+ primaryColor: DEFAULT_PRIMARY_COLOR,
1619
+ secondaryColor: DEFAULT_SECONDARY_COLOR
1620
+ };
1621
+ }
1622
+ };
1749
1623
  function UserMenuDropdown({
1750
1624
  displayLabel,
1751
1625
  children,
@@ -2674,7 +2548,180 @@ var UpdateLayout = ({ children }) => {
2674
2548
  };
2675
2549
  UpdateLayout.displayName = "UpdateLayout";
2676
2550
 
2677
- // src/saml-handlers.ts
2551
+ // src/utils/session.ts
2552
+ async function validateSession(token) {
2553
+ if (!token || typeof token !== "string" || !token.trim()) {
2554
+ return false;
2555
+ }
2556
+ const endpoint = `${getApiOrigin()}/enterprise-portal/user`;
2557
+ const response = await fetch(endpoint, {
2558
+ method: "GET",
2559
+ headers: {
2560
+ authorization: `Bearer ${token}`
2561
+ },
2562
+ // Short timeout for validation
2563
+ signal: AbortSignal.timeout(5e3)
2564
+ });
2565
+ if (response.status === 401) {
2566
+ return false;
2567
+ }
2568
+ if (!response.ok) {
2569
+ throw new Error(`Session validation failed with status ${response.status}`);
2570
+ }
2571
+ return true;
2572
+ }
2573
+
2574
+ // src/utils/format.ts
2575
+ function formatBytes(bytes, decimals = 1) {
2576
+ if (bytes === 0) return "0 Bytes";
2577
+ const k = 1024;
2578
+ const dm = decimals < 0 ? 0 : decimals;
2579
+ const sizes = ["Bytes", "KB", "MB", "GB", "TB"];
2580
+ const i = Math.floor(Math.log(bytes) / Math.log(k));
2581
+ return `${parseFloat((bytes / Math.pow(k, i)).toFixed(dm))} ${sizes[i]}`;
2582
+ }
2583
+ function formatDateShort(dateString) {
2584
+ if (!dateString) return "Never";
2585
+ const date = new Date(dateString);
2586
+ if (isNaN(date.getTime())) {
2587
+ return dateString;
2588
+ }
2589
+ return date.toLocaleDateString("en-US", {
2590
+ year: "numeric",
2591
+ month: "2-digit",
2592
+ day: "2-digit"
2593
+ });
2594
+ }
2595
+ function formatDate(dateString) {
2596
+ if (!dateString) return "Never";
2597
+ const date = new Date(dateString);
2598
+ if (isNaN(date.getTime())) {
2599
+ return dateString;
2600
+ }
2601
+ return date.toLocaleDateString("en-US", {
2602
+ month: "short",
2603
+ day: "numeric",
2604
+ year: "numeric",
2605
+ hour: "numeric",
2606
+ minute: "2-digit",
2607
+ hour12: true
2608
+ });
2609
+ }
2610
+ function formatDateTime(dateString) {
2611
+ const date = new Date(dateString);
2612
+ if (isNaN(date.getTime())) {
2613
+ return dateString;
2614
+ }
2615
+ return date.toLocaleString("en-US", {
2616
+ timeZone: "UTC",
2617
+ year: "numeric",
2618
+ month: "2-digit",
2619
+ day: "2-digit",
2620
+ hour: "2-digit",
2621
+ minute: "2-digit",
2622
+ second: "2-digit",
2623
+ hour12: false
2624
+ }) + " UTC";
2625
+ }
2626
+ function formatDateTimeLocal(dateString) {
2627
+ if (!dateString) return "N/A";
2628
+ try {
2629
+ const date = new Date(dateString);
2630
+ if (isNaN(date.getTime())) {
2631
+ return dateString;
2632
+ }
2633
+ return date.toLocaleDateString("en-US", {
2634
+ month: "numeric",
2635
+ day: "numeric",
2636
+ year: "numeric",
2637
+ hour: "numeric",
2638
+ minute: "2-digit",
2639
+ hour12: true
2640
+ });
2641
+ } catch {
2642
+ return "N/A";
2643
+ }
2644
+ }
2645
+
2646
+ // src/utils/release-helpers.ts
2647
+ function convertToReleaseEntry(release, channelName, options) {
2648
+ const sections = [];
2649
+ if (release.release_notes && release.release_notes.trim().length > 0) {
2650
+ if (options.releaseNotesMode === "markdown") {
2651
+ sections.push({
2652
+ title: "Release Notes",
2653
+ description: release.release_notes
2654
+ });
2655
+ } else {
2656
+ const releaseNotesItems = release.release_notes.split(/\r?\n/).map((line) => line.trim()).filter((line) => line.length > 0);
2657
+ sections.push({
2658
+ title: "Release Notes",
2659
+ description: releaseNotesItems.length === 0 ? release.release_notes : void 0,
2660
+ items: releaseNotesItems.length > 0 ? releaseNotesItems : void 0
2661
+ });
2662
+ }
2663
+ }
2664
+ const charts = release.helm_charts ? release.helm_charts.filter((chart) => !chart.is_kots_installer_only).map((chart) => `${chart.name} v${chart.version}`) : [];
2665
+ if (charts.length > 0) {
2666
+ sections.push({
2667
+ title: "Helm Charts",
2668
+ items: charts,
2669
+ description: "Latest chart versions included in this release."
2670
+ });
2671
+ }
2672
+ return {
2673
+ version: release.label || `Release ${release.release_sequence}`,
2674
+ channel: channelName || `Channel ${release.channel_sequence}`,
2675
+ releasedAt: release.release_date,
2676
+ sections
2677
+ };
2678
+ }
2679
+
2680
+ // src/utils/upload-with-progress.ts
2681
+ async function uploadSupportBundleWithProgress(file, appId, onProgress, signal) {
2682
+ return new Promise((resolve, reject) => {
2683
+ const xhr = new XMLHttpRequest();
2684
+ xhr.upload.addEventListener("progress", (e) => {
2685
+ if (e.lengthComputable) {
2686
+ const percent = Math.round(e.loaded / e.total * 100);
2687
+ onProgress(percent);
2688
+ }
2689
+ });
2690
+ xhr.addEventListener("load", () => {
2691
+ if (xhr.status === 200) {
2692
+ try {
2693
+ const response = JSON.parse(xhr.responseText);
2694
+ resolve(response);
2695
+ } catch (err) {
2696
+ reject(new Error("Failed to parse server response"));
2697
+ }
2698
+ } else {
2699
+ try {
2700
+ const response = JSON.parse(xhr.responseText);
2701
+ reject(new Error(response.error || `Upload failed: ${xhr.status}`));
2702
+ } catch {
2703
+ reject(new Error(`Upload failed: ${xhr.status} ${xhr.statusText}`));
2704
+ }
2705
+ }
2706
+ });
2707
+ xhr.addEventListener("error", () => {
2708
+ reject(new Error("Network error. Please check your connection."));
2709
+ });
2710
+ xhr.addEventListener("abort", () => {
2711
+ reject(new Error("Upload cancelled"));
2712
+ });
2713
+ signal.addEventListener("abort", () => {
2714
+ xhr.abort();
2715
+ });
2716
+ const basePath = process.env.NEXT_PUBLIC_BASE_PATH || "";
2717
+ const uploadUrl = `${basePath}/api/support-bundles/upload?appId=${encodeURIComponent(appId)}`;
2718
+ xhr.open("POST", uploadUrl, true);
2719
+ xhr.setRequestHeader("Content-Type", "application/gzip");
2720
+ xhr.send(file);
2721
+ });
2722
+ }
2723
+
2724
+ // src/api/saml.ts
2678
2725
  async function setSamlSessionImpl(token) {
2679
2726
  try {
2680
2727
  if (!token) {
@@ -2794,6 +2841,7 @@ exports.setSamlSessionImpl = setSamlSessionImpl;
2794
2841
  exports.updateNotifications = updateNotifications;
2795
2842
  exports.updateUser = updateUser;
2796
2843
  exports.uploadSupportBundle = uploadSupportBundle;
2844
+ exports.uploadSupportBundleWithProgress = uploadSupportBundleWithProgress;
2797
2845
  exports.validateSession = validateSession;
2798
2846
  exports.verifyMagicLink = verifyMagicLink;
2799
2847
  //# sourceMappingURL=index.js.map