@cobaltcore-dev/aurora 2.1.1 → 2.2.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 (173) hide show
  1. package/README.md +31 -25
  2. package/dist/client/AuroraApp.d.ts +9 -2
  3. package/dist/client/context/AppConfigContext.d.ts +44 -0
  4. package/dist/client/index.d.ts +2 -0
  5. package/dist/client/index.js +41221 -845
  6. package/dist/client/index.js.map +1 -1
  7. package/dist/client/trpcClient.d.ts +314 -0
  8. package/dist/client/utils/appConfigGating.d.ts +21 -0
  9. package/dist/server/index.d.ts +694 -3
  10. package/dist/server/index.js +1748 -722
  11. package/package.json +3 -3
  12. package/dist/client/AuthProvider-CVSAwW9f.mjs +0 -83
  13. package/dist/client/AuthProvider-CVSAwW9f.mjs.map +0 -1
  14. package/dist/client/ContentHeader-fKKZVu-o.mjs +0 -116
  15. package/dist/client/ContentHeader-fKKZVu-o.mjs.map +0 -1
  16. package/dist/client/DeleteFlavorModal-C4nAi7gY.mjs +0 -724
  17. package/dist/client/DeleteFlavorModal-C4nAi7gY.mjs.map +0 -1
  18. package/dist/client/DynamicBreadcrumbContext-CVcUQFou.mjs +0 -26
  19. package/dist/client/DynamicBreadcrumbContext-CVcUQFou.mjs.map +0 -1
  20. package/dist/client/FiltersInput-Becwxo_J.mjs +0 -85
  21. package/dist/client/FiltersInput-Becwxo_J.mjs.map +0 -1
  22. package/dist/client/FloatingIpActionModals-Cq10WljB.mjs +0 -466
  23. package/dist/client/FloatingIpActionModals-Cq10WljB.mjs.map +0 -1
  24. package/dist/client/RouteIdLevelDefaultError-DPF_x2tG.mjs +0 -26
  25. package/dist/client/RouteIdLevelDefaultError-DPF_x2tG.mjs.map +0 -1
  26. package/dist/client/Slot-CWb612-_.mjs +0 -28
  27. package/dist/client/Slot-CWb612-_.mjs.map +0 -1
  28. package/dist/client/SortInput-4g7nSTHW.mjs +0 -34
  29. package/dist/client/SortInput-4g7nSTHW.mjs.map +0 -1
  30. package/dist/client/StorageNotFound-B-zVinVD.mjs +0 -30
  31. package/dist/client/StorageNotFound-B-zVinVD.mjs.map +0 -1
  32. package/dist/client/TwoColumnDescriptionList-DKS42RKa.mjs +0 -28
  33. package/dist/client/TwoColumnDescriptionList-DKS42RKa.mjs.map +0 -1
  34. package/dist/client/_-CAsCx-Ay.mjs +0 -6
  35. package/dist/client/_-CAsCx-Ay.mjs.map +0 -1
  36. package/dist/client/_auth-SrDjHL6j.mjs +0 -12
  37. package/dist/client/_auth-SrDjHL6j.mjs.map +0 -1
  38. package/dist/client/_flavorId-BPvssEzn.mjs +0 -277
  39. package/dist/client/_flavorId-BPvssEzn.mjs.map +0 -1
  40. package/dist/client/_flavorId-CFUBcU-l.mjs +0 -27
  41. package/dist/client/_flavorId-CFUBcU-l.mjs.map +0 -1
  42. package/dist/client/_flavorId-CZcIp0Ih.mjs +0 -22
  43. package/dist/client/_flavorId-CZcIp0Ih.mjs.map +0 -1
  44. package/dist/client/_floatingIpId-B8r64AL9.mjs +0 -196
  45. package/dist/client/_floatingIpId-B8r64AL9.mjs.map +0 -1
  46. package/dist/client/_floatingIpId-lEobpOER.mjs +0 -26
  47. package/dist/client/_floatingIpId-lEobpOER.mjs.map +0 -1
  48. package/dist/client/_imageId-BAezmV0Y.mjs +0 -526
  49. package/dist/client/_imageId-BAezmV0Y.mjs.map +0 -1
  50. package/dist/client/_imageId-D-jqz3e3.mjs +0 -40
  51. package/dist/client/_imageId-D-jqz3e3.mjs.map +0 -1
  52. package/dist/client/_imageId-gMdrdnVt.mjs +0 -22
  53. package/dist/client/_imageId-gMdrdnVt.mjs.map +0 -1
  54. package/dist/client/_projectId-BYccdAtX.mjs +0 -77
  55. package/dist/client/_projectId-BYccdAtX.mjs.map +0 -1
  56. package/dist/client/_projectId-CBjZC1tv.mjs +0 -283
  57. package/dist/client/_projectId-CBjZC1tv.mjs.map +0 -1
  58. package/dist/client/_projectId-CLEa1zgw.mjs +0 -30
  59. package/dist/client/_projectId-CLEa1zgw.mjs.map +0 -1
  60. package/dist/client/_projectId-D3VOH5lN.mjs +0 -94
  61. package/dist/client/_projectId-D3VOH5lN.mjs.map +0 -1
  62. package/dist/client/_securityGroupId-BwgZnoiR.mjs +0 -29
  63. package/dist/client/_securityGroupId-BwgZnoiR.mjs.map +0 -1
  64. package/dist/client/_securityGroupId-Cz2NUHdB.mjs +0 -1819
  65. package/dist/client/_securityGroupId-Cz2NUHdB.mjs.map +0 -1
  66. package/dist/client/_serviceType-DS8DxsrP.mjs +0 -20
  67. package/dist/client/_serviceType-DS8DxsrP.mjs.map +0 -1
  68. package/dist/client/_serviceType-M8d9rOT6.mjs +0 -6
  69. package/dist/client/_serviceType-M8d9rOT6.mjs.map +0 -1
  70. package/dist/client/_storageType-BNpP1A2N.mjs +0 -13
  71. package/dist/client/_storageType-BNpP1A2N.mjs.map +0 -1
  72. package/dist/client/_storageType-BxSGKhAI.mjs +0 -15
  73. package/dist/client/_storageType-BxSGKhAI.mjs.map +0 -1
  74. package/dist/client/_storageType-DZYCmiLt.mjs +0 -30
  75. package/dist/client/_storageType-DZYCmiLt.mjs.map +0 -1
  76. package/dist/client/_storageType-UqAMP-8d.mjs +0 -859
  77. package/dist/client/_storageType-UqAMP-8d.mjs.map +0 -1
  78. package/dist/client/_storageType-u51_7OwJ.mjs +0 -7
  79. package/dist/client/_storageType-u51_7OwJ.mjs.map +0 -1
  80. package/dist/client/about-BmQTyLWc.mjs +0 -92
  81. package/dist/client/about-BmQTyLWc.mjs.map +0 -1
  82. package/dist/client/assets/__mocks__/svgMock.d.ts +0 -3
  83. package/dist/client/aurora-CIml-f2f.mjs +0 -19
  84. package/dist/client/aurora-CIml-f2f.mjs.map +0 -1
  85. package/dist/client/build-WuxXRAqf.mjs +0 -14530
  86. package/dist/client/build-WuxXRAqf.mjs.map +0 -1
  87. package/dist/client/cn-DM4Cy3jv.mjs +0 -10
  88. package/dist/client/cn-DM4Cy3jv.mjs.map +0 -1
  89. package/dist/client/flavors-CJVSNz6R.mjs +0 -15
  90. package/dist/client/flavors-CJVSNz6R.mjs.map +0 -1
  91. package/dist/client/flavors-CflJDIEH.mjs +0 -667
  92. package/dist/client/flavors-CflJDIEH.mjs.map +0 -1
  93. package/dist/client/flavors-DWMZ6TuJ.mjs +0 -8
  94. package/dist/client/flavors-DWMZ6TuJ.mjs.map +0 -1
  95. package/dist/client/floatingips-Cz9k80cc.mjs +0 -8
  96. package/dist/client/floatingips-Cz9k80cc.mjs.map +0 -1
  97. package/dist/client/floatingips-DXnRlLvV.mjs +0 -551
  98. package/dist/client/floatingips-DXnRlLvV.mjs.map +0 -1
  99. package/dist/client/floatingips-HRbuLxiN.mjs +0 -22
  100. package/dist/client/floatingips-HRbuLxiN.mjs.map +0 -1
  101. package/dist/client/floatingips-nN1kQmsu.mjs +0 -14
  102. package/dist/client/floatingips-nN1kQmsu.mjs.map +0 -1
  103. package/dist/client/formatBytes-CZv_XyCY.mjs +0 -38
  104. package/dist/client/formatBytes-CZv_XyCY.mjs.map +0 -1
  105. package/dist/client/helpers-1PpYf-fC.mjs +0 -6
  106. package/dist/client/helpers-1PpYf-fC.mjs.map +0 -1
  107. package/dist/client/hooks-D0yKIumu.mjs +0 -22
  108. package/dist/client/hooks-D0yKIumu.mjs.map +0 -1
  109. package/dist/client/imageHelpers-DBhL2ebL.mjs +0 -1272
  110. package/dist/client/imageHelpers-DBhL2ebL.mjs.map +0 -1
  111. package/dist/client/images-BsylWUiH.mjs +0 -2011
  112. package/dist/client/images-BsylWUiH.mjs.map +0 -1
  113. package/dist/client/images-NBf2bV43.mjs +0 -8
  114. package/dist/client/images-NBf2bV43.mjs.map +0 -1
  115. package/dist/client/images-zQq1nSVv.mjs +0 -15
  116. package/dist/client/images-zQq1nSVv.mjs.map +0 -1
  117. package/dist/client/md-kvaGCNAK.mjs +0 -336
  118. package/dist/client/md-kvaGCNAK.mjs.map +0 -1
  119. package/dist/client/network-DuZm76BZ.mjs +0 -8
  120. package/dist/client/network-DuZm76BZ.mjs.map +0 -1
  121. package/dist/client/objects-BudUAfWY.mjs +0 -12909
  122. package/dist/client/objects-BudUAfWY.mjs.map +0 -1
  123. package/dist/client/objects-Dc7sKUr8.mjs +0 -67
  124. package/dist/client/objects-Dc7sKUr8.mjs.map +0 -1
  125. package/dist/client/objects-Dw7oeTq2.mjs +0 -80
  126. package/dist/client/objects-Dw7oeTq2.mjs.map +0 -1
  127. package/dist/client/objects-_g7nGIn5.mjs +0 -25
  128. package/dist/client/objects-_g7nGIn5.mjs.map +0 -1
  129. package/dist/client/objects-eBxvY6_n.mjs +0 -78
  130. package/dist/client/objects-eBxvY6_n.mjs.map +0 -1
  131. package/dist/client/projects-yiK0HGSA.mjs +0 -7
  132. package/dist/client/projects-yiK0HGSA.mjs.map +0 -1
  133. package/dist/client/routeInfo-DP3v74Wg.mjs +0 -19
  134. package/dist/client/routeInfo-DP3v74Wg.mjs.map +0 -1
  135. package/dist/client/routes-CJj7SR_K.mjs +0 -10
  136. package/dist/client/routes-CJj7SR_K.mjs.map +0 -1
  137. package/dist/client/routes-xofA3ksU.mjs +0 -110
  138. package/dist/client/routes-xofA3ksU.mjs.map +0 -1
  139. package/dist/client/securitygroups-CSmsBzUb.mjs +0 -581
  140. package/dist/client/securitygroups-CSmsBzUb.mjs.map +0 -1
  141. package/dist/client/securitygroups-CtKne8UQ.mjs +0 -8
  142. package/dist/client/securitygroups-CtKne8UQ.mjs.map +0 -1
  143. package/dist/client/securitygroups-T7kaNFEp.mjs +0 -15
  144. package/dist/client/securitygroups-T7kaNFEp.mjs.map +0 -1
  145. package/dist/client/securitygroups-WLB1_IM6.mjs +0 -22
  146. package/dist/client/securitygroups-WLB1_IM6.mjs.map +0 -1
  147. package/dist/client/securitygroups-o0IXZM6S.mjs +0 -14
  148. package/dist/client/securitygroups-o0IXZM6S.mjs.map +0 -1
  149. package/dist/client/serviceCatalog-B3lKWC9V.mjs +0 -6
  150. package/dist/client/serviceCatalog-B3lKWC9V.mjs.map +0 -1
  151. package/dist/client/services-D1PbooD1.mjs +0 -6
  152. package/dist/client/services-D1PbooD1.mjs.map +0 -1
  153. package/dist/client/services-DEMVtFyn.mjs +0 -9
  154. package/dist/client/services-DEMVtFyn.mjs.map +0 -1
  155. package/dist/client/storageProviders-CJ5rOh13.mjs +0 -15
  156. package/dist/client/storageProviders-CJ5rOh13.mjs.map +0 -1
  157. package/dist/client/trpcClient-D7gpR7YG.mjs +0 -71
  158. package/dist/client/trpcClient-D7gpR7YG.mjs.map +0 -1
  159. package/dist/client/useBreadcrumbs-ha3IlaxX.mjs +0 -54
  160. package/dist/client/useBreadcrumbs-ha3IlaxX.mjs.map +0 -1
  161. package/dist/client/useErrorTranslation-Dc0eE8Zt.mjs +0 -83
  162. package/dist/client/useErrorTranslation-Dc0eE8Zt.mjs.map +0 -1
  163. package/dist/client/useModal-DCs1OJh7.mjs +0 -12
  164. package/dist/client/useModal-DCs1OJh7.mjs.map +0 -1
  165. package/dist/client/useModalTracking-BYd37pXm.mjs +0 -37
  166. package/dist/client/useModalTracking-BYd37pXm.mjs.map +0 -1
  167. package/dist/client/useProjectId-DBc5lpoU.mjs +0 -11
  168. package/dist/client/useProjectId-DBc5lpoU.mjs.map +0 -1
  169. package/dist/client/useSecurityGroupPermissions--hK4aR8Y.mjs +0 -294
  170. package/dist/client/useSecurityGroupPermissions--hK4aR8Y.mjs.map +0 -1
  171. package/dist/client/useSetBreadcrumb-tn7lBaQV.mjs +0 -19
  172. package/dist/client/useSetBreadcrumb-tn7lBaQV.mjs.map +0 -1
  173. package/dist/client/utils/trpcErrors.d.ts +0 -13
@@ -1,34 +0,0 @@
1
- import { F as e, Q as t, R as n, it as r } from "./build-WuxXRAqf.mjs";
2
- import { jsx as i, jsxs as a } from "react/jsx-runtime";
3
- import { useLingui as o } from "@lingui/react";
4
- //#region src/client/components/ListToolbar/SortInput.tsx
5
- var s = ({ sortBy: s, onSortByChange: c, sortDirection: l, onSortDirectionChange: u, options: d, selectClassName: f, selectWidth: p }) => {
6
- let { i18n: m, _: h } = o(), g = () => ({
7
- className: f,
8
- width: p,
9
- onChange: c,
10
- value: s,
11
- "data-testid": "sort-select",
12
- label: m._({ id: "/HgF9q" })
13
- }), _ = () => ({
14
- "data-testid": "direction-toggle",
15
- order: l,
16
- onChange: u
17
- });
18
- return /*#__PURE__*/ a(t, {
19
- gap: "0.5",
20
- alignment: "end",
21
- className: "w-full sm:w-auto",
22
- children: [/*#__PURE__*/ i(r, {
23
- ...g(),
24
- children: d.map((e) => /*#__PURE__*/ i(n, {
25
- value: e.value,
26
- children: e.label
27
- }, e.value))
28
- }), /*#__PURE__*/ i(e, { ..._() })]
29
- });
30
- };
31
- //#endregion
32
- export { s as t };
33
-
34
- //# sourceMappingURL=SortInput-4g7nSTHW.mjs.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"SortInput-4g7nSTHW.mjs","names":["React","Select","SelectOption","SortButton","Stack","SortInput","sortBy","onSortByChange","sortDirection","onSortDirectionChange","options","selectClassName","selectWidth","useLingui","getSelectProps","className","width","onChange","value","label","t","getSortButtonProps","order","gap","alignment","map","option"],"sources":["../../src/client/components/ListToolbar/SortInput.tsx"],"sourcesContent":["import React from \"react\"\nimport { useLingui } from \"@lingui/react/macro\"\nimport { Select, SelectOption, SortButton, Stack, SelectProps, ButtonProps } from \"@cloudoperators/juno-ui-components\"\nimport { SortOption } from \"./types\"\n\nexport interface SortInputProps {\n sortBy?: string | number | string[]\n onSortByChange: (param?: string | number | string[]) => void\n sortDirection: \"asc\" | \"desc\"\n onSortDirectionChange: (direction: \"asc\" | \"desc\") => void\n options: SortOption[]\n selectClassName?: string\n /** Passed through to the underlying Select. \"auto\" sizes the toggle to its content (use with a `min-w-*` selectClassName floor) instead of the default \"full\" width. */\n selectWidth?: SelectProps[\"width\"]\n}\n\nexport const SortInput: React.FC<SortInputProps> = ({\n sortBy,\n onSortByChange,\n sortDirection,\n onSortDirectionChange,\n options,\n selectClassName,\n selectWidth,\n}) => {\n const { t } = useLingui()\n\n const getSelectProps = (): SelectProps & { \"data-testid\"?: string } => ({\n className: selectClassName,\n width: selectWidth,\n onChange: onSortByChange,\n value: sortBy,\n \"data-testid\": \"sort-select\",\n label: t`Sort by`,\n })\n\n const getSortButtonProps = (): Omit<ButtonProps, \"onChange\"> & {\n \"data-testid\"?: string\n order: \"asc\" | \"desc\"\n onChange: (order: \"asc\" | \"desc\") => void\n } => ({\n \"data-testid\": \"direction-toggle\",\n order: sortDirection,\n onChange: onSortDirectionChange,\n })\n\n return (\n <Stack gap=\"0.5\" alignment=\"end\" className=\"w-full sm:w-auto\">\n <Select {...getSelectProps()}>\n {options.map((option) => (\n <SelectOption key={option.value} value={option.value}>\n {option.label}\n </SelectOption>\n ))}\n </Select>\n <SortButton {...getSortButtonProps()} />\n </Stack>\n )\n}\n"],"mappings":";;;;AAgBA,IAAaK,KAAuC,EAClDC,WACAC,mBACAC,kBACAC,0BACAC,YACAC,oBACAC,qBACD;CACC,IAAM,EAAA,MAAA,GAAA,GAAA,MAAQC,EAAAA,GAERC,WAAkE;EACtEC,WAAWJ;EACXK,OAAOJ;EACPK,UAAUV;EACVW,OAAOZ;EACP,eAAe;EACfa,OAAOC,EAAAA,EAAC,EAAA,IAAA,SAAQ,CAAA;CAClB,IAEMC,WAIA;EACJ,eAAe;EACfC,OAAOd;EACPS,UAAUR;CACZ;CAEA,OACE,gBAACL,GAAAA;EAAMmB,KAAI;EAAMC,WAAU;EAAMT,WAAU;EACzC,UAAA,CAAA,gBAACd,GAAAA;GAAQ,GAAGa,EAAAA;GACTJ,UAAAA,EAAQe,KAAKC,MACZ,gBAACxB,GAAAA;IAAgCgB,OAAOQ,EAAOR;IAC5CQ,UAAAA,EAAOP;GADSO,GAAAA,EAAOR,KAAK,CAAA;EAKnC,CAAA,GAAA,gBAACf,GAAAA,EAAY,GAAGkB,EAAAA,EAAAA,CAAAA,CAAAA;;AAGtB"}
@@ -1,30 +0,0 @@
1
- import { i as e, rt as t } from "./build-WuxXRAqf.mjs";
2
- import { jsx as n } from "react/jsx-runtime";
3
- import { useNavigate as r, useParams as i } from "@tanstack/react-router";
4
- import { Trans as a, useLingui as o } from "@lingui/react";
5
- //#region src/client/routes/_auth/projects/$projectId/storage/-components/StorageNotFound.tsx
6
- function s({ data: s }) {
7
- let { i18n: c, _: l } = o(), u = r(), { projectId: d } = i({ strict: !1 }), f = s?.reason === "storage-type-mismatch";
8
- return /*#__PURE__*/ n(t, {
9
- status: "error",
10
- code: 404,
11
- title: f ? c._({ id: "boJlGf" }) : c._({ id: "Zu31u6" }),
12
- body: f ? c._({ id: "cyMmud" }) : c._({ id: "E4WmGR" }),
13
- action: d ? /*#__PURE__*/ n(e, {
14
- variant: "primary",
15
- onClick: () => u({
16
- to: "/projects/$projectId",
17
- params: { projectId: d }
18
- }),
19
- children: /*#__PURE__*/ n(a, { id: "AGco1A" })
20
- }) : /*#__PURE__*/ n(e, {
21
- variant: "primary",
22
- onClick: () => u({ to: "/projects" }),
23
- children: /*#__PURE__*/ n(a, { id: "aKznJS" })
24
- })
25
- });
26
- }
27
- //#endregion
28
- export { s as t };
29
-
30
- //# sourceMappingURL=StorageNotFound-B-zVinVD.mjs.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"StorageNotFound-B-zVinVD.mjs","names":["Status","Button","useNavigate","useParams","StorageNotFound","data","useLingui","navigate","projectId","strict","isBadUrl","reason","status","code","title","t","body","action","variant","onClick","to","params"],"sources":["../../src/client/routes/_auth/projects/$projectId/storage/-components/StorageNotFound.tsx"],"sourcesContent":["import { Status, Button } from \"@cloudoperators/juno-ui-components\"\nimport { useLingui, Trans } from \"@lingui/react/macro\"\nimport { useNavigate, useParams } from \"@tanstack/react-router\"\nimport type { StorageNotFoundReason } from \"./utils/serviceAvailability\"\n\ninterface StorageNotFoundProps {\n data?: { reason?: StorageNotFoundReason }\n}\n\nexport function StorageNotFound({ data }: StorageNotFoundProps) {\n const { t } = useLingui()\n const navigate = useNavigate()\n const { projectId } = useParams({ strict: false })\n\n const isBadUrl = data?.reason === \"storage-type-mismatch\"\n\n return (\n <Status\n status=\"error\"\n code={404}\n title={isBadUrl ? t`Page Not Found` : t`Object Storage Not Found`}\n body={\n isBadUrl\n ? t`This address is not valid for this object storage service.`\n : t`This object storage service does not exist or is not available for this project.`\n }\n action={\n projectId ? (\n <Button variant=\"primary\" onClick={() => navigate({ to: \"/projects/$projectId\", params: { projectId } })}>\n <Trans>Go to Project</Trans>\n </Button>\n ) : (\n <Button variant=\"primary\" onClick={() => navigate({ to: \"/projects\" })}>\n <Trans>Go to Projects</Trans>\n </Button>\n )\n }\n />\n )\n}\n"],"mappings":";;;;;AASA,SAAgBI,EAAgB,EAAEC,WAA4B;CAC5D,IAAM,EAAA,MAAA,GAAA,GAAA,MAAQC,EAAAA,GACRC,IAAWL,EAAAA,GACX,EAAEM,iBAAcL,EAAU,EAAEM,QAAQ,GAAM,CAAA,GAE1CC,IAAWL,GAAMM,WAAW;CAElC,OACE,gBAACX,GAAAA;EACCY,QAAO;EACPC,MAAM;EACNC,OAAOJ,IAAWK,EAAAA,EAAC,EAAA,IAAA,SAAe,CAAA,IAAIA,EAAAA,EAAC,EAAA,IAAA,SAAyB,CAAA;EAChEC,MACEN,IACIK,EAAAA,EAAC,EAAA,IAAA,SAA2D,CAAA,IAC5DA,EAAAA,EAAC,EAAA,IAAA,SAAiF,CAAA;EAExFE,QACET,IACE,gBAACP,GAAAA;GAAOiB,SAAQ;GAAUC,eAAeZ,EAAS;IAAEa,IAAI;IAAwBC,QAAQ,EAAEb,aAAU;GAAE,CAAA;GACpG,UAAA,gBAAA,GAAA,EAAA,IAAA,SAAA,CAAA;EAGF,CAAA,IAAA,gBAACP,GAAAA;GAAOiB,SAAQ;GAAUC,eAAeZ,EAAS,EAAEa,IAAI,YAAY,CAAA;GAClE,UAAA,gBAAA,GAAA,EAAA,IAAA,SAAA,CAAA;;;AAMZ"}
@@ -1,28 +0,0 @@
1
- import { E as e, Q as t, n, s as r } from "./build-WuxXRAqf.mjs";
2
- import { jsx as i, jsxs as a } from "react/jsx-runtime";
3
- import { Fragment as o } from "react";
4
- //#region src/client/components/TwoColumnDescriptionList.tsx
5
- var s = ({ items: s }) => {
6
- let c = Math.ceil(s.length / 2), l = s.slice(0, c), u = s.slice(c);
7
- return /*#__PURE__*/ a(t, {
8
- gap: "6",
9
- className: "grid grid-cols-2",
10
- children: [/*#__PURE__*/ i(r, {
11
- alignTerms: "right",
12
- children: l.map(({ id: t, label: r, value: s }, c) => /*#__PURE__*/ a(o, { children: [/*#__PURE__*/ i(n, { children: r }), /*#__PURE__*/ i(e, { children: /*#__PURE__*/ i("div", {
13
- className: "truncate",
14
- children: s
15
- }) })] }, t ?? `left-${c}`))
16
- }), /*#__PURE__*/ i(r, {
17
- alignTerms: "right",
18
- children: u.map(({ id: t, label: r, value: s }, c) => /*#__PURE__*/ a(o, { children: [/*#__PURE__*/ i(n, { children: r }), /*#__PURE__*/ i(e, { children: /*#__PURE__*/ i("div", {
19
- className: "truncate",
20
- children: s
21
- }) })] }, t ?? `right-${c}`))
22
- })]
23
- });
24
- };
25
- //#endregion
26
- export { s as t };
27
-
28
- //# sourceMappingURL=TwoColumnDescriptionList-DKS42RKa.mjs.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"TwoColumnDescriptionList-DKS42RKa.mjs","names":["Fragment","DescriptionDefinition","DescriptionList","DescriptionTerm","Stack","TwoColumnDescriptionList","items","mid","Math","ceil","length","firstColumn","slice","secondColumn","gap","className","alignTerms","map","id","label","value","index","div"],"sources":["../../src/client/components/TwoColumnDescriptionList.tsx"],"sourcesContent":["import { Fragment, type ReactNode } from \"react\"\nimport { DescriptionDefinition, DescriptionList, DescriptionTerm, Stack } from \"@cloudoperators/juno-ui-components\"\n\nexport type DetailListItem = {\n id?: string\n label: string | ReactNode\n value: string | number | ReactNode | undefined\n}\n\ninterface TwoColumnDescriptionListProps {\n items: DetailListItem[]\n}\n\nexport const TwoColumnDescriptionList = ({ items }: TwoColumnDescriptionListProps) => {\n const mid = Math.ceil(items.length / 2)\n const firstColumn = items.slice(0, mid)\n const secondColumn = items.slice(mid)\n\n return (\n <Stack gap=\"6\" className=\"grid grid-cols-2\">\n <DescriptionList alignTerms=\"right\">\n {firstColumn.map(({ id, label, value }, index) => (\n <Fragment key={id ?? `left-${index}`}>\n <DescriptionTerm>{label}</DescriptionTerm>\n <DescriptionDefinition>\n <div className=\"truncate\">{value}</div>\n </DescriptionDefinition>\n </Fragment>\n ))}\n </DescriptionList>\n\n <DescriptionList alignTerms=\"right\">\n {secondColumn.map(({ id, label, value }, index) => (\n <Fragment key={id ?? `right-${index}`}>\n <DescriptionTerm>{label}</DescriptionTerm>\n <DescriptionDefinition>\n <div className=\"truncate\">{value}</div>\n </DescriptionDefinition>\n </Fragment>\n ))}\n </DescriptionList>\n </Stack>\n )\n}\n"],"mappings":";;;;AAaA,IAAaK,KAA4B,EAAEC,eAAsC;CAC/E,IAAMC,IAAMC,KAAKC,KAAKH,EAAMI,SAAS,CAAA,GAC/BC,IAAcL,EAAMM,MAAM,GAAGL,CAAAA,GAC7BM,IAAeP,EAAMM,MAAML,CAAAA;CAEjC,OACE,gBAACH,GAAAA;EAAMU,KAAI;EAAIC,WAAU;EACvB,UAAA,CAAA,gBAACb,GAAAA;GAAgBc,YAAW;GACzBL,UAAAA,EAAYM,KAAK,EAAEC,OAAIC,UAAOC,YAASC,MACtC,gBAACrB,GAAAA,EAAAA,UAAAA,CACC,gBAACG,GAAAA,EAAiBgB,UAAAA,EAAAA,CAAAA,GAClB,gBAAClB,GAAAA,EACC,UAAA,gBAACqB,OAAAA;IAAIP,WAAU;IAAYK,UAAAA;GAHhBF,CAAAA,EAAAA,CAAAA,CAAAA,EAAAA,GAAAA,KAAM,QAAQG,GAAO,CAAA;EASxC,CAAA,GAAA,gBAACnB,GAAAA;GAAgBc,YAAW;GACzBH,UAAAA,EAAaI,KAAK,EAAEC,OAAIC,UAAOC,YAASC,MACvC,gBAACrB,GAAAA,EAAAA,UAAAA,CACC,gBAACG,GAAAA,EAAiBgB,UAAAA,EAAAA,CAAAA,GAClB,gBAAClB,GAAAA,EACC,UAAA,gBAACqB,OAAAA;IAAIP,WAAU;IAAYK,UAAAA;GAHhBF,CAAAA,EAAAA,CAAAA,CAAAA,EAAAA,GAAAA,KAAM,SAASG,GAAO,CAAA;;;AAU/C"}
@@ -1,6 +0,0 @@
1
- //#region src/client/routes/_auth/projects/$projectId/services/$serviceType/$.tsx?tsr-split=component
2
- var e = () => null;
3
- //#endregion
4
- export { e as component };
5
-
6
- //# sourceMappingURL=_-CAsCx-Ay.mjs.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"_-CAsCx-Ay.mjs","names":["SplitComponent","component"],"sources":["../../src/client/routes/_auth/projects/$projectId/services/$serviceType/$.tsx?tsr-split=component"],"sourcesContent":["import { createFileRoute } from \"@tanstack/react-router\"\n\n// Catch-all so deep links under /services/$serviceType/** match (no 404). The extension mount\n// is rendered by the parent layout route ($serviceType.tsx) so it persists across navigation;\n// the extension's own router handles everything below the base path.\nexport const Route = createFileRoute(\"/_auth/projects/$projectId/services/$serviceType/$\")({\n component: () => null,\n})\n"],"mappings":";AAIA,IAAAA,UAEmB"}
@@ -1,12 +0,0 @@
1
- import { n as e } from "./AuthProvider-CVSAwW9f.mjs";
2
- import { n as t } from "./DynamicBreadcrumbContext-CVcUQFou.mjs";
3
- import { jsx as n } from "react/jsx-runtime";
4
- import { Outlet as r } from "@tanstack/react-router";
5
- //#region src/client/routes/_auth.tsx?tsr-split=component
6
- function i() {
7
- return e(), /*#__PURE__*/ n(t, { children: /*#__PURE__*/ n(r, {}) });
8
- }
9
- //#endregion
10
- export { i as component };
11
-
12
- //# sourceMappingURL=_auth-SrDjHL6j.mjs.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"_auth-SrDjHL6j.mjs","names":["Outlet","useAuth","DynamicBreadcrumbProvider","RouteComponent","component"],"sources":["../../src/client/routes/_auth.tsx?tsr-split=component"],"sourcesContent":["import { createFileRoute, Outlet, redirect } from \"@tanstack/react-router\"\nimport { useAuth } from \"../store/AuthProvider\"\nimport { DynamicBreadcrumbProvider } from \"@/client/context/DynamicBreadcrumbContext\"\nimport type { RouteInfo } from \"@/client/routes/routeInfo\"\nimport { msg } from \"@lingui/core/macro\"\n\nexport const Route = createFileRoute(\"/_auth\")({\n staticData: {\n crumb: { text: msg`Home`, icon: \"home\", to: \"/projects\" },\n } satisfies RouteInfo,\n component: RouteComponent,\n beforeLoad: async ({ context, location }) => {\n if (!context.auth?.isAuthenticated) {\n const redirectPath = `${location.pathname}${location.searchStr || \"\"}${location.hash || \"\"}`\n\n throw redirect({\n to: \"/\",\n search: { redirect: redirectPath },\n })\n }\n },\n})\n\nfunction RouteComponent() {\n useAuth()\n\n return (\n <DynamicBreadcrumbProvider>\n <Outlet />\n </DynamicBreadcrumbProvider>\n )\n}\n"],"mappings":";;;;;AAuBA,SAASG,IAAAA;CAGP,OAFAF,EAAAA,GAGE,gBAAC,GAAA,EACC,UAAA,gBAAC,GAAA,CAAA,CAAA,EAAA,CAAA;AAGP"}
@@ -1,277 +0,0 @@
1
- import { A as e, D as t, E as n, M as r, Q as i, c as a, g as o, i as s, n as c, r as l, rt as u, s as d, x as f } from "./build-WuxXRAqf.mjs";
2
- import { a as p } from "./trpcClient-D7gpR7YG.mjs";
3
- import { t as m } from "./_flavorId-CFUBcU-l.mjs";
4
- import { t as h } from "./useProjectId-DBc5lpoU.mjs";
5
- import { n as g, t as _ } from "./ContentHeader-fKKZVu-o.mjs";
6
- import { t as v } from "./useSetBreadcrumb-tn7lBaQV.mjs";
7
- import { t as y } from "./useErrorTranslation-Dc0eE8Zt.mjs";
8
- import { a as b, n as x, t as S } from "./DeleteFlavorModal-C4nAi7gY.mjs";
9
- import { t as C } from "./useModal-DCs1OJh7.mjs";
10
- import { Fragment as w, jsx as T, jsxs as E } from "react/jsx-runtime";
11
- import { Fragment as D } from "react";
12
- import { useNavigate as O, useParams as ee } from "@tanstack/react-router";
13
- import { Trans as k, useLingui as A } from "@lingui/react";
14
- //#region src/client/routes/_auth/projects/$projectId/compute/flavors/-components/FlavorDetailsView.tsx
15
- function te({ flavor: e, canListSpecs: t = !1 }) {
16
- let { i18n: r, _: a } = A(), o = h(), s = (e, t) => `${e} ${t}`, { data: l, isLoading: f, isError: m } = p.compute.getExtraSpecs.useQuery({
17
- project_id: o,
18
- flavorId: e.id
19
- }, { enabled: !!o && !!e.id && t }), _ = [
20
- {
21
- label: r._({ id: "S0kLOH" }),
22
- value: /*#__PURE__*/ T(g, { text: e.id })
23
- },
24
- {
25
- label: r._({ id: "6YtxFj" }),
26
- value: e.name
27
- },
28
- {
29
- label: r._({ id: "Nu4oKW" }),
30
- value: e?.description ?? ""
31
- },
32
- {
33
- label: r._({ id: "7d1a0d" }),
34
- value: e["os-flavor-access:is_public"] ? /*#__PURE__*/ T(k, { id: "l75CjT" }) : /*#__PURE__*/ T(k, { id: "1UzENP" })
35
- },
36
- {
37
- label: r._({ id: "E/QGRL" }),
38
- value: e["OS-FLV-DISABLED:disabled"] ? /*#__PURE__*/ T(k, { id: "l75CjT" }) : /*#__PURE__*/ T(k, { id: "1UzENP" })
39
- }
40
- ], v = [
41
- {
42
- label: r._({ id: "MZGbkp" }),
43
- value: e.vcpus
44
- },
45
- {
46
- label: r._({ id: "RGhYAo" }),
47
- value: s(e.ram, "MiB")
48
- },
49
- {
50
- label: r._({ id: "cJDQIO" }),
51
- value: s(e.disk, "GiB")
52
- },
53
- {
54
- label: r._({ id: "r9Aac8" }),
55
- value: s(e["OS-FLV-EXT-DATA:ephemeral"] || 0, "GiB")
56
- },
57
- {
58
- label: r._({ id: "vH2C/2" }),
59
- value: e.swap === 0 || e.swap === "" ? /*#__PURE__*/ T(k, { id: "EdQY6l" }) : s(Number(e.swap), "MiB")
60
- },
61
- {
62
- label: r._({ id: "u5HztT" }),
63
- value: e.rxtx_factor ?? ""
64
- }
65
- ], y = l ? Object.entries(l).map(([e, t]) => ({
66
- label: e,
67
- value: t
68
- })) : [];
69
- return /*#__PURE__*/ E(i, {
70
- direction: "vertical",
71
- gap: "6",
72
- className: "mt-6",
73
- children: [/*#__PURE__*/ E(i, {
74
- direction: "horizontal",
75
- gap: "6",
76
- className: "grid grid-cols-2",
77
- children: [/*#__PURE__*/ E(i, {
78
- direction: "vertical",
79
- gap: "2",
80
- children: [/*#__PURE__*/ T("h2", { children: /*#__PURE__*/ T(k, { id: "JlSgnX" }) }), /*#__PURE__*/ T(d, {
81
- alignTerms: "right",
82
- children: _.map(({ label: e, value: t }, r) => /*#__PURE__*/ E(D, { children: [/*#__PURE__*/ T(c, { children: e }), /*#__PURE__*/ T(n, { children: /*#__PURE__*/ T("div", {
83
- className: "truncate",
84
- children: t
85
- }) })] }, `basic-${r}`))
86
- })]
87
- }), /*#__PURE__*/ E(i, {
88
- direction: "vertical",
89
- gap: "2",
90
- children: [/*#__PURE__*/ T("h2", { children: /*#__PURE__*/ T(k, { id: "qQ1QBh" }) }), /*#__PURE__*/ T(d, {
91
- alignTerms: "right",
92
- children: v.map(({ label: e, value: t }, r) => /*#__PURE__*/ E(D, { children: [/*#__PURE__*/ T(c, { children: e }), /*#__PURE__*/ T(n, { children: /*#__PURE__*/ T("div", {
93
- className: "truncate",
94
- children: t
95
- }) })] }, `hardware-${r}`))
96
- })]
97
- })]
98
- }), t && /*#__PURE__*/ E(i, {
99
- direction: "vertical",
100
- gap: "2",
101
- children: [/*#__PURE__*/ T("h2", { children: /*#__PURE__*/ T(k, { id: "6GBt0m" }) }), f ? /*#__PURE__*/ T(u, { status: "progress" }) : m ? /*#__PURE__*/ T(u, {
102
- status: "error",
103
- title: r._({ id: "mXHHga" })
104
- }) : l && Object.keys(l).length > 0 ? /*#__PURE__*/ T(d, {
105
- alignTerms: "right",
106
- className: "grid-cols-2",
107
- children: y.map(({ label: e, value: t }, r) => /*#__PURE__*/ E(D, { children: [/*#__PURE__*/ T(c, {
108
- className: "col-span-1 break-all",
109
- children: e
110
- }), /*#__PURE__*/ T(n, {
111
- className: "col-span-1",
112
- children: /*#__PURE__*/ T("div", {
113
- className: "break-all",
114
- children: t
115
- })
116
- })] }, `extra-${r}`))
117
- }) : /*#__PURE__*/ T(u, {
118
- status: "empty",
119
- title: r._({ id: "qTRcSX" })
120
- })]
121
- })]
122
- });
123
- }
124
- //#endregion
125
- //#region src/client/routes/_auth/projects/$projectId/compute/flavors/$flavorId.tsx?tsr-split=component
126
- function j() {
127
- let { projectId: n, flavorId: c } = ee({ from: "/_auth/projects/$projectId/compute/flavors/$flavorId" }), { trpcClient: d } = m.useRouteContext(), h = O(), { i18n: g, _: D } = A(), { translateError: j, isRetryableError: M } = y(), N = p.useUtils(), { data: P, status: F, error: I, refetch: L } = p.compute.getFlavorById.useQuery({
128
- project_id: n,
129
- flavorId: c
130
- });
131
- v(m.id, P?.name);
132
- let { data: R } = p.compute.canUser.useQuery({
133
- project_id: n,
134
- permission: [
135
- "flavors:delete",
136
- "flavors:add_project",
137
- "flavors:remove_project",
138
- "flavor_specs:list",
139
- "flavor_specs:create",
140
- "flavor_specs:delete"
141
- ]
142
- }), z = R?.[0] ?? !1, B = (R?.[1] ?? !1) || (R?.[2] ?? !1), V = R?.[3] ?? !1, ne = (R?.[4] ?? !1) || (R?.[5] ?? !1), [H, U] = C(), [W, G] = C(), [K, q] = C(), J = () => {
143
- U(), N.compute.getExtraSpecs.invalidate({
144
- project_id: n,
145
- flavorId: c
146
- });
147
- }, Y = () => {
148
- h({
149
- to: "/projects/$projectId/compute/flavors",
150
- params: { projectId: n }
151
- });
152
- }, X = () => {
153
- h({
154
- to: "/projects/$projectId",
155
- params: { projectId: n }
156
- });
157
- }, re = () => {
158
- L();
159
- };
160
- if (F === "pending") return /*#__PURE__*/ T(u, {
161
- status: "progress",
162
- title: g._({ id: "YNgcgc" })
163
- });
164
- if (F === "error") {
165
- let t = I?.message || "UNKNOWN_ERROR", n = j(t), i = M(t);
166
- return /*#__PURE__*/ T(e, {
167
- className: "py-8",
168
- children: /*#__PURE__*/ T(u, {
169
- status: "error",
170
- code: ((e) => {
171
- if (e.includes("UNAUTHORIZED")) return 401;
172
- if (e.includes("FORBIDDEN")) return 403;
173
- if (e.includes("NOT_FOUND")) return 404;
174
- if (e.includes("SERVER_ERROR")) return 500;
175
- })(t),
176
- title: g._({ id: "FjONW3" }),
177
- body: n,
178
- action: /*#__PURE__*/ E(r, { children: [
179
- /*#__PURE__*/ T(s, {
180
- variant: "primary",
181
- onClick: Y,
182
- children: /*#__PURE__*/ T(k, { id: "iH8pgl" })
183
- }),
184
- /*#__PURE__*/ T(s, {
185
- onClick: X,
186
- children: /*#__PURE__*/ T(k, { id: "i0qMbr" })
187
- }),
188
- i && /*#__PURE__*/ T(s, {
189
- onClick: re,
190
- children: /*#__PURE__*/ T(k, { id: "qJb6G2" })
191
- })
192
- ] })
193
- })
194
- });
195
- }
196
- if (!P) return /*#__PURE__*/ T(e, {
197
- className: "py-8",
198
- children: /*#__PURE__*/ T(u, {
199
- status: "error",
200
- code: 404,
201
- title: g._({ id: "bpme7e" }),
202
- body: g._({ id: "y0u86k" }),
203
- action: /*#__PURE__*/ E(r, { children: [/*#__PURE__*/ T(s, {
204
- variant: "primary",
205
- onClick: Y,
206
- children: /*#__PURE__*/ T(k, { id: "iH8pgl" })
207
- }), /*#__PURE__*/ T(s, {
208
- onClick: X,
209
- children: /*#__PURE__*/ T(k, { id: "i0qMbr" })
210
- })] })
211
- })
212
- });
213
- let Z = P["os-flavor-access:is_public"] !== !1, Q = B && !Z || z, $ = ne && V, ie = Q || $ ? /*#__PURE__*/ E(i, {
214
- gap: "0.5",
215
- alignment: "center",
216
- children: [Q && /*#__PURE__*/ E(t, { children: [/*#__PURE__*/ T(a, {
217
- as: "div",
218
- children: /*#__PURE__*/ T(s, {
219
- icon: "moreVert",
220
- title: g._({ id: "PgNNGl" }),
221
- "aria-label": g._({ id: "PgNNGl" })
222
- })
223
- }), /*#__PURE__*/ E(o, { children: [B && !Z && /*#__PURE__*/ T(f, {
224
- label: g._({ id: "cWbW6w" }),
225
- onClick: G
226
- }), z && /*#__PURE__*/ E(w, { children: [/*#__PURE__*/ T(l, {}), /*#__PURE__*/ T(f, {
227
- label: g._({ id: "JT3I1g" }),
228
- onClick: q
229
- })] })] })] }), $ && /*#__PURE__*/ T(s, {
230
- variant: "primary",
231
- onClick: U,
232
- children: /*#__PURE__*/ T(k, { id: "SIfYq6" })
233
- })]
234
- }) : void 0;
235
- return /*#__PURE__*/ E(w, { children: [
236
- /*#__PURE__*/ T(_, {
237
- title: P.name,
238
- projectId: n,
239
- actions: ie
240
- }),
241
- /*#__PURE__*/ T(i, {
242
- direction: "vertical",
243
- children: /*#__PURE__*/ T(te, {
244
- flavor: P,
245
- canListSpecs: V
246
- })
247
- }),
248
- d && /*#__PURE__*/ E(w, { children: [
249
- H && /*#__PURE__*/ T(b, {
250
- client: d,
251
- isOpen: H,
252
- onClose: J,
253
- project: n,
254
- flavor: P
255
- }),
256
- W && /*#__PURE__*/ T(x, {
257
- client: d,
258
- isOpen: W,
259
- onClose: G,
260
- project: n,
261
- flavor: P
262
- }),
263
- K && /*#__PURE__*/ T(S, {
264
- client: d,
265
- isOpen: K,
266
- onClose: q,
267
- project: n,
268
- flavor: P,
269
- onSuccess: Y
270
- })
271
- ] })
272
- ] });
273
- }
274
- //#endregion
275
- export { j as component };
276
-
277
- //# sourceMappingURL=_flavorId-BPvssEzn.mjs.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"_flavorId-BPvssEzn.mjs","names":["Stack","DescriptionList","DescriptionTerm","DescriptionDefinition","Status","Fragment","ClipboardText","trpcReact","useProjectId","FlavorDetailsView","flavor","canListSpecs","useLingui","projectId","formatWithUnit","value","unit","data","extraSpecs","isLoading","isError","compute","getExtraSpecs","useQuery","project_id","flavorId","id","enabled","basicInfoItems","label","t","text","name","description","hardwareSpecItems","vcpus","ram","disk","swap","Number","rxtx_factor","extraSpecItems","Object","entries","map","key","direction","gap","className","h2","alignTerms","index","div","status","title","keys","length","Button","ButtonRow","Stack","PopupMenu","PopupMenuToggle","PopupMenuOptions","PopupMenuItem","PopupMenuSectionSeparator","Container","Status","useNavigate","useParams","Trans","useLingui","trpcReact","useSetBreadcrumb","FlavorDetailsView","useErrorTranslation","EditSpecModal","ManageAccessModal","DeleteFlavorModal","useModal","ContentHeader","Route","RouteComponent","projectId","flavorId","from","trpcClient","useRouteContext","navigate","t","translateError","isRetryableError","utils","useUtils","data","flavor","status","error","refetch","compute","getFlavorById","useQuery","project_id","id","name","permissionsData","canUser","permission","canDeleteFlavor","canManageAccess","canListSpecs","canManageSpecs","specModalOpen","toggleSpecModal","accessModalOpen","toggleAccessModal","deleteModalOpen","toggleDeleteModal","handleSpecModalClose","getExtraSpecs","invalidate","handleBack","to","params","handleHome","handleRetry","errorCode","message","translatedError","canRetry","getStatusCode","code","includes","undefined","isPublicFlavor","hasPopupMenuItems","canEditMetadata","hasMoreActions","headerActions","component"],"sources":["../../src/client/routes/_auth/projects/$projectId/compute/flavors/-components/FlavorDetailsView.tsx","../../src/client/routes/_auth/projects/$projectId/compute/flavors/$flavorId.tsx?tsr-split=component"],"sourcesContent":["import {\n Stack,\n DescriptionList,\n DescriptionTerm,\n DescriptionDefinition,\n Status,\n} from \"@cloudoperators/juno-ui-components/index\"\nimport { Trans, useLingui } from \"@lingui/react/macro\"\nimport { Fragment } from \"react\"\nimport type { Flavor } from \"@/server/Compute/types/flavor\"\nimport ClipboardText from \"@/client/components/ClipboardText\"\nimport { trpcReact } from \"@/client/trpcClient\"\nimport { useProjectId } from \"@/client/hooks/useProjectId\"\n\ninterface FlavorDetailsViewProps {\n flavor: Flavor\n canListSpecs?: boolean\n}\n\nexport function FlavorDetailsView({ flavor, canListSpecs = false }: FlavorDetailsViewProps) {\n const { t } = useLingui()\n const projectId = useProjectId()\n const formatWithUnit = (value: number, unit: string) => `${value} ${unit}`\n\n const {\n data: extraSpecs,\n isLoading,\n isError,\n } = trpcReact.compute.getExtraSpecs.useQuery(\n {\n project_id: projectId,\n flavorId: flavor.id,\n },\n {\n enabled: !!projectId && !!flavor.id && canListSpecs,\n }\n )\n\n const basicInfoItems = [\n { label: t`ID`, value: <ClipboardText text={flavor.id} /> },\n { label: t`Name`, value: flavor.name },\n { label: t`Description`, value: flavor?.description ?? \"\" },\n {\n label: t`Public`,\n value: flavor[\"os-flavor-access:is_public\"] ? <Trans>Yes</Trans> : <Trans>No</Trans>,\n },\n {\n label: t`Disabled`,\n value: flavor[\"OS-FLV-DISABLED:disabled\"] ? <Trans>Yes</Trans> : <Trans>No</Trans>,\n },\n ]\n\n const hardwareSpecItems = [\n { label: t`VCPUs`, value: flavor.vcpus },\n { label: t`RAM`, value: formatWithUnit(flavor.ram, \"MiB\") },\n { label: t`Root Disk`, value: formatWithUnit(flavor.disk, \"GiB\") },\n {\n label: t`Ephemeral Disk`,\n value: formatWithUnit(flavor[\"OS-FLV-EXT-DATA:ephemeral\"] || 0, \"GiB\"),\n },\n {\n label: t`Swap`,\n value: flavor.swap === 0 || flavor.swap === \"\" ? <Trans>None</Trans> : formatWithUnit(Number(flavor.swap), \"MiB\"),\n },\n { label: t`RX/TX Factor`, value: flavor.rxtx_factor ?? \"\" },\n ]\n\n const extraSpecItems = extraSpecs ? Object.entries(extraSpecs).map(([key, value]) => ({ label: key, value })) : []\n\n return (\n <Stack direction=\"vertical\" gap=\"6\" className=\"mt-6\">\n <Stack direction=\"horizontal\" gap=\"6\" className=\"grid grid-cols-2\">\n <Stack direction=\"vertical\" gap=\"2\">\n <h2>\n <Trans>Flavor Information</Trans>\n </h2>\n <DescriptionList alignTerms=\"right\">\n {basicInfoItems.map(({ label, value }, index) => (\n <Fragment key={`basic-${index}`}>\n <DescriptionTerm>{label}</DescriptionTerm>\n <DescriptionDefinition>\n <div className=\"truncate\">{value}</div>\n </DescriptionDefinition>\n </Fragment>\n ))}\n </DescriptionList>\n </Stack>\n\n <Stack direction=\"vertical\" gap=\"2\">\n <h2>\n <Trans>Hardware Specifications</Trans>\n </h2>\n <DescriptionList alignTerms=\"right\">\n {hardwareSpecItems.map(({ label, value }, index) => (\n <Fragment key={`hardware-${index}`}>\n <DescriptionTerm>{label}</DescriptionTerm>\n <DescriptionDefinition>\n <div className=\"truncate\">{value}</div>\n </DescriptionDefinition>\n </Fragment>\n ))}\n </DescriptionList>\n </Stack>\n </Stack>\n\n {canListSpecs && (\n <Stack direction=\"vertical\" gap=\"2\">\n <h2>\n <Trans>Metadata</Trans>\n </h2>\n {isLoading ? (\n <Status status=\"progress\" />\n ) : isError ? (\n <Status status=\"error\" title={t`Failed to Load Metadata`} />\n ) : extraSpecs && Object.keys(extraSpecs).length > 0 ? (\n <DescriptionList alignTerms=\"right\" className=\"grid-cols-2\">\n {extraSpecItems.map(({ label, value }, index) => (\n <Fragment key={`extra-${index}`}>\n <DescriptionTerm className=\"col-span-1 break-all\">{label}</DescriptionTerm>\n <DescriptionDefinition className=\"col-span-1\">\n <div className=\"break-all\">{value}</div>\n </DescriptionDefinition>\n </Fragment>\n ))}\n </DescriptionList>\n ) : (\n <Status status=\"empty\" title={t`No Metadata Properties Found`} />\n )}\n </Stack>\n )}\n </Stack>\n )\n}\n","import {\n Button,\n ButtonRow,\n Stack,\n PopupMenu,\n PopupMenuToggle,\n PopupMenuOptions,\n PopupMenuItem,\n PopupMenuSectionSeparator,\n Container,\n Status,\n} from \"@cloudoperators/juno-ui-components/index\"\nimport { createFileRoute, redirect, useNavigate, useParams } from \"@tanstack/react-router\"\nimport type { RouteInfo } from \"@/client/routes/routeInfo\"\nimport { Trans, useLingui } from \"@lingui/react/macro\"\nimport { getServiceIndex } from \"@/server/Authentication/helpers\"\nimport { trpcReact } from \"@/client/trpcClient\"\nimport { useSetBreadcrumb } from \"@/client/hooks/useSetBreadcrumb\"\nimport { FlavorDetailsView } from \"./-components/FlavorDetailsView\"\nimport { useErrorTranslation } from \"@/client/utils/useErrorTranslation\"\nimport { EditSpecModal } from \"./-components/EditSpecModal\"\nimport { ManageAccessModal } from \"./-components/ManageAccessModal\"\nimport { DeleteFlavorModal } from \"./-components/DeleteFlavorModal\"\nimport { useModal } from \"@/client/utils/useModal\"\nimport { ContentHeader } from \"@/client/components/ContentHeader/ContentHeader\"\nimport { RouteIdLevelDefaultError } from \"@/client/components/Errors/RouteIdLevelDefaultError\"\n\nfunction FlavorErrorComponent() {\n const { t } = useLingui()\n const navigate = useNavigate()\n const { projectId } = Route.useParams()\n\n return (\n <RouteIdLevelDefaultError\n action={\n <Button\n variant=\"primary\"\n onClick={() => navigate({ to: \"/projects/$projectId/compute/flavors\", params: { projectId } })}\n >\n {t`Back to Flavors`}\n </Button>\n }\n />\n )\n}\n\nexport const Route = createFileRoute(\"/_auth/projects/$projectId/compute/flavors/$flavorId\")({\n staticData: {\n section: \"compute\",\n service: \"flavors\",\n analytics: {\n name: \"compute.flavors.detail\",\n },\n } satisfies RouteInfo,\n loader: async ({ context, params }) => {\n const flavor = await context.trpcClient?.compute.getFlavorById.query({\n project_id: params.projectId,\n flavorId: params.flavorId,\n })\n return { flavorName: flavor?.name ?? null }\n },\n head: ({ loaderData }) => ({\n meta: [{ title: loaderData?.flavorName ?? \"Flavor Details\" }],\n }),\n component: RouteComponent,\n beforeLoad: async ({ context, params }) => {\n const { trpcClient } = context\n const { projectId } = params\n\n const availableServices = (await trpcClient?.auth.getAvailableServices.query()) || []\n\n const serviceIndex = getServiceIndex(availableServices)\n\n if (!serviceIndex[\"flavor\"] && !serviceIndex[\"compute\"]) {\n throw redirect({\n to: \"/projects/$projectId\",\n params: { projectId },\n })\n }\n },\n errorComponent: FlavorErrorComponent,\n})\n\nfunction RouteComponent() {\n const { projectId, flavorId } = useParams({\n from: \"/_auth/projects/$projectId/compute/flavors/$flavorId\",\n })\n const { trpcClient } = Route.useRouteContext()\n const navigate = useNavigate()\n const { t } = useLingui()\n const { translateError, isRetryableError } = useErrorTranslation()\n const utils = trpcReact.useUtils()\n\n const {\n data: flavor,\n status,\n error,\n refetch,\n } = trpcReact.compute.getFlavorById.useQuery({\n project_id: projectId,\n flavorId,\n })\n\n useSetBreadcrumb(Route.id, flavor?.name)\n\n const { data: permissionsData } = trpcReact.compute.canUser.useQuery({\n project_id: projectId,\n permission: [\n \"flavors:delete\",\n \"flavors:add_project\",\n \"flavors:remove_project\",\n \"flavor_specs:list\",\n \"flavor_specs:create\",\n \"flavor_specs:delete\",\n ],\n })\n\n const canDeleteFlavor = permissionsData?.[0] ?? false\n const canManageAccess = (permissionsData?.[1] ?? false) || (permissionsData?.[2] ?? false)\n const canListSpecs = permissionsData?.[3] ?? false\n const canManageSpecs = (permissionsData?.[4] ?? false) || (permissionsData?.[5] ?? false)\n\n const [specModalOpen, toggleSpecModal] = useModal()\n const [accessModalOpen, toggleAccessModal] = useModal()\n const [deleteModalOpen, toggleDeleteModal] = useModal()\n\n const handleSpecModalClose = () => {\n toggleSpecModal()\n utils.compute.getExtraSpecs.invalidate({ project_id: projectId, flavorId })\n }\n\n const handleBack = () => {\n navigate({\n to: \"/projects/$projectId/compute/flavors\",\n params: { projectId },\n })\n }\n\n const handleHome = () => {\n navigate({\n to: \"/projects/$projectId\",\n params: { projectId },\n })\n }\n\n const handleRetry = () => {\n refetch()\n }\n\n if (status === \"pending\") {\n return <Status status=\"progress\" title={t`Loading Flavor Details...`} />\n }\n\n if (status === \"error\") {\n const errorCode = error?.message || \"UNKNOWN_ERROR\"\n const translatedError = translateError(errorCode)\n const canRetry = isRetryableError(errorCode)\n\n const getStatusCode = (code: string): number | undefined => {\n if (code.includes(\"UNAUTHORIZED\")) return 401\n if (code.includes(\"FORBIDDEN\")) return 403\n if (code.includes(\"NOT_FOUND\")) return 404\n if (code.includes(\"SERVER_ERROR\")) return 500\n return undefined\n }\n\n return (\n <Container className=\"py-8\">\n <Status\n status=\"error\"\n code={getStatusCode(errorCode)}\n title={t`Error Loading Flavor`}\n body={translatedError}\n action={\n <ButtonRow>\n <Button variant=\"primary\" onClick={handleBack}>\n <Trans>Back</Trans>\n </Button>\n <Button onClick={handleHome}>\n <Trans>Home</Trans>\n </Button>\n {canRetry && (\n <Button onClick={handleRetry}>\n <Trans>Try Again</Trans>\n </Button>\n )}\n </ButtonRow>\n }\n />\n </Container>\n )\n }\n\n if (!flavor) {\n return (\n <Container className=\"py-8\">\n <Status\n status=\"error\"\n code={404}\n title={t`Flavor Not Found`}\n body={t`The requested flavor could not be found. It may have been deleted or you may not have access to it.`}\n action={\n <ButtonRow>\n <Button variant=\"primary\" onClick={handleBack}>\n <Trans>Back</Trans>\n </Button>\n <Button onClick={handleHome}>\n <Trans>Home</Trans>\n </Button>\n </ButtonRow>\n }\n />\n </Container>\n )\n }\n\n const isPublicFlavor = flavor[\"os-flavor-access:is_public\"] !== false\n const hasPopupMenuItems = (canManageAccess && !isPublicFlavor) || canDeleteFlavor\n const canEditMetadata = canManageSpecs && canListSpecs\n const hasMoreActions = hasPopupMenuItems || canEditMetadata\n\n const headerActions = hasMoreActions ? (\n <Stack gap=\"0.5\" alignment=\"center\">\n {hasPopupMenuItems && (\n <PopupMenu>\n <PopupMenuToggle as=\"div\">\n <Button icon=\"moreVert\" title={t`More Actions`} aria-label={t`More Actions`} />\n </PopupMenuToggle>\n <PopupMenuOptions>\n {canManageAccess && !isPublicFlavor && (\n <PopupMenuItem label={t`Manage Access`} onClick={toggleAccessModal} />\n )}\n {canDeleteFlavor && (\n <>\n <PopupMenuSectionSeparator />\n <PopupMenuItem label={t`Delete Flavor`} onClick={toggleDeleteModal} />\n </>\n )}\n </PopupMenuOptions>\n </PopupMenu>\n )}\n {canEditMetadata && (\n <Button variant=\"primary\" onClick={toggleSpecModal}>\n <Trans>Edit Metadata</Trans>\n </Button>\n )}\n </Stack>\n ) : undefined\n\n return (\n <>\n <ContentHeader title={flavor.name} projectId={projectId} actions={headerActions} />\n <Stack direction=\"vertical\">\n <FlavorDetailsView flavor={flavor} canListSpecs={canListSpecs} />\n </Stack>\n\n {trpcClient && (\n <>\n {specModalOpen && (\n <EditSpecModal\n client={trpcClient}\n isOpen={specModalOpen}\n onClose={handleSpecModalClose}\n project={projectId}\n flavor={flavor}\n />\n )}\n\n {accessModalOpen && (\n <ManageAccessModal\n client={trpcClient}\n isOpen={accessModalOpen}\n onClose={toggleAccessModal}\n project={projectId}\n flavor={flavor}\n />\n )}\n\n {deleteModalOpen && (\n <DeleteFlavorModal\n client={trpcClient}\n isOpen={deleteModalOpen}\n onClose={toggleDeleteModal}\n project={projectId}\n flavor={flavor}\n onSuccess={handleBack}\n />\n )}\n </>\n )}\n </>\n )\n}\n"],"mappings":";;;;;;;;;;;;;;AAmBA,SAAgBS,GAAkB,EAAEC,WAAQC,kBAAe,MAA+B;CACxF,IAAM,EAAA,MAAA,GAAA,GAAA,MAAQC,EAAAA,GACRC,IAAYL,EAAAA,GACZM,KAAkBC,GAAeC,MAAiB,GAAGD,EAAM,GAAGC,KAE9D,EACJC,MAAMC,GACNC,cACAC,eACEb,EAAUc,QAAQC,cAAcC,SAClC;EACEC,YAAYX;EACZY,UAAUf,EAAOgB;CACnB,GACA,EACEC,SAAS,CAAC,CAACd,KAAa,CAAC,CAACH,EAAOgB,MAAMf,EACzC,CAAA,GAGIiB,IAAiB;EACrB;GAAEC,OAAOC,EAAAA,EAAC,EAAA,IAAA,SAAG,CAAA;GAAGf,OAAO,gBAACT,GAAAA,EAAcyB,MAAMrB,EAAOgB,GAAAA,CAAAA;EAAO;EAC1D;GAAEG,OAAOC,EAAAA,EAAC,EAAA,IAAA,SAAK,CAAA;GAAGf,OAAOL,EAAOsB;EAAK;EACrC;GAAEH,OAAOC,EAAAA,EAAC,EAAA,IAAA,SAAY,CAAA;GAAGf,OAAOL,GAAQuB,eAAe;EAAG;EAC1D;GACEJ,OAAOC,EAAAA,EAAC,EAAA,IAAA,SAAO,CAAA;GACff,OAAOL,EAAO,gCAAgC,gBAAA,GAAA,EAAA,IAAA,SAAqB,CAAA,IAAA,gBAAA,GAAA,EAAA,IAAA,SAAA,CAAA;EACrE;EACA;GACEmB,OAAOC,EAAAA,EAAC,EAAA,IAAA,SAAS,CAAA;GACjBf,OAAOL,EAAO,8BAA8B,gBAAA,GAAA,EAAA,IAAA,SAAqB,CAAA,IAAA,gBAAA,GAAA,EAAA,IAAA,SAAA,CAAA;EACnE;CACD,GAEKwB,IAAoB;EACxB;GAAEL,OAAOC,EAAAA,EAAC,EAAA,IAAA,SAAM,CAAA;GAAGf,OAAOL,EAAOyB;EAAM;EACvC;GAAEN,OAAOC,EAAAA,EAAC,EAAA,IAAA,SAAI,CAAA;GAAGf,OAAOD,EAAeJ,EAAO0B,KAAK,KAAA;EAAO;EAC1D;GAAEP,OAAOC,EAAAA,EAAC,EAAA,IAAA,SAAU,CAAA;GAAGf,OAAOD,EAAeJ,EAAO2B,MAAM,KAAA;EAAO;EACjE;GACER,OAAOC,EAAAA,EAAC,EAAA,IAAA,SAAe,CAAA;GACvBf,OAAOD,EAAeJ,EAAO,gCAAgC,GAAG,KAAA;EAClE;EACA;GACEmB,OAAOC,EAAAA,EAAC,EAAA,IAAA,SAAK,CAAA;GACbf,OAAOL,EAAO4B,SAAS,KAAK5B,EAAO4B,SAAS,KAAK,gBAAA,GAAA,EAAA,IAAA,SAAsBxB,CAAAA,IAAAA,EAAeyB,OAAO7B,EAAO4B,IAAI,GAAG,KAAA;EAC7G;EACA;GAAET,OAAOC,EAAAA,EAAC,EAAA,IAAA,SAAa,CAAA;GAAGf,OAAOL,EAAO8B,eAAe;EAAG;CAC3D,GAEKC,IAAiBvB,IAAawB,OAAOC,QAAQzB,CAAAA,CAAAA,CAAY0B,KAAK,CAACC,GAAK9B,QAAY;EAAEc,OAAOgB;EAAK9B;CAAM,EAAA,IAAM,CAAA;CAEhH,OACE,gBAACf,GAAAA;EAAM8C,WAAU;EAAWC,KAAI;EAAIC,WAAU;EAC5C,UAAA,CAAA,gBAAChD,GAAAA;GAAM8C,WAAU;GAAaC,KAAI;GAAIC,WAAU;GAC9C,UAAA,CAAA,gBAAChD,GAAAA;IAAM8C,WAAU;IAAWC,KAAI;IAC9B,UAAA,CAAA,gBAACE,MAAAA,EACC,UAAA,gBAAA,GAAA,EAAA,IAAA,SAAA,CAAA,EAAA,CAAA,GAEF,gBAAChD,GAAAA;KAAgBiD,YAAW;KACzBtB,UAAAA,EAAegB,KAAK,EAAEf,UAAOd,YAASoC,MACrC,gBAAC9C,GAAAA,EAAAA,UAAAA,CACC,gBAACH,GAAAA,EAAiB2B,UAAAA,EAAAA,CAAAA,GAClB,gBAAC1B,GAAAA,EACC,UAAA,gBAACiD,OAAAA;MAAIJ,WAAU;MAAYjC,UAAAA;KAHhB,CAAA,EAAA,CAAA,CAAA,EAAA,GAAA,SAASoC,GAAO,CAAA;;GAUrC,CAAA,GAAA,gBAACnD,GAAAA;IAAM8C,WAAU;IAAWC,KAAI;IAC9B,UAAA,CAAA,gBAACE,MAAAA,EACC,UAAA,gBAAA,GAAA,EAAA,IAAA,SAAA,CAAA,EAAA,CAAA,GAEF,gBAAChD,GAAAA;KAAgBiD,YAAW;KACzBhB,UAAAA,EAAkBU,KAAK,EAAEf,UAAOd,YAASoC,MACxC,gBAAC9C,GAAAA,EAAAA,UAAAA,CACC,gBAACH,GAAAA,EAAiB2B,UAAAA,EAAAA,CAAAA,GAClB,gBAAC1B,GAAAA,EACC,UAAA,gBAACiD,OAAAA;MAAIJ,WAAU;MAAYjC,UAAAA;KAHhB,CAAA,EAAA,CAAA,CAAA,EAAA,GAAA,YAAYoC,GAAO,CAAA;;;EAWzCxC,CAAAA,GAAAA,KACC,gBAACX,GAAAA;GAAM8C,WAAU;GAAWC,KAAI;GAC9B,UAAA,CAAA,gBAACE,MAAAA,EACC,UAAA,gBAAA,GAAA,EAAA,IAAA,SAAA,CAAA,EAAA,CAAA,GAED9B,IACC,gBAACf,GAAAA,EAAOiD,QAAO,WACbjC,CAAAA,IAAAA,IACF,gBAAChB,GAAAA;IAAOiD,QAAO;IAAQC,OAAOxB,EAAAA,EAAC,EAAA,IAAA,SAAwB,CAAA;GACrDZ,CAAAA,IAAAA,KAAcwB,OAAOa,KAAKrC,CAAAA,CAAAA,CAAYsC,SAAS,IACjD,gBAACvD,GAAAA;IAAgBiD,YAAW;IAAQF,WAAU;IAC3CP,UAAAA,EAAeG,KAAK,EAAEf,UAAOd,YAASoC,MACrC,gBAAC9C,GAAAA,EAAAA,UAAAA,CACC,gBAACH,GAAAA;KAAgB8C,WAAU;KAAwBnB,UAAAA;IACnD,CAAA,GAAA,gBAAC1B,GAAAA;KAAsB6C,WAAU;KAC/B,UAAA,gBAACI,OAAAA;MAAIJ,WAAU;MAAajC,UAAAA;;IAHjB,CAAA,CAAA,EAAA,GAAA,SAASoC,GAAO,CAAA;GASnC,CAAA,IAAA,gBAAC/C,GAAAA;IAAOiD,QAAO;IAAQC,OAAOxB,EAAAA,EAAC,EAAA,IAAA,SAA6B,CAAA;;;;AAMxE;;;ACjDA,SAASmD,IAAAA;CACP,IAAM,EAAEC,cAAWC,gBAAaf,GAAU,EACxCgB,MAAM,uDACR,CAAA,GACM,EAAEC,kBAAeL,EAAMM,gBAAe,GACtCC,IAAWpB,EAAAA,GACX,EAAA,MAAA,GAAA,GAAA,MAAQG,EAAAA,GACR,EAAEmB,mBAAgBC,wBAAqBhB,EAAAA,GACvCiB,IAAQpB,EAAUqB,SAAQ,GAE1B,EACJC,MAAMC,GACNC,WACAC,UACAC,eACE1B,EAAU2B,QAAQC,cAAcC,SAAS;EAC3CC,YAAYnB;EACZC;CACF,CAAA;CAEAX,EAAiBQ,EAAMsB,IAAIR,GAAQS,IAAAA;CAEnC,IAAM,EAAEV,MAAMW,MAAoBjC,EAAU2B,QAAQO,QAAQL,SAAS;EACnEC,YAAYnB;EACZwB,YAAY;GACV;GACA;GACA;GACA;GACA;GACA;EAAqB;CAEzB,CAAA,GAEMC,IAAkBH,IAAkB,MAAM,IAC1CI,KAAmBJ,IAAkB,MAAM,QAAWA,IAAkB,MAAM,KAC9EK,IAAeL,IAAkB,MAAM,IACvCM,MAAkBN,IAAkB,MAAM,QAAWA,IAAkB,MAAM,KAE7E,CAACO,GAAeC,KAAmBlC,EAAAA,GACnC,CAACmC,GAAiBC,KAAqBpC,EAAAA,GACvC,CAACqC,GAAiBC,KAAqBtC,EAAAA,GAEvCuC,UAAuBA;EAE3B1B,AADAqB,EAAAA,GACArB,EAAMO,QAAQoB,cAAcC,WAAW;GAAElB,YAAYnB;GAAWC;EAAS,CAAA;CAC3E,GAEMqC,UAAaA;EACjBjC,EAAS;GACPkC,IAAI;GACJC,QAAQ,EAAExC,aAAU;EACtB,CAAA;CACF,GAEMyC,UAAaA;EACjBpC,EAAS;GACPkC,IAAI;GACJC,QAAQ,EAAExC,aAAU;EACtB,CAAA;CACF,GAEM0C,WAAcA;EAClB3B,EAAAA;CACF;CAEA,IAAIF,MAAW,WACb,OAAO,gBAAC,GAAA;EAAO,QAAO;EAAW,OAAOP,EAAAA,EAAC,EAAA,IAAA,SAAA,CAAA;;CAG3C,IAAIO,MAAW,SAAS;EACtB,IAAM8B,IAAY7B,GAAO8B,WAAW,iBAC9BC,IAAkBtC,EAAeoC,CAAAA,GACjCG,IAAWtC,EAAiBmC,CAAAA;EAUlC,OACE,gBAAC,GAAA;GAAU,WAAU;GACnB,UAAA,gBAAC,GAAA;IACC,QAAO;IACP,QAZiBK,MAAAA;KACrB,IAAIA,EAAKC,SAAS,cAAA,GAAiB,OAAO;KAC1C,IAAID,EAAKC,SAAS,WAAA,GAAc,OAAO;KACvC,IAAID,EAAKC,SAAS,WAAA,GAAc,OAAO;KACvC,IAAID,EAAKC,SAAS,cAAA,GAAiB,OAAO;IAE5C,EAMYF,CAAcJ,CAAAA;IACpB,OAAOrC,EAAAA,EAAC,EAAA,IAAA,SAAA,CAAA;IACR,MAAMuC;IACN,QACE,gBAAC,GAAA,EAAA,UAAA;KACC,gBAAC,GAAA;MAAO,SAAQ;MAAU,SAASP;MACjC,UAAA,gBAAA,GAAA,EAAA,IAAA,SAAA,CAAA;;KAEF,gBAAC,GAAA;MAAO,SAASG;MACf,UAAA,gBAAA,GAAA,EAAA,IAAA,SAAA,CAAA;;KAEDK,KACC,gBAAC,GAAA;MAAO,SAASJ;MACf,UAAA,gBAAA,GAAA,EAAA,IAAA,SAAA,CAAA;;;;;CAQhB;CAEA,IAAI,CAAC9B,GACH,OACE,gBAAC,GAAA;EAAU,WAAU;EACnB,UAAA,gBAAC,GAAA;GACC,QAAO;GACP,MAAM;GACN,OAAON,EAAAA,EAAC,EAAA,IAAA,SAAA,CAAA;GACR,MAAMA,EAAAA,EAAC,EAAA,IAAA,SAAA,CAAA;GACP,QACE,gBAAC,GAAA,EAAA,UAAA,CACC,gBAAC,GAAA;IAAO,SAAQ;IAAU,SAASgC;IACjC,UAAA,gBAAA,GAAA,EAAA,IAAA,SAAA,CAAA;GAEF,CAAA,GAAA,gBAAC,GAAA;IAAO,SAASG;IACf,UAAA,gBAAA,GAAA,EAAA,IAAA,SAAA,CAAA;;;;CASd,IAAMU,IAAiBvC,EAAO,kCAAkC,IAC1DwC,IAAqB1B,KAAmB,CAACyB,KAAmB1B,GAC5D4B,IAAkBzB,MAAkBD,GAGpC4B,KAFiBH,KAAqBC,IAG1C,gBAAC,GAAA;EAAM,KAAI;EAAM,WAAU;EACxBD,UAAAA,CAAAA,KACC,gBAAC,GAAA,EAAA,UAAA,CACC,gBAAC,GAAA;GAAgB,IAAG;GAClB,UAAA,gBAAC,GAAA;IAAO,MAAK;IAAW,OAAO9C,EAAAA,EAAC,EAAA,IAAA,SAAA,CAAA;IAAgB,cAAYA,EAAAA,EAAC,EAAA,IAAA,SAAA,CAAA;;EAE/D,CAAA,GAAA,gBAAC,GAAA,EAAA,UAAA,CACEoB,KAAmB,CAACyB,KACnB,gBAAC,GAAA;GAAc,OAAO7C,EAAAA,EAAC,EAAA,IAAA,SAAA,CAAA;GAAiB,SAAS0B;EAElDP,CAAAA,GAAAA,KACC,gBAAA,GAAA,EAAA,UAAA,CACE,gBAAC,GAAA,CAAA,CAAA,GACD,gBAAC,GAAA;GAAc,OAAOnB,EAAAA,EAAC,EAAA,IAAA,SAAA,CAAA;GAAiB,SAAS4B;EAM1DmB,CAAAA,CAAAA,EAAAA,CAAAA,CAAAA,EAAAA,CAAAA,CAAAA,EAAAA,CAAAA,GAAAA,KACC,gBAAC,GAAA;GAAO,SAAQ;GAAU,SAASvB;GACjC,UAAA,gBAAA,GAAA,EAAA,IAAA,SAAA,CAAA;;CAIJoB,CAAAA,IAAAA,KAAAA;CAEJ,OACE,gBAAA,GAAA,EAAA,UAAA;EACE,gBAAC,GAAA;GAAc,OAAOtC,EAAOS;GAAiBrB;GAAW,SAASuD;;EAClE,gBAAC,GAAA;GAAM,WAAU;GACf,UAAA,gBAAC,IAAA;IAA0B3C;IAAsBe;;;EAGlDxB,KACC,gBAAA,GAAA,EAAA,UAAA;GACG0B,KACC,gBAAC,GAAA;IACC,QAAQ1B;IACR,QAAQ0B;IACR,SAASM;IACT,SAASnC;IACDY;;GAIXmB,KACC,gBAAC,GAAA;IACC,QAAQ5B;IACR,QAAQ4B;IACR,SAASC;IACT,SAAShC;IACDY;;GAIXqB,KACC,gBAAC,GAAA;IACC,QAAQ9B;IACR,QAAQ8B;IACR,SAASC;IACT,SAASlC;IACDY;IACR,WAAW0B;;;;AAOzB"}
@@ -1,27 +0,0 @@
1
- import { t as e } from "./helpers-1PpYf-fC.mjs";
2
- import { createFileRoute as t, lazyRouteComponent as n, redirect as r } from "@tanstack/react-router";
3
- var i = t("/_auth/projects/$projectId/compute/flavors/$flavorId")({
4
- staticData: {
5
- section: "compute",
6
- service: "flavors",
7
- analytics: { name: "compute.flavors.detail" }
8
- },
9
- loader: async ({ context: e, params: t }) => ({ flavorName: (await e.trpcClient?.compute.getFlavorById.query({
10
- project_id: t.projectId,
11
- flavorId: t.flavorId
12
- }))?.name ?? null }),
13
- head: ({ loaderData: e }) => ({ meta: [{ title: e?.flavorName ?? "Flavor Details" }] }),
14
- component: n(() => import("./_flavorId-BPvssEzn.mjs"), "component"),
15
- beforeLoad: async ({ context: t, params: n }) => {
16
- let { trpcClient: i } = t, { projectId: a } = n, o = await i?.auth.getAvailableServices.query() || [], s = e(o);
17
- if (!s.flavor && !s.compute) throw r({
18
- to: "/projects/$projectId",
19
- params: { projectId: a }
20
- });
21
- },
22
- errorComponent: n(() => import("./_flavorId-CZcIp0Ih.mjs"), "errorComponent")
23
- });
24
- //#endregion
25
- export { i as t };
26
-
27
- //# sourceMappingURL=_flavorId-CFUBcU-l.mjs.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"_flavorId-CFUBcU-l.mjs","names":["createFileRoute","redirect","getServiceIndex","Route","staticData","section","service","analytics","name","RouteInfo","loader","context","params","flavor","trpcClient","compute","getFlavorById","query","project_id","projectId","flavorId","flavorName","head","loaderData","meta","title","component","lazyRouteComponent","$$splitComponentImporter","beforeLoad","availableServices","auth","getAvailableServices","serviceIndex","to","errorComponent","$$splitErrorComponentImporter"],"sources":["../../src/client/routes/_auth/projects/$projectId/compute/flavors/$flavorId.tsx"],"sourcesContent":["import {\n Button,\n ButtonRow,\n Stack,\n PopupMenu,\n PopupMenuToggle,\n PopupMenuOptions,\n PopupMenuItem,\n PopupMenuSectionSeparator,\n Container,\n Status,\n} from \"@cloudoperators/juno-ui-components/index\"\nimport { createFileRoute, redirect, useNavigate, useParams } from \"@tanstack/react-router\"\nimport type { RouteInfo } from \"@/client/routes/routeInfo\"\nimport { Trans, useLingui } from \"@lingui/react/macro\"\nimport { getServiceIndex } from \"@/server/Authentication/helpers\"\nimport { trpcReact } from \"@/client/trpcClient\"\nimport { useSetBreadcrumb } from \"@/client/hooks/useSetBreadcrumb\"\nimport { FlavorDetailsView } from \"./-components/FlavorDetailsView\"\nimport { useErrorTranslation } from \"@/client/utils/useErrorTranslation\"\nimport { EditSpecModal } from \"./-components/EditSpecModal\"\nimport { ManageAccessModal } from \"./-components/ManageAccessModal\"\nimport { DeleteFlavorModal } from \"./-components/DeleteFlavorModal\"\nimport { useModal } from \"@/client/utils/useModal\"\nimport { ContentHeader } from \"@/client/components/ContentHeader/ContentHeader\"\nimport { RouteIdLevelDefaultError } from \"@/client/components/Errors/RouteIdLevelDefaultError\"\n\nfunction FlavorErrorComponent() {\n const { t } = useLingui()\n const navigate = useNavigate()\n const { projectId } = Route.useParams()\n\n return (\n <RouteIdLevelDefaultError\n action={\n <Button\n variant=\"primary\"\n onClick={() => navigate({ to: \"/projects/$projectId/compute/flavors\", params: { projectId } })}\n >\n {t`Back to Flavors`}\n </Button>\n }\n />\n )\n}\n\nexport const Route = createFileRoute(\"/_auth/projects/$projectId/compute/flavors/$flavorId\")({\n staticData: {\n section: \"compute\",\n service: \"flavors\",\n analytics: {\n name: \"compute.flavors.detail\",\n },\n } satisfies RouteInfo,\n loader: async ({ context, params }) => {\n const flavor = await context.trpcClient?.compute.getFlavorById.query({\n project_id: params.projectId,\n flavorId: params.flavorId,\n })\n return { flavorName: flavor?.name ?? null }\n },\n head: ({ loaderData }) => ({\n meta: [{ title: loaderData?.flavorName ?? \"Flavor Details\" }],\n }),\n component: RouteComponent,\n beforeLoad: async ({ context, params }) => {\n const { trpcClient } = context\n const { projectId } = params\n\n const availableServices = (await trpcClient?.auth.getAvailableServices.query()) || []\n\n const serviceIndex = getServiceIndex(availableServices)\n\n if (!serviceIndex[\"flavor\"] && !serviceIndex[\"compute\"]) {\n throw redirect({\n to: \"/projects/$projectId\",\n params: { projectId },\n })\n }\n },\n errorComponent: FlavorErrorComponent,\n})\n\nfunction RouteComponent() {\n const { projectId, flavorId } = useParams({\n from: \"/_auth/projects/$projectId/compute/flavors/$flavorId\",\n })\n const { trpcClient } = Route.useRouteContext()\n const navigate = useNavigate()\n const { t } = useLingui()\n const { translateError, isRetryableError } = useErrorTranslation()\n const utils = trpcReact.useUtils()\n\n const {\n data: flavor,\n status,\n error,\n refetch,\n } = trpcReact.compute.getFlavorById.useQuery({\n project_id: projectId,\n flavorId,\n })\n\n useSetBreadcrumb(Route.id, flavor?.name)\n\n const { data: permissionsData } = trpcReact.compute.canUser.useQuery({\n project_id: projectId,\n permission: [\n \"flavors:delete\",\n \"flavors:add_project\",\n \"flavors:remove_project\",\n \"flavor_specs:list\",\n \"flavor_specs:create\",\n \"flavor_specs:delete\",\n ],\n })\n\n const canDeleteFlavor = permissionsData?.[0] ?? false\n const canManageAccess = (permissionsData?.[1] ?? false) || (permissionsData?.[2] ?? false)\n const canListSpecs = permissionsData?.[3] ?? false\n const canManageSpecs = (permissionsData?.[4] ?? false) || (permissionsData?.[5] ?? false)\n\n const [specModalOpen, toggleSpecModal] = useModal()\n const [accessModalOpen, toggleAccessModal] = useModal()\n const [deleteModalOpen, toggleDeleteModal] = useModal()\n\n const handleSpecModalClose = () => {\n toggleSpecModal()\n utils.compute.getExtraSpecs.invalidate({ project_id: projectId, flavorId })\n }\n\n const handleBack = () => {\n navigate({\n to: \"/projects/$projectId/compute/flavors\",\n params: { projectId },\n })\n }\n\n const handleHome = () => {\n navigate({\n to: \"/projects/$projectId\",\n params: { projectId },\n })\n }\n\n const handleRetry = () => {\n refetch()\n }\n\n if (status === \"pending\") {\n return <Status status=\"progress\" title={t`Loading Flavor Details...`} />\n }\n\n if (status === \"error\") {\n const errorCode = error?.message || \"UNKNOWN_ERROR\"\n const translatedError = translateError(errorCode)\n const canRetry = isRetryableError(errorCode)\n\n const getStatusCode = (code: string): number | undefined => {\n if (code.includes(\"UNAUTHORIZED\")) return 401\n if (code.includes(\"FORBIDDEN\")) return 403\n if (code.includes(\"NOT_FOUND\")) return 404\n if (code.includes(\"SERVER_ERROR\")) return 500\n return undefined\n }\n\n return (\n <Container className=\"py-8\">\n <Status\n status=\"error\"\n code={getStatusCode(errorCode)}\n title={t`Error Loading Flavor`}\n body={translatedError}\n action={\n <ButtonRow>\n <Button variant=\"primary\" onClick={handleBack}>\n <Trans>Back</Trans>\n </Button>\n <Button onClick={handleHome}>\n <Trans>Home</Trans>\n </Button>\n {canRetry && (\n <Button onClick={handleRetry}>\n <Trans>Try Again</Trans>\n </Button>\n )}\n </ButtonRow>\n }\n />\n </Container>\n )\n }\n\n if (!flavor) {\n return (\n <Container className=\"py-8\">\n <Status\n status=\"error\"\n code={404}\n title={t`Flavor Not Found`}\n body={t`The requested flavor could not be found. It may have been deleted or you may not have access to it.`}\n action={\n <ButtonRow>\n <Button variant=\"primary\" onClick={handleBack}>\n <Trans>Back</Trans>\n </Button>\n <Button onClick={handleHome}>\n <Trans>Home</Trans>\n </Button>\n </ButtonRow>\n }\n />\n </Container>\n )\n }\n\n const isPublicFlavor = flavor[\"os-flavor-access:is_public\"] !== false\n const hasPopupMenuItems = (canManageAccess && !isPublicFlavor) || canDeleteFlavor\n const canEditMetadata = canManageSpecs && canListSpecs\n const hasMoreActions = hasPopupMenuItems || canEditMetadata\n\n const headerActions = hasMoreActions ? (\n <Stack gap=\"0.5\" alignment=\"center\">\n {hasPopupMenuItems && (\n <PopupMenu>\n <PopupMenuToggle as=\"div\">\n <Button icon=\"moreVert\" title={t`More Actions`} aria-label={t`More Actions`} />\n </PopupMenuToggle>\n <PopupMenuOptions>\n {canManageAccess && !isPublicFlavor && (\n <PopupMenuItem label={t`Manage Access`} onClick={toggleAccessModal} />\n )}\n {canDeleteFlavor && (\n <>\n <PopupMenuSectionSeparator />\n <PopupMenuItem label={t`Delete Flavor`} onClick={toggleDeleteModal} />\n </>\n )}\n </PopupMenuOptions>\n </PopupMenu>\n )}\n {canEditMetadata && (\n <Button variant=\"primary\" onClick={toggleSpecModal}>\n <Trans>Edit Metadata</Trans>\n </Button>\n )}\n </Stack>\n ) : undefined\n\n return (\n <>\n <ContentHeader title={flavor.name} projectId={projectId} actions={headerActions} />\n <Stack direction=\"vertical\">\n <FlavorDetailsView flavor={flavor} canListSpecs={canListSpecs} />\n </Stack>\n\n {trpcClient && (\n <>\n {specModalOpen && (\n <EditSpecModal\n client={trpcClient}\n isOpen={specModalOpen}\n onClose={handleSpecModalClose}\n project={projectId}\n flavor={flavor}\n />\n )}\n\n {accessModalOpen && (\n <ManageAccessModal\n client={trpcClient}\n isOpen={accessModalOpen}\n onClose={toggleAccessModal}\n project={projectId}\n flavor={flavor}\n />\n )}\n\n {deleteModalOpen && (\n <DeleteFlavorModal\n client={trpcClient}\n isOpen={deleteModalOpen}\n onClose={toggleDeleteModal}\n project={projectId}\n flavor={flavor}\n onSuccess={handleBack}\n />\n )}\n </>\n )}\n </>\n )\n}\n"],"mappings":";;AA8CA,IAAaG,IAAQH,EAAgB,sDAAA,CAAA,CAAwD;CAC3FI,YAAY;EACVC,SAAS;EACTC,SAAS;EACTC,WAAW,EACTC,MAAM,yBACR;CACF;CACAE,QAAQ,OAAO,EAAEC,YAASC,iBAKjB,EAAES,aAAYR,MAJAF,EAAQG,YAAYC,QAAQC,cAAcC,MAAM;EACnEC,YAAYN,EAAOO;EACnBC,UAAUR,EAAOQ;CACnB,CAAA,EAAA,EAC6BZ,QAAQ,KAAK;CAE5Cc,OAAO,EAAEC,qBAAkB,EACzBC,MAAM,CAAC,EAAEC,OAAOF,GAAYF,cAAc,iBAAiB,CAAC,EAC9D;CACAK,WAASC,4CAAA,WAAA;CACTE,YAAY,OAAO,EAAElB,YAASC,gBAAQ;EACpC,IAAM,EAAEE,kBAAeH,GACjB,EAAEQ,iBAAcP,GAEhBkB,IAAoB,MAAOhB,GAAYiB,KAAKC,qBAAqBf,MAAAA,KAAY,CAAA,GAE7EgB,IAAe/B,EAAgB4B,CAAAA;EAErC,IAAI,CAACG,EAAa,UAAa,CAACA,EAAa,SAC3C,MAAMhC,EAAS;GACbiC,IAAI;GACJtB,QAAQ,EAAEO,aAAU;EACtB,CAAA;CAEJ;CACAgB,gBAAcR,4CAAA,gBAAA;AAChB,CAAA"}
@@ -1,22 +0,0 @@
1
- import { i as e } from "./build-WuxXRAqf.mjs";
2
- import { t } from "./_flavorId-CFUBcU-l.mjs";
3
- import { t as n } from "./RouteIdLevelDefaultError-DPF_x2tG.mjs";
4
- import { jsx as r } from "react/jsx-runtime";
5
- import { useNavigate as i } from "@tanstack/react-router";
6
- import { useLingui as a } from "@lingui/react";
7
- //#region src/client/routes/_auth/projects/$projectId/compute/flavors/$flavorId.tsx?tsr-split=errorComponent
8
- function o() {
9
- let { i18n: o, _: s } = a(), c = i(), { projectId: l } = t.useParams();
10
- return /*#__PURE__*/ r(n, { action: /*#__PURE__*/ r(e, {
11
- variant: "primary",
12
- onClick: () => c({
13
- to: "/projects/$projectId/compute/flavors",
14
- params: { projectId: l }
15
- }),
16
- children: o._({ id: "ergacm" })
17
- }) });
18
- }
19
- //#endregion
20
- export { o as errorComponent };
21
-
22
- //# sourceMappingURL=_flavorId-CZcIp0Ih.mjs.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"_flavorId-CZcIp0Ih.mjs","names":["Button","useNavigate","useLingui","RouteIdLevelDefaultError","FlavorErrorComponent","t","navigate","projectId","Route","useParams","to","params","errorComponent"],"sources":["../../src/client/routes/_auth/projects/$projectId/compute/flavors/$flavorId.tsx?tsr-split=errorComponent"],"sourcesContent":["import {\n Button,\n ButtonRow,\n Stack,\n PopupMenu,\n PopupMenuToggle,\n PopupMenuOptions,\n PopupMenuItem,\n PopupMenuSectionSeparator,\n Container,\n Status,\n} from \"@cloudoperators/juno-ui-components/index\"\nimport { createFileRoute, redirect, useNavigate, useParams } from \"@tanstack/react-router\"\nimport type { RouteInfo } from \"@/client/routes/routeInfo\"\nimport { Trans, useLingui } from \"@lingui/react/macro\"\nimport { getServiceIndex } from \"@/server/Authentication/helpers\"\nimport { trpcReact } from \"@/client/trpcClient\"\nimport { useSetBreadcrumb } from \"@/client/hooks/useSetBreadcrumb\"\nimport { FlavorDetailsView } from \"./-components/FlavorDetailsView\"\nimport { useErrorTranslation } from \"@/client/utils/useErrorTranslation\"\nimport { EditSpecModal } from \"./-components/EditSpecModal\"\nimport { ManageAccessModal } from \"./-components/ManageAccessModal\"\nimport { DeleteFlavorModal } from \"./-components/DeleteFlavorModal\"\nimport { useModal } from \"@/client/utils/useModal\"\nimport { ContentHeader } from \"@/client/components/ContentHeader/ContentHeader\"\nimport { RouteIdLevelDefaultError } from \"@/client/components/Errors/RouteIdLevelDefaultError\"\n\nfunction FlavorErrorComponent() {\n const { t } = useLingui()\n const navigate = useNavigate()\n const { projectId } = Route.useParams()\n\n return (\n <RouteIdLevelDefaultError\n action={\n <Button\n variant=\"primary\"\n onClick={() => navigate({ to: \"/projects/$projectId/compute/flavors\", params: { projectId } })}\n >\n {t`Back to Flavors`}\n </Button>\n }\n />\n )\n}\n\nexport const Route = createFileRoute(\"/_auth/projects/$projectId/compute/flavors/$flavorId\")({\n staticData: {\n section: \"compute\",\n service: \"flavors\",\n analytics: {\n name: \"compute.flavors.detail\",\n },\n } satisfies RouteInfo,\n loader: async ({ context, params }) => {\n const flavor = await context.trpcClient?.compute.getFlavorById.query({\n project_id: params.projectId,\n flavorId: params.flavorId,\n })\n return { flavorName: flavor?.name ?? null }\n },\n head: ({ loaderData }) => ({\n meta: [{ title: loaderData?.flavorName ?? \"Flavor Details\" }],\n }),\n component: RouteComponent,\n beforeLoad: async ({ context, params }) => {\n const { trpcClient } = context\n const { projectId } = params\n\n const availableServices = (await trpcClient?.auth.getAvailableServices.query()) || []\n\n const serviceIndex = getServiceIndex(availableServices)\n\n if (!serviceIndex[\"flavor\"] && !serviceIndex[\"compute\"]) {\n throw redirect({\n to: \"/projects/$projectId\",\n params: { projectId },\n })\n }\n },\n errorComponent: FlavorErrorComponent,\n})\n\nfunction RouteComponent() {\n const { projectId, flavorId } = useParams({\n from: \"/_auth/projects/$projectId/compute/flavors/$flavorId\",\n })\n const { trpcClient } = Route.useRouteContext()\n const navigate = useNavigate()\n const { t } = useLingui()\n const { translateError, isRetryableError } = useErrorTranslation()\n const utils = trpcReact.useUtils()\n\n const {\n data: flavor,\n status,\n error,\n refetch,\n } = trpcReact.compute.getFlavorById.useQuery({\n project_id: projectId,\n flavorId,\n })\n\n useSetBreadcrumb(Route.id, flavor?.name)\n\n const { data: permissionsData } = trpcReact.compute.canUser.useQuery({\n project_id: projectId,\n permission: [\n \"flavors:delete\",\n \"flavors:add_project\",\n \"flavors:remove_project\",\n \"flavor_specs:list\",\n \"flavor_specs:create\",\n \"flavor_specs:delete\",\n ],\n })\n\n const canDeleteFlavor = permissionsData?.[0] ?? false\n const canManageAccess = (permissionsData?.[1] ?? false) || (permissionsData?.[2] ?? false)\n const canListSpecs = permissionsData?.[3] ?? false\n const canManageSpecs = (permissionsData?.[4] ?? false) || (permissionsData?.[5] ?? false)\n\n const [specModalOpen, toggleSpecModal] = useModal()\n const [accessModalOpen, toggleAccessModal] = useModal()\n const [deleteModalOpen, toggleDeleteModal] = useModal()\n\n const handleSpecModalClose = () => {\n toggleSpecModal()\n utils.compute.getExtraSpecs.invalidate({ project_id: projectId, flavorId })\n }\n\n const handleBack = () => {\n navigate({\n to: \"/projects/$projectId/compute/flavors\",\n params: { projectId },\n })\n }\n\n const handleHome = () => {\n navigate({\n to: \"/projects/$projectId\",\n params: { projectId },\n })\n }\n\n const handleRetry = () => {\n refetch()\n }\n\n if (status === \"pending\") {\n return <Status status=\"progress\" title={t`Loading Flavor Details...`} />\n }\n\n if (status === \"error\") {\n const errorCode = error?.message || \"UNKNOWN_ERROR\"\n const translatedError = translateError(errorCode)\n const canRetry = isRetryableError(errorCode)\n\n const getStatusCode = (code: string): number | undefined => {\n if (code.includes(\"UNAUTHORIZED\")) return 401\n if (code.includes(\"FORBIDDEN\")) return 403\n if (code.includes(\"NOT_FOUND\")) return 404\n if (code.includes(\"SERVER_ERROR\")) return 500\n return undefined\n }\n\n return (\n <Container className=\"py-8\">\n <Status\n status=\"error\"\n code={getStatusCode(errorCode)}\n title={t`Error Loading Flavor`}\n body={translatedError}\n action={\n <ButtonRow>\n <Button variant=\"primary\" onClick={handleBack}>\n <Trans>Back</Trans>\n </Button>\n <Button onClick={handleHome}>\n <Trans>Home</Trans>\n </Button>\n {canRetry && (\n <Button onClick={handleRetry}>\n <Trans>Try Again</Trans>\n </Button>\n )}\n </ButtonRow>\n }\n />\n </Container>\n )\n }\n\n if (!flavor) {\n return (\n <Container className=\"py-8\">\n <Status\n status=\"error\"\n code={404}\n title={t`Flavor Not Found`}\n body={t`The requested flavor could not be found. It may have been deleted or you may not have access to it.`}\n action={\n <ButtonRow>\n <Button variant=\"primary\" onClick={handleBack}>\n <Trans>Back</Trans>\n </Button>\n <Button onClick={handleHome}>\n <Trans>Home</Trans>\n </Button>\n </ButtonRow>\n }\n />\n </Container>\n )\n }\n\n const isPublicFlavor = flavor[\"os-flavor-access:is_public\"] !== false\n const hasPopupMenuItems = (canManageAccess && !isPublicFlavor) || canDeleteFlavor\n const canEditMetadata = canManageSpecs && canListSpecs\n const hasMoreActions = hasPopupMenuItems || canEditMetadata\n\n const headerActions = hasMoreActions ? (\n <Stack gap=\"0.5\" alignment=\"center\">\n {hasPopupMenuItems && (\n <PopupMenu>\n <PopupMenuToggle as=\"div\">\n <Button icon=\"moreVert\" title={t`More Actions`} aria-label={t`More Actions`} />\n </PopupMenuToggle>\n <PopupMenuOptions>\n {canManageAccess && !isPublicFlavor && (\n <PopupMenuItem label={t`Manage Access`} onClick={toggleAccessModal} />\n )}\n {canDeleteFlavor && (\n <>\n <PopupMenuSectionSeparator />\n <PopupMenuItem label={t`Delete Flavor`} onClick={toggleDeleteModal} />\n </>\n )}\n </PopupMenuOptions>\n </PopupMenu>\n )}\n {canEditMetadata && (\n <Button variant=\"primary\" onClick={toggleSpecModal}>\n <Trans>Edit Metadata</Trans>\n </Button>\n )}\n </Stack>\n ) : undefined\n\n return (\n <>\n <ContentHeader title={flavor.name} projectId={projectId} actions={headerActions} />\n <Stack direction=\"vertical\">\n <FlavorDetailsView flavor={flavor} canListSpecs={canListSpecs} />\n </Stack>\n\n {trpcClient && (\n <>\n {specModalOpen && (\n <EditSpecModal\n client={trpcClient}\n isOpen={specModalOpen}\n onClose={handleSpecModalClose}\n project={projectId}\n flavor={flavor}\n />\n )}\n\n {accessModalOpen && (\n <ManageAccessModal\n client={trpcClient}\n isOpen={accessModalOpen}\n onClose={toggleAccessModal}\n project={projectId}\n flavor={flavor}\n />\n )}\n\n {deleteModalOpen && (\n <DeleteFlavorModal\n client={trpcClient}\n isOpen={deleteModalOpen}\n onClose={toggleDeleteModal}\n project={projectId}\n flavor={flavor}\n onSuccess={handleBack}\n />\n )}\n </>\n )}\n </>\n )\n}\n"],"mappings":";;;;;;;AA2BA,SAASI,IAAAA;CACP,IAAM,EAAA,MAAA,GAAA,GAAA,MAAQF,EAAAA,GACRI,IAAWL,EAAAA,GACX,EAAEM,iBAAcC,EAAMC,UAAS;CAErC,OACE,gBAAC,GAAA,EACC,QACE,gBAAC,GAAA;EACC,SAAQ;EACR,eAAeH,EAAS;GAAEI,IAAI;GAAwCC,QAAQ,EAAEJ,aAAU;EAAE,CAAA;EAE3FF,UAAAA,EAAAA,EAAC,EAAA,IAAA,SAAA,CAAA;;AAKZ"}