@cobaltcore-dev/aurora 0.4.0 → 0.5.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 (157) hide show
  1. package/README.md +73 -77
  2. package/dist/client/AuroraApp.d.ts +15 -0
  3. package/dist/client/{AuthProvider-D-5Jpa6F.mjs → AuthProvider-Co4d0WzB.mjs} +3 -3
  4. package/dist/client/{AuthProvider-D-5Jpa6F.mjs.map → AuthProvider-Co4d0WzB.mjs.map} +1 -1
  5. package/dist/client/{ContentHeader-BXZoN3B9.mjs → ContentHeader-xQVhO2yT.mjs} +20 -20
  6. package/dist/client/{ContentHeader-BXZoN3B9.mjs.map → ContentHeader-xQVhO2yT.mjs.map} +1 -1
  7. package/dist/client/{DeleteFlavorModal-BusYn32r.mjs → DeleteFlavorModal-CHTUZ3YV.mjs} +211 -202
  8. package/dist/client/DeleteFlavorModal-CHTUZ3YV.mjs.map +1 -0
  9. package/dist/client/{EditSecurityGroupModal-DK3WYikA.mjs → EditSecurityGroupModal-CWHHx2Xk.mjs} +22 -22
  10. package/dist/client/{EditSecurityGroupModal-DK3WYikA.mjs.map → EditSecurityGroupModal-CWHHx2Xk.mjs.map} +1 -1
  11. package/dist/client/{FiltersInput-OVeIJzIo.mjs → FiltersInput-UKJpNFdr.mjs} +10 -10
  12. package/dist/client/{FiltersInput-OVeIJzIo.mjs.map → FiltersInput-UKJpNFdr.mjs.map} +1 -1
  13. package/dist/client/{FloatingIpActionModals-Dok7fJss.mjs → FloatingIpActionModals-caXn6bYo.mjs} +54 -54
  14. package/dist/client/{FloatingIpActionModals-Dok7fJss.mjs.map → FloatingIpActionModals-caXn6bYo.mjs.map} +1 -1
  15. package/dist/client/{ImageToastNotifications-BG9LPnXf.mjs → ImageToastNotifications-BWimIzu_.mjs} +227 -227
  16. package/dist/client/{ImageToastNotifications-BG9LPnXf.mjs.map → ImageToastNotifications-BWimIzu_.mjs.map} +1 -1
  17. package/dist/client/{RouteError-pDEWC_k7.mjs → RouteError-CUj_m3gu.mjs} +6 -6
  18. package/dist/client/{RouteError-pDEWC_k7.mjs.map → RouteError-CUj_m3gu.mjs.map} +1 -1
  19. package/dist/client/{SortInput-DXWSqSny.mjs → SortInput-GQlQBlAj.mjs} +6 -6
  20. package/dist/client/{SortInput-DXWSqSny.mjs.map → SortInput-GQlQBlAj.mjs.map} +1 -1
  21. package/dist/client/{_auth-CJj1Cnbm.mjs → _auth-DXJkv9QO.mjs} +3 -3
  22. package/dist/client/{_auth-CJj1Cnbm.mjs.map → _auth-DXJkv9QO.mjs.map} +1 -1
  23. package/dist/client/_flavorId-C5dc1N_j.mjs +194 -0
  24. package/dist/client/_flavorId-C5dc1N_j.mjs.map +1 -0
  25. package/dist/client/{_flavorId-BoNcxYmF.mjs → _flavorId-sUWG0xuy.mjs} +15 -15
  26. package/dist/client/_flavorId-sUWG0xuy.mjs.map +1 -0
  27. package/dist/client/{_floatingIpId-DF_BSJN6.mjs → _floatingIpId-COK_TBrz2.mjs} +42 -42
  28. package/dist/client/_floatingIpId-COK_TBrz2.mjs.map +1 -0
  29. package/dist/client/{_floatingIpId-D33bOEmH.mjs → _floatingIpId-CT4y-60o.mjs} +3 -3
  30. package/dist/client/{_floatingIpId-D33bOEmH.mjs.map → _floatingIpId-CT4y-60o.mjs.map} +1 -1
  31. package/dist/client/_imageId-n3RcnhAR.mjs +534 -0
  32. package/dist/client/_imageId-n3RcnhAR.mjs.map +1 -0
  33. package/dist/client/{_pcaId-CbBhBrX1.mjs → _pcaId-B-f_6kqs.mjs} +99 -99
  34. package/dist/client/{_pcaId-CbBhBrX1.mjs.map → _pcaId-B-f_6kqs.mjs.map} +1 -1
  35. package/dist/client/{_pcaId-BYCoeK6_.mjs → _pcaId-ChnM_t-9.mjs} +3 -3
  36. package/dist/client/{_pcaId-BYCoeK6_.mjs.map → _pcaId-ChnM_t-9.mjs.map} +1 -1
  37. package/dist/client/_projectId-26bw-_rm.mjs +46 -0
  38. package/dist/client/_projectId-26bw-_rm.mjs.map +1 -0
  39. package/dist/client/{_projectId-BwLMEMGC.mjs → _projectId-BK9UqeYw.mjs} +14 -14
  40. package/dist/client/{_projectId-BwLMEMGC.mjs.map → _projectId-BK9UqeYw.mjs.map} +1 -1
  41. package/dist/client/{_projectId-D35MN1kY.mjs → _projectId-CCtpAQ8m.mjs} +78 -95
  42. package/dist/client/_projectId-CCtpAQ8m.mjs.map +1 -0
  43. package/dist/client/{_projectId-OW2xkK43.mjs → _projectId-Dhb4AyBD.mjs} +3 -3
  44. package/dist/client/{_projectId-OW2xkK43.mjs.map → _projectId-Dhb4AyBD.mjs.map} +1 -1
  45. package/dist/client/{_securityGroupId-B-Z-CzLp.mjs → _securityGroupId-CR1mKICQ.mjs} +3 -3
  46. package/dist/client/{_securityGroupId-B-Z-CzLp.mjs.map → _securityGroupId-CR1mKICQ.mjs.map} +1 -1
  47. package/dist/client/{_securityGroupId-B1bOYRbX.mjs → _securityGroupId-DroYG6cA.mjs} +254 -255
  48. package/dist/client/{_securityGroupId-B1bOYRbX.mjs.map → _securityGroupId-DroYG6cA.mjs.map} +1 -1
  49. package/dist/client/about-969pIiZ9.mjs +92 -0
  50. package/dist/client/{about-DLn1ShhF.mjs.map → about-969pIiZ9.mjs.map} +1 -1
  51. package/dist/client/aurora-DDzsst74.mjs +19 -0
  52. package/dist/client/{aurora-CRcxVUCo.mjs.map → aurora-DDzsst74.mjs.map} +1 -1
  53. package/dist/client/{build-BJDfnAyi.mjs → build-DracvfrJ.mjs} +5 -5
  54. package/dist/client/{build-BJDfnAyi.mjs.map → build-DracvfrJ.mjs.map} +1 -1
  55. package/dist/client/{buildFilterParams-TeyosGyK.mjs → buildFilterParams-DoZzMKX9.mjs} +1 -1
  56. package/dist/client/{buildFilterParams-TeyosGyK.mjs.map → buildFilterParams-DoZzMKX9.mjs.map} +1 -1
  57. package/dist/client/{cn-C3laVXMm.mjs → cn-DM4Cy3jv.mjs} +1 -1
  58. package/dist/client/{cn-C3laVXMm.mjs.map → cn-DM4Cy3jv.mjs.map} +1 -1
  59. package/dist/client/{constants-B-P2r5F1.mjs → constants-4lVQXort.mjs} +22 -22
  60. package/dist/client/{constants-B-P2r5F1.mjs.map → constants-4lVQXort.mjs.map} +1 -1
  61. package/dist/client/{containers-BjWqjNOx.mjs → containers-DGY2hoWw.mjs} +3 -3
  62. package/dist/client/{containers-BjWqjNOx.mjs.map → containers-DGY2hoWw.mjs.map} +1 -1
  63. package/dist/client/containers-ZMFTRaQL.mjs +3277 -0
  64. package/dist/client/containers-ZMFTRaQL.mjs.map +1 -0
  65. package/dist/client/{containers-DsRWc1L5.mjs → containers-xfsYgRyf.mjs} +2 -2
  66. package/dist/client/{containers-DsRWc1L5.mjs.map → containers-xfsYgRyf.mjs.map} +1 -1
  67. package/dist/client/{flavors-D8oElC2K.mjs → flavors-C4GtoybP.mjs} +2 -2
  68. package/dist/client/{flavors-D8oElC2K.mjs.map → flavors-C4GtoybP.mjs.map} +1 -1
  69. package/dist/client/{flavors-qvgPSI7J.mjs → flavors-CpirO_nr.mjs} +167 -148
  70. package/dist/client/flavors-CpirO_nr.mjs.map +1 -0
  71. package/dist/client/{flavors-BXPYAFyQ.mjs → flavors-DWMZ6TuJ.mjs} +2 -2
  72. package/dist/client/{flavors-BXPYAFyQ.mjs.map → flavors-DWMZ6TuJ.mjs.map} +1 -1
  73. package/dist/client/{floatingips-Fa6ocNUu.mjs → floatingips-BUf_oLRl.mjs} +74 -75
  74. package/dist/client/{floatingips-Fa6ocNUu.mjs.map → floatingips-BUf_oLRl.mjs.map} +1 -1
  75. package/dist/client/{formatBytes-tQBEnPoL.mjs → formatBytes-CZv_XyCY.mjs} +1 -1
  76. package/dist/client/{formatBytes-tQBEnPoL.mjs.map → formatBytes-CZv_XyCY.mjs.map} +1 -1
  77. package/dist/client/{helpers--JWXi40U.mjs → helpers-1PpYf-fC.mjs} +1 -1
  78. package/dist/client/{helpers--JWXi40U.mjs.map → helpers-1PpYf-fC.mjs.map} +1 -1
  79. package/dist/client/hooks-dSArr2Ca.mjs +2 -0
  80. package/dist/client/{images-tYfyOkX8.mjs → images-CsonlmFx.mjs} +3 -3
  81. package/dist/client/{images-tYfyOkX8.mjs.map → images-CsonlmFx.mjs.map} +1 -1
  82. package/dist/client/{images-CSFfefAu.mjs → images-Da1t5KPh.mjs} +507 -535
  83. package/dist/client/images-Da1t5KPh.mjs.map +1 -0
  84. package/dist/client/{images-DM9I8G0p.mjs → images-NBf2bV43.mjs} +2 -2
  85. package/dist/client/{images-DM9I8G0p.mjs.map → images-NBf2bV43.mjs.map} +1 -1
  86. package/dist/client/{images-CTLCY-yY.mjs → images-QnWf63uj.mjs} +2 -2
  87. package/dist/client/{images-CTLCY-yY.mjs.map → images-QnWf63uj.mjs.map} +1 -1
  88. package/dist/client/index.js +252 -258
  89. package/dist/client/index.js.map +1 -1
  90. package/dist/client/{md-BivyCkGC.mjs → md-sBiSNVSQ.mjs} +7 -7
  91. package/dist/client/{md-BivyCkGC.mjs.map → md-sBiSNVSQ.mjs.map} +1 -1
  92. package/dist/client/{network-rYLHyf15.mjs → network-DuZm76BZ.mjs} +2 -2
  93. package/dist/client/{network-rYLHyf15.mjs.map → network-DuZm76BZ.mjs.map} +1 -1
  94. package/dist/client/{objects-BciXwZ00.mjs → objects-B89dYCBq.mjs} +3 -3
  95. package/dist/client/{objects-BciXwZ00.mjs.map → objects-B89dYCBq.mjs.map} +1 -1
  96. package/dist/client/{objects-Cdew99tK.mjs → objects-CuFLUOe1.mjs} +2 -2
  97. package/dist/client/{objects-Cdew99tK.mjs.map → objects-CuFLUOe1.mjs.map} +1 -1
  98. package/dist/client/objects-H0NN_Sja.mjs +5460 -0
  99. package/dist/client/objects-H0NN_Sja.mjs.map +1 -0
  100. package/dist/client/{pca-oc7J0_Xd.mjs → pca-C-UFjicP.mjs} +42 -42
  101. package/dist/client/{pca-oc7J0_Xd.mjs.map → pca-C-UFjicP.mjs.map} +1 -1
  102. package/dist/client/{pca-COmKvp3J.mjs → pca-CtU6REww.mjs} +2 -2
  103. package/dist/client/{pca-COmKvp3J.mjs.map → pca-CtU6REww.mjs.map} +1 -1
  104. package/dist/client/{projects-Dl5XkXUP.mjs → projects-C-sjd9T5.mjs} +3 -3
  105. package/dist/client/{projects-Dl5XkXUP.mjs.map → projects-C-sjd9T5.mjs.map} +1 -1
  106. package/dist/client/{projects-BUabCzvw.mjs → projects-DNXsDnJM.mjs} +25 -21
  107. package/dist/client/projects-DNXsDnJM.mjs.map +1 -0
  108. package/dist/client/{projects-DI_L4oDw.mjs → projects-dhnQkuvV.mjs} +2 -2
  109. package/dist/client/{projects-DI_L4oDw.mjs.map → projects-dhnQkuvV.mjs.map} +1 -1
  110. package/dist/client/{projects-HoQ0gE5Y.mjs → projects-yiK0HGSA.mjs} +2 -2
  111. package/dist/client/{projects-HoQ0gE5Y.mjs.map → projects-yiK0HGSA.mjs.map} +1 -1
  112. package/dist/client/{securitygroups-BjkmHk2J.mjs → securitygroups-wHdrxZXd.mjs} +72 -73
  113. package/dist/client/{securitygroups-BjkmHk2J.mjs.map → securitygroups-wHdrxZXd.mjs.map} +1 -1
  114. package/dist/client/{trpcClient-BxguzNYF.mjs → trpcClient-BzPUgiM2.mjs} +1 -1
  115. package/dist/client/{trpcClient-BxguzNYF.mjs.map → trpcClient-BzPUgiM2.mjs.map} +1 -1
  116. package/dist/client/{useErrorTranslation-TZVwIAzq.mjs → useErrorTranslation-Dc0eE8Zt.mjs} +1 -1
  117. package/dist/client/{useErrorTranslation-TZVwIAzq.mjs.map → useErrorTranslation-Dc0eE8Zt.mjs.map} +1 -1
  118. package/dist/client/useListWithFiltering-DrgUwXef.mjs +157 -0
  119. package/dist/client/useListWithFiltering-DrgUwXef.mjs.map +1 -0
  120. package/dist/client/{useModal-DxxlilRm.mjs → useModal-DCs1OJh7.mjs} +1 -1
  121. package/dist/client/{useModal-DxxlilRm.mjs.map → useModal-DCs1OJh7.mjs.map} +1 -1
  122. package/dist/client/{useProjectId-OQv2KBbG.mjs → useProjectId-DBc5lpoU.mjs} +1 -1
  123. package/dist/client/{useProjectId-OQv2KBbG.mjs.map → useProjectId-DBc5lpoU.mjs.map} +1 -1
  124. package/dist/server/index.js +1281 -432
  125. package/package.json +6 -5
  126. package/dist/client/DeleteFlavorModal-BusYn32r.mjs.map +0 -1
  127. package/dist/client/ListToolbar-BojRTNbo.mjs +0 -129
  128. package/dist/client/ListToolbar-BojRTNbo.mjs.map +0 -1
  129. package/dist/client/_flavorId-BRonXvCo.mjs +0 -188
  130. package/dist/client/_flavorId-BRonXvCo.mjs.map +0 -1
  131. package/dist/client/_flavorId-BoNcxYmF.mjs.map +0 -1
  132. package/dist/client/_floatingIpId-DF_BSJN6.mjs.map +0 -1
  133. package/dist/client/_imageId-BL0I5_pv.mjs +0 -527
  134. package/dist/client/_imageId-BL0I5_pv.mjs.map +0 -1
  135. package/dist/client/_projectId-5NiasyXm.mjs +0 -26
  136. package/dist/client/_projectId-5NiasyXm.mjs.map +0 -1
  137. package/dist/client/_projectId-D35MN1kY.mjs.map +0 -1
  138. package/dist/client/about-DLn1ShhF.mjs +0 -92
  139. package/dist/client/aurora-CRcxVUCo.mjs +0 -19
  140. package/dist/client/containers-J7WFA18U.mjs +0 -3120
  141. package/dist/client/containers-J7WFA18U.mjs.map +0 -1
  142. package/dist/client/flavors-qvgPSI7J.mjs.map +0 -1
  143. package/dist/client/hooks-DEjb9d1F.mjs +0 -2
  144. package/dist/client/images-CSFfefAu.mjs.map +0 -1
  145. package/dist/client/objects-DaElrban.mjs +0 -5340
  146. package/dist/client/objects-DaElrban.mjs.map +0 -1
  147. package/dist/client/overview-BMhjFMIV.mjs +0 -15
  148. package/dist/client/overview-BMhjFMIV.mjs.map +0 -1
  149. package/dist/client/overview-BYIRj7_X.mjs +0 -15
  150. package/dist/client/overview-BYIRj7_X.mjs.map +0 -1
  151. package/dist/client/overview-DRCKNBH2.mjs +0 -15
  152. package/dist/client/overview-DRCKNBH2.mjs.map +0 -1
  153. package/dist/client/overview-urYLOVQE.mjs +0 -173
  154. package/dist/client/overview-urYLOVQE.mjs.map +0 -1
  155. package/dist/client/projects-BUabCzvw.mjs.map +0 -1
  156. package/dist/client/useListWithFiltering-CbhHJO4V.mjs +0 -32
  157. package/dist/client/useListWithFiltering-CbhHJO4V.mjs.map +0 -1
@@ -1,7 +1,7 @@
1
1
  import { jsx as e } from "react/jsx-runtime";
2
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" });
3
+ var t = () => /*#__PURE__*/ e("p", { children: "Storage service not found" });
4
4
  //#endregion
5
5
  export { t as notFoundComponent };
6
6
 
7
- //# sourceMappingURL=containers-DsRWc1L5.mjs.map
7
+ //# sourceMappingURL=containers-xfsYgRyf.mjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"containers-DsRWc1L5.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\n/**\n * Validates that the requested storage provider is available for the given project,\n * and redirects to an appropriate fallback route when it is not.\n *\n * Redirect rules (in priority order):\n * 1. No `object-store` service at all → redirect to the project overview.\n * 2. Unknown provider (neither \"swift\" nor \"ceph\") → redirect to the first\n * available provider, or to the project overview if none exist.\n * 3. Requested provider unavailable → redirect to the other provider,\n * or to the project overview if no alternative exists.\n *\n * Ceph has a temporary fallback flag (`cephFallbackEnabled`) that treats it as\n * available even when absent from the OpenStack service catalog.\n *\n * @throws {redirect} - Always throws a TanStack Router redirect; never returns normally\n * when the requested provider/project combination is unavailable.\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\",\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\",\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\",\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\",\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: {\n section: \"storage\",\n service: \"containers\",\n sectionCrumb: { labelKey: \"Storage\" },\n crumb: { useParamAsLabel: \"provider\" },\n } satisfies RouteInfo,\n validateSearch: containersSearchSchema,\n head: ({ match }) => ({\n meta: [\n {\n title:\n match.params.provider === \"swift\"\n ? \"Object Storage (Swift)\"\n : match.params.provider === \"ceph\"\n ? \"Object Storage (Ceph)\"\n : \"Storage Overview\",\n },\n ],\n }),\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 { t } = useLingui()\n\n let pageTitle: string\n switch (provider) {\n case \"swift\":\n pageTitle = t`Object Storage (Swift)`\n break\n case \"ceph\":\n pageTitle = t`Object Storage (Ceph)`\n break\n default:\n pageTitle = t`Storage Overview`\n }\n\n return (\n <div>\n <ContentHeader title={pageTitle} projectId={project} />\n {project ? (\n <ErrorBoundary\n resetKeys={[project, provider]}\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":";;AA0GA,IAAAA,UA+BW,kBAAC,KAAA,EAAA,UAAE,6BAAA,CAAA"}
1
+ {"version":3,"file":"containers-xfsYgRyf.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\n/**\n * Validates that the requested storage provider is available for the given project,\n * and redirects to an appropriate fallback route when it is not.\n *\n * Redirect rules (in priority order):\n * 1. No `object-store` service at all → redirect to the project overview.\n * 2. Unknown provider (neither \"swift\" nor \"ceph\") → redirect to the first\n * available provider, or to the project overview if none exist.\n * 3. Requested provider unavailable → redirect to the other provider,\n * or to the project overview if no alternative exists.\n *\n * Ceph has a temporary fallback flag (`cephFallbackEnabled`) that treats it as\n * available even when absent from the OpenStack service catalog.\n *\n * @throws {redirect} - Always throws a TanStack Router redirect; never returns normally\n * when the requested provider/project combination is unavailable.\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\",\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\",\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\",\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\",\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: {\n section: \"storage\",\n service: \"containers\",\n sectionCrumb: { labelKey: \"Storage\" },\n crumb: { useParamAsLabel: \"provider\" },\n } satisfies RouteInfo,\n validateSearch: containersSearchSchema,\n head: ({ match }) => ({\n meta: [\n {\n title:\n match.params.provider === \"swift\"\n ? \"Object Storage (Swift)\"\n : match.params.provider === \"ceph\"\n ? \"Object Storage (Ceph)\"\n : \"Storage Overview\",\n },\n ],\n }),\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 { t } = useLingui()\n\n let pageTitle: string\n switch (provider) {\n case \"swift\":\n pageTitle = t`Object Storage (Swift)`\n break\n case \"ceph\":\n pageTitle = t`Object Storage (Ceph)`\n break\n default:\n pageTitle = t`Storage Overview`\n }\n\n return (\n <div>\n <ContentHeader title={pageTitle} projectId={project} />\n {project ? (\n <ErrorBoundary\n resetKeys={[project, provider]}\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":";;AA0GA,IAAAA,UA+BW,gBAAC,KAAA,EAAA,UAAE,4BAAA,CAAA"}
@@ -8,9 +8,9 @@ var r = e("/_auth/projects/$projectId/compute/flavors/")({
8
8
  crumb: { labelKey: "Flavors" }
9
9
  },
10
10
  head: () => ({ meta: [{ title: n._({ id: "neiJm0" }) }] }),
11
- component: t(() => import("./flavors-qvgPSI7J.mjs"), "component")
11
+ component: t(() => import("./flavors-CpirO_nr.mjs"), "component")
12
12
  });
13
13
  //#endregion
14
14
  export { r as t };
15
15
 
16
- //# sourceMappingURL=flavors-D8oElC2K.mjs.map
16
+ //# sourceMappingURL=flavors-C4GtoybP.mjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"flavors-D8oElC2K.mjs","names":["createFileRoute","t","Route","staticData","section","service","sectionCrumb","labelKey","crumb","RouteInfo","head","meta","title","component","lazyRouteComponent","$$splitComponentImporter"],"sources":["../../src/client/routes/_auth/projects/$projectId/compute/flavors/index.tsx"],"sourcesContent":["import { createFileRoute } from \"@tanstack/react-router\"\nimport { t } from \"@lingui/core/macro\"\nimport { useLingui } from \"@lingui/react/macro\"\nimport { Flavors } from \"../-components/Flavors/List\"\nimport type { RouteInfo } from \"@/client/routes/routeInfo\"\nimport { ContentHeader } from \"@/client/components/ContentHeader/ContentHeader\"\n\nexport const Route = createFileRoute(\"/_auth/projects/$projectId/compute/flavors/\")({\n staticData: {\n section: \"compute\",\n service: \"flavors\",\n sectionCrumb: { labelKey: \"Compute\" },\n crumb: { labelKey: \"Flavors\" },\n } satisfies RouteInfo,\n head: () => ({ meta: [{ title: t`Flavors` }] }),\n component: RouteComponent,\n})\n\nfunction RouteComponent() {\n const { t } = useLingui()\n const { projectId } = Route.useParams()\n const { trpcClient } = Route.useRouteContext()\n return (\n <>\n <ContentHeader title={t`Flavors`} projectId={projectId} />\n <Flavors project={projectId} client={trpcClient!} />\n </>\n )\n}\n"],"mappings":";;AAOA,IAAaE,IAAQF,EAAgB,8CAAA,CAA+C;CAClFG,YAAY;EACVC,SAAS;EACTC,SAAS;EACTC,cAAc,EAAEC,UAAU,WAAU;EACpCC,OAAO,EAAED,UAAU,WAAU;EAC/B;CACAG,aAAa,EAAEC,MAAM,CAAC,EAAEC,OAAOX,EAAAA,EAAC,EAAA,IAAA,UAAA,CAAA,EAAU,CAAC,EAAE;CAC7CY,WAASC,0CAAA,YAAA;CACX,CAAA"}
1
+ {"version":3,"file":"flavors-C4GtoybP.mjs","names":["createFileRoute","t","Route","staticData","section","service","sectionCrumb","labelKey","crumb","RouteInfo","head","meta","title","component","lazyRouteComponent","$$splitComponentImporter"],"sources":["../../src/client/routes/_auth/projects/$projectId/compute/flavors/index.tsx"],"sourcesContent":["import { createFileRoute } from \"@tanstack/react-router\"\nimport { t } from \"@lingui/core/macro\"\nimport { useLingui } from \"@lingui/react/macro\"\nimport { Flavors } from \"../-components/Flavors/List\"\nimport type { RouteInfo } from \"@/client/routes/routeInfo\"\nimport { ContentHeader } from \"@/client/components/ContentHeader/ContentHeader\"\n\nexport const Route = createFileRoute(\"/_auth/projects/$projectId/compute/flavors/\")({\n staticData: {\n section: \"compute\",\n service: \"flavors\",\n sectionCrumb: { labelKey: \"Compute\" },\n crumb: { labelKey: \"Flavors\" },\n } satisfies RouteInfo,\n head: () => ({ meta: [{ title: t`Flavors` }] }),\n component: RouteComponent,\n})\n\nfunction RouteComponent() {\n const { t } = useLingui()\n const { projectId } = Route.useParams()\n const { trpcClient } = Route.useRouteContext()\n return (\n <>\n <ContentHeader title={t`Flavors`} projectId={projectId} />\n <Flavors project={projectId} client={trpcClient!} />\n </>\n )\n}\n"],"mappings":";;AAOA,IAAaE,IAAQF,EAAgB,6CAAA,EAA+C;CAClFG,YAAY;EACVC,SAAS;EACTC,SAAS;EACTC,cAAc,EAAEC,UAAU,UAAU;EACpCC,OAAO,EAAED,UAAU,UAAU;CAC/B;CACAG,aAAa,EAAEC,MAAM,CAAC,EAAEC,OAAOX,EAAAA,EAAC,EAAA,IAAA,SAAA,CAAA,EAAU,CAAA,EAAG;CAC7CY,WAASC,0CAAA,WAAA;AACX,CAAA"}
@@ -1,137 +1,143 @@
1
- import { C as e, E as t, G as n, I as r, M as i, Q as a, T as o, U as s, Y as c, at as l, c as u, et as d, f, it as p, j as m, l as h, n as g, nt as _, ot as v, q as y, w as b } from "./build-BJDfnAyi.mjs";
2
- import { t as x } from "./useErrorTranslation-TZVwIAzq.mjs";
3
- import { t as S } from "./flavors-D8oElC2K.mjs";
4
- import { n as C, r as w, t as T } from "./DeleteFlavorModal-BusYn32r.mjs";
5
- import { t as E } from "./ContentHeader-BXZoN3B9.mjs";
6
- import { t as D } from "./SortInput-DXWSqSny.mjs";
1
+ import { C as e, E as t, G as n, I as r, M as i, Q as a, T as o, U as s, Y as c, at as l, c as u, et as d, f, it as p, j as m, l as h, n as g, nt as _, ot as v, q as y, w as b } from "./build-DracvfrJ.mjs";
2
+ import { t as x } from "./useErrorTranslation-Dc0eE8Zt.mjs";
3
+ import { t as S } from "./flavors-C4GtoybP.mjs";
4
+ import { t as C } from "./ContentHeader-xQVhO2yT.mjs";
5
+ import { n as w, r as T, t as E } from "./DeleteFlavorModal-CHTUZ3YV.mjs";
6
+ import { t as D } from "./SortInput-GQlQBlAj.mjs";
7
7
  import { Fragment as O, jsx as k, jsxs as A } from "react/jsx-runtime";
8
8
  import { Suspense as j, startTransition as M, use as N, useCallback as P, useEffect as F, useRef as I, useState as L } from "react";
9
- import { Link as R, useNavigate as z, useParams as B, useSearch as V } from "@tanstack/react-router";
10
- import { TRPCClientError as H } from "@trpc/client";
11
- import { Trans as U, useLingui as W } from "@lingui/react";
9
+ import { useNavigate as R, useParams as z, useSearch as B } from "@tanstack/react-router";
10
+ import { TRPCClientError as V } from "@trpc/client";
11
+ import { Trans as H, useLingui as U } from "@lingui/react";
12
+ import { ErrorBoundary as W } from "react-error-boundary";
12
13
  //#region src/client/routes/_auth/projects/$projectId/compute/-components/Flavors/-components/FlavorListContainer.tsx
13
- var G = ({ flavors: e, isLoading: o, client: l, project: u, onFlavorDeleted: f, canDeleteFlavor: p, canMangageAccess: g, currentPage: v = 1, totalPages: y = 1, onPageChange: b }) => {
14
- let { i18n: x, _: S } = W(), E = z(), [D, j] = L(!1), [M, N] = L(!1), [P, F] = L(!1), [I, V] = L(null), { projectId: H } = B({ from: "/_auth/projects/$projectId/compute/flavors/" }), G = (e) => {
15
- V(e), j(!0);
16
- }, K = (e) => {
17
- V(e), N(!0);
14
+ var G = ({ flavors: e, isLoading: o, client: l, project: u, onFlavorDeleted: f, canDeleteFlavor: p, canMangageAccess: g, canManageSpecs: v, canListSpecs: y, currentPage: b = 1, totalPages: x = 1, onPageChange: S }) => {
15
+ let { i18n: C, _: D } = U(), j = R(), [M, N] = L(!1), [P, F] = L(!1), [I, B] = L(!1), [V, W] = L(null), { projectId: G } = z({ from: "/_auth/projects/$projectId/compute/flavors/" }), K = (e) => {
16
+ W(e), N(!0);
18
17
  }, q = (e) => {
19
- V(e), F(!0);
20
- }, J = () => {
21
- j(!1), V(null);
18
+ W(e), F(!0);
19
+ }, J = (e) => {
20
+ W(e), B(!0);
21
+ }, Y = () => {
22
+ N(!1), W(null);
22
23
  };
23
- return o ? /* @__PURE__ */ k("div", {
24
+ return o ? /*#__PURE__*/ k("div", {
24
25
  "data-testid": "loading",
25
- children: /* @__PURE__ */ k("div", {
26
+ children: /*#__PURE__*/ k("div", {
26
27
  "data-testid": "loading",
27
- children: /* @__PURE__ */ k(r, { children: /* @__PURE__ */ k(i, {
28
+ children: /*#__PURE__*/ k(r, { children: /*#__PURE__*/ k(i, {
28
29
  colSpan: 3,
29
- children: /* @__PURE__ */ A(_, {
30
+ children: /*#__PURE__*/ A(_, {
30
31
  distribution: "center",
31
32
  alignment: "center",
32
- children: [/* @__PURE__ */ k(a, { variant: "primary" }), /* @__PURE__ */ k(U, { id: "Z3FXyt" })]
33
+ children: [/*#__PURE__*/ k(a, { variant: "primary" }), /*#__PURE__*/ k(H, { id: "Z3FXyt" })]
33
34
  })
34
35
  }) })
35
36
  })
36
- }) : !e || e.length === 0 ? /* @__PURE__ */ k(s, {
37
+ }) : !e || e.length === 0 ? /*#__PURE__*/ k(s, {
37
38
  columns: 7,
38
39
  className: "flavors",
39
40
  "data-testid": "no-flavors",
40
- children: /* @__PURE__ */ k(r, { children: /* @__PURE__ */ A(i, {
41
+ children: /*#__PURE__*/ k(r, { children: /*#__PURE__*/ A(i, {
41
42
  colSpan: 7,
42
- children: [/* @__PURE__ */ k(m, { children: /* @__PURE__ */ k(U, { id: "PiyQJ/" }) }), /* @__PURE__ */ k("p", { children: /* @__PURE__ */ k(U, { id: "KSW/GC" }) })]
43
+ children: [/*#__PURE__*/ k(m, { children: /*#__PURE__*/ k(H, { id: "PiyQJ/" }) }), /*#__PURE__*/ k("p", { children: /*#__PURE__*/ k(H, { id: "KSW/GC" }) })]
43
44
  }) })
44
- }) : /* @__PURE__ */ A(O, { children: [
45
- /* @__PURE__ */ A(s, {
46
- columns: 6,
47
- minContentColumns: [5],
45
+ }) : /*#__PURE__*/ A(O, { children: [
46
+ /*#__PURE__*/ A(s, {
47
+ columns: 7,
48
+ minContentColumns: [6],
48
49
  className: "flavors",
49
50
  "data-testid": "flavors-table",
50
- children: [/* @__PURE__ */ A(r, { children: [
51
- /* @__PURE__ */ k(n, { children: /* @__PURE__ */ k(U, { id: "6YtxFj" }) }),
52
- /* @__PURE__ */ k(n, { children: /* @__PURE__ */ k(U, { id: "k5nYwm" }) }),
53
- /* @__PURE__ */ k(n, { children: /* @__PURE__ */ k(U, { id: "K+e/0e" }) }),
54
- /* @__PURE__ */ k(n, { children: /* @__PURE__ */ k(U, { id: "n0ZttO" }) }),
55
- /* @__PURE__ */ k(n, { children: /* @__PURE__ */ k(U, { id: "p4nMut" }) }),
56
- /* @__PURE__ */ k(n, {})
57
- ] }), e.map((e) => /* @__PURE__ */ A(r, {
51
+ children: [/*#__PURE__*/ A(r, { children: [
52
+ /*#__PURE__*/ k(n, { children: /*#__PURE__*/ k(H, { id: "6YtxFj" }) }),
53
+ /*#__PURE__*/ k(n, { children: /*#__PURE__*/ k(H, { id: "k5nYwm" }) }),
54
+ /*#__PURE__*/ k(n, { children: /*#__PURE__*/ k(H, { id: "K+e/0e" }) }),
55
+ /*#__PURE__*/ k(n, { children: /*#__PURE__*/ k(H, { id: "n0ZttO" }) }),
56
+ /*#__PURE__*/ k(n, { children: /*#__PURE__*/ k(H, { id: "p4nMut" }) }),
57
+ /*#__PURE__*/ k(n, { children: /*#__PURE__*/ k(H, { id: "HyyJ83" }) }),
58
+ /*#__PURE__*/ k(n, {})
59
+ ] }), e.map((e) => /*#__PURE__*/ A(r, {
58
60
  "data-testid": `flavor-row-${e.id}`,
59
- onClick: () => E({
61
+ onClick: () => j({
60
62
  to: "/projects/$projectId/compute/flavors/$flavorId",
61
63
  params: {
62
- projectId: H,
64
+ projectId: G,
63
65
  flavorId: e.id
64
66
  }
65
67
  }),
66
68
  children: [
67
- /* @__PURE__ */ k(i, { children: e.name || e.id }),
68
- /* @__PURE__ */ k(i, { children: e.vcpus || "–" }),
69
- /* @__PURE__ */ k(i, { children: e.ram || "–" }),
70
- /* @__PURE__ */ k(i, { children: e.disk || "–" }),
71
- /* @__PURE__ */ k(i, { children: e.swap || "–" }),
72
- /* @__PURE__ */ k(i, {
69
+ /*#__PURE__*/ k(i, { children: e.name || e.id }),
70
+ /*#__PURE__*/ k(i, { children: e.vcpus || "–" }),
71
+ /*#__PURE__*/ k(i, { children: e.ram || "–" }),
72
+ /*#__PURE__*/ k(i, { children: e.disk || "–" }),
73
+ /*#__PURE__*/ k(i, { children: e.swap || "–" }),
74
+ /*#__PURE__*/ k(i, { children: e["os-flavor-access:is_public"] === !1 ? C._({ id: "zwBp5t" }) : C._({ id: "7d1a0d" }) }),
75
+ /*#__PURE__*/ k(i, {
73
76
  onClick: (e) => e.stopPropagation(),
74
- children: /* @__PURE__ */ k(d, { children: /* @__PURE__ */ A(t, { children: [
75
- /* @__PURE__ */ k(c, { children: /* @__PURE__ */ k(R, {
76
- to: "/projects/$projectId/compute/flavors/$flavorId",
77
- params: {
78
- projectId: H,
79
- flavorId: e.id
80
- },
81
- className: "text-theme-default",
82
- children: x._({ id: "URmyfc" })
83
- }) }),
84
- /* @__PURE__ */ k(c, {
85
- label: x._({ id: "6GBt0m" }),
86
- onClick: () => K(e)
77
+ children: /*#__PURE__*/ k(d, { children: /*#__PURE__*/ A(t, { children: [
78
+ /*#__PURE__*/ k(c, {
79
+ label: C._({ id: "URmyfc" }),
80
+ onClick: () => j({
81
+ to: "/projects/$projectId/compute/flavors/$flavorId",
82
+ params: {
83
+ projectId: G,
84
+ flavorId: e.id
85
+ }
86
+ })
87
87
  }),
88
- g && /* @__PURE__ */ k(c, {
89
- label: x._({ id: "cWbW6w" }),
88
+ (v || y) && /*#__PURE__*/ k(c, {
89
+ label: v ? C._({ id: "SIfYq6" }) : C._({ id: "6GBt0m" }),
90
90
  onClick: () => q(e)
91
91
  }),
92
- p && /* @__PURE__ */ k(c, {
93
- label: x._({ id: "JT3I1g" }),
94
- onClick: () => G(e)
92
+ g && /*#__PURE__*/ k(c, {
93
+ label: C._({ id: "cWbW6w" }),
94
+ onClick: () => J(e),
95
+ disabled: e["os-flavor-access:is_public"] !== !1
96
+ }),
97
+ p && /*#__PURE__*/ k(c, {
98
+ label: C._({ id: "JT3I1g" }),
99
+ onClick: () => K(e)
95
100
  })
96
101
  ] }) })
97
102
  })
98
103
  ]
99
104
  }, e.id))]
100
105
  }),
101
- y > 1 && /* @__PURE__ */ k("div", {
106
+ x > 1 && /*#__PURE__*/ k("div", {
102
107
  className: "flex justify-center py-4",
103
- children: /* @__PURE__ */ k(h, {
108
+ children: /*#__PURE__*/ k(h, {
104
109
  variant: "input",
105
- currentPage: v,
106
- pages: y,
107
- onPressPrevious: () => b?.(Math.max(v - 1, 1)),
108
- onPressNext: () => b?.(Math.min(v + 1, y)),
109
- onSelectChange: (e) => b?.(e)
110
+ currentPage: b,
111
+ pages: x,
112
+ onPressPrevious: () => S?.(Math.max(b - 1, 1)),
113
+ onPressNext: () => S?.(Math.min(b + 1, x)),
114
+ onSelectChange: (e) => S?.(e)
110
115
  })
111
116
  }),
112
- /* @__PURE__ */ k(T, {
117
+ /*#__PURE__*/ k(E, {
113
118
  client: l,
114
- isOpen: D,
115
- onClose: J,
119
+ isOpen: M,
120
+ onClose: Y,
116
121
  project: u,
117
- flavor: I,
122
+ flavor: V,
118
123
  onSuccess: () => {
119
- I && f && f(I.name || ""), J();
124
+ V && f && f(V.name || ""), Y();
120
125
  }
121
126
  }),
122
- /* @__PURE__ */ k(w, {
127
+ /*#__PURE__*/ k(T, {
123
128
  client: l,
124
- isOpen: M,
125
- onClose: () => N(!1),
129
+ isOpen: P,
130
+ onClose: () => F(!1),
126
131
  project: u,
127
- flavor: I
132
+ flavor: V,
133
+ canEdit: v
128
134
  }),
129
- /* @__PURE__ */ k(C, {
135
+ /*#__PURE__*/ k(w, {
130
136
  client: l,
131
- isOpen: P,
132
- onClose: () => F(!1),
137
+ isOpen: I,
138
+ onClose: () => B(!1),
133
139
  project: u,
134
- flavor: I
140
+ flavor: V
135
141
  })
136
142
  ] });
137
143
  }, K = (e, t, n) => {
@@ -185,7 +191,7 @@ var G = ({ flavors: e, isLoading: o, client: l, project: u, onFlavorDeleted: f,
185
191
  }, n = (e) => e != null && e !== "" && String(e).trim() !== "", r = (e) => e != null && e !== "" && String(e).trim() !== "" && !isNaN(Number(e));
186
192
  return n(e.id) && (t.id = String(e.id).trim()), n(e.description) && (t.description = String(e.description).trim()), r(e.swap) && (t.swap = Number(e.swap)), r(e.rxtx_factor) && (t.rxtx_factor = Number(e.rxtx_factor)), r(e["OS-FLV-EXT-DATA:ephemeral"]) && (t["OS-FLV-EXT-DATA:ephemeral"] = Number(e["OS-FLV-EXT-DATA:ephemeral"])), e["os-flavor-access:is_public"] !== void 0 && (t["os-flavor-access:is_public"] = !!e["os-flavor-access:is_public"]), t;
187
193
  }, J = ({ client: e, isOpen: t, onClose: n, project: r, onSuccess: i }) => {
188
- let { i18n: s, _: c } = W(), { translateError: u } = x(), [d, f] = L({ "os-flavor-access:is_public": !0 }), [m, h] = L({}), [S, C] = L(!1), [w, T] = L(null), E = (e) => {
194
+ let { i18n: s, _: c } = U(), { translateError: u } = x(), [d, f] = L({ "os-flavor-access:is_public": !0 }), [m, h] = L({}), [S, C] = L(!1), [w, T] = L(null), E = (e) => {
189
195
  let { name: t, value: n, type: r, checked: i } = e.target;
190
196
  f((e) => ({
191
197
  ...e,
@@ -245,7 +251,7 @@ var G = ({ flavors: e, isLoading: o, client: l, project: u, onFlavorDeleted: f,
245
251
  }, M = () => {
246
252
  f({ "os-flavor-access:is_public": !0 }), h({}), T(null), n();
247
253
  };
248
- return /* @__PURE__ */ A(v, {
254
+ return /*#__PURE__*/ A(v, {
249
255
  onCancel: M,
250
256
  size: "large",
251
257
  title: s._({ id: "Rlp5zj" }),
@@ -253,18 +259,18 @@ var G = ({ flavors: e, isLoading: o, client: l, project: u, onFlavorDeleted: f,
253
259
  onConfirm: j,
254
260
  cancelButtonLabel: s._({ id: "dEgA5A" }),
255
261
  confirmButtonLabel: s._({ id: "wEfZld" }),
256
- children: [S && /* @__PURE__ */ k(_, {
262
+ children: [S && /*#__PURE__*/ k(_, {
257
263
  distribution: "center",
258
264
  alignment: "center",
259
- children: /* @__PURE__ */ k(a, { variant: "primary" })
260
- }), !S && /* @__PURE__ */ A(l, { children: [w && /* @__PURE__ */ k(p, { children: /* @__PURE__ */ k(y, {
265
+ children: /*#__PURE__*/ k(a, { variant: "primary" })
266
+ }), !S && /*#__PURE__*/ A(l, { children: [w && /*#__PURE__*/ k(p, { children: /*#__PURE__*/ k(y, {
261
267
  onDismiss: () => {
262
268
  T(null);
263
269
  },
264
270
  text: w,
265
271
  variant: "error"
266
- }) }), /* @__PURE__ */ A(g, { children: [
267
- /* @__PURE__ */ k(p, { children: /* @__PURE__ */ k(o, {
272
+ }) }), /*#__PURE__*/ A(g, { children: [
273
+ /*#__PURE__*/ k(p, { children: /*#__PURE__*/ k(o, {
268
274
  id: "id",
269
275
  name: "id",
270
276
  label: s._({ id: "s2ubkU" }),
@@ -273,7 +279,7 @@ var G = ({ flavors: e, isLoading: o, client: l, project: u, onFlavorDeleted: f,
273
279
  onBlur: O,
274
280
  errortext: m.id
275
281
  }) }),
276
- /* @__PURE__ */ k(p, { children: /* @__PURE__ */ k(o, {
282
+ /*#__PURE__*/ k(p, { children: /*#__PURE__*/ k(o, {
277
283
  id: "name",
278
284
  name: "name",
279
285
  label: s._({ id: "lWxDDh" }),
@@ -283,7 +289,7 @@ var G = ({ flavors: e, isLoading: o, client: l, project: u, onFlavorDeleted: f,
283
289
  errortext: m.name,
284
290
  required: !0
285
291
  }) }),
286
- /* @__PURE__ */ k(p, { children: /* @__PURE__ */ k(o, {
292
+ /*#__PURE__*/ k(p, { children: /*#__PURE__*/ k(o, {
287
293
  id: "description",
288
294
  name: "description",
289
295
  label: s._({ id: "Nu4oKW" }),
@@ -292,7 +298,7 @@ var G = ({ flavors: e, isLoading: o, client: l, project: u, onFlavorDeleted: f,
292
298
  onBlur: O,
293
299
  errortext: m.description
294
300
  }) }),
295
- /* @__PURE__ */ k(p, { children: /* @__PURE__ */ k(o, {
301
+ /*#__PURE__*/ k(p, { children: /*#__PURE__*/ k(o, {
296
302
  id: "vcpus",
297
303
  name: "vcpus",
298
304
  label: s._({ id: "MZGbkp" }),
@@ -303,7 +309,7 @@ var G = ({ flavors: e, isLoading: o, client: l, project: u, onFlavorDeleted: f,
303
309
  type: "number",
304
310
  required: !0
305
311
  }) }),
306
- /* @__PURE__ */ k(p, { children: /* @__PURE__ */ k(o, {
312
+ /*#__PURE__*/ k(p, { children: /*#__PURE__*/ k(o, {
307
313
  id: "ram",
308
314
  name: "ram",
309
315
  label: s._({ id: "K+e/0e" }),
@@ -314,7 +320,7 @@ var G = ({ flavors: e, isLoading: o, client: l, project: u, onFlavorDeleted: f,
314
320
  type: "number",
315
321
  required: !0
316
322
  }) }),
317
- /* @__PURE__ */ k(p, { children: /* @__PURE__ */ k(o, {
323
+ /*#__PURE__*/ k(p, { children: /*#__PURE__*/ k(o, {
318
324
  id: "disk",
319
325
  name: "disk",
320
326
  label: s._({ id: "AxZkIr" }),
@@ -325,7 +331,7 @@ var G = ({ flavors: e, isLoading: o, client: l, project: u, onFlavorDeleted: f,
325
331
  type: "number",
326
332
  required: !0
327
333
  }) }),
328
- /* @__PURE__ */ k(p, { children: /* @__PURE__ */ k(o, {
334
+ /*#__PURE__*/ k(p, { children: /*#__PURE__*/ k(o, {
329
335
  id: "OS-FLV-EXT-DATA:ephemeral",
330
336
  name: "OS-FLV-EXT-DATA:ephemeral",
331
337
  label: s._({ id: "X2OnDx" }),
@@ -335,7 +341,7 @@ var G = ({ flavors: e, isLoading: o, client: l, project: u, onFlavorDeleted: f,
335
341
  errortext: m["OS-FLV-EXT-DATA:ephemeral"],
336
342
  type: "number"
337
343
  }) }),
338
- /* @__PURE__ */ k(p, { children: /* @__PURE__ */ k(o, {
344
+ /*#__PURE__*/ k(p, { children: /*#__PURE__*/ k(o, {
339
345
  id: "swap",
340
346
  name: "swap",
341
347
  label: s._({ id: "p4nMut" }),
@@ -345,7 +351,7 @@ var G = ({ flavors: e, isLoading: o, client: l, project: u, onFlavorDeleted: f,
345
351
  errortext: m.swap,
346
352
  type: "number"
347
353
  }) }),
348
- /* @__PURE__ */ k(p, { children: /* @__PURE__ */ k(o, {
354
+ /*#__PURE__*/ k(p, { children: /*#__PURE__*/ k(o, {
349
355
  id: "rxtx_factor",
350
356
  name: "rxtx_factor",
351
357
  label: s._({ id: "u5HztT" }),
@@ -356,7 +362,7 @@ var G = ({ flavors: e, isLoading: o, client: l, project: u, onFlavorDeleted: f,
356
362
  errortext: m.rxtx_factor,
357
363
  type: "number"
358
364
  }) }),
359
- /* @__PURE__ */ k(p, { children: /* @__PURE__ */ k(b, {
365
+ /*#__PURE__*/ k(p, { children: /*#__PURE__*/ k(b, {
360
366
  name: "os-flavor-access:is_public",
361
367
  label: s._({ id: "vbajgL" }),
362
368
  helptext: s._({ id: "3nh/7E" }),
@@ -374,7 +380,7 @@ var G = ({ flavors: e, isLoading: o, client: l, project: u, onFlavorDeleted: f,
374
380
  ...e,
375
381
  listError: void 0
376
382
  })).catch((e) => {
377
- if (e instanceof H && e.data?.code === "FORBIDDEN") return {
383
+ if (e instanceof V && e.data?.code === "FORBIDDEN") return {
378
384
  flavors: [],
379
385
  privateFlavorError: void 0,
380
386
  listError: e.message
@@ -385,16 +391,21 @@ var G = ({ flavors: e, isLoading: o, client: l, project: u, onFlavorDeleted: f,
385
391
  permission: [
386
392
  "flavors:create",
387
393
  "flavors:delete",
388
- "flavors:list_projects"
394
+ "flavors:list_projects",
395
+ "flavor_specs:create",
396
+ "flavor_specs:delete",
397
+ "flavor_specs:list"
389
398
  ]
390
- }).then(([e, t, n]) => ({
399
+ }).then(([e, t, n, r, i, a]) => ({
391
400
  canCreate: e,
392
401
  canDelete: t,
393
- canManageAccess: n
402
+ canManageAccess: n,
403
+ canManageSpecs: r || i,
404
+ canListSpecs: a
394
405
  }));
395
406
  function Q({ flavorsPromise: t, permissionsPromise: n, client: r, project: i, onFlavorDeleted: a, onFlavorCreated: o, searchTerm: s, setSearchTerm: c, sortSettings: l, handleSortChange: d, createModalOpen: p, setCreateModalOpen: m, currentPage: h, onPageChange: g }) {
396
- let { i18n: v, _: b } = W(), { flavors: x, privateFlavorError: S, listError: C } = N(t), w = N(n), [T, E] = L(s), j = I(void 0);
397
- if (F(() => () => clearTimeout(j.current), []), C) return /* @__PURE__ */ k("p", { children: C });
407
+ let { i18n: v, _: b } = U(), { flavors: x, privateFlavorError: S, listError: C } = N(t), w = N(n), [T, E] = L(s), j = I(void 0);
408
+ if (F(() => () => clearTimeout(j.current), []), C) return /*#__PURE__*/ k("p", { children: C });
398
409
  let M = Math.max(1, Math.ceil(x.length / Y)), P = Math.min(h, M), R = x.slice((P - 1) * Y, P * Y);
399
410
  return F(() => {
400
411
  h > M && g(1);
@@ -402,27 +413,27 @@ function Q({ flavorsPromise: t, permissionsPromise: n, client: r, project: i, on
402
413
  M,
403
414
  h,
404
415
  g
405
- ]), /* @__PURE__ */ A(O, { children: [
406
- /* @__PURE__ */ k(J, {
416
+ ]), /*#__PURE__*/ A(O, { children: [
417
+ /*#__PURE__*/ k(J, {
407
418
  client: r,
408
419
  isOpen: p,
409
420
  project: i,
410
421
  onClose: () => m(!1),
411
422
  onSuccess: o
412
423
  }),
413
- S && /* @__PURE__ */ k(y, {
424
+ S && /*#__PURE__*/ k(y, {
414
425
  className: "mb-4",
415
426
  text: v._({ id: "3oc18/" }),
416
427
  variant: "warning"
417
428
  }),
418
- /* @__PURE__ */ A(_, {
429
+ /*#__PURE__*/ A(_, {
419
430
  distribution: "end",
420
431
  alignment: "center",
421
432
  gap: "2",
422
433
  className: "pb-2",
423
- children: [/* @__PURE__ */ k(_, {
434
+ children: [/*#__PURE__*/ k(_, {
424
435
  gap: "0.5",
425
- children: /* @__PURE__ */ k(D, {
436
+ children: /*#__PURE__*/ k(D, {
426
437
  options: l.options,
427
438
  sortBy: l.sortBy,
428
439
  sortDirection: l.sortDirection ?? "asc",
@@ -436,16 +447,16 @@ function Q({ flavorsPromise: t, permissionsPromise: n, client: r, project: i, on
436
447
  sortDirection: e
437
448
  })
438
449
  })
439
- }), w.canCreate && /* @__PURE__ */ k(u, {
450
+ }), w.canCreate && /*#__PURE__*/ k(u, {
440
451
  variant: "primary",
441
452
  label: v._({ id: "Rlp5zj" }),
442
453
  onClick: () => m(!0)
443
454
  })]
444
455
  }),
445
- /* @__PURE__ */ k(e, { children: /* @__PURE__ */ k(_, {
456
+ /*#__PURE__*/ k(e, { children: /*#__PURE__*/ k(_, {
446
457
  distribution: "end",
447
458
  alignment: "center",
448
- children: /* @__PURE__ */ k(f, {
459
+ children: /*#__PURE__*/ k(f, {
449
460
  placeholder: v._({ id: "U0sPCo" }),
450
461
  "data-testid": "searchbar",
451
462
  value: T,
@@ -461,7 +472,7 @@ function Q({ flavorsPromise: t, permissionsPromise: n, client: r, project: i, on
461
472
  }
462
473
  })
463
474
  }) }),
464
- /* @__PURE__ */ k(G, {
475
+ /*#__PURE__*/ k(G, {
465
476
  flavors: R,
466
477
  isLoading: !1,
467
478
  client: r,
@@ -469,6 +480,8 @@ function Q({ flavorsPromise: t, permissionsPromise: n, client: r, project: i, on
469
480
  onFlavorDeleted: a,
470
481
  canDeleteFlavor: w.canDelete,
471
482
  canMangageAccess: w.canManageAccess,
483
+ canManageSpecs: w.canManageSpecs,
484
+ canListSpecs: w.canListSpecs,
472
485
  currentPage: P,
473
486
  totalPages: M,
474
487
  onPageChange: g
@@ -476,7 +489,7 @@ function Q({ flavorsPromise: t, permissionsPromise: n, client: r, project: i, on
476
489
  ] });
477
490
  }
478
491
  var $ = ({ client: e, project: t }) => {
479
- let { i18n: n, _: r } = W(), i = z(), o = V({ strict: !1 }), [s, c] = L({
492
+ let { i18n: n, _: r } = U(), i = R(), o = B({ strict: !1 }), [s, c] = L({
480
493
  options: [
481
494
  {
482
495
  label: n._({ id: "6YtxFj" }),
@@ -556,41 +569,47 @@ var $ = ({ client: e, project: t }) => {
556
569
  page: e === 1 ? void 0 : e
557
570
  }) });
558
571
  }, [i]);
559
- return /* @__PURE__ */ A("div", {
572
+ return /*#__PURE__*/ A("div", {
560
573
  className: "relative",
561
- children: [f && /* @__PURE__ */ k(y, {
574
+ children: [f && /*#__PURE__*/ k(y, {
562
575
  className: "absolute -top-14 right-0 left-0 z-50",
563
576
  text: f.message,
564
577
  variant: "info",
565
578
  onDismiss: () => p(void 0),
566
579
  dismissible: !0
567
- }), /* @__PURE__ */ k(j, {
568
- fallback: /* @__PURE__ */ A(_, {
569
- className: "fixed inset-0",
570
- distribution: "center",
571
- alignment: "center",
572
- direction: "vertical",
573
- children: [/* @__PURE__ */ k(a, {
574
- variant: "primary",
575
- size: "large",
576
- className: "mb-2"
577
- }), /* @__PURE__ */ k(U, { id: "EqSPkP" })]
580
+ }), /*#__PURE__*/ k(W, {
581
+ fallbackRender: ({ error: e }) => /*#__PURE__*/ k(y, {
582
+ variant: "error",
583
+ text: e instanceof Error ? e.message : n._({ id: "W5A0Ly" })
578
584
  }),
579
- children: /* @__PURE__ */ k(Q, {
580
- flavorsPromise: g,
581
- permissionsPromise: b,
582
- client: e,
583
- project: t,
584
- onFlavorDeleted: S,
585
- onFlavorCreated: C,
586
- searchTerm: l,
587
- setSearchTerm: T,
588
- sortSettings: s,
589
- handleSortChange: w,
590
- createModalOpen: m,
591
- setCreateModalOpen: h,
592
- currentPage: d,
593
- onPageChange: E
585
+ children: /*#__PURE__*/ k(j, {
586
+ fallback: /*#__PURE__*/ A(_, {
587
+ className: "fixed inset-0",
588
+ distribution: "center",
589
+ alignment: "center",
590
+ direction: "vertical",
591
+ children: [/*#__PURE__*/ k(a, {
592
+ variant: "primary",
593
+ size: "large",
594
+ className: "mb-2"
595
+ }), /*#__PURE__*/ k(H, { id: "EqSPkP" })]
596
+ }),
597
+ children: /*#__PURE__*/ k(Q, {
598
+ flavorsPromise: g,
599
+ permissionsPromise: b,
600
+ client: e,
601
+ project: t,
602
+ onFlavorDeleted: S,
603
+ onFlavorCreated: C,
604
+ searchTerm: l,
605
+ setSearchTerm: T,
606
+ sortSettings: s,
607
+ handleSortChange: w,
608
+ createModalOpen: m,
609
+ setCreateModalOpen: h,
610
+ currentPage: d,
611
+ onPageChange: E
612
+ })
594
613
  })
595
614
  })]
596
615
  });
@@ -598,11 +617,11 @@ var $ = ({ client: e, project: t }) => {
598
617
  //#endregion
599
618
  //#region src/client/routes/_auth/projects/$projectId/compute/flavors/index.tsx?tsr-split=component
600
619
  function ee() {
601
- let { i18n: e, _: t } = W(), { projectId: n } = S.useParams(), { trpcClient: r } = S.useRouteContext();
602
- return /* @__PURE__ */ A(O, { children: [/* @__PURE__ */ k(E, {
620
+ let { i18n: e, _: t } = U(), { projectId: n } = S.useParams(), { trpcClient: r } = S.useRouteContext();
621
+ return /*#__PURE__*/ A(O, { children: [/*#__PURE__*/ k(C, {
603
622
  title: e._({ id: "neiJm0" }),
604
623
  projectId: n
605
- }), /* @__PURE__ */ k($, {
624
+ }), /*#__PURE__*/ k($, {
606
625
  project: n,
607
626
  client: r
608
627
  })] });
@@ -610,4 +629,4 @@ function ee() {
610
629
  //#endregion
611
630
  export { ee as component };
612
631
 
613
- //# sourceMappingURL=flavors-qvgPSI7J.mjs.map
632
+ //# sourceMappingURL=flavors-CpirO_nr.mjs.map