@cobaltcore-dev/aurora 2.0.0 → 2.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (115) hide show
  1. package/dist/client/ContentHeader-fKKZVu-o.mjs +116 -0
  2. package/dist/client/ContentHeader-fKKZVu-o.mjs.map +1 -0
  3. package/dist/client/{DeleteFlavorModal-C2MqUgGR.mjs → DeleteFlavorModal-Be2GFiB_.mjs} +3 -2
  4. package/dist/client/DeleteFlavorModal-Be2GFiB_.mjs.map +1 -0
  5. package/dist/client/{RouteIdLevelDefaultError-CSseJ1yG.mjs → RouteIdLevelDefaultError-DPF_x2tG.mjs} +9 -9
  6. package/dist/client/RouteIdLevelDefaultError-DPF_x2tG.mjs.map +1 -0
  7. package/dist/client/StorageNotFound-B-zVinVD.mjs +30 -0
  8. package/dist/client/StorageNotFound-B-zVinVD.mjs.map +1 -0
  9. package/dist/client/{_flavorId-DYv_StX22.mjs → _flavorId-0PioWpEp.mjs} +4 -4
  10. package/dist/client/_flavorId-0PioWpEp.mjs.map +1 -0
  11. package/dist/client/{_flavorId-YV3jCS5g.mjs → _flavorId-B7fp6Nk8.mjs} +3 -3
  12. package/dist/client/{_flavorId-YV3jCS5g.mjs.map → _flavorId-B7fp6Nk8.mjs.map} +1 -1
  13. package/dist/client/{_flavorId-CaA4-Pnf.mjs → _flavorId-CgueqKTs.mjs} +3 -3
  14. package/dist/client/{_flavorId-CaA4-Pnf.mjs.map → _flavorId-CgueqKTs.mjs.map} +1 -1
  15. package/dist/client/{_floatingIpId-Dpsc7GU4.mjs → _floatingIpId-B8r64AL9.mjs} +3 -3
  16. package/dist/client/{_floatingIpId-Dpsc7GU4.mjs.map → _floatingIpId-B8r64AL9.mjs.map} +1 -1
  17. package/dist/client/{_floatingIpId-BeYElanB.mjs → _floatingIpId-lEobpOER.mjs} +2 -2
  18. package/dist/client/{_floatingIpId-BeYElanB.mjs.map → _floatingIpId-lEobpOER.mjs.map} +1 -1
  19. package/dist/client/{_imageId-pBSS0YcC.mjs → _imageId-Ccv8PedW.mjs} +3 -3
  20. package/dist/client/{_imageId-pBSS0YcC.mjs.map → _imageId-Ccv8PedW.mjs.map} +1 -1
  21. package/dist/client/_imageId-CiqEQB_J.mjs +558 -0
  22. package/dist/client/{_imageId-mfKp3JHn.mjs.map → _imageId-CiqEQB_J.mjs.map} +1 -1
  23. package/dist/client/{_imageId-mpXUMCh_.mjs → _imageId-D9LR-02T.mjs} +3 -3
  24. package/dist/client/{_imageId-mpXUMCh_.mjs.map → _imageId-D9LR-02T.mjs.map} +1 -1
  25. package/dist/client/{_projectId-BnTBxKfp.mjs → _projectId-BDARsteX.mjs} +3 -3
  26. package/dist/client/{_projectId-BnTBxKfp.mjs.map → _projectId-BDARsteX.mjs.map} +1 -1
  27. package/dist/client/{_projectId-CVrdJ52s.mjs → _projectId-CtyAHqhH.mjs} +2 -2
  28. package/dist/client/{_projectId-CVrdJ52s.mjs.map → _projectId-CtyAHqhH.mjs.map} +1 -1
  29. package/dist/client/_projectId-D3VOH5lN.mjs +94 -0
  30. package/dist/client/_projectId-D3VOH5lN.mjs.map +1 -0
  31. package/dist/client/{_projectId-AjgJX6Gl.mjs → _projectId-ZBk6vka0.mjs} +83 -81
  32. package/dist/client/_projectId-ZBk6vka0.mjs.map +1 -0
  33. package/dist/client/{_securityGroupId-AO3wnH8g.mjs → _securityGroupId-BwgZnoiR.mjs} +2 -2
  34. package/dist/client/{_securityGroupId-AO3wnH8g.mjs.map → _securityGroupId-BwgZnoiR.mjs.map} +1 -1
  35. package/dist/client/{_securityGroupId-Bq0ZyG6z.mjs → _securityGroupId-Cz2NUHdB.mjs} +3 -3
  36. package/dist/client/{_securityGroupId-Bq0ZyG6z.mjs.map → _securityGroupId-Cz2NUHdB.mjs.map} +1 -1
  37. package/dist/client/{_storageType-CzZ4u9x_.mjs → _storageType-BNpP1A2N.mjs} +3 -2
  38. package/dist/client/_storageType-BNpP1A2N.mjs.map +1 -0
  39. package/dist/client/_storageType-BxSGKhAI.mjs +15 -0
  40. package/dist/client/_storageType-BxSGKhAI.mjs.map +1 -0
  41. package/dist/client/_storageType-DZYCmiLt.mjs +30 -0
  42. package/dist/client/_storageType-DZYCmiLt.mjs.map +1 -0
  43. package/dist/client/{_storageType-c-DAu8qr.mjs → _storageType-UqAMP-8d.mjs} +286 -285
  44. package/dist/client/_storageType-UqAMP-8d.mjs.map +1 -0
  45. package/dist/client/_storageType-u51_7OwJ.mjs +7 -0
  46. package/dist/client/_storageType-u51_7OwJ.mjs.map +1 -0
  47. package/dist/client/components/Errors/RouteIdLevelDefaultError.d.ts +2 -1
  48. package/dist/client/{flavors-ZudiAiTU.mjs → flavors-Ce3J-cFa.mjs} +2 -2
  49. package/dist/client/{flavors-ZudiAiTU.mjs.map → flavors-Ce3J-cFa.mjs.map} +1 -1
  50. package/dist/client/{flavors-Bgq3KZmx.mjs → flavors-D5ThLaXO.mjs} +84 -77
  51. package/dist/client/flavors-D5ThLaXO.mjs.map +1 -0
  52. package/dist/client/{floatingips-B1oLH8z6.mjs → floatingips-DXnRlLvV.mjs} +2 -2
  53. package/dist/client/{floatingips-B1oLH8z6.mjs.map → floatingips-DXnRlLvV.mjs.map} +1 -1
  54. package/dist/client/{floatingips-BtLg3yEQ.mjs → floatingips-HRbuLxiN.mjs} +3 -3
  55. package/dist/client/{floatingips-BtLg3yEQ.mjs.map → floatingips-HRbuLxiN.mjs.map} +1 -1
  56. package/dist/client/{floatingips-BeQEkVH8.mjs → floatingips-nN1kQmsu.mjs} +2 -2
  57. package/dist/client/{floatingips-BeQEkVH8.mjs.map → floatingips-nN1kQmsu.mjs.map} +1 -1
  58. package/dist/client/{images-CnTW3bpy.mjs → images-C8M3ysWR.mjs} +3 -3
  59. package/dist/client/{images-CnTW3bpy.mjs.map → images-C8M3ysWR.mjs.map} +1 -1
  60. package/dist/client/{images-DZHDYDQu.mjs → images-Cf5R28NR.mjs} +2 -2
  61. package/dist/client/{images-DZHDYDQu.mjs.map → images-Cf5R28NR.mjs.map} +1 -1
  62. package/dist/client/index.js +198 -197
  63. package/dist/client/index.js.map +1 -1
  64. package/dist/client/{objects-jYQBFzwg.mjs → objects-BudUAfWY.mjs} +4265 -4275
  65. package/dist/client/objects-BudUAfWY.mjs.map +1 -0
  66. package/dist/client/objects-Dc7sKUr8.mjs +67 -0
  67. package/dist/client/objects-Dc7sKUr8.mjs.map +1 -0
  68. package/dist/client/objects-Dw7oeTq2.mjs +80 -0
  69. package/dist/client/objects-Dw7oeTq2.mjs.map +1 -0
  70. package/dist/client/objects-_g7nGIn5.mjs +25 -0
  71. package/dist/client/objects-_g7nGIn5.mjs.map +1 -0
  72. package/dist/client/objects-eBxvY6_n.mjs +78 -0
  73. package/dist/client/objects-eBxvY6_n.mjs.map +1 -0
  74. package/dist/client/projects-yiK0HGSA.mjs.map +1 -1
  75. package/dist/client/{securitygroups-BRndk7wh.mjs → securitygroups-67fFxiwt.mjs} +2 -2
  76. package/dist/client/{securitygroups-BRndk7wh.mjs.map → securitygroups-67fFxiwt.mjs.map} +1 -1
  77. package/dist/client/{securitygroups--0PS2wbM.mjs → securitygroups-DXrfyuVF.mjs} +3 -3
  78. package/dist/client/{securitygroups--0PS2wbM.mjs.map → securitygroups-DXrfyuVF.mjs.map} +1 -1
  79. package/dist/client/{securitygroups-Cs2Op-tu.mjs → securitygroups-WLB1_IM6.mjs} +3 -3
  80. package/dist/client/{securitygroups-Cs2Op-tu.mjs.map → securitygroups-WLB1_IM6.mjs.map} +1 -1
  81. package/dist/client/{securitygroups-CdN4yAAw.mjs → securitygroups-o0IXZM6S.mjs} +2 -2
  82. package/dist/client/{securitygroups-CdN4yAAw.mjs.map → securitygroups-o0IXZM6S.mjs.map} +1 -1
  83. package/dist/client/serviceCatalog-B3lKWC9V.mjs +6 -0
  84. package/dist/client/serviceCatalog-B3lKWC9V.mjs.map +1 -0
  85. package/dist/client/storageProviders-CJ5rOh13.mjs +15 -0
  86. package/dist/client/storageProviders-CJ5rOh13.mjs.map +1 -0
  87. package/dist/client/trpcClient.d.ts +96 -3
  88. package/dist/client/utils/serviceCatalog.d.ts +9 -0
  89. package/dist/client/utils/storageProviders.d.ts +44 -0
  90. package/dist/server/index.d.ts +96 -3
  91. package/dist/server/index.js +1224 -387
  92. package/package.json +1 -1
  93. package/dist/client/ContentHeader-CPJbgYWn.mjs +0 -115
  94. package/dist/client/ContentHeader-CPJbgYWn.mjs.map +0 -1
  95. package/dist/client/DeleteFlavorModal-C2MqUgGR.mjs.map +0 -1
  96. package/dist/client/RouteIdLevelDefaultError-CSseJ1yG.mjs.map +0 -1
  97. package/dist/client/_flavorId-DYv_StX22.mjs.map +0 -1
  98. package/dist/client/_imageId-mfKp3JHn.mjs +0 -558
  99. package/dist/client/_projectId-AjgJX6Gl.mjs.map +0 -1
  100. package/dist/client/_projectId-DgciZslU.mjs +0 -92
  101. package/dist/client/_projectId-DgciZslU.mjs.map +0 -1
  102. package/dist/client/_storageType-BRWWJtow.mjs +0 -14
  103. package/dist/client/_storageType-BRWWJtow.mjs.map +0 -1
  104. package/dist/client/_storageType-CzZ4u9x_.mjs.map +0 -1
  105. package/dist/client/_storageType-c-DAu8qr.mjs.map +0 -1
  106. package/dist/client/_storageType-zeSZe--V.mjs +0 -7
  107. package/dist/client/_storageType-zeSZe--V.mjs.map +0 -1
  108. package/dist/client/flavors-Bgq3KZmx.mjs.map +0 -1
  109. package/dist/client/objects-25xsh4Ia.mjs +0 -66
  110. package/dist/client/objects-25xsh4Ia.mjs.map +0 -1
  111. package/dist/client/objects-KXY6dgwq.mjs +0 -82
  112. package/dist/client/objects-KXY6dgwq.mjs.map +0 -1
  113. package/dist/client/objects-QryuClU3.mjs +0 -82
  114. package/dist/client/objects-QryuClU3.mjs.map +0 -1
  115. package/dist/client/objects-jYQBFzwg.mjs.map +0 -1
@@ -0,0 +1,116 @@
1
+ import { H as e, Q as t, Z as n, _ as r, at as i, d as a, tt as o } from "./build-WuxXRAqf.mjs";
2
+ import { t as s } from "./Slot-CWb612-_.mjs";
3
+ import { t as c } from "./storageProviders-CJ5rOh13.mjs";
4
+ import { t as l } from "./routeInfo-DP3v74Wg.mjs";
5
+ import { jsx as u, jsxs as d } from "react/jsx-runtime";
6
+ import { useState as f } from "react";
7
+ import { useMatches as p, useParams as m, useRouteContext as h } from "@tanstack/react-router";
8
+ import { Trans as g, useLingui as _ } from "@lingui/react";
9
+ //#region src/client/components/ClipboardText.tsx
10
+ var v = ({ text: r, tooltipContent: i, className: s, truncateAt: c, showTooltip: l = !0, ...p }) => {
11
+ let { i18n: m, _: h } = _(), [g, v] = f(!1), [y, b] = f(!1), x = `copyableTooltip inline-flex items-center ${s || ""}`, S = async (e) => {
12
+ e.preventDefault(), e.stopPropagation();
13
+ try {
14
+ await navigator.clipboard.writeText(r), v(!0), b(!1), setTimeout(() => v(!1), 2e3);
15
+ } catch (e) {
16
+ console.error("Failed to copy text:", e);
17
+ }
18
+ }, C = c && r.length > c ? `${r.slice(0, c)}...` : r, w = () => g ? i || m._({ id: "u+VWhB" }) : m._({ id: "he3ygx" }), T = g && l || y && l;
19
+ return /*#__PURE__*/ u("div", {
20
+ ...p,
21
+ className: x,
22
+ children: /*#__PURE__*/ d(n, {
23
+ open: T,
24
+ children: [/*#__PURE__*/ u(o, {
25
+ onClick: S,
26
+ onMouseEnter: () => !g && b(!0),
27
+ onMouseLeave: () => b(!1),
28
+ "aria-label": m._({
29
+ id: "Wbg1jv",
30
+ values: { text: r }
31
+ }),
32
+ className: "cursor-pointer",
33
+ asChild: !0,
34
+ "data-testid": "clipboard-copy-trigger",
35
+ children: /*#__PURE__*/ u("button", {
36
+ type: "button",
37
+ className: "group border-none bg-transparent p-0 text-inherit",
38
+ children: /*#__PURE__*/ d(t, {
39
+ direction: "horizontal",
40
+ gap: "1",
41
+ className: "items-center hover:underline",
42
+ children: [/*#__PURE__*/ u("span", {
43
+ className: "select-none",
44
+ children: C
45
+ }), /*#__PURE__*/ u(a, {
46
+ icon: g ? "check" : "contentCopy",
47
+ size: "18"
48
+ })]
49
+ })
50
+ })
51
+ }), /*#__PURE__*/ u(e, { children: w() })]
52
+ })
53
+ });
54
+ };
55
+ //#endregion
56
+ //#region src/client/components/ContentHeader/ContentHeader.tsx
57
+ function y({ title: e, projectId: t, description: n, actions: a, badges: o }) {
58
+ let { slots: f } = h({ strict: !1 }), _ = p(), { provider: y } = m({ strict: !1 }), b = [..._].reverse().find((e) => l(e.staticData)), x = b && l(b.staticData) ? b.staticData.service : void 0, S = x === "containers" && y === c.CEPH ? "ceph-containers" : x, C = f?.servicePageActions && S ? /*#__PURE__*/ u(s, {
59
+ component: f.servicePageActions,
60
+ useShadowDOM: !1,
61
+ currentService: S
62
+ }) : null, w = f?.serviceBanner && S ? /*#__PURE__*/ u(s, {
63
+ component: f.serviceBanner,
64
+ useShadowDOM: !1,
65
+ currentService: S
66
+ }) : null, T = f?.projectOverviewBanner && !S ? /*#__PURE__*/ u(s, {
67
+ component: f.projectOverviewBanner,
68
+ useShadowDOM: !1
69
+ }) : null;
70
+ return /*#__PURE__*/ d("header", {
71
+ className: "mb-8",
72
+ children: [
73
+ /*#__PURE__*/ d("div", {
74
+ className: "flex flex-col sm:flex-row sm:items-center sm:justify-between",
75
+ children: [/*#__PURE__*/ d("div", {
76
+ className: "flex items-center gap-3",
77
+ children: [/*#__PURE__*/ u(i, { children: e }), C]
78
+ }), /*#__PURE__*/ d("div", {
79
+ className: "text-theme-light flex shrink-0 items-center gap-1 text-sm",
80
+ children: [/*#__PURE__*/ d("span", {
81
+ className: "font-semibold",
82
+ children: [
83
+ /*#__PURE__*/ u(g, { id: "mSfwLL" }),
84
+ ":",
85
+ " "
86
+ ]
87
+ }), /*#__PURE__*/ u(v, {
88
+ text: t,
89
+ truncateAt: 15
90
+ })]
91
+ })]
92
+ }),
93
+ n && /*#__PURE__*/ u("p", {
94
+ className: "text-sm font-normal",
95
+ children: n
96
+ }),
97
+ w,
98
+ T,
99
+ /*#__PURE__*/ u(r, { className: "mt-4" }),
100
+ (o || a) && /*#__PURE__*/ d("div", {
101
+ className: "mt-3 flex items-start justify-between",
102
+ children: [/*#__PURE__*/ d("div", {
103
+ className: "flex items-center gap-2",
104
+ children: [o, " "]
105
+ }), a && /*#__PURE__*/ u("div", {
106
+ className: "flex gap-2",
107
+ children: a
108
+ })]
109
+ })
110
+ ]
111
+ });
112
+ }
113
+ //#endregion
114
+ export { v as n, y as t };
115
+
116
+ //# sourceMappingURL=ContentHeader-fKKZVu-o.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ContentHeader-fKKZVu-o.mjs","names":["React","useState","Tooltip","TooltipTrigger","TooltipContent","Icon","Stack","ClipboardText","text","tooltipContent","className","truncateAt","showTooltip","props","useLingui","copied","setCopied","isHovering","setIsHovering","combinedClassName","handleCopy","e","preventDefault","stopPropagation","navigator","clipboard","writeText","setTimeout","err","console","error","displayText","length","slice","getTooltipContent","t","tooltipIsOpen","div","open","onClick","onMouseEnter","onMouseLeave","aria-label","asChild","data-testid","button","type","direction","gap","span","icon","size","Divider","ContentHeading","useRouteContext","useMatches","useParams","ClipboardText","Slot","isRouteInfo","STORAGE_PROVIDER","ContentHeader","title","projectId","description","actions","badges","slots","strict","matches","provider","activeMatch","reverse","find","m","staticData","routeService","service","undefined","currentService","CEPH","slotActions","servicePageActions","component","useShadowDOM","serviceBanner","projectOverviewBanner","header","className","div","span","text","truncateAt","p"],"sources":["../../src/client/components/ClipboardText.tsx","../../src/client/components/ContentHeader/ContentHeader.tsx"],"sourcesContent":["import React, { useState } from \"react\"\nimport { Tooltip, TooltipTrigger, TooltipContent, Icon, Stack } from \"@cloudoperators/juno-ui-components\"\nimport { useLingui } from \"@lingui/react/macro\"\n\nexport interface ClipboardTextProps extends React.HTMLAttributes<HTMLDivElement> {\n tooltipContent?: string\n text: string\n className?: string\n truncateAt?: number\n showTooltip?: boolean\n}\n\nconst ClipboardText: React.FC<ClipboardTextProps> = ({\n text,\n tooltipContent,\n className,\n truncateAt,\n showTooltip = true,\n ...props\n}) => {\n const { t } = useLingui()\n const [copied, setCopied] = useState(false)\n const [isHovering, setIsHovering] = useState(false)\n\n const combinedClassName = `copyableTooltip inline-flex items-center ${className || \"\"}`\n\n const handleCopy = async (e: React.MouseEvent) => {\n e.preventDefault()\n e.stopPropagation()\n\n try {\n await navigator.clipboard.writeText(text)\n setCopied(true)\n setIsHovering(false)\n setTimeout(() => setCopied(false), 2000)\n } catch (err) {\n console.error(\"Failed to copy text:\", err)\n }\n }\n\n const displayText = truncateAt && text.length > truncateAt ? `${text.slice(0, truncateAt)}...` : text\n\n // Determine tooltip content based on state\n const getTooltipContent = () => {\n if (copied) {\n return tooltipContent || t`Copied to clipboard!`\n }\n return t`Copy`\n }\n\n const tooltipIsOpen = (copied && showTooltip) || (isHovering && showTooltip)\n\n return (\n <div {...props} className={combinedClassName}>\n <Tooltip open={tooltipIsOpen}>\n <TooltipTrigger\n onClick={handleCopy}\n onMouseEnter={() => !copied && setIsHovering(true)}\n onMouseLeave={() => setIsHovering(false)}\n aria-label={t`Copy ${text} to clipboard`}\n className=\"cursor-pointer\"\n asChild\n data-testid=\"clipboard-copy-trigger\"\n >\n <button type=\"button\" className=\"group border-none bg-transparent p-0 text-inherit\">\n <Stack direction=\"horizontal\" gap=\"1\" className=\"items-center hover:underline\">\n <span className=\"select-none\">{displayText}</span>\n <Icon icon={copied ? \"check\" : \"contentCopy\"} size=\"18\" />\n </Stack>\n </button>\n </TooltipTrigger>\n <TooltipContent>{getTooltipContent()}</TooltipContent>\n </Tooltip>\n </div>\n )\n}\n\nexport default ClipboardText\n","import type { ReactNode } from \"react\"\nimport { Divider, ContentHeading } from \"@cloudoperators/juno-ui-components\"\nimport { Trans } from \"@lingui/react/macro\"\nimport { useRouteContext, useMatches, useParams } from \"@tanstack/react-router\"\nimport ClipboardText from \"../ClipboardText\"\nimport { Slot } from \"../Slot\"\nimport { isRouteInfo } from \"@/client/routes/routeInfo\"\nimport { STORAGE_PROVIDER } from \"@/client/utils/storageProviders\"\n\ninterface ContentHeaderProps {\n title: string\n projectId: string\n description?: string | null\n actions?: ReactNode\n badges?: ReactNode\n}\n\nexport function ContentHeader({ title, projectId, description, actions, badges }: ContentHeaderProps) {\n const { slots } = useRouteContext({ strict: false })\n const matches = useMatches()\n const { provider } = useParams({ strict: false }) as { provider?: string }\n\n const activeMatch = [...matches].reverse().find((m) => isRouteInfo(m.staticData))\n const routeService = activeMatch && isRouteInfo(activeMatch.staticData) ? activeMatch.staticData.service : undefined\n\n // Storage routes share service: \"containers\" for both Swift and Ceph.\n // Distinguish them by the $provider param. Both sides of this are nav service keys,\n // not `$storageType` URL nouns — see STORAGE_TYPE.\n const currentService =\n routeService === \"containers\" && provider === STORAGE_PROVIDER.CEPH ? \"ceph-containers\" : routeService\n\n const slotActions =\n slots?.servicePageActions && currentService ? (\n <Slot component={slots.servicePageActions} useShadowDOM={false} currentService={currentService} />\n ) : null\n\n const serviceBanner =\n slots?.serviceBanner && currentService ? (\n <Slot component={slots.serviceBanner} useShadowDOM={false} currentService={currentService} />\n ) : null\n\n const projectOverviewBanner =\n slots?.projectOverviewBanner && !currentService ? (\n <Slot component={slots.projectOverviewBanner} useShadowDOM={false} />\n ) : null\n\n return (\n <header className=\"mb-8\">\n <div className=\"flex flex-col sm:flex-row sm:items-center sm:justify-between\">\n <div className=\"flex items-center gap-3\">\n <ContentHeading>{title}</ContentHeading>\n {slotActions}\n </div>\n <div className=\"text-theme-light flex shrink-0 items-center gap-1 text-sm\">\n <span className=\"font-semibold\">\n <Trans>Project ID</Trans>:{\" \"}\n </span>\n <ClipboardText text={projectId} truncateAt={15} />\n </div>\n </div>\n {description && <p className=\"text-sm font-normal\">{description}</p>}\n {serviceBanner}\n {projectOverviewBanner}\n <Divider className=\"mt-4\" />\n {(badges || actions) && (\n <div className=\"mt-3 flex items-start justify-between\">\n <div className=\"flex items-center gap-2\">{badges} </div>\n {actions && <div className=\"flex gap-2\">{actions}</div>}\n </div>\n )}\n </header>\n )\n}\n"],"mappings":"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"}
@@ -223,7 +223,8 @@ function O({ client: i, project: l, flavor: f, isLoading: _, onClose: v, initial
223
223
  E.length === 0 && !A ? /*#__PURE__*/ m(u, {
224
224
  status: "empty",
225
225
  title: S._({ id: "qTRcSX" }),
226
- body: S._({ id: "PVTJPk" })
226
+ body: S._({ id: "PVTJPk" }),
227
+ className: "m-0"
227
228
  }) : /*#__PURE__*/ h(d, {
228
229
  className: "mb-6 grid-cols-2",
229
230
  alignTerms: "left",
@@ -798,4 +799,4 @@ var z = ({ client: e, isOpen: t, onClose: n, project: i, flavor: a }) => {
798
799
  //#endregion
799
800
  export { k as a, j as i, z as n, T as o, A as r, B as t };
800
801
 
801
- //# sourceMappingURL=DeleteFlavorModal-C2MqUgGR.mjs.map
802
+ //# sourceMappingURL=DeleteFlavorModal-Be2GFiB_.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"DeleteFlavorModal-Be2GFiB_.mjs","names":["useErrorTranslation","useLingui","translateError","errorCode","t","isRetryableError","includes","React","useState","useEffect","useMemo","useErrorTranslation","Modal","Button","Status","Stack","DescriptionList","DescriptionTerm","DescriptionDefinition","TextInput","Message","toast","buildInitialSpecs","extraSpecs","Object","entries","map","key","value","isEditing","createExtraSpecsPromise","client","project","flavorId","compute","getExtraSpecs","query","project_id","EditSpecModalInner","flavor","isLoading","onClose","initialSpecs","useLingui","translateError","specs","setSpecs","errors","setErrors","isAddingNew","setIsAddingNew","newKey","setNewKey","newValue","setNewValue","operationInProgress","setOperationInProgress","validationMessage","setValidationMessage","isModalDisabled","some","e","validateKey","rowIndex","normalized","trim","t","isDuplicate","entry","idx","handleAddNew","keyError","length","createExtraSpecs","mutate","id","extra_specs","success","description","error","errorMsg","Error","message","handleCancelAdd","handleEdit","index","i","editingValue","handleSaveEdit","spec","trimmedValue","handleCancelEdit","handleDelete","deleteExtraSpec","filter","_","handleValueChange","prev","next","handleClose","open","onCancel","size","title","cancelButtonLabel","disableCancelButton","status","className","div","variant","text","direction","label","onClick","disabled","body","alignTerms","onChange","target","placeholder","invalid","autoFocus","gap","icon","aria-label","Fragment","span","data-testid","EditSpecModal","isOpen","extraSpecsData","setExtraSpecsData","isLoadingSpecs","setIsLoadingSpecs","loadError","setLoadError","cancelled","loadData","getFlavorCreatedToast","name","message","description","getFlavorDeletedToast","getFlavorAccessAddedToast","projectId","flavorName","getFlavorAccessRemovedToast","getFlavorAccessAddErrorToast","errorMessage","getFlavorAccessRemoveErrorToast","React","useState","useEffect","useMemo","useErrorTranslation","Modal","Message","DescriptionList","DescriptionTerm","DescriptionDefinition","Stack","Status","Button","TextInput","toast","getFlavorAccessAddedToast","getFlavorAccessRemovedToast","getFlavorAccessRemoveErrorToast","buildInitialAccess","flavorAccess","map","access","projectId","tenant_id","createPermissionsPromise","client","project","compute","canUser","query","project_id","permission","then","canAdd","canRemove","createFlavorAccessPromise","flavorId","getFlavorAccess","ManageAccessModalInner","flavor","isLoading","onClose","initialAccess","useLingui","translateError","setAccess","errors","setErrors","isAddingNew","setIsAddingNew","newProjectId","setNewProjectId","deletingProjectIds","setDeletingProjectIds","Set","addingProjectId","setAddingProjectId","isPublicFlavor","validateProjectId","normalized","trim","t","isDuplicate","some","entry","handleAddNew","error","trimmedProjectId","addTenantAccess","mutate","id","targetProjectId","prev","message","options","name","success","errorMessage","Error","handleCancelAdd","handleDelete","add","removeTenantAccess","filter","a","next","delete","handleClose","flavorName","open","onCancel","size","title","p","className","isAnyOperationInProgress","status","div","variant","text","direction","label","onClick","disabled","length","span","value","onChange","e","target","placeholder","invalid","autoFocus","wrapperClassName","icon","progress","isDeleting","has","Fragment","gap","alignment","data-testid","ManageAccessModal","isOpen","flavorAccessData","setFlavorAccessData","permissionsData","setPermissionsData","isLoadingData","setIsLoadingData","loadError","setLoadError","cancelled","loadData","accessData","permissions","Promise","all","deduped","idx","arr","findIndex","body","z","useForm","useStore","React","useState","Modal","Stack","Form","FormSection","TextInput","DescriptionList","DescriptionTerm","DescriptionDefinition","Message","useErrorTranslation","useModalTracking","DeleteFlavorModal","client","isOpen","onClose","project","flavor","onSuccess","useLingui","translateError","isLoading","setIsLoading","formError","setFormError","trackClose","markSubmitted","resetTracking","actionPrefix","formSchema","object","confirm","string","refine","value","message","t","form","defaultValues","validators","onSubmit","id","compute","deleteFlavor","mutate","project_id","flavorId","handleClose","error","errorMessage","canDelete","store","state","isSubmitting","values","reset","confirmLabel","flavorName","name","open","onCancel","title","size","confirmButtonLabel","confirmButtonVariant","onConfirm","handleSubmit","cancelButtonLabel","disableConfirmButton","disableCancelButton","disableCloseButton","direction","gap","variant","p","className","vcpus","ram","disk","swap","Number","e","preventDefault","Field","children","field","label","onChange","handleChange","target","placeholder","autoFocus","disabled","required"],"sources":["../../src/client/utils/useErrorTranslation.ts","../../src/client/routes/_auth/projects/$projectId/compute/flavors/-components/EditSpecModal.tsx","../../src/client/routes/_auth/projects/$projectId/compute/flavors/-components/FlavorToastNotifications.tsx","../../src/client/routes/_auth/projects/$projectId/compute/flavors/-components/ManageAccessModal.tsx","../../src/client/routes/_auth/projects/$projectId/compute/flavors/-components/DeleteFlavorModal.tsx"],"sourcesContent":["import { useLingui } from \"@lingui/react/macro\"\n\nexport const useErrorTranslation = () => {\n const { t } = useLingui()\n\n const translateError = (errorCode: string): string => {\n switch (errorCode) {\n // List Flavor\n case \"FLAVORS_UNAUTHORIZED\":\n return t`Your session has expired. Please log in again.`\n case \"FLAVORS_FORBIDDEN\":\n return t`You don't have permission to access flavors for this project.`\n case \"FLAVORS_NOT_FOUND\":\n return t`Flavor service is not available for this project.`\n case \"FLAVORS_SERVER_ERROR\":\n return t`Server is experiencing issues. Please try again later.`\n case \"FLAVORS_FETCH_FAILED\":\n return t`Failed to fetch flavors from server.`\n case \"FLAVORS_PARSE_ERROR\":\n return t`Server returned unexpected data format.`\n\n // Get flavor\n case \"GET_FLAVOR_DETAILS_UNAUTHORIZED\":\n return t`You are not authorized to view flavor details. Please log in again.`\n case \"GET_FLAVOR_DETAILS_FORBIDDEN\":\n return t`You don't have permission to view this flavor's details.`\n case \"GET_FLAVOR_DETAILS_NOT_FOUND\":\n return t`The flavor could not be found. It may have been deleted.`\n case \"GET_FLAVOR_DETAILS_SERVER_ERROR\":\n return t`Server error occurred while fetching flavor details. Please try again later.`\n case \"GET_FLAVOR_DETAILS_INVALID_ID\":\n return t`Flavor ID is required and cannot be empty.`\n case \"GET_FLAVOR_DETAILS_PARSE_ERROR\":\n return t`Server returned unexpected data format for flavor details.`\n case \"GET_FLAVOR_DETAILS_FAILED\":\n return t`Failed to load flavor details. Please try again.`\n\n // Create Flavor\n case \"CREATE_FLAVOR_INVALID_DATA\":\n return t`The flavor data provided is invalid. Please check your input.`\n case \"CREATE_FLAVOR_UNAUTHORIZED\":\n return t`You are not authorized to create flavors. Please log in again.`\n case \"CREATE_FLAVOR_FORBIDDEN\":\n return t`You don't have permission to create flavors in this project.`\n case \"CREATE_FLAVOR_CONFLICT\":\n return t`A flavor with this ID or name already exists. Please use different values.`\n case \"CREATE_FLAVOR_SERVER_ERROR\":\n return t`Server error occurred while creating the flavor. Please try again later.`\n case \"CREATE_FLAVOR_FAILED\":\n return t`Failed to create the flavor. Please try again.`\n\n // Delete Flavor\n case \"DELETE_FLAVOR_UNAUTHORIZED\":\n return t`You are not authorized to delete flavors. Please log in again.`\n case \"DELETE_FLAVOR_FORBIDDEN\":\n return t`You don't have permission to delete flavors in this project.`\n case \"DELETE_FLAVOR_NOT_FOUND\":\n return t`The flavor could not be found. It may have already been deleted.`\n case \"DELETE_FLAVOR_SERVER_ERROR\":\n return t`Server error occurred while deleting the flavor. Please try again later.`\n case \"DELETE_FLAVOR_FAILED\":\n return t`Failed to delete the flavor. Please try again.`\n case \"DELETE_FLAVOR_INVALID_ID\":\n return t`Flavor ID is required and cannot be empty.`\n\n // Create Metadata\n case \"CREATE_EXTRA_SPECS_UNAUTHORIZED\":\n return t`You are not authorized to create extra specs. Please log in again.`\n case \"CREATE_EXTRA_SPECS_FORBIDDEN\":\n return t`You don't have permission to create extra specs for this flavor.`\n case \"CREATE_EXTRA_SPECS_NOT_FOUND\":\n return t`The flavor could not be found. It may have been deleted.`\n case \"CREATE_EXTRA_SPECS_CONFLICT\":\n return t`This extra spec keys already exist. Please use different keys.`\n case \"CREATE_EXTRA_SPECS_INVALID_DATA\":\n return t`The extra spec data provided is invalid. Please check your input.`\n case \"CREATE_EXTRA_SPECS_SERVER_ERROR\":\n return t`Server error occurred while creating extra specs. Please try again later.`\n case \"CREATE_EXTRA_SPECS_PARSE_ERROR\":\n return t`Server returned unexpected data format for extra specs.`\n case \"CREATE_EXTRA_SPECS_FAILED\":\n return t`Failed to create extra specs. Please try again.`\n\n // Get Metadata\n case \"GET_EXTRA_SPECS_UNAUTHORIZED\":\n return t`You are not authorized to view extra specs. Please log in again.`\n case \"GET_EXTRA_SPECS_FORBIDDEN\":\n return t`You don't have permission to view extra specs for this flavor.`\n case \"GET_EXTRA_SPECS_NOT_FOUND\":\n return t`The flavor could not be found or has no extra specs.`\n case \"GET_EXTRA_SPECS_SERVER_ERROR\":\n return t`Server error occurred while fetching extra specs. Please try again later.`\n case \"GET_EXTRA_SPECS_PARSE_ERROR\":\n return t`Server returned unexpected data format for extra specs.`\n case \"GET_EXTRA_SPECS_FAILED\":\n return t`Failed to load extra specs. Please try again.`\n\n // Delete Metadata\n case \"DELETE_EXTRA_SPEC_UNAUTHORIZED\":\n return t`You are not authorized to delete extra specs. Please log in again.`\n case \"DELETE_EXTRA_SPEC_FORBIDDEN\":\n return t`You don't have permission to delete extra specs for this flavor.`\n case \"DELETE_EXTRA_SPEC_NOT_FOUND\":\n return t`The extra spec could not be found. It may have already been deleted.`\n case \"DELETE_EXTRA_SPEC_SERVER_ERROR\":\n return t`Server error occurred while deleting the extra spec. Please try again later.`\n case \"DELETE_EXTRA_SPEC_INVALID_KEY\":\n return t`Extra spec key is required and cannot be empty.`\n case \"DELETE_EXTRA_SPEC_FAILED\":\n return t`Failed to delete the extra spec. Please try again.`\n\n // Get Flavor Access\n case \"GET_FLAVOR_ACCESS_UNAUTHORIZED\":\n return t`You are not authorized to access flavor access information. Please log in again.`\n case \"GET_FLAVOR_ACCESS_FORBIDDEN\":\n return t`You don't have permission to access flavor access information for this flavor.`\n case \"GET_FLAVOR_ACCESS_NOT_FOUND\":\n return t`The flavor could not be found. It may have been deleted.`\n case \"GET_FLAVOR_ACCESS_SERVER_ERROR\":\n return t`Server error occurred while fetching flavor access information. Please try again later.`\n case \"GET_FLAVOR_ACCESS_FAILED\":\n return t`Failed to fetch flavor access information. Please try again.`\n\n // Add Tenant Access\n case \"ADD_TENANT_ACCESS_FAILED\":\n return t`Failed to add tenant access to flavor. Please try again.`\n case \"ADD_TENANT_ACCESS_INVALID_DATA\":\n return t`The tenant ID provided is invalid. Please check your input.`\n case \"ADD_TENANT_ACCESS_UNAUTHORIZED\":\n return t`You are not authorized to add tenant access. Please log in again.`\n case \"ADD_TENANT_ACCESS_FORBIDDEN\":\n return t`You don't have permission to add tenant access to this flavor.`\n case \"ADD_TENANT_ACCESS_NOT_FOUND\":\n return t`The flavor or tenant could not be found. Please verify they exist.`\n case \"ADD_TENANT_ACCESS_CONFLICT\":\n return t`This tenant already has access to the flavor.`\n case \"ADD_TENANT_ACCESS_SERVER_ERROR\":\n return t`Server error occurred while adding tenant access. Please try again later.`\n\n // Remove Tenant Access\n case \"REMOVE_TENANT_ACCESS_FAILED\":\n return t`Failed to remove tenant access from flavor. Please try again.`\n case \"REMOVE_TENANT_ACCESS_INVALID_DATA\":\n return t`The tenant ID provided is invalid. Please check your input.`\n case \"REMOVE_TENANT_ACCESS_UNAUTHORIZED\":\n return t`You are not authorized to remove tenant access. Please log in again.`\n case \"REMOVE_TENANT_ACCESS_FORBIDDEN\":\n return t`You don't have permission to remove tenant access from this flavor.`\n case \"REMOVE_TENANT_ACCESS_NOT_FOUND\":\n return t`The flavor or tenant could not be found. It may have already been removed.`\n case \"REMOVE_TENANT_ACCESS_CONFLICT\":\n return t`This tenant does not have access to the flavor.`\n case \"REMOVE_TENANT_ACCESS_SERVER_ERROR\":\n return t`Server error occurred while removing tenant access. Please try again later.`\n\n // Service Connection Errors\n case \"COMPUTE_SERVICE_UNAVAILABLE\":\n return t`The compute service is currently unavailable for this project. Please try again later.`\n case \"COMPUTE_SERVICE_CONNECTION_FAILED\":\n return t`Unable to connect to the compute service. Please check your connection and try again.`\n\n default:\n return t`An unexpected error occurred. Please try again.`\n }\n }\n\n const isRetryableError = (errorCode: string): boolean => {\n return [\"FLAVORS_SERVER_ERROR\", \"FLAVORS_FETCH_FAILED\"].includes(errorCode)\n }\n\n return { translateError, isRetryableError }\n}\n","import React, { useState, useEffect, useMemo } from \"react\"\nimport { useLingui } from \"@lingui/react/macro\"\nimport { TrpcClient } from \"@/client/trpcClient\"\nimport { useErrorTranslation } from \"@/client/utils/useErrorTranslation\"\nimport {\n Modal,\n Button,\n Status,\n Stack,\n DescriptionList,\n DescriptionTerm,\n DescriptionDefinition,\n TextInput,\n Message,\n toast,\n} from \"@cloudoperators/juno-ui-components\"\nimport { Flavor } from \"@/server/Compute/types/flavor\"\n\ninterface EditSpecModalProps {\n client: TrpcClient\n isOpen: boolean\n onClose: () => void\n project: string\n flavor: Flavor | null\n}\n\ninterface SpecEntry {\n key: string\n value: string\n isEditing?: boolean\n editingValue?: string\n}\n\nfunction buildInitialSpecs(extraSpecs: Record<string, string>): SpecEntry[] {\n return Object.entries(extraSpecs).map(([key, value]) => ({\n key,\n value,\n isEditing: false,\n }))\n}\n\nconst createExtraSpecsPromise = (client: TrpcClient, project: string, flavorId: string) => {\n return client.compute.getExtraSpecs.query({\n project_id: project,\n flavorId: flavorId,\n })\n}\n\nfunction EditSpecModalInner({\n client,\n project,\n flavor,\n isLoading,\n onClose,\n initialSpecs,\n}: {\n client: TrpcClient\n project: string\n flavor: Flavor\n isLoading: boolean\n onClose: () => void\n initialSpecs: SpecEntry[]\n}) {\n const { t } = useLingui()\n const { translateError } = useErrorTranslation()\n\n const [specs, setSpecs] = useState<SpecEntry[]>(initialSpecs)\n const [errors, setErrors] = useState<{ [key: string]: string }>({})\n const [isAddingNew, setIsAddingNew] = useState(false)\n const [newKey, setNewKey] = useState(\"\")\n const [newValue, setNewValue] = useState(\"\")\n const [operationInProgress, setOperationInProgress] = useState(false)\n const [validationMessage, setValidationMessage] = useState<string | null>(null)\n\n const isModalDisabled = operationInProgress || isAddingNew || specs.some((e) => e.isEditing)\n\n const validateKey = (key: string, rowIndex?: number): string | null => {\n const normalized = key?.trim()\n if (!normalized) {\n return t`Key is required`\n }\n const isDuplicate = specs.some((entry, idx) => entry.key.trim() === normalized && idx !== rowIndex)\n if (isDuplicate) {\n return t`A property with this key already exists`\n }\n return null\n }\n\n const handleAddNew = async () => {\n const keyError = validateKey(newKey, specs.length)\n if (keyError) {\n setErrors({ newKey: \"error\" })\n setValidationMessage(keyError)\n return\n }\n if (!newValue.trim()) {\n setErrors({ newValue: \"error\" })\n setValidationMessage(t`Value is required`)\n return\n }\n\n setOperationInProgress(true)\n try {\n await client.compute.createExtraSpecs.mutate({\n project_id: project,\n flavorId: flavor.id,\n extra_specs: { [newKey.trim()]: newValue.trim() },\n })\n\n setSpecs([...specs, { key: newKey.trim(), value: newValue.trim(), isEditing: false }])\n setNewKey(\"\")\n setNewValue(\"\")\n setIsAddingNew(false)\n setErrors({})\n setValidationMessage(null)\n\n toast.success(t`Property Created`, {\n description: t`Property was successfully created.`,\n })\n } catch (error) {\n const errorMsg = translateError(error instanceof Error ? error.message : \"Failed to create property\")\n setValidationMessage(errorMsg)\n } finally {\n setOperationInProgress(false)\n }\n }\n\n const handleCancelAdd = () => {\n setNewKey(\"\")\n setNewValue(\"\")\n setIsAddingNew(false)\n setErrors({})\n setValidationMessage(null)\n }\n\n const handleEdit = (index: number) => {\n setSpecs(\n specs.map((e, i) => (i === index ? { ...e, isEditing: true, editingValue: e.value } : { ...e, isEditing: false }))\n )\n setIsAddingNew(false)\n }\n\n const handleSaveEdit = async (index: number) => {\n const spec = specs[index]\n\n if (!spec.value.trim()) {\n setErrors({ [`edit-value-${index}`]: \"error\" })\n setValidationMessage(t`Value is required`)\n return\n }\n\n setOperationInProgress(true)\n try {\n const trimmedValue = spec.value.trim()\n\n // Create/update the spec (OpenStack API handles upsert)\n await client.compute.createExtraSpecs.mutate({\n project_id: project,\n flavorId: flavor.id,\n extra_specs: { [spec.key]: trimmedValue },\n })\n\n setSpecs(specs.map((e, i) => (i === index ? { key: spec.key, value: trimmedValue, isEditing: false } : e)))\n setErrors({})\n setValidationMessage(null)\n\n toast.success(t`Property Updated`, {\n description: t`Property was successfully updated.`,\n })\n } catch (error) {\n const errorMsg = translateError(error instanceof Error ? error.message : \"Failed to update property\")\n setValidationMessage(errorMsg)\n } finally {\n setOperationInProgress(false)\n }\n }\n\n const handleCancelEdit = (index: number) => {\n setSpecs(\n specs.map((e, i) => (i === index ? { key: e.key, value: e.editingValue ?? e.value, isEditing: false } : e))\n )\n setErrors({})\n setValidationMessage(null)\n }\n\n const handleDelete = async (index: number) => {\n const spec = specs[index]\n setOperationInProgress(true)\n\n try {\n await client.compute.deleteExtraSpec.mutate({\n project_id: project,\n flavorId: flavor.id,\n key: spec.key,\n })\n\n setSpecs(specs.filter((_, i) => i !== index))\n setErrors({})\n setValidationMessage(null)\n\n toast.success(t`Property Deleted`, {\n description: t`Property was successfully deleted.`,\n })\n } catch (error) {\n const errorMsg = translateError(error instanceof Error ? error.message : \"Failed to delete property\")\n setValidationMessage(errorMsg)\n } finally {\n setOperationInProgress(false)\n }\n }\n\n const handleValueChange = (index: number, value: string) => {\n setSpecs(specs.map((entry, i) => (i === index ? { ...entry, value } : entry)))\n if (errors[`edit-value-${index}`]) {\n setErrors((prev) => {\n const next = { ...prev }\n delete next[`edit-value-${index}`]\n return next\n })\n setValidationMessage(null)\n }\n }\n\n const handleClose = () => {\n if (!operationInProgress) {\n setIsAddingNew(false)\n setNewKey(\"\")\n setNewValue(\"\")\n setErrors({})\n setValidationMessage(null)\n onClose()\n }\n }\n\n return (\n <Modal\n open\n onCancel={handleClose}\n size=\"xl\"\n title={t`Edit Metadata`}\n cancelButtonLabel={t`Close`}\n disableCancelButton={operationInProgress}\n >\n {isLoading ? (\n <Status status=\"progress\" title={t`Loading Metadata...`} className=\"mt-0\" />\n ) : (\n <div>\n {validationMessage && <Message variant=\"error\" text={validationMessage} className=\"mb-4\" />}\n\n <Stack direction=\"horizontal\" className=\"mb-4 justify-end\">\n <Button label={t`Add Property`} onClick={() => setIsAddingNew(true)} disabled={isModalDisabled} />\n </Stack>\n\n {specs.length === 0 && !isAddingNew ? (\n <Status\n status=\"empty\"\n title={t`No Metadata Properties Found`}\n body={t`Click \"Add Property\" to create one.`}\n className=\"m-0\"\n />\n ) : (\n <DescriptionList className=\"mb-6 grid-cols-2\" alignTerms=\"left\">\n <>\n {isAddingNew && (\n <>\n <DescriptionTerm className=\"col-span-1\">\n <TextInput\n value={newKey}\n onChange={(e) => {\n setNewKey(e.target.value)\n if (errors.newKey) {\n setErrors((prev) => {\n const next = { ...prev }\n delete next.newKey\n return next\n })\n setValidationMessage(null)\n }\n }}\n placeholder={t`property_key`}\n invalid={!!errors.newKey}\n autoFocus\n disabled={operationInProgress}\n />\n </DescriptionTerm>\n <DescriptionDefinition className=\"col-span-1 flex items-center gap-2\">\n <div className=\"flex-1\">\n <TextInput\n value={newValue}\n onChange={(e) => {\n setNewValue(e.target.value)\n if (errors.newValue) {\n setErrors((prev) => {\n const next = { ...prev }\n delete next.newValue\n return next\n })\n setValidationMessage(null)\n }\n }}\n placeholder={t`Value`}\n invalid={!!errors.newValue}\n disabled={operationInProgress}\n />\n </div>\n <Stack direction=\"horizontal\" gap=\"2\" className=\"shrink-0\">\n <Button\n size=\"small\"\n variant=\"primary\"\n onClick={handleAddNew}\n icon=\"check\"\n title={t`Save`}\n aria-label={t`Save`}\n disabled={operationInProgress}\n />\n <Button\n size=\"small\"\n variant=\"subdued\"\n onClick={handleCancelAdd}\n icon=\"close\"\n title={t`Discard`}\n aria-label={t`Discard`}\n disabled={operationInProgress}\n />\n </Stack>\n </DescriptionDefinition>\n </>\n )}\n </>\n\n <>\n {specs.map((entry, index) => (\n <React.Fragment key={index}>\n <DescriptionTerm className=\"col-span-1\">\n {entry.isEditing ? (\n <span className=\"jn:text-theme-high block break-all\" title={entry.key}>\n {entry.key}\n </span>\n ) : (\n <span className=\"jn:text-theme-high block break-all\" title={entry.key}>\n {entry.key}\n </span>\n )}\n </DescriptionTerm>\n <DescriptionDefinition className=\"col-span-1 flex items-center gap-2\">\n {entry.isEditing ? (\n <>\n <div className=\"flex-1\">\n <TextInput\n value={entry.value}\n onChange={(e) => handleValueChange(index, e.target.value)}\n invalid={!!errors[`edit-value-${index}`]}\n disabled={operationInProgress}\n />\n </div>\n <Stack direction=\"horizontal\" gap=\"2\" className=\"shrink-0\">\n <Button\n size=\"small\"\n variant=\"primary\"\n onClick={() => handleSaveEdit(index)}\n icon=\"check\"\n title={t`Save`}\n aria-label={t`Save`}\n disabled={operationInProgress}\n />\n <Button\n size=\"small\"\n variant=\"subdued\"\n onClick={() => handleCancelEdit(index)}\n icon=\"close\"\n title={t`Discard`}\n aria-label={t`Discard`}\n disabled={operationInProgress}\n />\n </Stack>\n </>\n ) : (\n <>\n <span className=\"jn:text-theme-default flex-1 break-all\" title={entry.value}>\n {entry.value}\n </span>\n <Stack direction=\"horizontal\" gap=\"2\" className=\"shrink-0\">\n <Button\n size=\"small\"\n variant=\"subdued\"\n onClick={() => handleEdit(index)}\n icon=\"edit\"\n data-testid={`edit-${entry.key}`}\n title={t`Edit`}\n disabled={isModalDisabled}\n />\n <Button\n size=\"small\"\n onClick={() => handleDelete(index)}\n icon=\"deleteForever\"\n data-testid={`delete-${entry.key}`}\n title={t`Delete`}\n aria-label={t`Delete`}\n disabled={isModalDisabled}\n />\n </Stack>\n </>\n )}\n </DescriptionDefinition>\n </React.Fragment>\n ))}\n </>\n </DescriptionList>\n )}\n </div>\n )}\n </Modal>\n )\n}\n\nexport const EditSpecModal: React.FC<EditSpecModalProps> = ({ client, isOpen, onClose, project, flavor }) => {\n const { t } = useLingui()\n const { translateError } = useErrorTranslation()\n\n const [extraSpecsData, setExtraSpecsData] = useState<Record<string, string> | null>(null)\n const [isLoadingSpecs, setIsLoadingSpecs] = useState(false)\n const [loadError, setLoadError] = useState<string | null>(null)\n\n useEffect(() => {\n if (!isOpen || !flavor?.id) {\n setExtraSpecsData(null)\n setLoadError(null)\n return\n }\n\n let cancelled = false\n setIsLoadingSpecs(true)\n setLoadError(null)\n\n const loadData = async () => {\n try {\n const specs = await createExtraSpecsPromise(client, project, flavor.id)\n if (cancelled) return\n setExtraSpecsData(specs)\n } catch (error) {\n if (cancelled) return\n setLoadError(error instanceof Error ? error.message : \"Failed to Load Metadata\")\n } finally {\n if (!cancelled) setIsLoadingSpecs(false)\n }\n }\n\n loadData()\n return () => {\n cancelled = true\n }\n }, [isOpen, flavor?.id, client, project])\n\n const initialSpecs = useMemo(() => (extraSpecsData ? buildInitialSpecs(extraSpecsData) : []), [extraSpecsData])\n\n if (!isOpen || !flavor) {\n return null\n }\n\n if (isLoadingSpecs) {\n return (\n <Modal open onCancel={onClose} size=\"xl\" title={t`Edit Metadata`}>\n <Status status=\"progress\" title={t`Loading Metadata...`} className=\"mt-0\" />\n </Modal>\n )\n }\n\n if (loadError) {\n return (\n <Modal open onCancel={onClose} size=\"xl\" title={t`Edit Metadata`}>\n <Status status=\"error\" title={t`Failed to Load Metadata`} body={translateError(loadError)} className=\"mt-0\" />\n </Modal>\n )\n }\n\n return (\n <EditSpecModalInner\n key={flavor.id}\n client={client}\n project={project}\n flavor={flavor}\n isLoading={false}\n onClose={onClose}\n initialSpecs={initialSpecs}\n />\n )\n}\n","import { ReactNode } from \"react\"\nimport { NotificationOptions } from \"@cloudoperators/juno-ui-components\"\nimport { Trans } from \"@lingui/react/macro\"\n\ntype ToastReturnType = { message: ReactNode } & NotificationOptions\n\nexport const getFlavorCreatedToast = (name: string): ToastReturnType => ({\n message: <Trans>Flavor Created</Trans>,\n description: <Trans>Flavor \"{name}\" was successfully created.</Trans>,\n})\n\nexport const getFlavorDeletedToast = (name: string): ToastReturnType => ({\n message: <Trans>Flavor Deleted</Trans>,\n description: <Trans>Flavor \"{name}\" was successfully deleted.</Trans>,\n})\n\nexport const getFlavorAccessAddedToast = (projectId: string, flavorName: string): ToastReturnType => ({\n message: <Trans>Access Added</Trans>,\n description: (\n <Trans>\n Project \"{projectId}\" now has access to flavor \"{flavorName}\".\n </Trans>\n ),\n})\n\nexport const getFlavorAccessRemovedToast = (projectId: string, flavorName: string): ToastReturnType => ({\n message: <Trans>Access Removed</Trans>,\n description: (\n <Trans>\n Access for project \"{projectId}\" to flavor \"{flavorName}\" was successfully revoked.\n </Trans>\n ),\n})\n\nexport const getFlavorAccessAddErrorToast = (projectId: string, errorMessage: string): ToastReturnType => ({\n message: <Trans>Failed to Add Access</Trans>,\n description: (\n <Trans>\n Could not add access for project \"{projectId}\": {errorMessage}\n </Trans>\n ),\n})\n\nexport const getFlavorAccessRemoveErrorToast = (projectId: string, errorMessage: string): ToastReturnType => ({\n message: <Trans>Failed to Remove Access</Trans>,\n description: (\n <Trans>\n Could not remove access for project \"{projectId}\": {errorMessage}\n </Trans>\n ),\n})\n","import React, { useState, useEffect, useMemo } from \"react\"\nimport { TrpcClient } from \"@/client/trpcClient\"\nimport { useLingui } from \"@lingui/react/macro\"\nimport { useErrorTranslation } from \"@/client/utils/useErrorTranslation\"\nimport {\n Modal,\n Message,\n DescriptionList,\n DescriptionTerm,\n DescriptionDefinition,\n Stack,\n Status,\n Button,\n TextInput,\n toast,\n} from \"@cloudoperators/juno-ui-components\"\nimport { Flavor } from \"@/server/Compute/types/flavor\"\nimport {\n getFlavorAccessAddedToast,\n getFlavorAccessRemovedToast,\n getFlavorAccessRemoveErrorToast,\n} from \"./FlavorToastNotifications\"\n\ninterface ManageAccessProps {\n client: TrpcClient\n isOpen: boolean\n onClose: () => void\n project: string\n flavor: Flavor | null\n}\n\ninterface FlavorAccess {\n flavor_id: string\n tenant_id: string\n}\n\ninterface AccessEntry {\n projectId: string\n}\n\nfunction buildInitialAccess(flavorAccess: FlavorAccess[]): AccessEntry[] {\n return flavorAccess.map((access) => ({\n projectId: access.tenant_id,\n }))\n}\n\nconst createPermissionsPromise = (client: TrpcClient, project: string) => {\n return client.compute.canUser\n .query({\n project_id: project,\n permission: [\"flavors:add_project\", \"flavors:remove_project\"],\n })\n .then(([canAdd, canRemove]) => ({ canAdd, canRemove }))\n}\n\nconst createFlavorAccessPromise = (client: TrpcClient, project: string, flavorId: string) => {\n return client.compute.getFlavorAccess.query({\n project_id: project,\n flavorId: flavorId,\n })\n}\n\nfunction ManageAccessModalInner({\n client,\n project,\n flavor,\n isLoading,\n onClose,\n initialAccess,\n canAdd,\n canRemove,\n}: {\n client: TrpcClient\n project: string\n flavor: Flavor\n isLoading: boolean\n onClose: () => void\n initialAccess: AccessEntry[]\n canAdd: boolean\n canRemove: boolean\n}) {\n const { t } = useLingui()\n const { translateError } = useErrorTranslation()\n\n const [access, setAccess] = useState<AccessEntry[]>(initialAccess)\n const [errors, setErrors] = useState<{ [key: string]: string }>({})\n const [isAddingNew, setIsAddingNew] = useState(false)\n const [newProjectId, setNewProjectId] = useState(\"\")\n const [deletingProjectIds, setDeletingProjectIds] = useState<Set<string>>(new Set())\n const [addingProjectId, setAddingProjectId] = useState(false)\n\n const isPublicFlavor = flavor[\"os-flavor-access:is_public\"] !== false\n\n const validateProjectId = (projectId: string): string | null => {\n const normalized = projectId?.trim()\n if (!normalized) {\n return t`Project ID is required`\n }\n const isDuplicate = access.some((entry) => entry.projectId.trim() === normalized)\n if (isDuplicate) {\n return t`This project already has access`\n }\n return null\n }\n\n const handleAddNew = async () => {\n const error = validateProjectId(newProjectId)\n if (error) {\n setErrors({ newProjectId: error })\n return\n }\n\n const trimmedProjectId = newProjectId.trim()\n setAddingProjectId(true)\n setErrors({})\n\n try {\n await client.compute.addTenantAccess.mutate({\n project_id: project,\n flavorId: flavor.id,\n targetProjectId: trimmedProjectId,\n })\n\n setAccess((prev) => [...prev, { projectId: trimmedProjectId }])\n setNewProjectId(\"\")\n setIsAddingNew(false)\n\n const { message, ...options } = getFlavorAccessAddedToast(trimmedProjectId, flavor.name)\n toast.success(message, options)\n } catch (error) {\n const errorMessage = translateError(error instanceof Error ? error.message : \"Failed to add access\")\n setErrors({ newProjectId: errorMessage })\n // Error shown inline via Message component above the form\n } finally {\n setAddingProjectId(false)\n }\n }\n\n const handleCancelAdd = () => {\n setNewProjectId(\"\")\n setIsAddingNew(false)\n setErrors({})\n }\n\n const handleDelete = async (projectId: string) => {\n setErrors({})\n setDeletingProjectIds((prev) => new Set(prev).add(projectId))\n\n try {\n await client.compute.removeTenantAccess.mutate({\n project_id: project,\n flavorId: flavor.id,\n targetProjectId: projectId,\n })\n\n setAccess((prev) => prev.filter((a) => a.projectId !== projectId))\n\n const { message, ...options } = getFlavorAccessRemovedToast(projectId, flavor.name)\n toast.success(message, options)\n } catch (error) {\n const errorMessage = translateError(error instanceof Error ? error.message : \"Failed to remove access\")\n const { message, ...options } = getFlavorAccessRemoveErrorToast(projectId, errorMessage)\n toast.error(message, options)\n } finally {\n setDeletingProjectIds((prev) => {\n const next = new Set(prev)\n next.delete(projectId)\n return next\n })\n }\n }\n\n const handleClose = () => {\n setIsAddingNew(false)\n setNewProjectId(\"\")\n setErrors({})\n onClose()\n }\n\n if (isPublicFlavor) {\n const flavorName = flavor.name\n return (\n <Modal open onCancel={handleClose} size=\"large\" title={t`Manage Access - ${flavorName}`}>\n <p className=\"jn:text-theme-light py-8 text-center\">\n {t`This is a public flavor. All projects have access to it.`}\n </p>\n </Modal>\n )\n }\n\n const flavorName = flavor.name\n const isAnyOperationInProgress = addingProjectId || deletingProjectIds.size > 0\n\n return (\n <Modal open onCancel={handleClose} size=\"large\" title={t`Manage Access - ${flavorName}`}>\n {isLoading ? (\n <Status status=\"progress\" title={t`Loading Access...`} className=\"mt-0\" />\n ) : (\n <div>\n {errors.newProjectId && <Message variant=\"error\" text={errors.newProjectId} className=\"mb-4\" />}\n\n {canAdd && (\n <Stack direction=\"horizontal\" className=\"mb-4 justify-end\">\n <Button\n label={t`Add Project`}\n onClick={() => setIsAddingNew(true)}\n disabled={isAddingNew || isAnyOperationInProgress}\n />\n </Stack>\n )}\n\n {access.length === 0 && !isAddingNew ? (\n <p className=\"jn:text-theme-light py-8 text-center\">\n {canAdd\n ? t`No project access configured. Click \"Add Project\" to grant access.`\n : t`No project access configured.`}\n </p>\n ) : (\n <DescriptionList className=\"mb-6\">\n <>\n {isAddingNew && (\n <>\n <DescriptionTerm className=\"flex items-center justify-end\">\n <span className=\"jn:text-theme-high\">{t`Project`}</span>\n </DescriptionTerm>\n <DescriptionDefinition>\n <div className=\"flex w-full items-center gap-2\">\n <div className=\"flex-1\">\n <TextInput\n value={newProjectId}\n onChange={(e) => {\n setNewProjectId(e.target.value)\n if (errors.newProjectId) {\n setErrors({})\n }\n }}\n placeholder={t`Enter project ID`}\n invalid={!!errors.newProjectId}\n autoFocus\n wrapperClassName=\"w-full\"\n disabled={addingProjectId}\n />\n </div>\n <div className=\"flex shrink-0 gap-2\">\n <Button\n size=\"small\"\n variant=\"primary\"\n onClick={handleAddNew}\n icon=\"check\"\n title={t`Add`}\n disabled={addingProjectId}\n progress={addingProjectId}\n />\n <Button\n size=\"small\"\n variant=\"subdued\"\n onClick={handleCancelAdd}\n icon=\"close\"\n title={t`Cancel`}\n disabled={addingProjectId}\n />\n </div>\n </div>\n </DescriptionDefinition>\n </>\n )}\n </>\n\n <>\n {access.map((entry) => {\n const isDeleting = deletingProjectIds.has(entry.projectId)\n return (\n <React.Fragment key={entry.projectId}>\n <DescriptionTerm>\n <span className=\"jn:text-theme-high\">{t`Project`}</span>\n </DescriptionTerm>\n <DescriptionDefinition>\n <Stack direction=\"horizontal\" gap=\"2\" alignment=\"center\" className=\"justify-between\">\n <span className=\"jn:text-theme-high block max-w-xs truncate\" title={entry.projectId}>\n {entry.projectId}\n </span>\n {canRemove && (\n <Button\n size=\"small\"\n onClick={() => handleDelete(entry.projectId)}\n icon=\"deleteForever\"\n data-testid={`delete-${entry.projectId}`}\n title={t`Remove`}\n disabled={isDeleting || isAddingNew}\n progress={isDeleting}\n />\n )}\n </Stack>\n </DescriptionDefinition>\n </React.Fragment>\n )\n })}\n </>\n </DescriptionList>\n )}\n </div>\n )}\n </Modal>\n )\n}\n\nexport const ManageAccessModal: React.FC<ManageAccessProps> = ({ client, isOpen, onClose, project, flavor }) => {\n const { t } = useLingui()\n const { translateError } = useErrorTranslation()\n\n const [flavorAccessData, setFlavorAccessData] = useState<FlavorAccess[] | null>(null)\n const [permissionsData, setPermissionsData] = useState<{ canAdd: boolean; canRemove: boolean } | null>(null)\n const [isLoadingData, setIsLoadingData] = useState(true)\n const [loadError, setLoadError] = useState<string | null>(null)\n\n useEffect(() => {\n if (!isOpen || !flavor?.id) {\n setFlavorAccessData(null)\n setPermissionsData(null)\n setLoadError(null)\n return\n }\n\n let cancelled = false\n setIsLoadingData(true)\n setLoadError(null)\n\n const loadData = async () => {\n try {\n const [accessData, permissions] = await Promise.all([\n createFlavorAccessPromise(client, project, flavor.id),\n createPermissionsPromise(client, project),\n ])\n if (cancelled) return\n // Deduplicate\n const deduped = accessData.filter(\n (entry, idx, arr) => arr.findIndex((e) => e.tenant_id === entry.tenant_id) === idx\n )\n setFlavorAccessData(deduped)\n setPermissionsData(permissions)\n } catch (error) {\n if (cancelled) return\n setLoadError(error instanceof Error ? error.message : \"Failed to Load Access Data\")\n } finally {\n if (!cancelled) setIsLoadingData(false)\n }\n }\n\n loadData()\n return () => {\n cancelled = true\n }\n }, [isOpen, flavor?.id, client, project])\n\n const initialAccess = useMemo(\n () => (flavorAccessData ? buildInitialAccess(flavorAccessData) : []),\n [flavorAccessData]\n )\n\n if (!isOpen || !flavor) {\n return null\n }\n\n const flavorName = flavor.name\n\n if (isLoadingData) {\n return (\n <Modal open onCancel={onClose} size=\"large\" title={t`Manage Access - ${flavorName}`}>\n <Status status=\"progress\" title={t`Loading Access...`} className=\"mt-0\" />\n </Modal>\n )\n }\n\n if (loadError) {\n return (\n <Modal open onCancel={onClose} size=\"large\" title={t`Manage Access - ${flavorName}`}>\n <Status status=\"error\" title={t`Failed to Load Access`} body={translateError(loadError)} className=\"mt-0\" />\n </Modal>\n )\n }\n\n return (\n <ManageAccessModalInner\n key={flavor.id}\n client={client}\n project={project}\n flavor={flavor}\n isLoading={false}\n onClose={onClose}\n initialAccess={initialAccess}\n canAdd={permissionsData?.canAdd ?? false}\n canRemove={permissionsData?.canRemove ?? false}\n />\n )\n}\n","import { z } from \"zod\"\nimport { useForm, useStore } from \"@tanstack/react-form\"\nimport React, { useState } from \"react\"\nimport { useLingui } from \"@lingui/react/macro\"\nimport { TrpcClient } from \"@/client/trpcClient\"\nimport {\n Modal,\n Stack,\n Form,\n FormSection,\n TextInput,\n DescriptionList,\n DescriptionTerm,\n DescriptionDefinition,\n Message,\n} from \"@cloudoperators/juno-ui-components\"\nimport { Flavor } from \"@/server/Compute/types/flavor\"\nimport { Trans } from \"@lingui/react/macro\"\nimport { useErrorTranslation } from \"@/client/utils/useErrorTranslation\"\nimport { useModalTracking } from \"@/client/hooks/useModalTracking\"\n\ninterface DeleteFlavorModalProps {\n client: TrpcClient\n isOpen: boolean\n onClose: () => void\n project: string\n flavor: Flavor | null\n onSuccess: () => void\n}\n\nexport const DeleteFlavorModal: React.FC<DeleteFlavorModalProps> = ({\n client,\n isOpen,\n onClose,\n project,\n flavor,\n onSuccess,\n}) => {\n const { t } = useLingui()\n const { translateError } = useErrorTranslation()\n const [isLoading, setIsLoading] = useState(false)\n const [formError, setFormError] = useState<string | null>(null)\n\n const { trackClose, markSubmitted, resetTracking } = useModalTracking({\n isOpen,\n actionPrefix: \"compute.flavor.delete\",\n })\n\n const formSchema = z.object({\n confirm: z.string().refine((value) => value === \"delete\", {\n message: t`Type \"delete\" to confirm`,\n }),\n })\n\n const form = useForm({\n defaultValues: {\n confirm: \"\",\n },\n validators: {\n onSubmit: formSchema,\n },\n onSubmit: async () => {\n if (!flavor?.id) {\n setFormError(t`No flavor selected for deletion.`)\n return\n }\n\n if (isLoading) return\n\n markSubmitted()\n setFormError(null)\n\n try {\n setIsLoading(true)\n\n await client.compute.deleteFlavor.mutate({\n project_id: project,\n flavorId: flavor.id,\n })\n onSuccess()\n handleClose()\n } catch (error) {\n const errorMessage = (error as Error)?.message\n ? translateError((error as Error).message)\n : t`Failed to delete flavor. Please try again.`\n setFormError(errorMessage)\n } finally {\n setIsLoading(false)\n }\n },\n })\n\n const canDelete = useStore(form.store, (state) => state.isSubmitting || state.values.confirm !== \"delete\")\n\n const handleClose = () => {\n trackClose()\n setIsLoading(false)\n setFormError(null)\n form.reset()\n resetTracking()\n onClose()\n }\n\n const confirmLabel = isLoading ? t`Deleting...` : t`Delete Flavor`\n const flavorName = flavor?.name\n\n return (\n <Modal\n open={isOpen}\n onCancel={handleClose}\n title={t`Delete Flavor \"${flavorName}\"`}\n size=\"small\"\n confirmButtonLabel={confirmLabel}\n confirmButtonVariant=\"primary-danger\"\n onConfirm={form.handleSubmit}\n cancelButtonLabel={t`Cancel`}\n disableConfirmButton={canDelete || isLoading}\n disableCancelButton={isLoading}\n disableCloseButton={isLoading}\n >\n <Stack direction=\"vertical\" gap=\"4\">\n {formError && <Message variant=\"error\">{formError}</Message>}\n\n <p className=\"text-theme-default\">\n <Trans>This action cannot be undone. The flavor will be permanently deleted.</Trans>\n </p>\n\n {flavor && (\n <DescriptionList>\n <DescriptionTerm>{t`Name`}</DescriptionTerm>\n <DescriptionDefinition>{flavor.name}</DescriptionDefinition>\n\n <DescriptionTerm>{t`ID`}</DescriptionTerm>\n <DescriptionDefinition>{flavor.id}</DescriptionDefinition>\n\n <DescriptionTerm>{t`VCPUs`}</DescriptionTerm>\n <DescriptionDefinition>{flavor.vcpus}</DescriptionDefinition>\n\n <DescriptionTerm>{t`RAM`}</DescriptionTerm>\n <DescriptionDefinition>{flavor.ram} MiB</DescriptionDefinition>\n\n <DescriptionTerm>{t`Disk`}</DescriptionTerm>\n <DescriptionDefinition>{flavor.disk} GiB</DescriptionDefinition>\n\n <DescriptionTerm>{t`Swap`}</DescriptionTerm>\n <DescriptionDefinition>\n {flavor.swap === 0 || flavor.swap === \"\" ? <Trans>None</Trans> : `${Number(flavor.swap)} MiB`}\n </DescriptionDefinition>\n </DescriptionList>\n )}\n\n <Form\n className=\"mb-0\"\n id=\"delete-flavor-form\"\n onSubmit={(e) => {\n e.preventDefault()\n form.handleSubmit()\n }}\n >\n <FormSection>\n <form.Field\n name=\"confirm\"\n children={(field) => (\n <TextInput\n id={field.name}\n name={field.name}\n label={t`Type \"delete\" to confirm`}\n value={field.state.value}\n onChange={(e) => field.handleChange(e.target.value)}\n placeholder=\"delete\"\n autoFocus\n disabled={isLoading}\n required\n />\n )}\n />\n </FormSection>\n </Form>\n </Stack>\n </Modal>\n )\n}\n"],"mappings":"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"}
@@ -3,24 +3,24 @@ import { jsx as n } from "react/jsx-runtime";
3
3
  import { useNavigate as r, useParams as i } from "@tanstack/react-router";
4
4
  import { useLingui as a } from "@lingui/react";
5
5
  //#region src/client/components/Errors/RouteIdLevelDefaultError.tsx
6
- var o = ({ errorTitle: o, errorDescription: s, action: c }) => {
7
- let { i18n: l, _: u } = a(), d = r(), { projectId: f } = i({ strict: !1 });
6
+ var o = ({ errorTitle: o, errorDescription: s, action: c, code: l = 404 }) => {
7
+ let { i18n: u, _: d } = a(), f = r(), { projectId: p } = i({ strict: !1 });
8
8
  return /*#__PURE__*/ n(t, {
9
- code: 404,
9
+ code: l ?? void 0,
10
10
  status: "error",
11
- title: o || l._({ id: "NcFUCo" }),
12
- body: s || l._({ id: "eHWorn" }),
11
+ title: o || u._({ id: "NcFUCo" }),
12
+ body: s || u._({ id: "eHWorn" }),
13
13
  action: c ?? /*#__PURE__*/ n(e, {
14
14
  variant: "primary",
15
- onClick: () => d(f ? {
15
+ onClick: () => f(p ? {
16
16
  to: "/projects/$projectId",
17
- params: { projectId: f }
17
+ params: { projectId: p }
18
18
  } : { to: "/" }),
19
- children: f ? l._({ id: "u4xWZf" }) : l._({ id: "UmuIdg" })
19
+ children: p ? u._({ id: "u4xWZf" }) : u._({ id: "UmuIdg" })
20
20
  })
21
21
  });
22
22
  };
23
23
  //#endregion
24
24
  export { o as t };
25
25
 
26
- //# sourceMappingURL=RouteIdLevelDefaultError-CSseJ1yG.mjs.map
26
+ //# sourceMappingURL=RouteIdLevelDefaultError-DPF_x2tG.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"RouteIdLevelDefaultError-DPF_x2tG.mjs","names":["useParams","useNavigate","Button","Status","RouteIdLevelDefaultError","errorTitle","errorDescription","action","code","useLingui","navigate","projectId","strict","navigateToProjectId","to","params","undefined","status","title","t","body","variant","onClick"],"sources":["../../src/client/components/Errors/RouteIdLevelDefaultError.tsx"],"sourcesContent":["import { ReactNode } from \"react\"\nimport { useLingui } from \"@lingui/react/macro\"\nimport { useParams, useNavigate } from \"@tanstack/react-router\"\nimport { Button, Status } from \"@cloudoperators/juno-ui-components\"\n\ninterface RouteIdLevelDefaultErrorProps {\n errorTitle?: string\n errorDescription?: string\n action?: ReactNode\n code?: number | string | null\n}\n\n/**\n * Renders the default error state for resource detail pages at the route-ID\n * level, while keeping the surrounding application layout visible.\n *\n * This is similar to the service-level not-found component, but remains\n * separate to make route error handling easier to trace. Callers can provide\n * resource-specific titles, descriptions, and actions; otherwise, the default\n * action navigates back to the current project.\n */\nexport const RouteIdLevelDefaultError = ({\n errorTitle,\n errorDescription,\n action,\n code = 404,\n}: RouteIdLevelDefaultErrorProps) => {\n const { t } = useLingui()\n const navigate = useNavigate()\n const { projectId } = useParams({ strict: false })\n\n const navigateToProjectId = () =>\n projectId ? navigate({ to: \"/projects/$projectId\", params: { projectId } }) : navigate({ to: \"/\" })\n\n return (\n <Status\n code={code ?? undefined}\n status=\"error\"\n title={errorTitle || t`Resource Not Found`}\n body={errorDescription || t`The Resource you are looking for does not exist or is not accessible.`}\n action={\n action ?? (\n <Button variant=\"primary\" onClick={navigateToProjectId}>\n {projectId ? t`Go to Project Home` : t`Go to Home`}\n </Button>\n )\n }\n />\n )\n}\n"],"mappings":";;;;;AAqBA,IAAaI,KAA4B,EACvCC,eACAC,qBACAC,WACAC,UAAO,UACuB;CAC9B,IAAM,EAAA,MAAA,GAAA,GAAA,MAAQC,EAAAA,GACRC,IAAWT,EAAAA,GACX,EAAEU,iBAAcX,EAAU,EAAEY,QAAQ,GAAM,CAAA;CAKhD,OACE,gBAACT,GAAAA;EACCK,MAAMA,KAAQQ,KAAAA;EACdC,QAAO;EACPC,OAAOb,KAAcc,EAAAA,EAAC,EAAA,IAAA,SAAmB,CAAA;EACzCC,MAAMd,KAAoBa,EAAAA,EAAC,EAAA,IAAA,SAAsE,CAAA;EACjGZ,QACEA,KACE,gBAACL,GAAAA;GAAOmB,SAAQ;GAAUC,eAVpBZ,EAAZC,IAAqB;IAAEG,IAAI;IAAwBC,QAAQ,EAAEJ,aAAU;GAAE,IAAc,EAAEG,IAAI,IAAI,CAAA;GAWxFH,UAAAA,IAAYQ,EAAAA,EAAC,EAAA,IAAA,SAAmB,CAAA,IAAIA,EAAAA,EAAC,EAAA,IAAA,SAAW,CAAA;;;AAM7D"}
@@ -0,0 +1,30 @@
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
@@ -0,0 +1 @@
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,10 +1,10 @@
1
1
  import { A as e, D as t, E as n, M as r, Q as i, at as a, c as o, g as s, i as c, n as l, r as u, rt as d, s as f, x as p } from "./build-WuxXRAqf.mjs";
2
2
  import { a as m } from "./trpcClient-D7gpR7YG.mjs";
3
- import { t as h } from "./_flavorId-CaA4-Pnf.mjs";
3
+ import { t as h } from "./_flavorId-CgueqKTs.mjs";
4
4
  import { t as g } from "./useProjectId-DBc5lpoU.mjs";
5
- import { n as _, t as v } from "./ContentHeader-CPJbgYWn.mjs";
5
+ import { n as _, t as v } from "./ContentHeader-fKKZVu-o.mjs";
6
6
  import { t as y } from "./useSetBreadcrumb-tn7lBaQV.mjs";
7
- import { a as b, n as x, o as S, t as C } from "./DeleteFlavorModal-C2MqUgGR.mjs";
7
+ import { a as b, n as x, o as S, t as C } from "./DeleteFlavorModal-Be2GFiB_.mjs";
8
8
  import { t as w } from "./useModal-DCs1OJh7.mjs";
9
9
  import { Fragment as T, jsx as E, jsxs as D } from "react/jsx-runtime";
10
10
  import { Fragment as O } from "react";
@@ -273,4 +273,4 @@ function M() {
273
273
  //#endregion
274
274
  export { M as component };
275
275
 
276
- //# sourceMappingURL=_flavorId-DYv_StX22.mjs.map
276
+ //# sourceMappingURL=_flavorId-0PioWpEp.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"_flavorId-0PioWpEp.mjs","names":["Stack","ContentHeading","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","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 ContentHeading,\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 <ContentHeading>\n <Trans>Flavor Information</Trans>\n </ContentHeading>\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 <ContentHeading>\n <Trans>Hardware Specifications</Trans>\n </ContentHeading>\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 <ContentHeading>\n <Trans>Metadata</Trans>\n </ContentHeading>\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":"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"}
@@ -1,6 +1,6 @@
1
1
  import { i as e } from "./build-WuxXRAqf.mjs";
2
- import { t } from "./_flavorId-CaA4-Pnf.mjs";
3
- import { t as n } from "./RouteIdLevelDefaultError-CSseJ1yG.mjs";
2
+ import { t } from "./_flavorId-CgueqKTs.mjs";
3
+ import { t as n } from "./RouteIdLevelDefaultError-DPF_x2tG.mjs";
4
4
  import { jsx as r } from "react/jsx-runtime";
5
5
  import { useNavigate as i } from "@tanstack/react-router";
6
6
  import { useLingui as a } from "@lingui/react";
@@ -19,4 +19,4 @@ function o() {
19
19
  //#endregion
20
20
  export { o as errorComponent };
21
21
 
22
- //# sourceMappingURL=_flavorId-YV3jCS5g.mjs.map
22
+ //# sourceMappingURL=_flavorId-B7fp6Nk8.mjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"_flavorId-YV3jCS5g.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"}
1
+ {"version":3,"file":"_flavorId-B7fp6Nk8.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"}