@cobaltcore-dev/aurora 0.1.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 (142) hide show
  1. package/LICENSE +201 -0
  2. package/README.md +141 -0
  3. package/dist/client/AuroraApp.d.ts +7 -0
  4. package/dist/client/AuthProvider-D-5Jpa6F.mjs +100 -0
  5. package/dist/client/AuthProvider-D-5Jpa6F.mjs.map +1 -0
  6. package/dist/client/ContentHeader-H8KGY3Wd.mjs +81 -0
  7. package/dist/client/ContentHeader-H8KGY3Wd.mjs.map +1 -0
  8. package/dist/client/DeleteFlavorModal-B98oiHWx.mjs +629 -0
  9. package/dist/client/DeleteFlavorModal-B98oiHWx.mjs.map +1 -0
  10. package/dist/client/EditSecurityGroupModal-wQVNIVg1.mjs +137 -0
  11. package/dist/client/EditSecurityGroupModal-wQVNIVg1.mjs.map +1 -0
  12. package/dist/client/FloatingIpActionModals-qu1NMI5a.mjs +417 -0
  13. package/dist/client/FloatingIpActionModals-qu1NMI5a.mjs.map +1 -0
  14. package/dist/client/ImageToastNotifications-wsQDNEh7.mjs +1267 -0
  15. package/dist/client/ImageToastNotifications-wsQDNEh7.mjs.map +1 -0
  16. package/dist/client/ListToolbar-CHlkZrpl.mjs +223 -0
  17. package/dist/client/ListToolbar-CHlkZrpl.mjs.map +1 -0
  18. package/dist/client/RouteError-BwgDIwJE.mjs +25 -0
  19. package/dist/client/RouteError-BwgDIwJE.mjs.map +1 -0
  20. package/dist/client/_auth-CsliQdkJ.mjs +11 -0
  21. package/dist/client/_auth-CsliQdkJ.mjs.map +1 -0
  22. package/dist/client/_flavorId-D_A53VYa.mjs +56 -0
  23. package/dist/client/_flavorId-D_A53VYa.mjs.map +1 -0
  24. package/dist/client/_flavorId-DbhYLFxY.mjs +190 -0
  25. package/dist/client/_flavorId-DbhYLFxY.mjs.map +1 -0
  26. package/dist/client/_floatingIpId-BGgftRBQ.mjs +21 -0
  27. package/dist/client/_floatingIpId-BGgftRBQ.mjs.map +1 -0
  28. package/dist/client/_floatingIpId-D5myuLFz.mjs +228 -0
  29. package/dist/client/_floatingIpId-D5myuLFz.mjs.map +1 -0
  30. package/dist/client/_imageId-BoHX155h.mjs +27 -0
  31. package/dist/client/_imageId-BoHX155h.mjs.map +1 -0
  32. package/dist/client/_imageId-CTa0c3Av.mjs +530 -0
  33. package/dist/client/_imageId-CTa0c3Av.mjs.map +1 -0
  34. package/dist/client/_pcaId-C7Lrv1H_.mjs +242 -0
  35. package/dist/client/_pcaId-C7Lrv1H_.mjs.map +1 -0
  36. package/dist/client/_pcaId-DBgz5V_9.mjs +21 -0
  37. package/dist/client/_pcaId-DBgz5V_9.mjs.map +1 -0
  38. package/dist/client/_projectId-B9fln31N.mjs +8 -0
  39. package/dist/client/_projectId-B9fln31N.mjs.map +1 -0
  40. package/dist/client/_projectId-Be1Erj68.mjs +300 -0
  41. package/dist/client/_projectId-Be1Erj68.mjs.map +1 -0
  42. package/dist/client/_projectId-C-E4NNgo.mjs +84 -0
  43. package/dist/client/_projectId-C-E4NNgo.mjs.map +1 -0
  44. package/dist/client/_projectId-INhedXor.mjs +26 -0
  45. package/dist/client/_projectId-INhedXor.mjs.map +1 -0
  46. package/dist/client/_securityGroupId-DQoRQ-yA.mjs +1647 -0
  47. package/dist/client/_securityGroupId-DQoRQ-yA.mjs.map +1 -0
  48. package/dist/client/_securityGroupId-ihjy8Lcd.mjs +21 -0
  49. package/dist/client/_securityGroupId-ihjy8Lcd.mjs.map +1 -0
  50. package/dist/client/about-oT6ccz8T.mjs +92 -0
  51. package/dist/client/about-oT6ccz8T.mjs.map +1 -0
  52. package/dist/client/aurora-D_NPTbo-.mjs +19 -0
  53. package/dist/client/aurora-D_NPTbo-.mjs.map +1 -0
  54. package/dist/client/build-eu9eg0zF.mjs +14619 -0
  55. package/dist/client/build-eu9eg0zF.mjs.map +1 -0
  56. package/dist/client/buildFilterParams-BDOIRDeD.mjs +15 -0
  57. package/dist/client/buildFilterParams-BDOIRDeD.mjs.map +1 -0
  58. package/dist/client/cn-C3laVXMm.mjs +10 -0
  59. package/dist/client/cn-C3laVXMm.mjs.map +1 -0
  60. package/dist/client/constants-ByHCdNsI.mjs +128 -0
  61. package/dist/client/constants-ByHCdNsI.mjs.map +1 -0
  62. package/dist/client/containers-B_ozmVlx.mjs +74 -0
  63. package/dist/client/containers-B_ozmVlx.mjs.map +1 -0
  64. package/dist/client/containers-Dx7TYruP.mjs +7 -0
  65. package/dist/client/containers-Dx7TYruP.mjs.map +1 -0
  66. package/dist/client/containers-rn_ntCJu.mjs +3029 -0
  67. package/dist/client/containers-rn_ntCJu.mjs.map +1 -0
  68. package/dist/client/flavors-CT4auvLO.mjs +565 -0
  69. package/dist/client/flavors-CT4auvLO.mjs.map +1 -0
  70. package/dist/client/flavors-DRZb9LJP.mjs +8 -0
  71. package/dist/client/flavors-DRZb9LJP.mjs.map +1 -0
  72. package/dist/client/flavors-DtgMd0Ii.mjs +12 -0
  73. package/dist/client/flavors-DtgMd0Ii.mjs.map +1 -0
  74. package/dist/client/floatingips-DG5cFJSZ.mjs +12 -0
  75. package/dist/client/floatingips-DG5cFJSZ.mjs.map +1 -0
  76. package/dist/client/floatingips-iCMR0ZiL.mjs +436 -0
  77. package/dist/client/floatingips-iCMR0ZiL.mjs.map +1 -0
  78. package/dist/client/formatBytes-GYujK0dP.mjs +38 -0
  79. package/dist/client/formatBytes-GYujK0dP.mjs.map +1 -0
  80. package/dist/client/helpers--JWXi40U.mjs +6 -0
  81. package/dist/client/helpers--JWXi40U.mjs.map +1 -0
  82. package/dist/client/hooks-s-I8vWww.mjs +2 -0
  83. package/dist/client/images-BTqRflJv2.mjs +1794 -0
  84. package/dist/client/images-BTqRflJv2.mjs.map +1 -0
  85. package/dist/client/images-DRTfx8k2.mjs +8 -0
  86. package/dist/client/images-DRTfx8k2.mjs.map +1 -0
  87. package/dist/client/images-xBfsjxkX.mjs +12 -0
  88. package/dist/client/images-xBfsjxkX.mjs.map +1 -0
  89. package/dist/client/index.d.ts +1 -0
  90. package/dist/client/index.js +1033 -0
  91. package/dist/client/index.js.map +1 -0
  92. package/dist/client/md-CI9FmfYv.mjs +390 -0
  93. package/dist/client/md-CI9FmfYv.mjs.map +1 -0
  94. package/dist/client/network-DFVVVNS5.mjs +8 -0
  95. package/dist/client/network-DFVVVNS5.mjs.map +1 -0
  96. package/dist/client/objects-CKk6cST_.mjs +4762 -0
  97. package/dist/client/objects-CKk6cST_.mjs.map +1 -0
  98. package/dist/client/objects-DkDKVSmQ.mjs +8 -0
  99. package/dist/client/objects-DkDKVSmQ.mjs.map +1 -0
  100. package/dist/client/objects-r_Vl31oj.mjs +80 -0
  101. package/dist/client/objects-r_Vl31oj.mjs.map +1 -0
  102. package/dist/client/overview-B7pXx6bt.mjs +173 -0
  103. package/dist/client/overview-B7pXx6bt.mjs.map +1 -0
  104. package/dist/client/overview-CKGLIu6W.mjs +12 -0
  105. package/dist/client/overview-CKGLIu6W.mjs.map +1 -0
  106. package/dist/client/overview-Ca8r3SAz.mjs +16 -0
  107. package/dist/client/overview-Ca8r3SAz.mjs.map +1 -0
  108. package/dist/client/overview-DkPM0Od5.mjs +12 -0
  109. package/dist/client/overview-DkPM0Od5.mjs.map +1 -0
  110. package/dist/client/overview-Dxm7Ef3X.mjs +12 -0
  111. package/dist/client/overview-Dxm7Ef3X.mjs.map +1 -0
  112. package/dist/client/overview-ag4Envez.mjs +16 -0
  113. package/dist/client/overview-ag4Envez.mjs.map +1 -0
  114. package/dist/client/pca-BGv7Mprl.mjs +12 -0
  115. package/dist/client/pca-BGv7Mprl.mjs.map +1 -0
  116. package/dist/client/pca-DpULpMu5.mjs +167 -0
  117. package/dist/client/pca-DpULpMu5.mjs.map +1 -0
  118. package/dist/client/projects-BuN69cxO.mjs +144 -0
  119. package/dist/client/projects-BuN69cxO.mjs.map +1 -0
  120. package/dist/client/projects-D1pP0XdA.mjs +12 -0
  121. package/dist/client/projects-D1pP0XdA.mjs.map +1 -0
  122. package/dist/client/projects-MbS1USl2.mjs +7 -0
  123. package/dist/client/projects-MbS1USl2.mjs.map +1 -0
  124. package/dist/client/projects-_Dfn6eQT.mjs +22 -0
  125. package/dist/client/projects-_Dfn6eQT.mjs.map +1 -0
  126. package/dist/client/securitygroups-DURjFfYK.mjs +12 -0
  127. package/dist/client/securitygroups-DURjFfYK.mjs.map +1 -0
  128. package/dist/client/securitygroups-KC2qvmH8.mjs +442 -0
  129. package/dist/client/securitygroups-KC2qvmH8.mjs.map +1 -0
  130. package/dist/client/trpcClient-BxguzNYF.mjs +57 -0
  131. package/dist/client/trpcClient-BxguzNYF.mjs.map +1 -0
  132. package/dist/client/useErrorTranslation-TZVwIAzq.mjs +83 -0
  133. package/dist/client/useErrorTranslation-TZVwIAzq.mjs.map +1 -0
  134. package/dist/client/useListWithFiltering-mMX_EfyI.mjs +32 -0
  135. package/dist/client/useListWithFiltering-mMX_EfyI.mjs.map +1 -0
  136. package/dist/client/useModal-Dg4CBeqL.mjs +12 -0
  137. package/dist/client/useModal-Dg4CBeqL.mjs.map +1 -0
  138. package/dist/client/useProjectId-BWaeJZOy.mjs +11 -0
  139. package/dist/client/useProjectId-BWaeJZOy.mjs.map +1 -0
  140. package/dist/server/index.d.ts +35 -0
  141. package/dist/server/index.js +36514 -0
  142. package/package.json +129 -0
@@ -0,0 +1,15 @@
1
+ //#region src/client/utils/buildFilterParams.ts
2
+ var e = (e) => {
3
+ let t = {};
4
+ return e.selectedFilters?.length && e.selectedFilters.filter((e) => !e.inactive).forEach((e) => {
5
+ if (e.value === "true" || e.value === "false") {
6
+ t[e.name] = e.value === "true";
7
+ return;
8
+ }
9
+ t[e.name] = e.value;
10
+ }), t;
11
+ };
12
+ //#endregion
13
+ export { e as t };
14
+
15
+ //# sourceMappingURL=buildFilterParams-BDOIRDeD.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"buildFilterParams-BDOIRDeD.mjs","names":["buildFilterParams","filterSettings","params","selectedFilters","length","filter","sf","inactive","forEach","value","name"],"sources":["../../src/client/utils/buildFilterParams.ts"],"sourcesContent":["import { FilterSettings } from \"@/client/components/ListToolbar/types\"\n\n/**\n * Builds filter parameters from current filter settings\n */\nexport const buildFilterParams = (filterSettings: FilterSettings): Record<string, string | boolean> => {\n const params: Record<string, string | boolean> = {}\n\n if (!filterSettings.selectedFilters?.length) return params\n\n filterSettings.selectedFilters\n .filter((sf) => !sf.inactive)\n .forEach((sf) => {\n if (sf.value === \"true\" || sf.value === \"false\") {\n params[sf.name] = sf.value === \"true\"\n return\n }\n params[sf.name] = sf.value\n })\n return params\n}\n"],"mappings":";AAKA,IAAaA,KAAqBC,MAAAA;CAChC,IAAMC,IAA2C,EAAC;AAalD,QAXKD,EAAeE,iBAAiBC,UAErCH,EAAeE,gBACZE,QAAQC,MAAO,CAACA,EAAGC,SAAQ,CAC3BC,SAASF,MAAAA;AACR,MAAIA,EAAGG,UAAU,UAAUH,EAAGG,UAAU,SAAS;AAC/CP,KAAOI,EAAGI,QAAQJ,EAAGG,UAAU;AAC/B;;AAEFP,IAAOI,EAAGI,QAAQJ,EAAGG;GACvB,EAVkDP"}
@@ -0,0 +1,10 @@
1
+ import { clsx as e } from "clsx";
2
+ import { twMerge as t } from "tailwind-merge";
3
+ //#region src/client/utils/cn.ts
4
+ function n(...n) {
5
+ return t(e(n));
6
+ }
7
+ //#endregion
8
+ export { n as t };
9
+
10
+ //# sourceMappingURL=cn-C3laVXMm.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cn-C3laVXMm.mjs","names":["clsx","twMerge","cn","inputs"],"sources":["../../src/client/utils/cn.ts"],"sourcesContent":["import { type ClassValue, clsx } from \"clsx\"\nimport { twMerge } from \"tailwind-merge\"\n\n/**\n * A utility function that combines clsx and tailwind-merge\n *\n * This function takes multiple class values (strings, objects, arrays, etc.)\n * and combines them into a single string of CSS classes.\n * It then uses tailwind-merge to resolve any Tailwind CSS conflicts.\n *\n * @param inputs - Class values to be combined\n * @returns A string of CSS classes with Tailwind conflicts resolved\n *\n * @example\n * // Basic usage\n * cn('text-red-500', 'bg-blue-500')\n * // => 'text-red-500 bg-blue-500'\n *\n * @example\n * // With conditionals\n * cn('text-white', isError && 'bg-red-500', !isError && 'bg-blue-500')\n * // => 'text-white bg-red-500' or 'text-white bg-blue-500'\n *\n * @example\n * // Resolving conflicts\n * cn('text-red-500', 'text-blue-500')\n * // => 'text-blue-500' (the latter class wins)\n */\nexport function cn(...inputs: ClassValue[]): string {\n return twMerge(clsx(inputs))\n}\n"],"mappings":";;;AA4BA,SAAgBE,EAAG,GAAGC,GAAoB;AACxC,QAAOF,EAAQD,EAAKG,EAAAA,CAAAA"}
@@ -0,0 +1,128 @@
1
+ import { $ as e, D as t, W as n, b as r, i, q as a, s as o } from "./build-eu9eg0zF.mjs";
2
+ import { r as s } from "./trpcClient-BxguzNYF.mjs";
3
+ import { c, n as l, p as u } from "./md-CI9FmfYv.mjs";
4
+ import { t as d } from "./useProjectId-BWaeJZOy.mjs";
5
+ import "./hooks-s-I8vWww.mjs";
6
+ import { jsx as f, jsxs as p } from "react/jsx-runtime";
7
+ import { Trans as m, useLingui as h } from "@lingui/react";
8
+ import { z as g } from "zod";
9
+ import { i18n as _ } from "@lingui/core";
10
+ import { useForm as v, useStore as y } from "@tanstack/react-form";
11
+ //#region src/client/routes/_auth/projects/$projectId/services/pca/-components/-modals/DeletePcaModal.tsx
12
+ var b = ({ pca: c, open: l, onClose: u, onSuccess: _ }) => {
13
+ let { i18n: b, _: x } = h(), S = d(), C = s.useUtils(), { isPending: w, ...T } = s.services.pca.delete.useMutation({ onSettled: () => C.services.pca.list.invalidate() }), E = v({
14
+ defaultValues: { delete: "" },
15
+ validators: { onSubmit: g.object({ delete: g.string().refine((e) => e === "delete", { message: b._({ id: "fnCEAB" }) }) }) },
16
+ onSubmit: async () => {
17
+ w || (await T.mutateAsync({
18
+ project_id: S,
19
+ certificate_authority_id: c.id
20
+ }), O(), _?.());
21
+ }
22
+ }), D = y(E.store, (e) => e.isSubmitting || e.values.delete !== "delete"), O = () => {
23
+ E.reset(), u();
24
+ };
25
+ return /* @__PURE__ */ p(o, {
26
+ open: l,
27
+ size: "large",
28
+ title: b._({ id: "ctc4XR" }),
29
+ onCancel: O,
30
+ cancelButtonLabel: b._({ id: "dEgA5A" }),
31
+ confirmButtonLabel: b._({ id: "cnGeoo" }),
32
+ onConfirm: E.handleSubmit,
33
+ disableConfirmButton: w || D,
34
+ children: [
35
+ T.error?.message && /* @__PURE__ */ f(r, {
36
+ dismissible: !1,
37
+ variant: "error",
38
+ className: "mb-4",
39
+ children: T.error.message
40
+ }),
41
+ w && /* @__PURE__ */ p("div", {
42
+ className: "mb-4 flex items-center justify-center gap-2",
43
+ children: [/* @__PURE__ */ f(n, { variant: "primary" }), /* @__PURE__ */ f("span", {
44
+ className: "text-theme-high text-sm",
45
+ children: /* @__PURE__ */ f(m, { id: "nWNviN" })
46
+ })]
47
+ }),
48
+ /* @__PURE__ */ p(a, {
49
+ gap: "2.5",
50
+ direction: "vertical",
51
+ className: "mb-2.5",
52
+ children: [/* @__PURE__ */ f("p", { children: /* @__PURE__ */ f(m, { id: "nNKXt7" }) }), /* @__PURE__ */ f("p", { children: /* @__PURE__ */ f(m, {
53
+ id: "go9U+C",
54
+ components: { 0: /* @__PURE__ */ f("strong", {}) }
55
+ }) })]
56
+ }),
57
+ !w && /* @__PURE__ */ f(t, {
58
+ className: "mb-0",
59
+ id: "delete-pca-form",
60
+ onSubmit: (e) => {
61
+ e.preventDefault(), E.handleSubmit();
62
+ },
63
+ children: /* @__PURE__ */ f(i, { children: /* @__PURE__ */ f(E.Field, {
64
+ name: "delete",
65
+ children: (t) => /* @__PURE__ */ f(e, {
66
+ id: t.name,
67
+ name: t.name,
68
+ value: t.state.value,
69
+ onChange: (e) => t.handleChange(e.target.value),
70
+ placeholder: b._({ id: "QytzQr" }),
71
+ helptext: b._({ id: "VMh1t1" }),
72
+ required: !0
73
+ })
74
+ }) })
75
+ })
76
+ ]
77
+ });
78
+ }, x = {
79
+ CREATING: {
80
+ text: "CREATING",
81
+ icon: /* @__PURE__ */ f(l, {
82
+ size: 18,
83
+ color: "white",
84
+ fill: "#4FB81C"
85
+ })
86
+ },
87
+ AWAITING_CERTIFICATE: {
88
+ text: "AWAITING_CERTIFICATE",
89
+ icon: /* @__PURE__ */ f(u, {
90
+ size: 18,
91
+ color: "white",
92
+ fill: "#969696"
93
+ })
94
+ },
95
+ READY: {
96
+ text: "READY",
97
+ icon: /* @__PURE__ */ f(c, {
98
+ size: 18,
99
+ color: "white",
100
+ fill: "#C70000"
101
+ })
102
+ },
103
+ FAILED: {
104
+ text: "FAILED",
105
+ icon: /* @__PURE__ */ f(c, {
106
+ size: 18,
107
+ color: "white",
108
+ fill: "#C70000"
109
+ })
110
+ },
111
+ UNEXPECTED: {
112
+ text: "UNEXPECTED",
113
+ icon: /* @__PURE__ */ f(c, {
114
+ size: 18,
115
+ color: "white",
116
+ fill: "#C70000"
117
+ })
118
+ }
119
+ }, S = () => [
120
+ _._({ id: "RS0o7b" }),
121
+ _._({ id: "S0kLOH" }),
122
+ _._({ id: "okXQSt" }),
123
+ ""
124
+ ];
125
+ //#endregion
126
+ export { S as n, b as r, x as t };
127
+
128
+ //# sourceMappingURL=constants-ByHCdNsI.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"constants-ByHCdNsI.mjs","names":["z","useForm","useStore","Modal","Form","FormSection","Spinner","Message","TextInput","Stack","trpcReact","useProjectId","DeletePcaModal","pca","open","onClose","onSuccess","useLingui","projectId","utils","useUtils","isPending","deletePcaMutation","services","delete","useMutation","onSettled","list","invalidate","formSchema","object","string","refine","value","message","t","form","defaultValues","validators","onSubmit","mutateAsync","project_id","certificate_authority_id","id","handleClose","canDelete","store","state","isSubmitting","values","reset","size","title","onCancel","cancelButtonLabel","confirmButtonLabel","onConfirm","handleSubmit","disableConfirmButton","error","dismissible","variant","className","div","span","gap","direction","p","strong","e","preventDefault","Field","name","children","field","onChange","handleChange","target","placeholder","helptext","required","MdError","MdRemoveCircle","MdCheckCircle","STATE_CONFIG","CREATING","text","icon","size","color","fill","AWAITING_CERTIFICATE","READY","FAILED","UNEXPECTED","TABLE_COLUMNS","t"],"sources":["../../src/client/routes/_auth/projects/$projectId/services/pca/-components/-modals/DeletePcaModal.tsx","../../src/client/routes/_auth/projects/$projectId/services/pca/-components/-table/constants.tsx"],"sourcesContent":["import { z } from \"zod\"\nimport { useForm, useStore } from \"@tanstack/react-form\"\nimport { Trans, useLingui } from \"@lingui/react/macro\"\nimport { Modal, Form, FormSection, Spinner, Message, TextInput, Stack } from \"@cloudoperators/juno-ui-components\"\nimport type { CertificateAuthority } from \"@/server/Services/types/pca\"\nimport { trpcReact } from \"@/client/trpcClient\"\nimport { useProjectId } from \"@/client/hooks\"\n\nexport interface DeletePcaModalProps {\n pca: CertificateAuthority\n open: boolean\n onClose: () => void\n onSuccess?: () => void\n}\n\nexport const DeletePcaModal = ({ pca, open, onClose, onSuccess }: DeletePcaModalProps) => {\n const { t } = useLingui()\n const projectId = useProjectId()\n const utils = trpcReact.useUtils()\n\n const { isPending, ...deletePcaMutation } = trpcReact.services.pca.delete.useMutation({\n onSettled: () => utils.services.pca.list.invalidate(),\n })\n\n const formSchema = z.object({\n delete: z.string().refine((value) => value === \"delete\", {\n message: t`Type “delete” to confirm`,\n }),\n })\n\n const form = useForm({\n defaultValues: {\n delete: \"\",\n },\n validators: {\n onSubmit: formSchema,\n },\n onSubmit: async () => {\n if (isPending) return\n\n await deletePcaMutation.mutateAsync({\n project_id: projectId,\n certificate_authority_id: pca.id,\n })\n handleClose()\n onSuccess?.()\n },\n })\n\n // creates a reactive subscription so the component re-renders, which allows the confirm button to enable once the user types \"delete\".\n const canDelete = useStore(form.store, (state) => state.isSubmitting || state.values.delete !== \"delete\")\n\n const handleClose = () => {\n form.reset()\n onClose()\n }\n\n return (\n <Modal\n open={open}\n size=\"large\"\n title={t`Delete certificate authority`}\n onCancel={handleClose}\n cancelButtonLabel={t`Cancel`}\n confirmButtonLabel={t`Delete`}\n onConfirm={form.handleSubmit}\n disableConfirmButton={isPending || canDelete}\n >\n {deletePcaMutation.error?.message && (\n <Message dismissible={false} variant=\"error\" className=\"mb-4\">\n {deletePcaMutation.error.message}\n </Message>\n )}\n\n {isPending && (\n <div className=\"mb-4 flex items-center justify-center gap-2\">\n <Spinner variant=\"primary\" />\n <span className=\"text-theme-high text-sm\">\n <Trans>Deleting certificate authority...</Trans>\n </span>\n </div>\n )}\n\n <Stack gap=\"2.5\" direction=\"vertical\" className=\"mb-2.5\">\n <p>\n <Trans>\n Deleting this Certificate Authority is permanent, and all the associated certificates will no longer apply\n to entities.\n </Trans>\n </p>\n <p>\n <Trans>\n To confirm, type <strong>\"delete\"</strong> in the field below.\n </Trans>\n </p>\n </Stack>\n\n {!isPending && (\n <Form\n className=\"mb-0\"\n id=\"delete-pca-form\"\n onSubmit={(e) => {\n e.preventDefault()\n form.handleSubmit()\n }}\n >\n <FormSection>\n <form.Field\n name=\"delete\"\n children={(field) => (\n <TextInput\n id={field.name}\n name={field.name}\n value={field.state.value}\n onChange={(e) => field.handleChange(e.target.value)}\n placeholder={t`Type \"delete\" to confirm`}\n helptext={t`The text must match “delete” in lowercase.`}\n required\n />\n )}\n />\n </FormSection>\n </Form>\n )}\n </Modal>\n )\n}\n","import { MdError, MdRemoveCircle, MdCheckCircle } from \"react-icons/md\"\nimport { t } from \"@lingui/core/macro\"\nimport { CertificateAuthorityState } from \"@/server/Services/types/pca\"\n\ntype PcaDisplayState = {\n text: string\n icon: React.ReactNode\n}\n\n// will replace text and icon after design-sync with Marta\nexport const STATE_CONFIG: Record<CertificateAuthorityState, PcaDisplayState> = {\n CREATING: {\n text: \"CREATING\",\n icon: <MdCheckCircle size={18} color=\"white\" fill=\"#4FB81C\" />,\n },\n AWAITING_CERTIFICATE: {\n text: \"AWAITING_CERTIFICATE\",\n icon: <MdRemoveCircle size={18} color=\"white\" fill=\"#969696\" />,\n },\n READY: {\n text: \"READY\",\n icon: <MdError size={18} color=\"white\" fill=\"#C70000\" />,\n },\n FAILED: {\n text: \"FAILED\",\n icon: <MdError size={18} color=\"white\" fill=\"#C70000\" />,\n },\n UNEXPECTED: {\n text: \"UNEXPECTED\",\n icon: <MdError size={18} color=\"white\" fill=\"#C70000\" />,\n },\n} as const\n\nexport const TABLE_COLUMNS = () =>\n [\n t`State`,\n t`ID`,\n t`Subject information`,\n \"\", // empty column for item-action with context menu containing \"Delete CA\" button\n ] as const\n"],"mappings":"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"}
@@ -0,0 +1,74 @@
1
+ import { t as e } from "./helpers--JWXi40U.mjs";
2
+ import { createFileRoute as t, lazyRouteComponent as n, redirect as r } from "@tanstack/react-router";
3
+ import { z as i } from "zod";
4
+ //#region src/client/routes/_auth/projects/$projectId/storage/$provider/containers/index.tsx
5
+ var a = () => import("./containers-Dx7TYruP.mjs"), o = () => import("./containers-rn_ntCJu.mjs"), s = (t, n) => {
6
+ let { provider: i, projectId: a } = n, o = e(t);
7
+ if (!o["object-store"]) throw r({
8
+ to: "/projects/$projectId/compute/overview",
9
+ params: { projectId: a }
10
+ });
11
+ let s = !!o["object-store"].swift, c = !!o["object-store"].ceph || !0, l = s ? "swift" : c ? "ceph" : null;
12
+ if (i !== "swift" && i !== "ceph") throw r(l ? {
13
+ to: "/projects/$projectId/storage/$provider/containers",
14
+ params: {
15
+ ...n,
16
+ provider: l
17
+ }
18
+ } : {
19
+ to: "/projects/$projectId/compute/overview",
20
+ params: { projectId: a }
21
+ });
22
+ if (i === "swift" && !s) throw r(c ? {
23
+ to: "/projects/$projectId/storage/$provider/containers",
24
+ params: {
25
+ ...n,
26
+ provider: "ceph"
27
+ }
28
+ } : {
29
+ to: "/projects/$projectId/compute/overview",
30
+ params: { projectId: a }
31
+ });
32
+ if (i === "ceph" && !c) throw r(s ? {
33
+ to: "/projects/$projectId/storage/$provider/containers",
34
+ params: {
35
+ ...n,
36
+ provider: "swift"
37
+ }
38
+ } : {
39
+ to: "/projects/$projectId/compute/overview",
40
+ params: { projectId: a }
41
+ });
42
+ }, c = i.object({
43
+ sortBy: i.enum([
44
+ "name",
45
+ "count",
46
+ "bytes",
47
+ "last_modified"
48
+ ]).optional(),
49
+ sortDirection: i.enum(["asc", "desc"]).optional(),
50
+ search: i.string().optional()
51
+ }), l = t("/_auth/projects/$projectId/storage/$provider/containers/")({
52
+ staticData: {
53
+ section: "storage",
54
+ service: "containers"
55
+ },
56
+ validateSearch: c,
57
+ component: n(o, "component"),
58
+ notFoundComponent: n(a, "notFoundComponent"),
59
+ loader: async ({ context: e }) => {
60
+ let { trpcClient: t } = e;
61
+ return {
62
+ client: t,
63
+ availableServices: await t?.auth.getAvailableServices.query()
64
+ };
65
+ },
66
+ beforeLoad: async ({ context: e, params: t }) => {
67
+ let { trpcClient: n } = e;
68
+ s(await n?.auth.getAvailableServices.query(), t);
69
+ }
70
+ });
71
+ //#endregion
72
+ export { l as t };
73
+
74
+ //# sourceMappingURL=containers-B_ozmVlx.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"containers-B_ozmVlx.mjs","names":["createFileRoute","redirect","z","getServiceIndex","checkServiceAvailability","availableServices","type","name","params","projectId","provider","serviceIndex","to","hasSwift","Boolean","hasCeph","cephFallbackEnabled","hasEffectiveCeph","fallbackProvider","containersSearchSchema","object","sortBy","enum","optional","sortDirection","search","string","Route","staticData","section","service","RouteInfo","validateSearch","component","lazyRouteComponent","$$splitComponentImporter","notFoundComponent","$$splitNotFoundComponentImporter","loader","context","trpcClient","auth","getAvailableServices","query","client","beforeLoad"],"sources":["../../src/client/routes/_auth/projects/$projectId/storage/$provider/containers/index.tsx"],"sourcesContent":["import { createFileRoute, redirect, useParams } from \"@tanstack/react-router\"\nimport { z } from \"zod\"\nimport { getServiceIndex } from \"@/server/Authentication/helpers\"\nimport { ErrorBoundary } from \"react-error-boundary\"\nimport { SwiftContainers } from \"../../-components/Swift/Containers\"\nimport { CephContainers } from \"../../-components/Ceph/Containers\"\nimport { Trans, useLingui } from \"@lingui/react/macro\"\nimport type { RouteInfo } from \"@/client/routes/routeInfo\"\nimport { ContentHeader } from \"@/client/components/ContentHeader/ContentHeader\"\n\nexport const checkServiceAvailability = (\n availableServices: {\n type: string\n name: string\n }[],\n params: {\n projectId: string\n provider: string\n }\n) => {\n const { provider, projectId } = params\n\n const serviceIndex = getServiceIndex(availableServices)\n\n // Redirect to the \"Projects Overview\" page if no storage services available\n if (!serviceIndex[\"object-store\"]) {\n throw redirect({\n to: \"/projects/$projectId/compute/overview\",\n params: { projectId },\n })\n }\n\n // Check provider availability\n const hasSwift = Boolean(serviceIndex[\"object-store\"][\"swift\"])\n const hasCeph = Boolean(serviceIndex[\"object-store\"][\"ceph\"])\n\n // TEMPORARY: Allow Ceph access even if not in catalog (relies on env config)\n // TODO: Properly register Ceph in OpenStack service catalog\n const cephFallbackEnabled = true // Set to false once Ceph is in catalog\n\n // Effective availability includes fallback flag for Ceph\n const hasEffectiveCeph = hasCeph || cephFallbackEnabled\n const fallbackProvider = hasSwift ? \"swift\" : hasEffectiveCeph ? \"ceph\" : null\n\n if (provider !== \"swift\" && provider !== \"ceph\") {\n if (!fallbackProvider) {\n throw redirect({\n to: \"/projects/$projectId/compute/overview\",\n params: { projectId },\n })\n }\n throw redirect({\n to: \"/projects/$projectId/storage/$provider/containers\",\n params: { ...params, provider: fallbackProvider },\n })\n }\n\n if (provider === \"swift\" && !hasSwift) {\n if (!hasEffectiveCeph) {\n throw redirect({\n to: \"/projects/$projectId/compute/overview\",\n params: { projectId },\n })\n }\n\n throw redirect({\n to: \"/projects/$projectId/storage/$provider/containers\",\n params: { ...params, provider: \"ceph\" },\n })\n }\n\n if (provider === \"ceph\" && !hasEffectiveCeph) {\n if (!hasSwift) {\n throw redirect({\n to: \"/projects/$projectId/compute/overview\",\n params: { projectId },\n })\n }\n\n throw redirect({\n to: \"/projects/$projectId/storage/$provider/containers\",\n params: { ...params, provider: \"swift\" },\n })\n }\n}\n\n// Search params schema\n// - sortBy: active sort column — persisted for deep links and back navigation\n// - sortDirection: \"asc\" | \"desc\" — persisted alongside sortBy\n// - search: active filter string — persisted so deep links preserve the current search\nconst containersSearchSchema = z.object({\n sortBy: z.enum([\"name\", \"count\", \"bytes\", \"last_modified\"]).optional(),\n sortDirection: z.enum([\"asc\", \"desc\"]).optional(),\n search: z.string().optional(),\n})\n\nexport const Route = createFileRoute(\"/_auth/projects/$projectId/storage/$provider/containers/\")({\n staticData: { section: \"storage\", service: \"containers\" } satisfies RouteInfo,\n validateSearch: containersSearchSchema,\n component: () => {\n return <StorageDashboard />\n },\n notFoundComponent: () => {\n return <p>Storage service not found</p>\n },\n loader: async ({ context }) => {\n const { trpcClient } = context\n const availableServices = await trpcClient?.auth.getAvailableServices.query()\n\n return {\n client: trpcClient,\n availableServices,\n }\n },\n beforeLoad: async ({ context, params }) => {\n const { trpcClient } = context\n const availableServices = await trpcClient?.auth.getAvailableServices.query()\n checkServiceAvailability(availableServices!, params)\n },\n})\n\nfunction StorageDashboard() {\n const { project, provider } = useParams({\n from: \"/_auth/projects/$projectId/storage/$provider/containers/\",\n select: (params) => {\n return { project: params.projectId, provider: params.provider }\n },\n })\n\n const { setPageTitle } = Route.useRouteContext()\n const { t } = useLingui()\n\n let pageTitle: string\n switch (provider) {\n case \"swift\":\n case \"ceph\":\n pageTitle = t`Object Storage`\n break\n default:\n pageTitle = t`Storage Overview`\n }\n setPageTitle(pageTitle)\n\n return (\n <div>\n <ContentHeader title={pageTitle} projectId={project} />\n {project ? (\n <ErrorBoundary\n fallback={\n <div className=\"p-4 text-center\">\n <Trans>Error loading component</Trans>\n </div>\n }\n >\n {(() => {\n switch (provider) {\n case \"swift\":\n return <SwiftContainers />\n case \"ceph\":\n return <CephContainers />\n default:\n return <div>Storage Overview Page</div> // replace when available\n }\n })()}\n </ErrorBoundary>\n ) : (\n <div className=\"p-4 text-center\">\n <Trans>No project selected</Trans>\n </div>\n )}\n </div>\n )\n}\n"],"mappings":";;;;kGAUaI,KACXC,GAIAG,MAAAA;CAKA,IAAM,EAAEE,aAAUD,iBAAcD,GAE1BG,IAAeR,EAAgBE,EAAAA;AAGrC,KAAI,CAACM,EAAa,gBAChB,OAAMV,EAAS;EACbW,IAAI;EACJJ,QAAQ,EAAEC,cAAU;EACtB,CAAA;CAIF,IAAMI,IAAWC,EAAQH,EAAa,gBAAgB,OAQhDM,IAPUH,EAAQH,EAAa,gBAAgB,QAIzB,IAItBO,IAAmBL,IAAW,UAAUI,IAAmB,SAAS;AAE1E,KAAIP,MAAa,WAAWA,MAAa,OAOvC,OAAMT,EANDiB,IAMU;EACbN,IAAI;EACJJ,QAAQ;GAAE,GAAGA;GAAQE,UAAUQ;GAAiB;EAClD,GARiB;EACbN,IAAI;EACJJ,QAAQ,EAAEC,cAAU;EACtB,CAAA;AAQJ,KAAIC,MAAa,WAAW,CAACG,EAQ3B,OAAMZ,EAPDgB,IAOU;EACbL,IAAI;EACJJ,QAAQ;GAAE,GAAGA;GAAQE,UAAU;GAAO;EACxC,GATiB;EACbE,IAAI;EACJJ,QAAQ,EAAEC,cAAU;EACtB,CAAA;AASJ,KAAIC,MAAa,UAAU,CAACO,EAQ1B,OAAMhB,EAPDY,IAOU;EACbD,IAAI;EACJJ,QAAQ;GAAE,GAAGA;GAAQE,UAAU;GAAQ;EACzC,GATiB;EACbE,IAAI;EACJJ,QAAQ,EAAEC,cAAU;EACtB,CAAA;GAcAU,IAAyBjB,EAAEkB,OAAO;CACtCC,QAAQnB,EAAEoB,KAAK;EAAC;EAAQ;EAAS;EAAS;EAAgB,CAAA,CAAEC,UAAQ;CACpEC,eAAetB,EAAEoB,KAAK,CAAC,OAAO,OAAO,CAAA,CAAEC,UAAQ;CAC/CE,QAAQvB,EAAEwB,QAAM,CAAGH,UAAQ;CAC7B,CAAA,EAEaI,IAAQ3B,EAAgB,2DAAA,CAA4D;CAC/F4B,YAAY;EAAEC,SAAS;EAAWC,SAAS;EAAa;CACxDE,gBAAgBb;CAChBc,WAASC,EAAAC,GAAA,YAAA;CAGTC,mBAAiBF,EAAAG,GAAA,oBAAA;CAGjBC,QAAQ,OAAO,EAAEC,iBAAS;EACxB,IAAM,EAAEC,kBAAeD;AAGvB,SAAO;GACLK,QAAQJ;GACRnC,mBAJwB,MAAMmC,GAAYC,KAAKC,qBAAqBC,OAAAA;GAKtE;;CAEFE,YAAY,OAAO,EAAEN,YAAS/B,gBAAQ;EACpC,IAAM,EAAEgC,kBAAeD;AAEvBnC,IAD0B,MAAMoC,GAAYC,KAAKC,qBAAqBC,OAAAA,EACzBnC,EAAAA;;CAEjD,CAAA"}
@@ -0,0 +1,7 @@
1
+ import { jsx as e } from "react/jsx-runtime";
2
+ //#region src/client/routes/_auth/projects/$projectId/storage/$provider/containers/index.tsx?tsr-split=notFoundComponent
3
+ var t = () => /* @__PURE__ */ e("p", { children: "Storage service not found" });
4
+ //#endregion
5
+ export { t as notFoundComponent };
6
+
7
+ //# sourceMappingURL=containers-Dx7TYruP.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"containers-Dx7TYruP.mjs","names":["SplitNotFoundComponent","notFoundComponent"],"sources":["../../src/client/routes/_auth/projects/$projectId/storage/$provider/containers/index.tsx?tsr-split=notFoundComponent"],"sourcesContent":["import { createFileRoute, redirect, useParams } from \"@tanstack/react-router\"\nimport { z } from \"zod\"\nimport { getServiceIndex } from \"@/server/Authentication/helpers\"\nimport { ErrorBoundary } from \"react-error-boundary\"\nimport { SwiftContainers } from \"../../-components/Swift/Containers\"\nimport { CephContainers } from \"../../-components/Ceph/Containers\"\nimport { Trans, useLingui } from \"@lingui/react/macro\"\nimport type { RouteInfo } from \"@/client/routes/routeInfo\"\nimport { ContentHeader } from \"@/client/components/ContentHeader/ContentHeader\"\n\nexport const checkServiceAvailability = (\n availableServices: {\n type: string\n name: string\n }[],\n params: {\n projectId: string\n provider: string\n }\n) => {\n const { provider, projectId } = params\n\n const serviceIndex = getServiceIndex(availableServices)\n\n // Redirect to the \"Projects Overview\" page if no storage services available\n if (!serviceIndex[\"object-store\"]) {\n throw redirect({\n to: \"/projects/$projectId/compute/overview\",\n params: { projectId },\n })\n }\n\n // Check provider availability\n const hasSwift = Boolean(serviceIndex[\"object-store\"][\"swift\"])\n const hasCeph = Boolean(serviceIndex[\"object-store\"][\"ceph\"])\n\n // TEMPORARY: Allow Ceph access even if not in catalog (relies on env config)\n // TODO: Properly register Ceph in OpenStack service catalog\n const cephFallbackEnabled = true // Set to false once Ceph is in catalog\n\n // Effective availability includes fallback flag for Ceph\n const hasEffectiveCeph = hasCeph || cephFallbackEnabled\n const fallbackProvider = hasSwift ? \"swift\" : hasEffectiveCeph ? \"ceph\" : null\n\n if (provider !== \"swift\" && provider !== \"ceph\") {\n if (!fallbackProvider) {\n throw redirect({\n to: \"/projects/$projectId/compute/overview\",\n params: { projectId },\n })\n }\n throw redirect({\n to: \"/projects/$projectId/storage/$provider/containers\",\n params: { ...params, provider: fallbackProvider },\n })\n }\n\n if (provider === \"swift\" && !hasSwift) {\n if (!hasEffectiveCeph) {\n throw redirect({\n to: \"/projects/$projectId/compute/overview\",\n params: { projectId },\n })\n }\n\n throw redirect({\n to: \"/projects/$projectId/storage/$provider/containers\",\n params: { ...params, provider: \"ceph\" },\n })\n }\n\n if (provider === \"ceph\" && !hasEffectiveCeph) {\n if (!hasSwift) {\n throw redirect({\n to: \"/projects/$projectId/compute/overview\",\n params: { projectId },\n })\n }\n\n throw redirect({\n to: \"/projects/$projectId/storage/$provider/containers\",\n params: { ...params, provider: \"swift\" },\n })\n }\n}\n\n// Search params schema\n// - sortBy: active sort column — persisted for deep links and back navigation\n// - sortDirection: \"asc\" | \"desc\" — persisted alongside sortBy\n// - search: active filter string — persisted so deep links preserve the current search\nconst containersSearchSchema = z.object({\n sortBy: z.enum([\"name\", \"count\", \"bytes\", \"last_modified\"]).optional(),\n sortDirection: z.enum([\"asc\", \"desc\"]).optional(),\n search: z.string().optional(),\n})\n\nexport const Route = createFileRoute(\"/_auth/projects/$projectId/storage/$provider/containers/\")({\n staticData: { section: \"storage\", service: \"containers\" } satisfies RouteInfo,\n validateSearch: containersSearchSchema,\n component: () => {\n return <StorageDashboard />\n },\n notFoundComponent: () => {\n return <p>Storage service not found</p>\n },\n loader: async ({ context }) => {\n const { trpcClient } = context\n const availableServices = await trpcClient?.auth.getAvailableServices.query()\n\n return {\n client: trpcClient,\n availableServices,\n }\n },\n beforeLoad: async ({ context, params }) => {\n const { trpcClient } = context\n const availableServices = await trpcClient?.auth.getAvailableServices.query()\n checkServiceAvailability(availableServices!, params)\n },\n})\n\nfunction StorageDashboard() {\n const { project, provider } = useParams({\n from: \"/_auth/projects/$projectId/storage/$provider/containers/\",\n select: (params) => {\n return { project: params.projectId, provider: params.provider }\n },\n })\n\n const { setPageTitle } = Route.useRouteContext()\n const { t } = useLingui()\n\n let pageTitle: string\n switch (provider) {\n case \"swift\":\n case \"ceph\":\n pageTitle = t`Object Storage`\n break\n default:\n pageTitle = t`Storage Overview`\n }\n setPageTitle(pageTitle)\n\n return (\n <div>\n <ContentHeader title={pageTitle} projectId={project} />\n {project ? (\n <ErrorBoundary\n fallback={\n <div className=\"p-4 text-center\">\n <Trans>Error loading component</Trans>\n </div>\n }\n >\n {(() => {\n switch (provider) {\n case \"swift\":\n return <SwiftContainers />\n case \"ceph\":\n return <CephContainers />\n default:\n return <div>Storage Overview Page</div> // replace when available\n }\n })()}\n </ErrorBoundary>\n ) : (\n <div className=\"p-4 text-center\">\n <Trans>No project selected</Trans>\n </div>\n )}\n </div>\n )\n}\n"],"mappings":";;AAyFA,IAAAA,UAcW,kBAAC,KAAA,EAAA,UAAE,6BAAA,CAAA"}