@cobaltcore-dev/aurora 0.5.0 → 0.6.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 (113) hide show
  1. package/dist/client/{ContentHeader-xQVhO2yT.mjs → ContentHeader-kx1Th5Sq.mjs} +18 -18
  2. package/dist/client/{ContentHeader-xQVhO2yT.mjs.map → ContentHeader-kx1Th5Sq.mjs.map} +1 -1
  3. package/dist/client/{DeleteFlavorModal-CHTUZ3YV.mjs → DeleteFlavorModal-C3cb7YiJ.mjs} +155 -155
  4. package/dist/client/{DeleteFlavorModal-CHTUZ3YV.mjs.map → DeleteFlavorModal-C3cb7YiJ.mjs.map} +1 -1
  5. package/dist/client/{EditSecurityGroupModal-CWHHx2Xk.mjs → EditSecurityGroupModal-CpP54WIK.mjs} +18 -18
  6. package/dist/client/{EditSecurityGroupModal-CWHHx2Xk.mjs.map → EditSecurityGroupModal-CpP54WIK.mjs.map} +1 -1
  7. package/dist/client/{FiltersInput-UKJpNFdr.mjs → FiltersInput-DxcyR6Bp.mjs} +18 -18
  8. package/dist/client/{FiltersInput-UKJpNFdr.mjs.map → FiltersInput-DxcyR6Bp.mjs.map} +1 -1
  9. package/dist/client/{FloatingIpActionModals-caXn6bYo.mjs → FloatingIpActionModals-BP8RWHbu.mjs} +55 -55
  10. package/dist/client/{FloatingIpActionModals-caXn6bYo.mjs.map → FloatingIpActionModals-BP8RWHbu.mjs.map} +1 -1
  11. package/dist/client/{ImageToastNotifications-BWimIzu_.mjs → ImageToastNotifications-TZ3EfQg-.mjs} +323 -371
  12. package/dist/client/ImageToastNotifications-TZ3EfQg-.mjs.map +1 -0
  13. package/dist/client/{RouteError-CUj_m3gu.mjs → RouteError-QSV7qOoJ.mjs} +2 -2
  14. package/dist/client/{RouteError-CUj_m3gu.mjs.map → RouteError-QSV7qOoJ.mjs.map} +1 -1
  15. package/dist/client/{SortInput-GQlQBlAj.mjs → SortInput-CYv2_Pur.mjs} +5 -5
  16. package/dist/client/{SortInput-GQlQBlAj.mjs.map → SortInput-CYv2_Pur.mjs.map} +1 -1
  17. package/dist/client/{_flavorId-sUWG0xuy.mjs → _flavorId-C2x43-6S.mjs} +9 -9
  18. package/dist/client/{_flavorId-sUWG0xuy.mjs.map → _flavorId-C2x43-6S.mjs.map} +1 -1
  19. package/dist/client/{_flavorId-C5dc1N_j.mjs → _flavorId-CR8ZUI-P.mjs} +46 -46
  20. package/dist/client/{_flavorId-C5dc1N_j.mjs.map → _flavorId-CR8ZUI-P.mjs.map} +1 -1
  21. package/dist/client/{_floatingIpId-CT4y-60o.mjs → _floatingIpId-BCk41_Lb.mjs} +2 -2
  22. package/dist/client/{_floatingIpId-CT4y-60o.mjs.map → _floatingIpId-BCk41_Lb.mjs.map} +1 -1
  23. package/dist/client/{_floatingIpId-COK_TBrz2.mjs → _floatingIpId-BGrOAmPT.mjs} +33 -33
  24. package/dist/client/_floatingIpId-BGrOAmPT.mjs.map +1 -0
  25. package/dist/client/_imageId-CvfD832b.mjs +534 -0
  26. package/dist/client/{_imageId-n3RcnhAR.mjs.map → _imageId-CvfD832b.mjs.map} +1 -1
  27. package/dist/client/_pcaId-BxBt5DXi.mjs +459 -0
  28. package/dist/client/_pcaId-BxBt5DXi.mjs.map +1 -0
  29. package/dist/client/{_pcaId-ChnM_t-9.mjs → _pcaId-DOHycvCf.mjs} +2 -2
  30. package/dist/client/{_pcaId-ChnM_t-9.mjs.map → _pcaId-DOHycvCf.mjs.map} +1 -1
  31. package/dist/client/{_projectId-26bw-_rm.mjs → _projectId-BDSWnMGj.mjs} +3 -3
  32. package/dist/client/{_projectId-26bw-_rm.mjs.map → _projectId-BDSWnMGj.mjs.map} +1 -1
  33. package/dist/client/{_projectId-Dhb4AyBD.mjs → _projectId-DOgwFiqD.mjs} +2 -2
  34. package/dist/client/{_projectId-Dhb4AyBD.mjs.map → _projectId-DOgwFiqD.mjs.map} +1 -1
  35. package/dist/client/_projectId-DS4nR59B.mjs +299 -0
  36. package/dist/client/_projectId-DS4nR59B.mjs.map +1 -0
  37. package/dist/client/{_projectId-BK9UqeYw.mjs → _projectId-MxcHrXW4.mjs} +12 -12
  38. package/dist/client/_projectId-MxcHrXW4.mjs.map +1 -0
  39. package/dist/client/{_securityGroupId-CR1mKICQ.mjs → _securityGroupId-CJJanWiY.mjs} +2 -2
  40. package/dist/client/{_securityGroupId-CR1mKICQ.mjs.map → _securityGroupId-CJJanWiY.mjs.map} +1 -1
  41. package/dist/client/{_securityGroupId-DroYG6cA.mjs → _securityGroupId-KKw4RPdH.mjs} +328 -328
  42. package/dist/client/{_securityGroupId-DroYG6cA.mjs.map → _securityGroupId-KKw4RPdH.mjs.map} +1 -1
  43. package/dist/client/{containers-DGY2hoWw.mjs → _storageType-4wSxI__0.mjs} +18 -15
  44. package/dist/client/_storageType-4wSxI__0.mjs.map +1 -0
  45. package/dist/client/{containers-ZMFTRaQL.mjs → _storageType-DYjo-6ej.mjs} +1054 -1088
  46. package/dist/client/_storageType-DYjo-6ej.mjs.map +1 -0
  47. package/dist/client/{containers-xfsYgRyf.mjs → _storageType-zeSZe--V.mjs} +2 -2
  48. package/dist/client/_storageType-zeSZe--V.mjs.map +1 -0
  49. package/dist/client/{about-969pIiZ9.mjs → about-Bo9vxGHy.mjs} +8 -8
  50. package/dist/client/{about-969pIiZ9.mjs.map → about-Bo9vxGHy.mjs.map} +1 -1
  51. package/dist/client/{build-DracvfrJ.mjs → build-DeJcDjPi.mjs} +3798 -3372
  52. package/dist/client/build-DeJcDjPi.mjs.map +1 -0
  53. package/dist/client/constants-BmcGYeR-.mjs +153 -0
  54. package/dist/client/constants-BmcGYeR-.mjs.map +1 -0
  55. package/dist/client/{flavors-C4GtoybP.mjs → flavors-BxFVqgnb.mjs} +2 -2
  56. package/dist/client/{flavors-C4GtoybP.mjs.map → flavors-BxFVqgnb.mjs.map} +1 -1
  57. package/dist/client/{flavors-CpirO_nr.mjs → flavors-CfdgjsZY.mjs} +192 -192
  58. package/dist/client/{flavors-CpirO_nr.mjs.map → flavors-CfdgjsZY.mjs.map} +1 -1
  59. package/dist/client/{floatingips-BUf_oLRl.mjs → floatingips-ByRb82wS.mjs} +123 -123
  60. package/dist/client/{floatingips-BUf_oLRl.mjs.map → floatingips-ByRb82wS.mjs.map} +1 -1
  61. package/dist/client/{images-Da1t5KPh.mjs → images-CKqIXUq52.mjs} +613 -613
  62. package/dist/client/images-CKqIXUq52.mjs.map +1 -0
  63. package/dist/client/{images-CsonlmFx.mjs → images-C_dX7nY6.mjs} +2 -2
  64. package/dist/client/{images-CsonlmFx.mjs.map → images-C_dX7nY6.mjs.map} +1 -1
  65. package/dist/client/{images-QnWf63uj.mjs → images-CenluYV8.mjs} +2 -2
  66. package/dist/client/{images-QnWf63uj.mjs.map → images-CenluYV8.mjs.map} +1 -1
  67. package/dist/client/index.js +382 -425
  68. package/dist/client/index.js.map +1 -1
  69. package/dist/client/{md-sBiSNVSQ.mjs → md-CYTrL5dq.mjs} +52 -16
  70. package/dist/client/{md-sBiSNVSQ.mjs.map → md-CYTrL5dq.mjs.map} +1 -1
  71. package/dist/client/{objects-H0NN_Sja.mjs → objects-BJM6YeuF.mjs} +2131 -1883
  72. package/dist/client/objects-BJM6YeuF.mjs.map +1 -0
  73. package/dist/client/{objects-B89dYCBq.mjs → objects-gxSjvbvF.mjs} +36 -21
  74. package/dist/client/objects-gxSjvbvF.mjs.map +1 -0
  75. package/dist/client/{objects-CuFLUOe1.mjs → objects-o2Cj_ndZ.mjs} +2 -2
  76. package/dist/client/objects-o2Cj_ndZ.mjs.map +1 -0
  77. package/dist/client/{pca-CtU6REww.mjs → pca-Bl8NmoVZ.mjs} +2 -2
  78. package/dist/client/{pca-CtU6REww.mjs.map → pca-Bl8NmoVZ.mjs.map} +1 -1
  79. package/dist/client/pca-RSiWpJs9.mjs +182 -0
  80. package/dist/client/pca-RSiWpJs9.mjs.map +1 -0
  81. package/dist/client/{projects-DNXsDnJM.mjs → projects-CgclWI16.mjs} +33 -27
  82. package/dist/client/{projects-DNXsDnJM.mjs.map → projects-CgclWI16.mjs.map} +1 -1
  83. package/dist/client/{projects-dhnQkuvV.mjs → projects-D2iewAzu.mjs} +2 -2
  84. package/dist/client/{projects-dhnQkuvV.mjs.map → projects-D2iewAzu.mjs.map} +1 -1
  85. package/dist/client/{projects-C-sjd9T5.mjs → projects-pe2_dCnV.mjs} +2 -2
  86. package/dist/client/{projects-C-sjd9T5.mjs.map → projects-pe2_dCnV.mjs.map} +1 -1
  87. package/dist/client/projects-yiK0HGSA.mjs.map +1 -1
  88. package/dist/client/{securitygroups-wHdrxZXd.mjs → securitygroups-DahZkVYQ.mjs} +111 -111
  89. package/dist/client/{securitygroups-wHdrxZXd.mjs.map → securitygroups-DahZkVYQ.mjs.map} +1 -1
  90. package/dist/client/{useListWithFiltering-DrgUwXef.mjs → useListWithFiltering-DaYcu5AB.mjs} +12 -12
  91. package/dist/client/{useListWithFiltering-DrgUwXef.mjs.map → useListWithFiltering-DaYcu5AB.mjs.map} +1 -1
  92. package/dist/server/index.js +7 -6
  93. package/package.json +4 -4
  94. package/dist/client/ImageToastNotifications-BWimIzu_.mjs.map +0 -1
  95. package/dist/client/_floatingIpId-COK_TBrz2.mjs.map +0 -1
  96. package/dist/client/_imageId-n3RcnhAR.mjs +0 -534
  97. package/dist/client/_pcaId-B-f_6kqs.mjs +0 -466
  98. package/dist/client/_pcaId-B-f_6kqs.mjs.map +0 -1
  99. package/dist/client/_projectId-BK9UqeYw.mjs.map +0 -1
  100. package/dist/client/_projectId-CCtpAQ8m.mjs +0 -299
  101. package/dist/client/_projectId-CCtpAQ8m.mjs.map +0 -1
  102. package/dist/client/build-DracvfrJ.mjs.map +0 -1
  103. package/dist/client/constants-4lVQXort.mjs +0 -128
  104. package/dist/client/constants-4lVQXort.mjs.map +0 -1
  105. package/dist/client/containers-DGY2hoWw.mjs.map +0 -1
  106. package/dist/client/containers-ZMFTRaQL.mjs.map +0 -1
  107. package/dist/client/containers-xfsYgRyf.mjs.map +0 -1
  108. package/dist/client/images-Da1t5KPh.mjs.map +0 -1
  109. package/dist/client/objects-B89dYCBq.mjs.map +0 -1
  110. package/dist/client/objects-CuFLUOe1.mjs.map +0 -1
  111. package/dist/client/objects-H0NN_Sja.mjs.map +0 -1
  112. package/dist/client/pca-C-UFjicP.mjs +0 -167
  113. package/dist/client/pca-C-UFjicP.mjs.map +0 -1
@@ -1 +1 @@
1
- {"version":3,"file":"DeleteFlavorModal-CHTUZ3YV.mjs","names":["React","DataGridRow","DataGridCell","TextInput","ButtonRow","Button","SpecFormRow","specKey","value","errors","isLoading","onKeyChange","onValueChange","onSave","onCancel","useLingui","className","onChange","e","target","placeholder","t","errortext","key","required","icon","onClick","variant","title","disabled","React","useState","useEffect","DataGridRow","DataGridCell","Button","Stack","Spinner","SpecRow","specKey","value","isDeleting","onDelete","canDelete","useLingui","confirm","setConfirm","timer","setTimeout","clearTimeout","handleConfirmDelete","button","variant","onClick","title","t","aria-label","data-testid","disabled","icon","className","distribution","alignment","React","use","Suspense","useState","startTransition","ErrorBoundary","useErrorTranslation","Modal","Message","DataGrid","DataGridRow","DataGridHeadCell","DataGridCell","Stack","Button","Spinner","SpecFormRow","SpecRow","createPermissionsPromise","client","project","compute","canUser","query","project_id","permission","then","canCreate","canDelete","createExtraSpecsPromise","flavorId","getExtraSpecs","SpecsLoading","colSpan","distribution","alignment","variant","SpecsError","error","useLingui","translateError","message","Error","t","text","EditSpecContent","permissionsPromise","extraSpecsPromise","flavor","onSpecsUpdate","isAddingSpec","setIsAddingSpec","setMessage","permissions","initialExtraSpecs","extraSpecs","setExtraSpecs","key","setKey","value","setValue","errors","setErrors","isDeleting","setIsDeleting","validateForm","trimmedKey","trim","trimmedValue","newErrors","Object","keys","includes","length","resetForm","handleSave","type","createExtraSpecs","mutate","id","extra_specs","newSpecs","handleDelete","keyToDelete","deleteExtraSpec","handleKeyChange","newKey","prev","undefined","handleValueChange","newValue","shouldShowEmptyState","direction","className","label","data-testid","onClick","disabled","columns","specKey","isLoading","onKeyChange","onValueChange","onSave","onCancel","entries","map","specValue","onDelete","EditSpecModal","isOpen","onClose","canEdit","setExtraSpecsPromise","resolvedCanEdit","setResolvedCanEdit","useMemo","Promise","resolve","useEffect","title","handleClose","handleSpecsUpdate","specs","open","size","div","onDismiss","fallbackRender","fallback","React","DataGridRow","DataGridCell","TextInput","ButtonRow","Button","TenantAccessFormRow","tenantId","errors","isLoading","onTenantIdChange","onSave","onCancel","useLingui","className","value","onChange","e","target","placeholder","t","errortext","required","icon","onClick","variant","title","disabled","React","useState","useEffect","DataGridRow","DataGridCell","Button","Stack","Spinner","TenantAccessRow","access","isDeleting","onDelete","canDelete","useLingui","confirm","setConfirm","timer","setTimeout","clearTimeout","handleConfirmDelete","button","variant","onClick","title","t","aria-label","data-testid","disabled","tenantId","tenant_id","icon","className","distribution","alignment","React","use","Suspense","useState","startTransition","useEffect","useMemo","useErrorTranslation","Modal","Message","DataGrid","DataGridRow","DataGridHeadCell","DataGridCell","Stack","Spinner","Button","TenantAccessFormRow","TenantAccessRow","createPermissionsPromise","client","project","compute","canUser","query","project_id","permission","then","canAdd","canRemove","createFlavorAccessPromise","flavorId","getFlavorAccess","AccessLoading","colSpan","distribution","alignment","variant","AccessContent","permissionsPromise","flavorAccessPromise","flavor","onAccessUpdate","isAddingAccess","setIsAddingAccess","setMessage","useLingui","translateError","permissions","flavorAccess","tenantId","setTenantId","errors","setErrors","deletingTenants","setDeletingTenants","Set","isLoading","setIsLoading","isPublicFlavor","shouldShowEmptyState","length","validateForm","trimmedTenantId","trim","newErrors","some","access","tenant_id","Object","keys","resetForm","handleSave","text","t","type","updatedAccess","addTenantAccess","mutate","id","targetProjectId","error","errorMessage","message","handleRemoveTenant","tenantIdToRemove","prev","add","removeTenantAccess","newSet","delete","handleTenantIdChange","newTenantId","undefined","columns","className","direction","label","data-testid","onClick","disabled","onTenantIdChange","onSave","onCancel","map","isDeleting","has","onDelete","canDelete","ManageAccessModal","isOpen","onClose","filter","entry","idx","arr","findIndex","e","catch","msg","flavorAccessOverride","setFlavorAccessOverride","accessKey","activeFlavorAccessPromise","key","promise","handleClose","handleAccessUpdate","deduplicated","Promise","resolve","flavorName","name","title","open","size","div","onDismiss","dismissible","fallback","React","useState","Modal","Message","Spinner","ModalFooter","Button","ButtonRow","DataGrid","DataGridRow","DataGridHeadCell","DataGridCell","Stack","useErrorTranslation","DeleteFlavorModal","client","isOpen","onClose","project","flavor","onSuccess","useLingui","translateError","isLoading","setIsLoading","generalError","setGeneralError","handleDelete","id","t","compute","deleteFlavor","mutate","project_id","flavorId","handleClose","error","errorMessage","message","dismissError","onCancel","title","open","onConfirm","modalFooter","className","variant","onClick","disabled","size","distribution","alignment","div","onDismiss","text","columns","name","vcpus","ram","disk","swap"],"sources":["../../src/client/routes/_auth/projects/$projectId/compute/-components/Flavors/-components/SpecFormRow.tsx","../../src/client/routes/_auth/projects/$projectId/compute/-components/Flavors/-components/SpecRow.tsx","../../src/client/routes/_auth/projects/$projectId/compute/-components/Flavors/-components/EditSpecModal.tsx","../../src/client/routes/_auth/projects/$projectId/compute/-components/Flavors/-components/TenantAccessFormRow.tsx","../../src/client/routes/_auth/projects/$projectId/compute/-components/Flavors/-components/TenantAccessRow.tsx","../../src/client/routes/_auth/projects/$projectId/compute/-components/Flavors/-components/ManageAccessModal.tsx","../../src/client/routes/_auth/projects/$projectId/compute/-components/Flavors/-components/DeleteFlavorModal.tsx"],"sourcesContent":["import React from \"react\"\nimport { useLingui } from \"@lingui/react/macro\"\nimport { DataGridRow, DataGridCell, TextInput, ButtonRow, Button } from \"@cloudoperators/juno-ui-components\"\n\ninterface SpecFormRowProps {\n specKey: string\n value: string\n errors: { key?: string; value?: string }\n isLoading: boolean\n onKeyChange: (key: string) => void\n onValueChange: (value: string) => void\n onSave: () => void\n onCancel: () => void\n}\n\nexport const SpecFormRow: React.FC<SpecFormRowProps> = ({\n specKey,\n value,\n errors,\n isLoading,\n onKeyChange,\n onValueChange,\n onSave,\n onCancel,\n}) => {\n const { t } = useLingui()\n\n return (\n <DataGridRow>\n <DataGridCell className=\"pl-0\">\n <TextInput\n value={specKey}\n onChange={(e) => onKeyChange(e.target.value)}\n placeholder={t`Enter key`}\n errortext={errors.key}\n required\n />\n </DataGridCell>\n <DataGridCell className=\"pl-0\">\n <TextInput\n value={value}\n onChange={(e) => onValueChange(e.target.value)}\n placeholder={t`Enter value`}\n errortext={errors.value}\n required\n />\n </DataGridCell>\n <DataGridCell>\n <ButtonRow>\n <Button icon=\"check\" onClick={onSave} variant=\"primary\" title={t`Save Metadata`} disabled={isLoading} />\n <Button icon=\"cancel\" onClick={onCancel} title={t`Cancel`} disabled={isLoading} />\n </ButtonRow>\n </DataGridCell>\n </DataGridRow>\n )\n}\n","import React, { useState, useEffect } from \"react\"\nimport { useLingui } from \"@lingui/react/macro\"\nimport { DataGridRow, DataGridCell, Button, Stack, Spinner } from \"@cloudoperators/juno-ui-components\"\n\ninterface SpecRowProps {\n specKey: string\n value: string\n isDeleting: boolean\n onDelete: () => void\n canDelete?: boolean\n}\n\nexport const SpecRow: React.FC<SpecRowProps> = ({ specKey, value, isDeleting, onDelete, canDelete }) => {\n const { t } = useLingui()\n const [confirm, setConfirm] = useState(false)\n useEffect(() => {\n if (confirm) {\n const timer = setTimeout(() => {\n setConfirm(false)\n }, 3000)\n\n return () => clearTimeout(timer)\n }\n }, [confirm])\n\n const handleConfirmDelete = () => {\n setConfirm(false)\n onDelete()\n }\n\n const button = () => {\n if (!canDelete) {\n return <></>\n }\n if (confirm) {\n return (\n <Button\n variant=\"primary-danger\"\n onClick={handleConfirmDelete}\n title={t`Delete`}\n aria-label={t`Delete`}\n data-testid=\"confirm-deletion\"\n disabled={isDeleting}\n >\n {t`Delete`}\n </Button>\n )\n } else {\n return (\n <Button\n icon=\"deleteForever\"\n onClick={() => setConfirm(true)}\n title={t`Delete ${specKey}`}\n aria-label={t`Delete ${specKey}`}\n data-testid={`delete-${specKey}`}\n disabled={isDeleting}\n />\n )\n }\n }\n\n return (\n <DataGridRow>\n <DataGridCell>{specKey}</DataGridCell>\n <DataGridCell className=\"break-all\">{value}</DataGridCell>\n <DataGridCell>\n {isDeleting ? (\n <Stack distribution=\"center\" alignment=\"center\">\n <Spinner variant=\"primary\" />\n </Stack>\n ) : (\n <Stack distribution=\"end\" alignment=\"end\">\n {button()}\n </Stack>\n )}\n </DataGridCell>\n </DataGridRow>\n )\n}\n","import React, { use, Suspense, useState, startTransition } from \"react\"\nimport { ErrorBoundary } from \"react-error-boundary\"\nimport { TrpcClient } from \"@/client/trpcClient\"\nimport { useLingui } from \"@lingui/react/macro\"\nimport { useErrorTranslation } from \"@/client/utils/useErrorTranslation\"\nimport {\n Modal,\n Message,\n DataGrid,\n DataGridRow,\n DataGridHeadCell,\n DataGridCell,\n Stack,\n Button,\n Spinner,\n} from \"@cloudoperators/juno-ui-components\"\nimport { Flavor } from \"@/server/Compute/types/flavor\"\nimport { SpecFormRow } from \"./SpecFormRow\"\nimport { SpecRow } from \"./SpecRow\"\n\ninterface EditSpecModalProps {\n client: TrpcClient\n isOpen: boolean\n onClose: () => void\n project: string\n flavor: Flavor | null\n canEdit?: boolean\n}\n\nconst createPermissionsPromise = (client: TrpcClient, project: string) => {\n return client.compute.canUser\n .query({\n project_id: project,\n permission: [\"flavor_specs:create\", \"flavor_specs:delete\"],\n })\n .then(([canCreate, canDelete]) => ({ canCreate, canDelete }))\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 SpecsLoading() {\n return (\n <DataGridRow>\n <DataGridCell colSpan={3}>\n <Stack distribution=\"center\" alignment=\"center\">\n <Spinner variant=\"primary\" />\n </Stack>\n </DataGridCell>\n </DataGridRow>\n )\n}\n\nfunction SpecsError({ error }: { error: unknown }) {\n const { t } = useLingui()\n const { translateError } = useErrorTranslation()\n const message = error instanceof Error ? translateError(error.message) : t`An unexpected error occurred.`\n return <Message variant=\"error\" text={message} />\n}\n\nfunction EditSpecContent({\n permissionsPromise,\n extraSpecsPromise,\n client,\n project,\n flavor,\n onSpecsUpdate,\n isAddingSpec,\n setIsAddingSpec,\n setMessage,\n}: {\n permissionsPromise: Promise<{ canCreate: boolean; canDelete: boolean }>\n extraSpecsPromise: Promise<Record<string, string>>\n client: TrpcClient\n project: string\n flavor: Flavor\n onSpecsUpdate: (specs: Record<string, string>) => void\n isAddingSpec: boolean\n setIsAddingSpec: (adding: boolean) => void\n message: { text: string; type: \"error\" | \"info\" } | null\n setMessage: (msg: { text: string; type: \"error\" | \"info\" } | null) => void\n}) {\n const { t } = useLingui()\n const { translateError } = useErrorTranslation()\n\n const permissions = use(permissionsPromise)\n const initialExtraSpecs = use(extraSpecsPromise)\n\n const [extraSpecs, setExtraSpecs] = useState(initialExtraSpecs)\n const [key, setKey] = useState(\"\")\n const [value, setValue] = useState(\"\")\n const [errors, setErrors] = useState<{ key?: string; value?: string }>({})\n const [isDeleting, setIsDeleting] = useState<string | null>(null)\n\n const validateForm = () => {\n const trimmedKey = key.trim()\n const trimmedValue = value.trim()\n const newErrors: { key?: string; value?: string } = {}\n\n if (!trimmedKey) {\n newErrors.key = \"Key is required.\"\n } else if (Object.keys(extraSpecs).includes(trimmedKey)) {\n newErrors.key = \"Key already exists.\"\n }\n\n if (!trimmedValue) {\n newErrors.value = \"Value is required.\"\n }\n\n setErrors(newErrors)\n return Object.keys(newErrors).length === 0\n }\n\n const resetForm = () => {\n setKey(\"\")\n setValue(\"\")\n setErrors({})\n }\n\n const handleSave = async () => {\n if (!validateForm()) {\n setMessage({ text: t`Please fix the validation errors below.`, type: \"error\" })\n return\n }\n\n try {\n const trimmedKey = key.trim()\n const trimmedValue = value.trim()\n\n await client.compute.createExtraSpecs.mutate({\n project_id: project,\n flavorId: flavor.id,\n extra_specs: { [trimmedKey]: trimmedValue },\n })\n\n const newSpecs = { [trimmedKey]: trimmedValue, ...extraSpecs }\n setExtraSpecs(newSpecs)\n onSpecsUpdate(newSpecs)\n\n setMessage({\n text: t`Metadata \"${trimmedKey}\" has been added successfully.`,\n type: \"info\",\n })\n resetForm()\n setIsAddingSpec(false)\n } catch (error) {\n setMessage({\n text: translateError(error instanceof Error ? error.message : \"Failed to create extra spec\"),\n type: \"error\",\n })\n }\n }\n\n const handleDelete = async (keyToDelete: string) => {\n try {\n setIsDeleting(keyToDelete)\n await client.compute.deleteExtraSpec.mutate({\n project_id: project,\n flavorId: flavor.id,\n key: keyToDelete,\n })\n\n const newSpecs = { ...extraSpecs }\n delete newSpecs[keyToDelete]\n setExtraSpecs(newSpecs)\n onSpecsUpdate(newSpecs)\n\n setMessage({\n text: t`Metadata \"${keyToDelete}\" has been deleted successfully.`,\n type: \"info\",\n })\n } catch (error) {\n setMessage({\n text: translateError(error instanceof Error ? error.message : `Failed to delete extra spec \"${keyToDelete}\"`),\n type: \"error\",\n })\n } finally {\n setIsDeleting(null)\n }\n }\n\n const handleKeyChange = (newKey: string) => {\n setKey(newKey)\n if (errors.key) setErrors((prev) => ({ ...prev, key: undefined }))\n }\n\n const handleValueChange = (newValue: string) => {\n setValue(newValue)\n if (errors.value) setErrors((prev) => ({ ...prev, value: undefined }))\n }\n\n const shouldShowEmptyState = Object.keys(extraSpecs).length === 0 && !isAddingSpec\n\n return (\n <>\n {permissions.canCreate && (\n <Stack direction=\"horizontal\" className=\"bg-theme-background-lvl-1 justify-end p-2\">\n <Button\n label={t`Add Metadata`}\n data-testid=\"addExtraButton\"\n onClick={() => setIsAddingSpec(true)}\n variant=\"primary\"\n disabled={isAddingSpec}\n />\n </Stack>\n )}\n\n <DataGrid columns={3}>\n <DataGridRow>\n <DataGridHeadCell>{t`Key`}</DataGridHeadCell>\n <DataGridHeadCell>{t`Value`}</DataGridHeadCell>\n <DataGridHeadCell></DataGridHeadCell>\n </DataGridRow>\n\n {isAddingSpec && (\n <SpecFormRow\n specKey={key}\n value={value}\n errors={errors}\n isLoading={false}\n onKeyChange={handleKeyChange}\n onValueChange={handleValueChange}\n onSave={handleSave}\n onCancel={() => {\n resetForm()\n setIsAddingSpec(false)\n setMessage(null)\n }}\n />\n )}\n\n {Object.entries(extraSpecs).map(([specKey, specValue]) => (\n <SpecRow\n key={specKey}\n specKey={specKey}\n value={specValue}\n isDeleting={isDeleting === specKey}\n onDelete={() => handleDelete(specKey)}\n canDelete={permissions.canDelete}\n />\n ))}\n\n {shouldShowEmptyState && (\n <DataGridRow>\n <DataGridCell colSpan={3} className=\"text-theme-default py-4 text-center\">\n {t`No extra specs found. Click \"Add Metadata\" to create one.`}\n </DataGridCell>\n </DataGridRow>\n )}\n </DataGrid>\n </>\n )\n}\n\nexport const EditSpecModal: React.FC<EditSpecModalProps> = ({ client, isOpen, onClose, project, flavor, canEdit }) => {\n const { t } = useLingui()\n\n const [message, setMessage] = useState<{ text: string; type: \"error\" | \"info\" } | null>(null)\n const [isAddingSpec, setIsAddingSpec] = useState(false)\n const [extraSpecsPromise, setExtraSpecsPromise] = useState<Promise<Record<string, string>> | null>(null)\n const [resolvedCanEdit, setResolvedCanEdit] = useState<boolean | undefined>(canEdit)\n\n const permissionsPromise = React.useMemo(() => {\n if (!isOpen) return null\n if (canEdit !== undefined) return Promise.resolve({ canCreate: canEdit, canDelete: canEdit })\n return createPermissionsPromise(client, project)\n }, [client, project, isOpen, canEdit])\n\n React.useEffect(() => {\n if (canEdit !== undefined) {\n setResolvedCanEdit(canEdit)\n return\n }\n permissionsPromise?.then(({ canCreate, canDelete }) => setResolvedCanEdit(canCreate || canDelete))\n }, [permissionsPromise, canEdit])\n\n const title = resolvedCanEdit ? t`Edit Metadata` : t`Metadata`\n\n React.useEffect(() => {\n if (isOpen && flavor?.id) {\n startTransition(() => {\n setExtraSpecsPromise(createExtraSpecsPromise(client, project, flavor.id))\n })\n }\n }, [isOpen, flavor?.id, client, project])\n\n const handleClose = () => {\n setMessage(null)\n setIsAddingSpec(false)\n setExtraSpecsPromise(null)\n onClose()\n }\n\n const handleSpecsUpdate = (specs: Record<string, string>) => {\n startTransition(() => {\n setExtraSpecsPromise(Promise.resolve(specs))\n })\n }\n\n if (!isOpen || !flavor || !permissionsPromise || !extraSpecsPromise) {\n return null\n }\n\n return (\n <Modal onCancel={handleClose} title={title} open={isOpen} size=\"xl\">\n <div>\n {message && (\n <Message onDismiss={() => setMessage(null)} text={message.text} variant={message.type} className=\"mb-4\" />\n )}\n\n <ErrorBoundary fallbackRender={({ error }) => <SpecsError error={error} />}>\n <Suspense fallback={<SpecsLoading />}>\n <EditSpecContent\n permissionsPromise={permissionsPromise}\n extraSpecsPromise={extraSpecsPromise}\n client={client}\n project={project}\n flavor={flavor}\n onSpecsUpdate={handleSpecsUpdate}\n isAddingSpec={isAddingSpec}\n setIsAddingSpec={setIsAddingSpec}\n message={message}\n setMessage={setMessage}\n />\n </Suspense>\n </ErrorBoundary>\n </div>\n </Modal>\n )\n}\n","import React from \"react\"\nimport { useLingui } from \"@lingui/react/macro\"\nimport { DataGridRow, DataGridCell, TextInput, ButtonRow, Button } from \"@cloudoperators/juno-ui-components\"\n\ninterface TenantAccessFormRowProps {\n tenantId: string\n errors: { tenantId?: string }\n isLoading: boolean\n onTenantIdChange: (tenantId: string) => void\n onSave: () => void\n onCancel: () => void\n}\n\nexport const TenantAccessFormRow: React.FC<TenantAccessFormRowProps> = ({\n tenantId,\n errors,\n isLoading,\n onTenantIdChange,\n onSave,\n onCancel,\n}) => {\n const { t } = useLingui()\n\n return (\n <DataGridRow>\n <DataGridCell className=\"pl-0\">\n <TextInput\n value={tenantId}\n onChange={(e) => onTenantIdChange(e.target.value)}\n placeholder={t`Enter tenant ID`}\n errortext={errors.tenantId}\n required\n />\n </DataGridCell>\n <DataGridCell>\n <ButtonRow>\n <Button icon=\"check\" onClick={onSave} variant=\"primary\" title={t`Add Tenant Access`} disabled={isLoading} />\n <Button icon=\"cancel\" onClick={onCancel} title={t`Cancel`} disabled={isLoading} />\n </ButtonRow>\n </DataGridCell>\n </DataGridRow>\n )\n}\n","import React, { useState, useEffect } from \"react\"\nimport { useLingui } from \"@lingui/react/macro\"\nimport { DataGridRow, DataGridCell, Button, Stack, Spinner } from \"@cloudoperators/juno-ui-components\"\n\ninterface FlavorAccess {\n flavor_id: string\n tenant_id: string\n}\n\ninterface TenantAccessRowProps {\n access: FlavorAccess\n isDeleting: boolean\n onDelete: () => void\n canDelete: boolean\n}\n\nexport const TenantAccessRow: React.FC<TenantAccessRowProps> = ({ access, isDeleting, onDelete, canDelete }) => {\n const { t } = useLingui()\n const [confirm, setConfirm] = useState(false)\n\n useEffect(() => {\n if (confirm) {\n const timer = setTimeout(() => {\n setConfirm(false)\n }, 3000)\n\n return () => clearTimeout(timer)\n }\n }, [confirm])\n\n const handleConfirmDelete = () => {\n setConfirm(false)\n onDelete()\n }\n\n const button = () => {\n if (!canDelete) {\n return <></>\n }\n if (confirm) {\n return (\n <Button\n variant=\"primary-danger\"\n onClick={handleConfirmDelete}\n title={t`Remove tenant access`}\n aria-label={t`Remove tenant access`}\n data-testid=\"confirm-removal\"\n disabled={isDeleting}\n >\n {t`Remove`}\n </Button>\n )\n } else {\n const tenantId = access.tenant_id\n\n return (\n <Button\n icon=\"deleteForever\"\n onClick={() => setConfirm(true)}\n title={t`Remove access for ${tenantId}`}\n aria-label={t`Remove access for ${tenantId}`}\n data-testid={`remove-${tenantId}`}\n disabled={isDeleting}\n />\n )\n }\n }\n\n return (\n <DataGridRow>\n <DataGridCell className=\"break-all\">{access.tenant_id}</DataGridCell>\n <DataGridCell>\n {isDeleting ? (\n <Stack distribution=\"center\" alignment=\"center\">\n <Spinner variant=\"primary\" />\n </Stack>\n ) : (\n <Stack distribution=\"end\" alignment=\"end\">\n {button()}\n </Stack>\n )}\n </DataGridCell>\n </DataGridRow>\n )\n}\n","import React, { use, Suspense, useState, startTransition, 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 DataGrid,\n DataGridRow,\n DataGridHeadCell,\n DataGridCell,\n Stack,\n Spinner,\n Button,\n} from \"@cloudoperators/juno-ui-components\"\nimport { Flavor } from \"@/server/Compute/types/flavor\"\nimport { TenantAccessFormRow } from \"./TenantAccessFormRow\"\nimport { TenantAccessRow } from \"./TenantAccessRow\"\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\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 AccessLoading() {\n return (\n <DataGridRow>\n <DataGridCell colSpan={2}>\n <Stack distribution=\"center\" alignment=\"center\">\n <Spinner variant=\"primary\" />\n </Stack>\n </DataGridCell>\n </DataGridRow>\n )\n}\n\nfunction AccessContent({\n permissionsPromise,\n flavorAccessPromise,\n client,\n project,\n flavor,\n onAccessUpdate,\n isAddingAccess,\n setIsAddingAccess,\n setMessage,\n}: {\n permissionsPromise: Promise<{ canAdd: boolean; canRemove: boolean }>\n flavorAccessPromise: Promise<FlavorAccess[]>\n client: TrpcClient\n project: string\n flavor: Flavor\n onAccessUpdate: (access: FlavorAccess[]) => void\n isAddingAccess: boolean\n setIsAddingAccess: (adding: boolean) => void\n setMessage: (msg: { text: string; type: \"error\" | \"info\" } | null) => void\n}) {\n const { t } = useLingui()\n const { translateError } = useErrorTranslation()\n\n const permissions = use(permissionsPromise)\n const flavorAccess = use(flavorAccessPromise) // Direkt verwenden - React 19 macht es reaktiv\n\n const [tenantId, setTenantId] = useState(\"\")\n const [errors, setErrors] = useState<{ tenantId?: string }>({})\n const [deletingTenants, setDeletingTenants] = useState<Set<string>>(new Set())\n const [isLoading, setIsLoading] = useState(false)\n\n const isPublicFlavor = flavor[\"os-flavor-access:is_public\"] !== false\n const shouldShowEmptyState = flavorAccess.length === 0 && !isAddingAccess\n\n const validateForm = () => {\n const trimmedTenantId = tenantId.trim()\n const newErrors: { tenantId?: string } = {}\n\n if (!trimmedTenantId) {\n newErrors.tenantId = \"Tenant ID is required.\"\n } else if (flavorAccess.some((access) => access.tenant_id === trimmedTenantId)) {\n newErrors.tenantId = \"This tenant already has access to this flavor.\"\n }\n\n setErrors(newErrors)\n return Object.keys(newErrors).length === 0\n }\n\n const resetForm = () => {\n setTenantId(\"\")\n setErrors({})\n }\n\n const handleSave = async () => {\n if (!validateForm()) {\n setMessage({ text: t`Please fix the validation errors below.`, type: \"error\" })\n return\n }\n\n setIsLoading(true)\n try {\n const trimmedTenantId = tenantId.trim()\n\n const updatedAccess = await client.compute.addTenantAccess.mutate({\n project_id: project,\n flavorId: flavor.id,\n targetProjectId: trimmedTenantId,\n })\n\n onAccessUpdate(updatedAccess)\n\n setMessage({\n text: t`Tenant access for \"${trimmedTenantId}\" has been added successfully.`,\n type: \"info\",\n })\n resetForm()\n setIsAddingAccess(false)\n } catch (error) {\n const errorMessage = (error as Error)?.message || \"Failed to add tenant access\"\n\n setMessage({\n text: translateError(errorMessage || \"Failed to add tenant access\"),\n type: \"error\",\n })\n } finally {\n setIsLoading(false)\n }\n }\n\n const handleRemoveTenant = async (tenantIdToRemove: string) => {\n setDeletingTenants((prev) => new Set(prev).add(tenantIdToRemove))\n\n try {\n const updatedAccess = await client.compute.removeTenantAccess.mutate({\n project_id: project,\n flavorId: flavor.id,\n targetProjectId: tenantIdToRemove,\n })\n\n onAccessUpdate(updatedAccess)\n setMessage({\n text: t`Tenant access for \"${tenantIdToRemove}\" has been removed successfully.`,\n type: \"info\",\n })\n } catch (error) {\n const errorMessage = (error as Error)?.message || \"Failed to remove tenant access\"\n\n setMessage({\n text: translateError(errorMessage || `Failed to remove tenant access for \"${tenantIdToRemove}\"`),\n type: \"error\",\n })\n } finally {\n setDeletingTenants((prev) => {\n const newSet = new Set(prev)\n newSet.delete(tenantIdToRemove)\n return newSet\n })\n }\n }\n\n const handleTenantIdChange = (newTenantId: string) => {\n setTenantId(newTenantId)\n if (errors.tenantId) setErrors((prev) => ({ ...prev, tenantId: undefined }))\n }\n\n if (isPublicFlavor) {\n return (\n <DataGrid columns={2}>\n <DataGridRow>\n <DataGridHeadCell>{t`Tenant ID`}</DataGridHeadCell>\n <DataGridHeadCell> </DataGridHeadCell>\n </DataGridRow>\n <DataGridRow>\n <DataGridCell colSpan={2} className=\"text-theme-default py-4 text-center\">\n {t`This is a public flavor. All tenants have access to it.`}\n </DataGridCell>\n </DataGridRow>\n </DataGrid>\n )\n }\n\n return (\n <>\n {permissions.canAdd && (\n <Stack direction=\"horizontal\" className=\"bg-theme-background-lvl-1 justify-end p-2\">\n <Button\n label={t`Add Tenant Access`}\n data-testid=\"addTenantButton\"\n onClick={() => setIsAddingAccess(true)}\n variant=\"primary\"\n disabled={isAddingAccess}\n />\n </Stack>\n )}\n\n <DataGrid columns={2}>\n <DataGridRow>\n <DataGridHeadCell>{t`Tenant ID`}</DataGridHeadCell>\n <DataGridHeadCell></DataGridHeadCell>\n </DataGridRow>\n\n {isAddingAccess && (\n <TenantAccessFormRow\n tenantId={tenantId}\n errors={errors}\n isLoading={isLoading}\n onTenantIdChange={handleTenantIdChange}\n onSave={handleSave}\n onCancel={() => {\n resetForm()\n setIsAddingAccess(false)\n setMessage(null)\n }}\n />\n )}\n\n {flavorAccess.map((access) => (\n <TenantAccessRow\n key={access.tenant_id}\n access={access}\n isDeleting={deletingTenants.has(access.tenant_id)}\n onDelete={() => handleRemoveTenant(access.tenant_id)}\n canDelete={permissions.canRemove}\n />\n ))}\n\n {shouldShowEmptyState && (\n <DataGridRow>\n <DataGridCell colSpan={2} className=\"text-theme-default py-4 text-center\">\n {t`No specific tenant access configured for this private flavor. Click \"Add Tenant Access\" to grant access.`}\n </DataGridCell>\n </DataGridRow>\n )}\n </DataGrid>\n </>\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 [message, setMessage] = useState<{ text: string; type: \"error\" | \"info\" } | null>(null)\n const [isAddingAccess, setIsAddingAccess] = useState(false)\n\n const permissionsPromise = useMemo(\n () => (isOpen ? createPermissionsPromise(client, project) : null),\n [client, project, isOpen]\n )\n\n const flavorAccessPromise = useMemo(() => {\n if (!isOpen || !flavor?.id) return null\n return createFlavorAccessPromise(client, project, flavor.id)\n .then((access) =>\n access.filter((entry, idx, arr) => arr.findIndex((e) => e.tenant_id === entry.tenant_id) === idx)\n )\n .catch((error) => {\n const msg = translateError((error as Error)?.message || \"GET_FLAVOR_ACCESS_FAILED\")\n setMessage({ text: msg, type: \"error\" })\n return [] as FlavorAccess[]\n })\n }, [isOpen, flavor?.id, client, project])\n\n useEffect(() => {\n if (isOpen) setMessage(null)\n }, [isOpen, flavor?.id])\n\n // After add/remove, the server returns the updated list. We store it as an override so\n // the UI reflects the change immediately without refetching. The key prevents a stale\n // override from a previously opened flavor from leaking into the current modal session.\n const [flavorAccessOverride, setFlavorAccessOverride] = useState<{\n key: string\n promise: Promise<FlavorAccess[]>\n } | null>(null)\n\n const accessKey = `${isOpen}-${flavor?.id}`\n const activeFlavorAccessPromise =\n flavorAccessOverride?.key === accessKey ? flavorAccessOverride.promise : flavorAccessPromise\n\n const handleClose = () => {\n setMessage(null)\n setIsAddingAccess(false)\n setFlavorAccessOverride(null)\n onClose()\n }\n\n const handleAccessUpdate = (access: FlavorAccess[]) => {\n const deduplicated = access.filter(\n (entry, idx, arr) => arr.findIndex((e) => e.tenant_id === entry.tenant_id) === idx\n )\n startTransition(() => {\n setFlavorAccessOverride({ key: accessKey, promise: Promise.resolve(deduplicated) })\n })\n }\n\n if (!isOpen || !flavor || !permissionsPromise || !activeFlavorAccessPromise) {\n return null\n }\n const flavorName = flavor.name\n\n return (\n <Modal onCancel={handleClose} title={t`Manage Access - ${flavorName}`} open={isOpen} size=\"xl\">\n <div>\n {message && (\n <Message\n onDismiss={() => setMessage(null)}\n text={message.text}\n variant={message.type}\n className=\"mb-4\"\n dismissible\n />\n )}\n\n <Suspense fallback={<AccessLoading />}>\n <AccessContent\n permissionsPromise={permissionsPromise}\n flavorAccessPromise={activeFlavorAccessPromise}\n client={client}\n project={project}\n flavor={flavor}\n onAccessUpdate={handleAccessUpdate}\n isAddingAccess={isAddingAccess}\n setIsAddingAccess={setIsAddingAccess}\n setMessage={setMessage}\n />\n </Suspense>\n </div>\n </Modal>\n )\n}\n","import React, { useState } from \"react\"\nimport { useLingui } from \"@lingui/react/macro\"\nimport { TrpcClient } from \"@/client/trpcClient\"\nimport {\n Modal,\n Message,\n Spinner,\n ModalFooter,\n Button,\n ButtonRow,\n DataGrid,\n DataGridRow,\n DataGridHeadCell,\n DataGridCell,\n Stack,\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\"\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 [generalError, setGeneralError] = useState<string | null>(null)\n\n const handleDelete = async () => {\n if (!flavor?.id) {\n setGeneralError(t`No flavor selected for deletion.`)\n return\n }\n\n setGeneralError(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 setGeneralError(errorMessage)\n } finally {\n setIsLoading(false)\n }\n }\n\n const handleClose = () => {\n setGeneralError(null)\n onClose()\n }\n\n const dismissError = () => {\n setGeneralError(null)\n }\n\n return (\n <Modal\n onCancel={handleClose}\n title={t`Delete Flavor`}\n open={isOpen}\n onConfirm={handleDelete}\n modalFooter={\n <ModalFooter className=\"flex justify-end\">\n <ButtonRow>\n <Button variant=\"primary-danger\" onClick={handleDelete} disabled={isLoading}>\n {isLoading ? <Spinner size=\"small\" /> : <Trans>Delete</Trans>}\n </Button>\n <Button variant=\"default\" onClick={handleClose}>\n <Trans>Cancel</Trans>\n </Button>\n </ButtonRow>\n </ModalFooter>\n }\n >\n {isLoading && (\n <Stack distribution=\"center\" alignment=\"center\">\n <Spinner variant=\"primary\" />\n </Stack>\n )}\n {!isLoading && (\n <div>\n {generalError && <Message onDismiss={dismissError} text={generalError} variant=\"error\" className=\"mb-4\" />}\n\n <Message\n text={t`This action cannot be undone. The flavor will be permanently deleted.`}\n variant=\"danger\"\n className=\"mb-4\"\n />\n\n {flavor && (\n <DataGrid columns={2}>\n <DataGridRow>\n <DataGridHeadCell>{t`Name`}</DataGridHeadCell>\n <DataGridCell>{flavor.name}</DataGridCell>\n </DataGridRow>\n <DataGridRow>\n <DataGridHeadCell>{t`ID`}</DataGridHeadCell>\n <DataGridCell>{flavor.id}</DataGridCell>\n </DataGridRow>\n <DataGridRow>\n <DataGridHeadCell>{t`VCPUs`}</DataGridHeadCell>\n <DataGridCell>{flavor.vcpus}</DataGridCell>\n </DataGridRow>\n <DataGridRow>\n <DataGridHeadCell>{t`RAM`}</DataGridHeadCell>\n <DataGridCell>{flavor.ram} MiB</DataGridCell>\n </DataGridRow>\n <DataGridRow>\n <DataGridHeadCell>{t`Disk`}</DataGridHeadCell>\n <DataGridCell>{flavor.disk} GiB</DataGridCell>\n </DataGridRow>\n {flavor.swap && (\n <DataGridRow>\n <DataGridHeadCell>{t`Swap`}</DataGridHeadCell>\n <DataGridCell>{flavor.swap} MiB</DataGridCell>\n </DataGridRow>\n )}\n </DataGrid>\n )}\n </div>\n )}\n </Modal>\n )\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"DeleteFlavorModal-C3cb7YiJ.mjs","names":["React","DataGridRow","DataGridCell","TextInput","ButtonRow","Button","SpecFormRow","specKey","value","errors","isLoading","onKeyChange","onValueChange","onSave","onCancel","useLingui","className","onChange","e","target","placeholder","t","errortext","key","required","icon","onClick","variant","title","disabled","React","useState","useEffect","DataGridRow","DataGridCell","Button","Stack","Spinner","SpecRow","specKey","value","isDeleting","onDelete","canDelete","useLingui","confirm","setConfirm","timer","setTimeout","clearTimeout","handleConfirmDelete","button","variant","onClick","title","t","aria-label","data-testid","disabled","icon","className","distribution","alignment","React","use","Suspense","useState","startTransition","ErrorBoundary","useErrorTranslation","Modal","Message","DataGrid","DataGridRow","DataGridHeadCell","DataGridCell","Stack","Button","Spinner","SpecFormRow","SpecRow","createPermissionsPromise","client","project","compute","canUser","query","project_id","permission","then","canCreate","canDelete","createExtraSpecsPromise","flavorId","getExtraSpecs","SpecsLoading","colSpan","distribution","alignment","variant","SpecsError","error","useLingui","translateError","message","Error","t","text","EditSpecContent","permissionsPromise","extraSpecsPromise","flavor","onSpecsUpdate","isAddingSpec","setIsAddingSpec","setMessage","permissions","initialExtraSpecs","extraSpecs","setExtraSpecs","key","setKey","value","setValue","errors","setErrors","isDeleting","setIsDeleting","validateForm","trimmedKey","trim","trimmedValue","newErrors","Object","keys","includes","length","resetForm","handleSave","type","createExtraSpecs","mutate","id","extra_specs","newSpecs","handleDelete","keyToDelete","deleteExtraSpec","handleKeyChange","newKey","prev","undefined","handleValueChange","newValue","shouldShowEmptyState","direction","className","label","data-testid","onClick","disabled","columns","specKey","isLoading","onKeyChange","onValueChange","onSave","onCancel","entries","map","specValue","onDelete","EditSpecModal","isOpen","onClose","canEdit","setExtraSpecsPromise","resolvedCanEdit","setResolvedCanEdit","useMemo","Promise","resolve","useEffect","title","handleClose","handleSpecsUpdate","specs","open","size","div","onDismiss","fallbackRender","fallback","React","DataGridRow","DataGridCell","TextInput","ButtonRow","Button","TenantAccessFormRow","tenantId","errors","isLoading","onTenantIdChange","onSave","onCancel","useLingui","className","value","onChange","e","target","placeholder","t","errortext","required","icon","onClick","variant","title","disabled","React","useState","useEffect","DataGridRow","DataGridCell","Button","Stack","Spinner","TenantAccessRow","access","isDeleting","onDelete","canDelete","useLingui","confirm","setConfirm","timer","setTimeout","clearTimeout","handleConfirmDelete","button","variant","onClick","title","t","aria-label","data-testid","disabled","tenantId","tenant_id","icon","className","distribution","alignment","React","use","Suspense","useState","startTransition","useEffect","useMemo","useErrorTranslation","Modal","Message","DataGrid","DataGridRow","DataGridHeadCell","DataGridCell","Stack","Spinner","Button","TenantAccessFormRow","TenantAccessRow","createPermissionsPromise","client","project","compute","canUser","query","project_id","permission","then","canAdd","canRemove","createFlavorAccessPromise","flavorId","getFlavorAccess","AccessLoading","colSpan","distribution","alignment","variant","AccessContent","permissionsPromise","flavorAccessPromise","flavor","onAccessUpdate","isAddingAccess","setIsAddingAccess","setMessage","useLingui","translateError","permissions","flavorAccess","tenantId","setTenantId","errors","setErrors","deletingTenants","setDeletingTenants","Set","isLoading","setIsLoading","isPublicFlavor","shouldShowEmptyState","length","validateForm","trimmedTenantId","trim","newErrors","some","access","tenant_id","Object","keys","resetForm","handleSave","text","t","type","updatedAccess","addTenantAccess","mutate","id","targetProjectId","error","errorMessage","message","handleRemoveTenant","tenantIdToRemove","prev","add","removeTenantAccess","newSet","delete","handleTenantIdChange","newTenantId","undefined","columns","className","direction","label","data-testid","onClick","disabled","onTenantIdChange","onSave","onCancel","map","isDeleting","has","onDelete","canDelete","ManageAccessModal","isOpen","onClose","filter","entry","idx","arr","findIndex","e","catch","msg","flavorAccessOverride","setFlavorAccessOverride","accessKey","activeFlavorAccessPromise","key","promise","handleClose","handleAccessUpdate","deduplicated","Promise","resolve","flavorName","name","title","open","size","div","onDismiss","dismissible","fallback","React","useState","Modal","Message","Spinner","ModalFooter","Button","ButtonRow","DataGrid","DataGridRow","DataGridHeadCell","DataGridCell","Stack","useErrorTranslation","DeleteFlavorModal","client","isOpen","onClose","project","flavor","onSuccess","useLingui","translateError","isLoading","setIsLoading","generalError","setGeneralError","handleDelete","id","t","compute","deleteFlavor","mutate","project_id","flavorId","handleClose","error","errorMessage","message","dismissError","onCancel","title","open","onConfirm","modalFooter","className","variant","onClick","disabled","size","distribution","alignment","div","onDismiss","text","columns","name","vcpus","ram","disk","swap"],"sources":["../../src/client/routes/_auth/projects/$projectId/compute/-components/Flavors/-components/SpecFormRow.tsx","../../src/client/routes/_auth/projects/$projectId/compute/-components/Flavors/-components/SpecRow.tsx","../../src/client/routes/_auth/projects/$projectId/compute/-components/Flavors/-components/EditSpecModal.tsx","../../src/client/routes/_auth/projects/$projectId/compute/-components/Flavors/-components/TenantAccessFormRow.tsx","../../src/client/routes/_auth/projects/$projectId/compute/-components/Flavors/-components/TenantAccessRow.tsx","../../src/client/routes/_auth/projects/$projectId/compute/-components/Flavors/-components/ManageAccessModal.tsx","../../src/client/routes/_auth/projects/$projectId/compute/-components/Flavors/-components/DeleteFlavorModal.tsx"],"sourcesContent":["import React from \"react\"\nimport { useLingui } from \"@lingui/react/macro\"\nimport { DataGridRow, DataGridCell, TextInput, ButtonRow, Button } from \"@cloudoperators/juno-ui-components\"\n\ninterface SpecFormRowProps {\n specKey: string\n value: string\n errors: { key?: string; value?: string }\n isLoading: boolean\n onKeyChange: (key: string) => void\n onValueChange: (value: string) => void\n onSave: () => void\n onCancel: () => void\n}\n\nexport const SpecFormRow: React.FC<SpecFormRowProps> = ({\n specKey,\n value,\n errors,\n isLoading,\n onKeyChange,\n onValueChange,\n onSave,\n onCancel,\n}) => {\n const { t } = useLingui()\n\n return (\n <DataGridRow>\n <DataGridCell className=\"pl-0\">\n <TextInput\n value={specKey}\n onChange={(e) => onKeyChange(e.target.value)}\n placeholder={t`Enter key`}\n errortext={errors.key}\n required\n />\n </DataGridCell>\n <DataGridCell className=\"pl-0\">\n <TextInput\n value={value}\n onChange={(e) => onValueChange(e.target.value)}\n placeholder={t`Enter value`}\n errortext={errors.value}\n required\n />\n </DataGridCell>\n <DataGridCell>\n <ButtonRow>\n <Button icon=\"check\" onClick={onSave} variant=\"primary\" title={t`Save Metadata`} disabled={isLoading} />\n <Button icon=\"cancel\" onClick={onCancel} title={t`Cancel`} disabled={isLoading} />\n </ButtonRow>\n </DataGridCell>\n </DataGridRow>\n )\n}\n","import React, { useState, useEffect } from \"react\"\nimport { useLingui } from \"@lingui/react/macro\"\nimport { DataGridRow, DataGridCell, Button, Stack, Spinner } from \"@cloudoperators/juno-ui-components\"\n\ninterface SpecRowProps {\n specKey: string\n value: string\n isDeleting: boolean\n onDelete: () => void\n canDelete?: boolean\n}\n\nexport const SpecRow: React.FC<SpecRowProps> = ({ specKey, value, isDeleting, onDelete, canDelete }) => {\n const { t } = useLingui()\n const [confirm, setConfirm] = useState(false)\n useEffect(() => {\n if (confirm) {\n const timer = setTimeout(() => {\n setConfirm(false)\n }, 3000)\n\n return () => clearTimeout(timer)\n }\n }, [confirm])\n\n const handleConfirmDelete = () => {\n setConfirm(false)\n onDelete()\n }\n\n const button = () => {\n if (!canDelete) {\n return <></>\n }\n if (confirm) {\n return (\n <Button\n variant=\"primary-danger\"\n onClick={handleConfirmDelete}\n title={t`Delete`}\n aria-label={t`Delete`}\n data-testid=\"confirm-deletion\"\n disabled={isDeleting}\n >\n {t`Delete`}\n </Button>\n )\n } else {\n return (\n <Button\n icon=\"deleteForever\"\n onClick={() => setConfirm(true)}\n title={t`Delete ${specKey}`}\n aria-label={t`Delete ${specKey}`}\n data-testid={`delete-${specKey}`}\n disabled={isDeleting}\n />\n )\n }\n }\n\n return (\n <DataGridRow>\n <DataGridCell>{specKey}</DataGridCell>\n <DataGridCell className=\"break-all\">{value}</DataGridCell>\n <DataGridCell>\n {isDeleting ? (\n <Stack distribution=\"center\" alignment=\"center\">\n <Spinner variant=\"primary\" />\n </Stack>\n ) : (\n <Stack distribution=\"end\" alignment=\"end\">\n {button()}\n </Stack>\n )}\n </DataGridCell>\n </DataGridRow>\n )\n}\n","import React, { use, Suspense, useState, startTransition } from \"react\"\nimport { ErrorBoundary } from \"react-error-boundary\"\nimport { TrpcClient } from \"@/client/trpcClient\"\nimport { useLingui } from \"@lingui/react/macro\"\nimport { useErrorTranslation } from \"@/client/utils/useErrorTranslation\"\nimport {\n Modal,\n Message,\n DataGrid,\n DataGridRow,\n DataGridHeadCell,\n DataGridCell,\n Stack,\n Button,\n Spinner,\n} from \"@cloudoperators/juno-ui-components\"\nimport { Flavor } from \"@/server/Compute/types/flavor\"\nimport { SpecFormRow } from \"./SpecFormRow\"\nimport { SpecRow } from \"./SpecRow\"\n\ninterface EditSpecModalProps {\n client: TrpcClient\n isOpen: boolean\n onClose: () => void\n project: string\n flavor: Flavor | null\n canEdit?: boolean\n}\n\nconst createPermissionsPromise = (client: TrpcClient, project: string) => {\n return client.compute.canUser\n .query({\n project_id: project,\n permission: [\"flavor_specs:create\", \"flavor_specs:delete\"],\n })\n .then(([canCreate, canDelete]) => ({ canCreate, canDelete }))\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 SpecsLoading() {\n return (\n <DataGridRow>\n <DataGridCell colSpan={3}>\n <Stack distribution=\"center\" alignment=\"center\">\n <Spinner variant=\"primary\" />\n </Stack>\n </DataGridCell>\n </DataGridRow>\n )\n}\n\nfunction SpecsError({ error }: { error: unknown }) {\n const { t } = useLingui()\n const { translateError } = useErrorTranslation()\n const message = error instanceof Error ? translateError(error.message) : t`An unexpected error occurred.`\n return <Message variant=\"error\" text={message} />\n}\n\nfunction EditSpecContent({\n permissionsPromise,\n extraSpecsPromise,\n client,\n project,\n flavor,\n onSpecsUpdate,\n isAddingSpec,\n setIsAddingSpec,\n setMessage,\n}: {\n permissionsPromise: Promise<{ canCreate: boolean; canDelete: boolean }>\n extraSpecsPromise: Promise<Record<string, string>>\n client: TrpcClient\n project: string\n flavor: Flavor\n onSpecsUpdate: (specs: Record<string, string>) => void\n isAddingSpec: boolean\n setIsAddingSpec: (adding: boolean) => void\n message: { text: string; type: \"error\" | \"info\" } | null\n setMessage: (msg: { text: string; type: \"error\" | \"info\" } | null) => void\n}) {\n const { t } = useLingui()\n const { translateError } = useErrorTranslation()\n\n const permissions = use(permissionsPromise)\n const initialExtraSpecs = use(extraSpecsPromise)\n\n const [extraSpecs, setExtraSpecs] = useState(initialExtraSpecs)\n const [key, setKey] = useState(\"\")\n const [value, setValue] = useState(\"\")\n const [errors, setErrors] = useState<{ key?: string; value?: string }>({})\n const [isDeleting, setIsDeleting] = useState<string | null>(null)\n\n const validateForm = () => {\n const trimmedKey = key.trim()\n const trimmedValue = value.trim()\n const newErrors: { key?: string; value?: string } = {}\n\n if (!trimmedKey) {\n newErrors.key = \"Key is required.\"\n } else if (Object.keys(extraSpecs).includes(trimmedKey)) {\n newErrors.key = \"Key already exists.\"\n }\n\n if (!trimmedValue) {\n newErrors.value = \"Value is required.\"\n }\n\n setErrors(newErrors)\n return Object.keys(newErrors).length === 0\n }\n\n const resetForm = () => {\n setKey(\"\")\n setValue(\"\")\n setErrors({})\n }\n\n const handleSave = async () => {\n if (!validateForm()) {\n setMessage({ text: t`Please fix the validation errors below.`, type: \"error\" })\n return\n }\n\n try {\n const trimmedKey = key.trim()\n const trimmedValue = value.trim()\n\n await client.compute.createExtraSpecs.mutate({\n project_id: project,\n flavorId: flavor.id,\n extra_specs: { [trimmedKey]: trimmedValue },\n })\n\n const newSpecs = { [trimmedKey]: trimmedValue, ...extraSpecs }\n setExtraSpecs(newSpecs)\n onSpecsUpdate(newSpecs)\n\n setMessage({\n text: t`Metadata \"${trimmedKey}\" has been added successfully.`,\n type: \"info\",\n })\n resetForm()\n setIsAddingSpec(false)\n } catch (error) {\n setMessage({\n text: translateError(error instanceof Error ? error.message : \"Failed to create extra spec\"),\n type: \"error\",\n })\n }\n }\n\n const handleDelete = async (keyToDelete: string) => {\n try {\n setIsDeleting(keyToDelete)\n await client.compute.deleteExtraSpec.mutate({\n project_id: project,\n flavorId: flavor.id,\n key: keyToDelete,\n })\n\n const newSpecs = { ...extraSpecs }\n delete newSpecs[keyToDelete]\n setExtraSpecs(newSpecs)\n onSpecsUpdate(newSpecs)\n\n setMessage({\n text: t`Metadata \"${keyToDelete}\" has been deleted successfully.`,\n type: \"info\",\n })\n } catch (error) {\n setMessage({\n text: translateError(error instanceof Error ? error.message : `Failed to delete extra spec \"${keyToDelete}\"`),\n type: \"error\",\n })\n } finally {\n setIsDeleting(null)\n }\n }\n\n const handleKeyChange = (newKey: string) => {\n setKey(newKey)\n if (errors.key) setErrors((prev) => ({ ...prev, key: undefined }))\n }\n\n const handleValueChange = (newValue: string) => {\n setValue(newValue)\n if (errors.value) setErrors((prev) => ({ ...prev, value: undefined }))\n }\n\n const shouldShowEmptyState = Object.keys(extraSpecs).length === 0 && !isAddingSpec\n\n return (\n <>\n {permissions.canCreate && (\n <Stack direction=\"horizontal\" className=\"bg-theme-background-lvl-1 justify-end p-2\">\n <Button\n label={t`Add Metadata`}\n data-testid=\"addExtraButton\"\n onClick={() => setIsAddingSpec(true)}\n variant=\"primary\"\n disabled={isAddingSpec}\n />\n </Stack>\n )}\n\n <DataGrid columns={3}>\n <DataGridRow>\n <DataGridHeadCell>{t`Key`}</DataGridHeadCell>\n <DataGridHeadCell>{t`Value`}</DataGridHeadCell>\n <DataGridHeadCell></DataGridHeadCell>\n </DataGridRow>\n\n {isAddingSpec && (\n <SpecFormRow\n specKey={key}\n value={value}\n errors={errors}\n isLoading={false}\n onKeyChange={handleKeyChange}\n onValueChange={handleValueChange}\n onSave={handleSave}\n onCancel={() => {\n resetForm()\n setIsAddingSpec(false)\n setMessage(null)\n }}\n />\n )}\n\n {Object.entries(extraSpecs).map(([specKey, specValue]) => (\n <SpecRow\n key={specKey}\n specKey={specKey}\n value={specValue}\n isDeleting={isDeleting === specKey}\n onDelete={() => handleDelete(specKey)}\n canDelete={permissions.canDelete}\n />\n ))}\n\n {shouldShowEmptyState && (\n <DataGridRow>\n <DataGridCell colSpan={3} className=\"text-theme-default py-4 text-center\">\n {t`No extra specs found. Click \"Add Metadata\" to create one.`}\n </DataGridCell>\n </DataGridRow>\n )}\n </DataGrid>\n </>\n )\n}\n\nexport const EditSpecModal: React.FC<EditSpecModalProps> = ({ client, isOpen, onClose, project, flavor, canEdit }) => {\n const { t } = useLingui()\n\n const [message, setMessage] = useState<{ text: string; type: \"error\" | \"info\" } | null>(null)\n const [isAddingSpec, setIsAddingSpec] = useState(false)\n const [extraSpecsPromise, setExtraSpecsPromise] = useState<Promise<Record<string, string>> | null>(null)\n const [resolvedCanEdit, setResolvedCanEdit] = useState<boolean | undefined>(canEdit)\n\n const permissionsPromise = React.useMemo(() => {\n if (!isOpen) return null\n if (canEdit !== undefined) return Promise.resolve({ canCreate: canEdit, canDelete: canEdit })\n return createPermissionsPromise(client, project)\n }, [client, project, isOpen, canEdit])\n\n React.useEffect(() => {\n if (canEdit !== undefined) {\n setResolvedCanEdit(canEdit)\n return\n }\n permissionsPromise?.then(({ canCreate, canDelete }) => setResolvedCanEdit(canCreate || canDelete))\n }, [permissionsPromise, canEdit])\n\n const title = resolvedCanEdit ? t`Edit Metadata` : t`Metadata`\n\n React.useEffect(() => {\n if (isOpen && flavor?.id) {\n startTransition(() => {\n setExtraSpecsPromise(createExtraSpecsPromise(client, project, flavor.id))\n })\n }\n }, [isOpen, flavor?.id, client, project])\n\n const handleClose = () => {\n setMessage(null)\n setIsAddingSpec(false)\n setExtraSpecsPromise(null)\n onClose()\n }\n\n const handleSpecsUpdate = (specs: Record<string, string>) => {\n startTransition(() => {\n setExtraSpecsPromise(Promise.resolve(specs))\n })\n }\n\n if (!isOpen || !flavor || !permissionsPromise || !extraSpecsPromise) {\n return null\n }\n\n return (\n <Modal onCancel={handleClose} title={title} open={isOpen} size=\"xl\">\n <div>\n {message && (\n <Message onDismiss={() => setMessage(null)} text={message.text} variant={message.type} className=\"mb-4\" />\n )}\n\n <ErrorBoundary fallbackRender={({ error }) => <SpecsError error={error} />}>\n <Suspense fallback={<SpecsLoading />}>\n <EditSpecContent\n permissionsPromise={permissionsPromise}\n extraSpecsPromise={extraSpecsPromise}\n client={client}\n project={project}\n flavor={flavor}\n onSpecsUpdate={handleSpecsUpdate}\n isAddingSpec={isAddingSpec}\n setIsAddingSpec={setIsAddingSpec}\n message={message}\n setMessage={setMessage}\n />\n </Suspense>\n </ErrorBoundary>\n </div>\n </Modal>\n )\n}\n","import React from \"react\"\nimport { useLingui } from \"@lingui/react/macro\"\nimport { DataGridRow, DataGridCell, TextInput, ButtonRow, Button } from \"@cloudoperators/juno-ui-components\"\n\ninterface TenantAccessFormRowProps {\n tenantId: string\n errors: { tenantId?: string }\n isLoading: boolean\n onTenantIdChange: (tenantId: string) => void\n onSave: () => void\n onCancel: () => void\n}\n\nexport const TenantAccessFormRow: React.FC<TenantAccessFormRowProps> = ({\n tenantId,\n errors,\n isLoading,\n onTenantIdChange,\n onSave,\n onCancel,\n}) => {\n const { t } = useLingui()\n\n return (\n <DataGridRow>\n <DataGridCell className=\"pl-0\">\n <TextInput\n value={tenantId}\n onChange={(e) => onTenantIdChange(e.target.value)}\n placeholder={t`Enter tenant ID`}\n errortext={errors.tenantId}\n required\n />\n </DataGridCell>\n <DataGridCell>\n <ButtonRow>\n <Button icon=\"check\" onClick={onSave} variant=\"primary\" title={t`Add Tenant Access`} disabled={isLoading} />\n <Button icon=\"cancel\" onClick={onCancel} title={t`Cancel`} disabled={isLoading} />\n </ButtonRow>\n </DataGridCell>\n </DataGridRow>\n )\n}\n","import React, { useState, useEffect } from \"react\"\nimport { useLingui } from \"@lingui/react/macro\"\nimport { DataGridRow, DataGridCell, Button, Stack, Spinner } from \"@cloudoperators/juno-ui-components\"\n\ninterface FlavorAccess {\n flavor_id: string\n tenant_id: string\n}\n\ninterface TenantAccessRowProps {\n access: FlavorAccess\n isDeleting: boolean\n onDelete: () => void\n canDelete: boolean\n}\n\nexport const TenantAccessRow: React.FC<TenantAccessRowProps> = ({ access, isDeleting, onDelete, canDelete }) => {\n const { t } = useLingui()\n const [confirm, setConfirm] = useState(false)\n\n useEffect(() => {\n if (confirm) {\n const timer = setTimeout(() => {\n setConfirm(false)\n }, 3000)\n\n return () => clearTimeout(timer)\n }\n }, [confirm])\n\n const handleConfirmDelete = () => {\n setConfirm(false)\n onDelete()\n }\n\n const button = () => {\n if (!canDelete) {\n return <></>\n }\n if (confirm) {\n return (\n <Button\n variant=\"primary-danger\"\n onClick={handleConfirmDelete}\n title={t`Remove tenant access`}\n aria-label={t`Remove tenant access`}\n data-testid=\"confirm-removal\"\n disabled={isDeleting}\n >\n {t`Remove`}\n </Button>\n )\n } else {\n const tenantId = access.tenant_id\n\n return (\n <Button\n icon=\"deleteForever\"\n onClick={() => setConfirm(true)}\n title={t`Remove access for ${tenantId}`}\n aria-label={t`Remove access for ${tenantId}`}\n data-testid={`remove-${tenantId}`}\n disabled={isDeleting}\n />\n )\n }\n }\n\n return (\n <DataGridRow>\n <DataGridCell className=\"break-all\">{access.tenant_id}</DataGridCell>\n <DataGridCell>\n {isDeleting ? (\n <Stack distribution=\"center\" alignment=\"center\">\n <Spinner variant=\"primary\" />\n </Stack>\n ) : (\n <Stack distribution=\"end\" alignment=\"end\">\n {button()}\n </Stack>\n )}\n </DataGridCell>\n </DataGridRow>\n )\n}\n","import React, { use, Suspense, useState, startTransition, 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 DataGrid,\n DataGridRow,\n DataGridHeadCell,\n DataGridCell,\n Stack,\n Spinner,\n Button,\n} from \"@cloudoperators/juno-ui-components\"\nimport { Flavor } from \"@/server/Compute/types/flavor\"\nimport { TenantAccessFormRow } from \"./TenantAccessFormRow\"\nimport { TenantAccessRow } from \"./TenantAccessRow\"\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\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 AccessLoading() {\n return (\n <DataGridRow>\n <DataGridCell colSpan={2}>\n <Stack distribution=\"center\" alignment=\"center\">\n <Spinner variant=\"primary\" />\n </Stack>\n </DataGridCell>\n </DataGridRow>\n )\n}\n\nfunction AccessContent({\n permissionsPromise,\n flavorAccessPromise,\n client,\n project,\n flavor,\n onAccessUpdate,\n isAddingAccess,\n setIsAddingAccess,\n setMessage,\n}: {\n permissionsPromise: Promise<{ canAdd: boolean; canRemove: boolean }>\n flavorAccessPromise: Promise<FlavorAccess[]>\n client: TrpcClient\n project: string\n flavor: Flavor\n onAccessUpdate: (access: FlavorAccess[]) => void\n isAddingAccess: boolean\n setIsAddingAccess: (adding: boolean) => void\n setMessage: (msg: { text: string; type: \"error\" | \"info\" } | null) => void\n}) {\n const { t } = useLingui()\n const { translateError } = useErrorTranslation()\n\n const permissions = use(permissionsPromise)\n const flavorAccess = use(flavorAccessPromise) // Direkt verwenden - React 19 macht es reaktiv\n\n const [tenantId, setTenantId] = useState(\"\")\n const [errors, setErrors] = useState<{ tenantId?: string }>({})\n const [deletingTenants, setDeletingTenants] = useState<Set<string>>(new Set())\n const [isLoading, setIsLoading] = useState(false)\n\n const isPublicFlavor = flavor[\"os-flavor-access:is_public\"] !== false\n const shouldShowEmptyState = flavorAccess.length === 0 && !isAddingAccess\n\n const validateForm = () => {\n const trimmedTenantId = tenantId.trim()\n const newErrors: { tenantId?: string } = {}\n\n if (!trimmedTenantId) {\n newErrors.tenantId = \"Tenant ID is required.\"\n } else if (flavorAccess.some((access) => access.tenant_id === trimmedTenantId)) {\n newErrors.tenantId = \"This tenant already has access to this flavor.\"\n }\n\n setErrors(newErrors)\n return Object.keys(newErrors).length === 0\n }\n\n const resetForm = () => {\n setTenantId(\"\")\n setErrors({})\n }\n\n const handleSave = async () => {\n if (!validateForm()) {\n setMessage({ text: t`Please fix the validation errors below.`, type: \"error\" })\n return\n }\n\n setIsLoading(true)\n try {\n const trimmedTenantId = tenantId.trim()\n\n const updatedAccess = await client.compute.addTenantAccess.mutate({\n project_id: project,\n flavorId: flavor.id,\n targetProjectId: trimmedTenantId,\n })\n\n onAccessUpdate(updatedAccess)\n\n setMessage({\n text: t`Tenant access for \"${trimmedTenantId}\" has been added successfully.`,\n type: \"info\",\n })\n resetForm()\n setIsAddingAccess(false)\n } catch (error) {\n const errorMessage = (error as Error)?.message || \"Failed to add tenant access\"\n\n setMessage({\n text: translateError(errorMessage || \"Failed to add tenant access\"),\n type: \"error\",\n })\n } finally {\n setIsLoading(false)\n }\n }\n\n const handleRemoveTenant = async (tenantIdToRemove: string) => {\n setDeletingTenants((prev) => new Set(prev).add(tenantIdToRemove))\n\n try {\n const updatedAccess = await client.compute.removeTenantAccess.mutate({\n project_id: project,\n flavorId: flavor.id,\n targetProjectId: tenantIdToRemove,\n })\n\n onAccessUpdate(updatedAccess)\n setMessage({\n text: t`Tenant access for \"${tenantIdToRemove}\" has been removed successfully.`,\n type: \"info\",\n })\n } catch (error) {\n const errorMessage = (error as Error)?.message || \"Failed to remove tenant access\"\n\n setMessage({\n text: translateError(errorMessage || `Failed to remove tenant access for \"${tenantIdToRemove}\"`),\n type: \"error\",\n })\n } finally {\n setDeletingTenants((prev) => {\n const newSet = new Set(prev)\n newSet.delete(tenantIdToRemove)\n return newSet\n })\n }\n }\n\n const handleTenantIdChange = (newTenantId: string) => {\n setTenantId(newTenantId)\n if (errors.tenantId) setErrors((prev) => ({ ...prev, tenantId: undefined }))\n }\n\n if (isPublicFlavor) {\n return (\n <DataGrid columns={2}>\n <DataGridRow>\n <DataGridHeadCell>{t`Tenant ID`}</DataGridHeadCell>\n <DataGridHeadCell> </DataGridHeadCell>\n </DataGridRow>\n <DataGridRow>\n <DataGridCell colSpan={2} className=\"text-theme-default py-4 text-center\">\n {t`This is a public flavor. All tenants have access to it.`}\n </DataGridCell>\n </DataGridRow>\n </DataGrid>\n )\n }\n\n return (\n <>\n {permissions.canAdd && (\n <Stack direction=\"horizontal\" className=\"bg-theme-background-lvl-1 justify-end p-2\">\n <Button\n label={t`Add Tenant Access`}\n data-testid=\"addTenantButton\"\n onClick={() => setIsAddingAccess(true)}\n variant=\"primary\"\n disabled={isAddingAccess}\n />\n </Stack>\n )}\n\n <DataGrid columns={2}>\n <DataGridRow>\n <DataGridHeadCell>{t`Tenant ID`}</DataGridHeadCell>\n <DataGridHeadCell></DataGridHeadCell>\n </DataGridRow>\n\n {isAddingAccess && (\n <TenantAccessFormRow\n tenantId={tenantId}\n errors={errors}\n isLoading={isLoading}\n onTenantIdChange={handleTenantIdChange}\n onSave={handleSave}\n onCancel={() => {\n resetForm()\n setIsAddingAccess(false)\n setMessage(null)\n }}\n />\n )}\n\n {flavorAccess.map((access) => (\n <TenantAccessRow\n key={access.tenant_id}\n access={access}\n isDeleting={deletingTenants.has(access.tenant_id)}\n onDelete={() => handleRemoveTenant(access.tenant_id)}\n canDelete={permissions.canRemove}\n />\n ))}\n\n {shouldShowEmptyState && (\n <DataGridRow>\n <DataGridCell colSpan={2} className=\"text-theme-default py-4 text-center\">\n {t`No specific tenant access configured for this private flavor. Click \"Add Tenant Access\" to grant access.`}\n </DataGridCell>\n </DataGridRow>\n )}\n </DataGrid>\n </>\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 [message, setMessage] = useState<{ text: string; type: \"error\" | \"info\" } | null>(null)\n const [isAddingAccess, setIsAddingAccess] = useState(false)\n\n const permissionsPromise = useMemo(\n () => (isOpen ? createPermissionsPromise(client, project) : null),\n [client, project, isOpen]\n )\n\n const flavorAccessPromise = useMemo(() => {\n if (!isOpen || !flavor?.id) return null\n return createFlavorAccessPromise(client, project, flavor.id)\n .then((access) =>\n access.filter((entry, idx, arr) => arr.findIndex((e) => e.tenant_id === entry.tenant_id) === idx)\n )\n .catch((error) => {\n const msg = translateError((error as Error)?.message || \"GET_FLAVOR_ACCESS_FAILED\")\n setMessage({ text: msg, type: \"error\" })\n return [] as FlavorAccess[]\n })\n }, [isOpen, flavor?.id, client, project])\n\n useEffect(() => {\n if (isOpen) setMessage(null)\n }, [isOpen, flavor?.id])\n\n // After add/remove, the server returns the updated list. We store it as an override so\n // the UI reflects the change immediately without refetching. The key prevents a stale\n // override from a previously opened flavor from leaking into the current modal session.\n const [flavorAccessOverride, setFlavorAccessOverride] = useState<{\n key: string\n promise: Promise<FlavorAccess[]>\n } | null>(null)\n\n const accessKey = `${isOpen}-${flavor?.id}`\n const activeFlavorAccessPromise =\n flavorAccessOverride?.key === accessKey ? flavorAccessOverride.promise : flavorAccessPromise\n\n const handleClose = () => {\n setMessage(null)\n setIsAddingAccess(false)\n setFlavorAccessOverride(null)\n onClose()\n }\n\n const handleAccessUpdate = (access: FlavorAccess[]) => {\n const deduplicated = access.filter(\n (entry, idx, arr) => arr.findIndex((e) => e.tenant_id === entry.tenant_id) === idx\n )\n startTransition(() => {\n setFlavorAccessOverride({ key: accessKey, promise: Promise.resolve(deduplicated) })\n })\n }\n\n if (!isOpen || !flavor || !permissionsPromise || !activeFlavorAccessPromise) {\n return null\n }\n const flavorName = flavor.name\n\n return (\n <Modal onCancel={handleClose} title={t`Manage Access - ${flavorName}`} open={isOpen} size=\"xl\">\n <div>\n {message && (\n <Message\n onDismiss={() => setMessage(null)}\n text={message.text}\n variant={message.type}\n className=\"mb-4\"\n dismissible\n />\n )}\n\n <Suspense fallback={<AccessLoading />}>\n <AccessContent\n permissionsPromise={permissionsPromise}\n flavorAccessPromise={activeFlavorAccessPromise}\n client={client}\n project={project}\n flavor={flavor}\n onAccessUpdate={handleAccessUpdate}\n isAddingAccess={isAddingAccess}\n setIsAddingAccess={setIsAddingAccess}\n setMessage={setMessage}\n />\n </Suspense>\n </div>\n </Modal>\n )\n}\n","import React, { useState } from \"react\"\nimport { useLingui } from \"@lingui/react/macro\"\nimport { TrpcClient } from \"@/client/trpcClient\"\nimport {\n Modal,\n Message,\n Spinner,\n ModalFooter,\n Button,\n ButtonRow,\n DataGrid,\n DataGridRow,\n DataGridHeadCell,\n DataGridCell,\n Stack,\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\"\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 [generalError, setGeneralError] = useState<string | null>(null)\n\n const handleDelete = async () => {\n if (!flavor?.id) {\n setGeneralError(t`No flavor selected for deletion.`)\n return\n }\n\n setGeneralError(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 setGeneralError(errorMessage)\n } finally {\n setIsLoading(false)\n }\n }\n\n const handleClose = () => {\n setGeneralError(null)\n onClose()\n }\n\n const dismissError = () => {\n setGeneralError(null)\n }\n\n return (\n <Modal\n onCancel={handleClose}\n title={t`Delete Flavor`}\n open={isOpen}\n onConfirm={handleDelete}\n modalFooter={\n <ModalFooter className=\"flex justify-end\">\n <ButtonRow>\n <Button variant=\"primary-danger\" onClick={handleDelete} disabled={isLoading}>\n {isLoading ? <Spinner size=\"small\" /> : <Trans>Delete</Trans>}\n </Button>\n <Button variant=\"default\" onClick={handleClose}>\n <Trans>Cancel</Trans>\n </Button>\n </ButtonRow>\n </ModalFooter>\n }\n >\n {isLoading && (\n <Stack distribution=\"center\" alignment=\"center\">\n <Spinner variant=\"primary\" />\n </Stack>\n )}\n {!isLoading && (\n <div>\n {generalError && <Message onDismiss={dismissError} text={generalError} variant=\"error\" className=\"mb-4\" />}\n\n <Message\n text={t`This action cannot be undone. The flavor will be permanently deleted.`}\n variant=\"danger\"\n className=\"mb-4\"\n />\n\n {flavor && (\n <DataGrid columns={2}>\n <DataGridRow>\n <DataGridHeadCell>{t`Name`}</DataGridHeadCell>\n <DataGridCell>{flavor.name}</DataGridCell>\n </DataGridRow>\n <DataGridRow>\n <DataGridHeadCell>{t`ID`}</DataGridHeadCell>\n <DataGridCell>{flavor.id}</DataGridCell>\n </DataGridRow>\n <DataGridRow>\n <DataGridHeadCell>{t`VCPUs`}</DataGridHeadCell>\n <DataGridCell>{flavor.vcpus}</DataGridCell>\n </DataGridRow>\n <DataGridRow>\n <DataGridHeadCell>{t`RAM`}</DataGridHeadCell>\n <DataGridCell>{flavor.ram} MiB</DataGridCell>\n </DataGridRow>\n <DataGridRow>\n <DataGridHeadCell>{t`Disk`}</DataGridHeadCell>\n <DataGridCell>{flavor.disk} GiB</DataGridCell>\n </DataGridRow>\n {flavor.swap && (\n <DataGridRow>\n <DataGridHeadCell>{t`Swap`}</DataGridHeadCell>\n <DataGridCell>{flavor.swap} MiB</DataGridCell>\n </DataGridRow>\n )}\n </DataGrid>\n )}\n </div>\n )}\n </Modal>\n )\n}\n"],"mappings":"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"}
@@ -1,4 +1,4 @@
1
- import { B as e, Q as t, T as n, at as r, c as i, h as a, it as o, n as s, ot as c, q as l, s as u, w as d } from "./build-DracvfrJ.mjs";
1
+ import { B as e, H as t, R as n, U as r, a as i, ct as a, et as o, f as s, i as c, ot as l, r as u, s as d } from "./build-DeJcDjPi.mjs";
2
2
  import { jsx as f, jsxs as p } from "react/jsx-runtime";
3
3
  import { useEffect as m, useState as h } from "react";
4
4
  import { Trans as g, useLingui as _ } from "@lingui/react";
@@ -40,36 +40,36 @@ var v = ({ securityGroup: v, open: y, onClose: b, onUpdate: x, isLoading: S = !1
40
40
  }, N = () => {
41
41
  k({}), b();
42
42
  };
43
- return /*#__PURE__*/ p(c, {
43
+ return /*#__PURE__*/ p(u, {
44
44
  open: y,
45
45
  onCancel: N,
46
46
  size: "large",
47
47
  title: w._({ id: "yu9G3x" }),
48
- modalFooter: /*#__PURE__*/ f(e, {
48
+ modalFooter: /*#__PURE__*/ f(s, {
49
49
  className: "flex justify-end",
50
- children: /*#__PURE__*/ p(a, { children: [/*#__PURE__*/ f(i, {
50
+ children: /*#__PURE__*/ p(c, { children: [/*#__PURE__*/ f(a, {
51
51
  variant: "default",
52
52
  onClick: N,
53
53
  disabled: S,
54
54
  children: /*#__PURE__*/ f(g, { id: "dEgA5A" })
55
- }), /*#__PURE__*/ f(i, {
55
+ }), /*#__PURE__*/ f(a, {
56
56
  variant: "primary",
57
57
  onClick: (e) => {
58
58
  M(e);
59
59
  },
60
60
  disabled: S,
61
61
  "data-testid": "update-security-group-button",
62
- children: S ? /*#__PURE__*/ f(t, { size: "small" }) : /*#__PURE__*/ f(g, { id: "Df0YHr" })
62
+ children: S ? /*#__PURE__*/ f(n, { size: "small" }) : /*#__PURE__*/ f(g, { id: "Df0YHr" })
63
63
  })] })
64
64
  }),
65
65
  children: [
66
- C && /*#__PURE__*/ f(l, {
66
+ C && /*#__PURE__*/ f(e, {
67
67
  dismissible: !1,
68
68
  variant: "error",
69
69
  className: "mb-4",
70
70
  children: C
71
71
  }),
72
- /*#__PURE__*/ f(l, {
72
+ /*#__PURE__*/ f(e, {
73
73
  dismissible: !1,
74
74
  variant: "info",
75
75
  className: "mb-4",
@@ -77,19 +77,19 @@ var v = ({ securityGroup: v, open: y, onClose: b, onUpdate: x, isLoading: S = !1
77
77
  }),
78
78
  S && /*#__PURE__*/ p("div", {
79
79
  className: "mb-4 flex items-center justify-center gap-2",
80
- children: [/*#__PURE__*/ f(t, { variant: "primary" }), /*#__PURE__*/ f("span", {
80
+ children: [/*#__PURE__*/ f(n, { variant: "primary" }), /*#__PURE__*/ f("span", {
81
81
  className: "text-theme-high text-sm",
82
82
  children: /*#__PURE__*/ f(g, { id: "V804LY" })
83
83
  })]
84
84
  }),
85
- !S && /*#__PURE__*/ f(r, {
85
+ !S && /*#__PURE__*/ f(i, {
86
86
  className: "mb-6",
87
- children: /*#__PURE__*/ p(s, {
87
+ children: /*#__PURE__*/ p(t, {
88
88
  className: "mb-6",
89
89
  children: [
90
- /*#__PURE__*/ f(o, {
90
+ /*#__PURE__*/ f(d, {
91
91
  className: "mb-6",
92
- children: /*#__PURE__*/ f(n, {
92
+ children: /*#__PURE__*/ f(r, {
93
93
  id: "name",
94
94
  name: "name",
95
95
  label: w._({ id: "6YtxFj" }),
@@ -101,9 +101,9 @@ var v = ({ securityGroup: v, open: y, onClose: b, onUpdate: x, isLoading: S = !1
101
101
  disabled: S
102
102
  })
103
103
  }),
104
- /*#__PURE__*/ f(o, {
104
+ /*#__PURE__*/ f(d, {
105
105
  className: "mb-6",
106
- children: /*#__PURE__*/ f(u, {
106
+ children: /*#__PURE__*/ f(o, {
107
107
  id: "description",
108
108
  name: "description",
109
109
  label: w._({ id: "Nu4oKW" }),
@@ -114,9 +114,9 @@ var v = ({ securityGroup: v, open: y, onClose: b, onUpdate: x, isLoading: S = !1
114
114
  rows: 3
115
115
  })
116
116
  }),
117
- /*#__PURE__*/ f(o, {
117
+ /*#__PURE__*/ f(d, {
118
118
  className: "mb-0",
119
- children: /*#__PURE__*/ f(d, {
119
+ children: /*#__PURE__*/ f(l, {
120
120
  id: "stateful",
121
121
  name: "stateful",
122
122
  label: w._({ id: "Jim5X9" }),
@@ -134,4 +134,4 @@ var v = ({ securityGroup: v, open: y, onClose: b, onUpdate: x, isLoading: S = !1
134
134
  //#endregion
135
135
  export { v as t };
136
136
 
137
- //# sourceMappingURL=EditSecurityGroupModal-CWHHx2Xk.mjs.map
137
+ //# sourceMappingURL=EditSecurityGroupModal-CpP54WIK.mjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"EditSecurityGroupModal-CWHHx2Xk.mjs","names":["React","useState","useEffect","Modal","Form","FormRow","FormSection","TextInput","Checkbox","Button","ButtonRow","Spinner","ModalFooter","Textarea","Message","EditSecurityGroupModal","securityGroup","open","onClose","onUpdate","isLoading","error","useLingui","properties","setProperties","name","description","stateful","errors","setErrors","handleInputChange","e","value","type","target","checked","prev","newErrors","validateForm","trim","t","Object","keys","length","handleSubmit","preventDefault","updateData","undefined","id","handleClose","onCancel","size","title","modalFooter","className","variant","onClick","disabled","data-testid","dismissible","div","span","label","onChange","required","errortext","placeholder","rows"],"sources":["../../src/client/routes/_auth/projects/$projectId/network/securitygroups/-components/-modals/EditSecurityGroupModal.tsx"],"sourcesContent":["import React, { useState, useEffect } from \"react\"\nimport { Trans, useLingui } from \"@lingui/react/macro\"\nimport {\n Modal,\n Form,\n FormRow,\n FormSection,\n TextInput,\n Checkbox,\n Button,\n ButtonRow,\n Spinner,\n ModalFooter,\n Textarea,\n Message,\n} from \"@cloudoperators/juno-ui-components\"\nimport type { SecurityGroup } from \"@/server/Network/types/securityGroup\"\nimport { UpdateSecurityGroupInput } from \"@/server/Network/types/securityGroup\"\n\ninterface EditSecurityGroupModalProps {\n securityGroup: SecurityGroup\n open: boolean\n onClose: () => void\n onUpdate?: (\n securityGroupId: string,\n data: Omit<UpdateSecurityGroupInput, \"securityGroupId\" | \"project_id\">\n ) => Promise<void>\n isLoading?: boolean\n error?: string | null\n}\n\ninterface SecurityGroupProperties {\n name: string\n description: string\n stateful: boolean\n}\n\nexport const EditSecurityGroupModal: React.FC<EditSecurityGroupModalProps> = ({\n securityGroup,\n open,\n onClose,\n onUpdate,\n isLoading = false,\n error = null,\n}) => {\n const { t } = useLingui()\n\n const [properties, setProperties] = useState<SecurityGroupProperties>({\n name: securityGroup.name || \"\",\n description: securityGroup.description || \"\",\n stateful: securityGroup.stateful ?? true,\n })\n const [errors, setErrors] = useState<{ [key: string]: string }>({})\n\n // Update properties when securityGroup changes\n useEffect(() => {\n setProperties({\n name: securityGroup.name || \"\",\n description: securityGroup.description || \"\",\n stateful: securityGroup.stateful ?? true,\n })\n }, [securityGroup])\n\n const handleInputChange = (e: React.ChangeEvent<HTMLInputElement | HTMLTextAreaElement>) => {\n const { name, value, type } = e.target\n const checked = (e.target as HTMLInputElement).checked\n\n setProperties((prev) => ({\n ...prev,\n [name]: type === \"checkbox\" ? checked : value,\n }))\n\n if (errors[name]) {\n setErrors((prev) => {\n const newErrors = { ...prev }\n delete newErrors[name]\n return newErrors\n })\n }\n }\n\n const validateForm = (): boolean => {\n const newErrors: { [key: string]: string } = {}\n\n if (!properties.name || properties.name.trim() === \"\") {\n newErrors.name = t`Security group name is required`\n }\n\n setErrors(newErrors)\n return Object.keys(newErrors).length === 0\n }\n\n const handleSubmit = async (e: React.FormEvent) => {\n e.preventDefault()\n\n if (!validateForm()) {\n return\n }\n\n if (onUpdate) {\n const updateData: Omit<UpdateSecurityGroupInput, \"securityGroupId\" | \"project_id\"> = {\n name: properties.name.trim(),\n description: properties.description.trim() || undefined,\n stateful: properties.stateful,\n }\n\n await onUpdate(securityGroup.id, updateData)\n }\n }\n\n const handleClose = () => {\n setErrors({})\n onClose()\n }\n\n return (\n <Modal\n open={open}\n onCancel={handleClose}\n size=\"large\"\n title={t`Edit Security Group`}\n modalFooter={\n <ModalFooter className=\"flex justify-end\">\n <ButtonRow>\n <Button variant=\"default\" onClick={handleClose} disabled={isLoading}>\n <Trans>Cancel</Trans>\n </Button>\n <Button\n variant=\"primary\"\n onClick={(e) => {\n handleSubmit(e)\n }}\n disabled={isLoading}\n data-testid=\"update-security-group-button\"\n >\n {isLoading ? <Spinner size=\"small\" /> : <Trans>Update Security Group</Trans>}\n </Button>\n </ButtonRow>\n </ModalFooter>\n }\n >\n {/* Error Message */}\n {error && (\n <Message dismissible={false} variant=\"error\" className=\"mb-4\">\n {error}\n </Message>\n )}\n\n {/* Info message about stateful changes */}\n <Message dismissible={false} variant=\"info\" className=\"mb-4\">\n <Trans>\n Note: The 'stateful' attribute cannot be changed if this security group is currently in use by one or more\n ports.\n </Trans>\n </Message>\n\n {isLoading && (\n <div className=\"mb-4 flex items-center justify-center gap-2\">\n <Spinner variant=\"primary\" />\n <span className=\"text-theme-high text-sm\">\n <Trans>Updating security group...</Trans>\n </span>\n </div>\n )}\n\n {!isLoading && (\n <Form className=\"mb-6\">\n <FormSection className=\"mb-6\">\n <FormRow className=\"mb-6\">\n <TextInput\n id=\"name\"\n name=\"name\"\n label={t`Name`}\n value={properties.name}\n onChange={handleInputChange}\n required\n errortext={errors.name}\n placeholder={t`Type name`}\n disabled={isLoading}\n />\n </FormRow>\n\n <FormRow className=\"mb-6\">\n <Textarea\n id=\"description\"\n name=\"description\"\n label={t`Description`}\n value={properties.description}\n onChange={handleInputChange}\n placeholder={t`Description`}\n disabled={isLoading}\n rows={3}\n />\n </FormRow>\n\n <FormRow className=\"mb-0\">\n <Checkbox\n id=\"stateful\"\n name=\"stateful\"\n label={t`Stateful`}\n checked={properties.stateful}\n onChange={handleInputChange}\n disabled={isLoading}\n />\n </FormRow>\n </FormSection>\n </Form>\n )}\n </Modal>\n )\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"EditSecurityGroupModal-CpP54WIK.mjs","names":["React","useState","useEffect","Modal","Form","FormRow","FormSection","TextInput","Checkbox","Button","ButtonRow","Spinner","ModalFooter","Textarea","Message","EditSecurityGroupModal","securityGroup","open","onClose","onUpdate","isLoading","error","useLingui","properties","setProperties","name","description","stateful","errors","setErrors","handleInputChange","e","value","type","target","checked","prev","newErrors","validateForm","trim","t","Object","keys","length","handleSubmit","preventDefault","updateData","undefined","id","handleClose","onCancel","size","title","modalFooter","className","variant","onClick","disabled","data-testid","dismissible","div","span","label","onChange","required","errortext","placeholder","rows"],"sources":["../../src/client/routes/_auth/projects/$projectId/network/securitygroups/-components/-modals/EditSecurityGroupModal.tsx"],"sourcesContent":["import React, { useState, useEffect } from \"react\"\nimport { Trans, useLingui } from \"@lingui/react/macro\"\nimport {\n Modal,\n Form,\n FormRow,\n FormSection,\n TextInput,\n Checkbox,\n Button,\n ButtonRow,\n Spinner,\n ModalFooter,\n Textarea,\n Message,\n} from \"@cloudoperators/juno-ui-components\"\nimport type { SecurityGroup } from \"@/server/Network/types/securityGroup\"\nimport { UpdateSecurityGroupInput } from \"@/server/Network/types/securityGroup\"\n\ninterface EditSecurityGroupModalProps {\n securityGroup: SecurityGroup\n open: boolean\n onClose: () => void\n onUpdate?: (\n securityGroupId: string,\n data: Omit<UpdateSecurityGroupInput, \"securityGroupId\" | \"project_id\">\n ) => Promise<void>\n isLoading?: boolean\n error?: string | null\n}\n\ninterface SecurityGroupProperties {\n name: string\n description: string\n stateful: boolean\n}\n\nexport const EditSecurityGroupModal: React.FC<EditSecurityGroupModalProps> = ({\n securityGroup,\n open,\n onClose,\n onUpdate,\n isLoading = false,\n error = null,\n}) => {\n const { t } = useLingui()\n\n const [properties, setProperties] = useState<SecurityGroupProperties>({\n name: securityGroup.name || \"\",\n description: securityGroup.description || \"\",\n stateful: securityGroup.stateful ?? true,\n })\n const [errors, setErrors] = useState<{ [key: string]: string }>({})\n\n // Update properties when securityGroup changes\n useEffect(() => {\n setProperties({\n name: securityGroup.name || \"\",\n description: securityGroup.description || \"\",\n stateful: securityGroup.stateful ?? true,\n })\n }, [securityGroup])\n\n const handleInputChange = (e: React.ChangeEvent<HTMLInputElement | HTMLTextAreaElement>) => {\n const { name, value, type } = e.target\n const checked = (e.target as HTMLInputElement).checked\n\n setProperties((prev) => ({\n ...prev,\n [name]: type === \"checkbox\" ? checked : value,\n }))\n\n if (errors[name]) {\n setErrors((prev) => {\n const newErrors = { ...prev }\n delete newErrors[name]\n return newErrors\n })\n }\n }\n\n const validateForm = (): boolean => {\n const newErrors: { [key: string]: string } = {}\n\n if (!properties.name || properties.name.trim() === \"\") {\n newErrors.name = t`Security group name is required`\n }\n\n setErrors(newErrors)\n return Object.keys(newErrors).length === 0\n }\n\n const handleSubmit = async (e: React.FormEvent) => {\n e.preventDefault()\n\n if (!validateForm()) {\n return\n }\n\n if (onUpdate) {\n const updateData: Omit<UpdateSecurityGroupInput, \"securityGroupId\" | \"project_id\"> = {\n name: properties.name.trim(),\n description: properties.description.trim() || undefined,\n stateful: properties.stateful,\n }\n\n await onUpdate(securityGroup.id, updateData)\n }\n }\n\n const handleClose = () => {\n setErrors({})\n onClose()\n }\n\n return (\n <Modal\n open={open}\n onCancel={handleClose}\n size=\"large\"\n title={t`Edit Security Group`}\n modalFooter={\n <ModalFooter className=\"flex justify-end\">\n <ButtonRow>\n <Button variant=\"default\" onClick={handleClose} disabled={isLoading}>\n <Trans>Cancel</Trans>\n </Button>\n <Button\n variant=\"primary\"\n onClick={(e) => {\n handleSubmit(e)\n }}\n disabled={isLoading}\n data-testid=\"update-security-group-button\"\n >\n {isLoading ? <Spinner size=\"small\" /> : <Trans>Update Security Group</Trans>}\n </Button>\n </ButtonRow>\n </ModalFooter>\n }\n >\n {/* Error Message */}\n {error && (\n <Message dismissible={false} variant=\"error\" className=\"mb-4\">\n {error}\n </Message>\n )}\n\n {/* Info message about stateful changes */}\n <Message dismissible={false} variant=\"info\" className=\"mb-4\">\n <Trans>\n Note: The 'stateful' attribute cannot be changed if this security group is currently in use by one or more\n ports.\n </Trans>\n </Message>\n\n {isLoading && (\n <div className=\"mb-4 flex items-center justify-center gap-2\">\n <Spinner variant=\"primary\" />\n <span className=\"text-theme-high text-sm\">\n <Trans>Updating security group...</Trans>\n </span>\n </div>\n )}\n\n {!isLoading && (\n <Form className=\"mb-6\">\n <FormSection className=\"mb-6\">\n <FormRow className=\"mb-6\">\n <TextInput\n id=\"name\"\n name=\"name\"\n label={t`Name`}\n value={properties.name}\n onChange={handleInputChange}\n required\n errortext={errors.name}\n placeholder={t`Type name`}\n disabled={isLoading}\n />\n </FormRow>\n\n <FormRow className=\"mb-6\">\n <Textarea\n id=\"description\"\n name=\"description\"\n label={t`Description`}\n value={properties.description}\n onChange={handleInputChange}\n placeholder={t`Description`}\n disabled={isLoading}\n rows={3}\n />\n </FormRow>\n\n <FormRow className=\"mb-0\">\n <Checkbox\n id=\"stateful\"\n name=\"stateful\"\n label={t`Stateful`}\n checked={properties.stateful}\n onChange={handleInputChange}\n disabled={isLoading}\n />\n </FormRow>\n </FormSection>\n </Form>\n )}\n </Modal>\n )\n}\n"],"mappings":"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"}
@@ -1,23 +1,23 @@
1
- import { a as e, c as t, d as n, m as r, nt as i, r as a, st as o, y as s } from "./build-DracvfrJ.mjs";
1
+ import { M as e, Q as t, Z as n, b as r, ct as i, j as a, lt as o, u as s } from "./build-DeJcDjPi.mjs";
2
2
  import { jsx as c, jsxs as l } from "react/jsx-runtime";
3
3
  import { useCallback as u, useState as d } from "react";
4
4
  import { useLingui as f } from "@lingui/react";
5
5
  //#region src/client/components/ListToolbar/SelectedFilters.tsx
6
6
  var p = ({ selectedFilters: e, onDelete: n, onClear: r }) => {
7
- let { i18n: a, _: o } = f();
8
- return /*#__PURE__*/ l(i, {
7
+ let { i18n: o, _: s } = f();
8
+ return /*#__PURE__*/ l(t, {
9
9
  gap: "2",
10
10
  wrap: !0,
11
11
  alignment: "start",
12
12
  distribution: "start",
13
- children: [e.map((e) => /*#__PURE__*/ c(s, {
13
+ children: [e.map((e) => /*#__PURE__*/ c(a, {
14
14
  closeable: !0,
15
15
  pillKey: e.name,
16
16
  pillValue: e.value,
17
17
  onClose: () => n(e)
18
- }, `${e.name}:${e.value}`)), e.length > 1 && /*#__PURE__*/ c(t, {
18
+ }, `${e.name}:${e.value}`)), e.length > 1 && /*#__PURE__*/ c(i, {
19
19
  size: "small",
20
- label: a._({ id: "yYxB17" }),
20
+ label: o._({ id: "yYxB17" }),
21
21
  onClick: r
22
22
  })]
23
23
  });
@@ -28,7 +28,7 @@ function m(e) {
28
28
  return e == null ? !0 : typeof e == "string" || Array.isArray(e) ? e.length === 0 : e instanceof Map || e instanceof Set ? e.size === 0 : typeof e == "object" ? Object.keys(e).length === 0 : !1;
29
29
  }
30
30
  var h = ({ filters: t, onChange: i }) => {
31
- let { i18n: s, _: p } = f(), [h, g] = d(""), [_, v] = d(""), y = t.find((e) => e.filterName === h)?.values?.filter((e) => e), b = u((e) => {
31
+ let { i18n: a, _: p } = f(), [h, g] = d(""), [_, v] = d(""), y = t.find((e) => e.filterName === h)?.values?.filter((e) => e), b = u((e) => {
32
32
  v(e), !m(h) && !m(e) && i({
33
33
  name: h,
34
34
  value: e
@@ -43,7 +43,7 @@ var h = ({ filters: t, onChange: i }) => {
43
43
  className: "w-full sm:flex-1 sm:min-w-0",
44
44
  name: "filter",
45
45
  "data-testid": "select-filterValue",
46
- label: s._({ id: "0cVgUw" }),
46
+ label: a._({ id: "0cVgUw" }),
47
47
  value: h,
48
48
  onChange: (e) => {
49
49
  g(String(e));
@@ -56,26 +56,26 @@ var h = ({ filters: t, onChange: i }) => {
56
56
  disabled: !h,
57
57
  onChange: b
58
58
  });
59
- return /*#__PURE__*/ l(o, {
59
+ return /*#__PURE__*/ l(r, {
60
60
  className: "flex w-full flex-col sm:w-auto sm:flex-row sm:items-end",
61
- children: [/*#__PURE__*/ c(a, {
61
+ children: [/*#__PURE__*/ c(o, {
62
62
  ...x(),
63
- children: t?.map(({ displayName: e, filterName: t }) => /*#__PURE__*/ c(n, {
63
+ children: t?.map(({ displayName: e, filterName: t }) => /*#__PURE__*/ c(s, {
64
64
  value: t,
65
65
  label: e,
66
66
  "data-testid": t
67
67
  }, t))
68
- }), /*#__PURE__*/ c(e, {
68
+ }), /*#__PURE__*/ c(n, {
69
69
  ...S(),
70
- children: y?.map((e) => /*#__PURE__*/ c(r, {
71
- value: e,
72
- label: e,
73
- "data-testid": e
74
- }, e))
70
+ children: y?.map((t) => /*#__PURE__*/ c(e, {
71
+ value: t,
72
+ label: t,
73
+ "data-testid": t
74
+ }, t))
75
75
  })]
76
76
  });
77
77
  };
78
78
  //#endregion
79
79
  export { p as n, h as t };
80
80
 
81
- //# sourceMappingURL=FiltersInput-UKJpNFdr.mjs.map
81
+ //# sourceMappingURL=FiltersInput-DxcyR6Bp.mjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"FiltersInput-UKJpNFdr.mjs","names":["Button","Pill","Stack","SelectedFilters","selectedFilters","onDelete","onClear","useLingui","gap","wrap","alignment","distribution","map","filter","closeable","pillKey","name","pillValue","value","onClose","length","size","label","t","onClick","useCallback","useState","InputGroup","ComboBox","ComboBoxOption","SelectOption","Select","isEmpty","value","Array","isArray","length","Map","Set","size","Object","keys","FiltersInput","filters","onChange","useLingui","selectedFilterName","setSelectedFilterName","selectedFilterValue","setSelectedFilterValue","filterValues","find","filter","filterName","values","handleValueChange","name","setTimeout","getSelectProps","className","label","t","String","getComboBoxProps","disabled","map","displayName","data-testid"],"sources":["../../src/client/components/ListToolbar/SelectedFilters.tsx","../../src/client/components/ListToolbar/FiltersInput.tsx"],"sourcesContent":["import { useLingui } from \"@lingui/react/macro\"\nimport { Button, Pill, Stack } from \"@cloudoperators/juno-ui-components\"\nimport { SelectedFilter } from \"./types\"\n\nexport type SelectedFiltersProps = {\n /**\n * Array of currently active filters to be displayed as closeable pills.\n */\n selectedFilters: SelectedFilter[]\n\n /**\n * Callback function invoked when a user removes an individual filter pill.\n */\n onDelete: (filter: SelectedFilter) => void\n\n /**\n * Callback function invoked when the \"Clear all\" button is clicked.\n */\n onClear: () => void\n}\n\n/**\n * SelectedFilters Component\n *\n * Displays currently active filters as closeable pill components with individual\n * remove buttons and an optional \"Clear all\" button (shown when 2+ filters are active).\n *\n * The pills are arranged in a flexible, wrapping layout that adapts to available space.\n */\nexport const SelectedFilters = ({ selectedFilters, onDelete, onClear }: SelectedFiltersProps) => {\n const { t } = useLingui()\n\n return (\n <Stack gap=\"2\" wrap={true} alignment=\"start\" distribution=\"start\">\n {/* Render a closeable pill for each selected filter */}\n {selectedFilters.map((filter) => (\n <Pill\n key={`${filter.name}:${filter.value}`}\n closeable\n pillKey={filter.name}\n pillValue={filter.value}\n onClose={() => onDelete(filter)}\n />\n ))}\n {selectedFilters.length > 1 && <Button size=\"small\" label={t`Clear all`} onClick={onClear} />}\n </Stack>\n )\n}\n","import { useCallback, useState } from \"react\"\nimport { useLingui } from \"@lingui/react/macro\"\nimport {\n InputGroup,\n ComboBox,\n ComboBoxProps,\n ComboBoxOption,\n SelectOption,\n Select,\n SelectProps,\n} from \"@cloudoperators/juno-ui-components\"\nimport { Filter, SelectedFilter } from \"./types\"\n\nexport type FiltersInputProps = {\n filters: Filter[]\n onChange: (filter: SelectedFilter) => void\n}\n\nfunction isEmpty(value: unknown) {\n if (value == null) return true\n if (typeof value === \"string\" || Array.isArray(value)) return value.length === 0\n if (value instanceof Map || value instanceof Set) return value.size === 0\n if (typeof value === \"object\") return Object.keys(value).length === 0\n return false\n}\n\nexport const FiltersInput = ({ filters, onChange }: FiltersInputProps) => {\n const { t } = useLingui()\n\n const [selectedFilterName, setSelectedFilterName] = useState<string>(\"\")\n const [selectedFilterValue, setSelectedFilterValue] = useState<string>(\"\")\n\n const filterValues: string[] | undefined = filters\n .find((filter) => filter.filterName === selectedFilterName)\n ?.values?.filter((value) => value)\n\n const handleValueChange = useCallback(\n (value: string) => {\n setSelectedFilterValue(value)\n if (!isEmpty(selectedFilterName) && !isEmpty(value)) {\n onChange({\n name: selectedFilterName,\n value: value,\n })\n }\n setTimeout(() => {\n setSelectedFilterValue(\"\")\n }, 0)\n },\n [selectedFilterName, setSelectedFilterValue, onChange]\n )\n\n const getSelectProps = (): SelectProps & { \"data-testid\"?: string } => ({\n className: \"w-full sm:flex-1 sm:min-w-0\",\n name: \"filter\",\n \"data-testid\": \"select-filterValue\",\n label: t`Filter by`,\n value: selectedFilterName,\n onChange: (value: string | number | string[] | undefined) => {\n setSelectedFilterName(String(value))\n },\n })\n\n const getComboBoxProps = (): ComboBoxProps & { \"data-testid\"?: string } => ({\n className: \"w-full sm:flex-1 sm:min-w-0\",\n name: \"filterValue\",\n \"data-testid\": \"combobox-filterValue\",\n value: selectedFilterValue,\n disabled: !selectedFilterName,\n onChange: handleValueChange,\n })\n\n return (\n <InputGroup className=\"flex w-full flex-col sm:w-auto sm:flex-row sm:items-end\">\n <Select {...getSelectProps()}>\n {filters?.map(({ displayName, filterName }) => (\n <SelectOption value={filterName} label={displayName} key={filterName} data-testid={filterName} />\n ))}\n </Select>\n <ComboBox {...getComboBoxProps()}>\n {filterValues?.map((value) => (\n <ComboBoxOption value={value} key={value} label={value} data-testid={value} />\n ))}\n </ComboBox>\n </InputGroup>\n )\n}\n"],"mappings":";;;;;AA6BA,IAAaG,KAAmB,EAAEC,oBAAiBC,aAAUC,iBAA+B;CAC1F,IAAM,EAAA,MAAA,GAAA,GAAA,MAAQC,EAAAA;CAEd,OACE,gBAACL,GAAAA;EAAMM,KAAI;EAAIC,MAAM;EAAMC,WAAU;EAAQC,cAAa;aAEvDP,EAAgBQ,KAAKC,MACpB,gBAACZ,GAAAA;GAECa,WAAS;GACTC,SAASF,EAAOG;GAChBC,WAAWJ,EAAOK;GAClBC,eAAed,EAASQ,CAAAA;KAJnB,GAAGA,EAAOG,KAAK,GAAGH,EAAOK,OAAO,CAAA,GAOxCd,EAAgBgB,SAAS,KAAK,gBAACpB,GAAAA;GAAOqB,MAAK;GAAQC,OAAOC,EAAAA,EAAC,EAAA,IAAA,SAAU,CAAA;GAAGC,SAASlB;;;AAGxF;;;AC7BA,SAAS0B,EAAQC,GAAc;CAK7B,OAJIA,KAAS,OAAa,KACtB,OAAOA,KAAU,YAAYC,MAAMC,QAAQF,CAAAA,IAAeA,EAAMG,WAAW,IAC3EH,aAAiBI,OAAOJ,aAAiBK,MAAYL,EAAMM,SAAS,IACpE,OAAON,KAAU,WAAiBO,OAAOC,KAAKR,CAAAA,EAAOG,WAAW,IAC7D;AACT;AAEA,IAAaM,KAAgB,EAAEC,YAASC,kBAA6B;CACnE,IAAM,EAAA,MAAA,GAAA,GAAA,MAAQC,EAAAA,GAER,CAACC,GAAoBC,KAAyBrB,EAAiB,EAAA,GAC/D,CAACsB,GAAqBC,KAA0BvB,EAAiB,EAAA,GAEjEwB,IAAqCP,EACxCQ,MAAMC,MAAWA,EAAOC,eAAeP,CAAAA,GACtCQ,QAAQF,QAAQnB,MAAUA,CAAAA,GAExBsB,IAAoB9B,GACvBQ,MAAAA;EAQCwB,AAPAR,EAAuBhB,CAAAA,GACnB,CAACD,EAAQc,CAAAA,KAAuB,CAACd,EAAQC,CAAAA,KAC3CW,EAAS;GACPY,MAAMV;GACCb;EACT,CAAA,GAEFwB,iBAAW;GACTR,EAAuB,EAAA;EACzB,GAAG,CAAA;CACL,GACA;EAACH;EAAoBG;EAAwBL;EAAS,GAGlDc,WAAkE;EACtEC,WAAW;EACXH,MAAM;EACN,eAAe;EACfI,OAAOC,EAAAA,EAAC,EAAA,IAAA,SAAU,CAAA;EAClB5B,OAAOa;EACPF,WAAWX,MAAAA;GACTc,EAAsBe,OAAO7B,CAAAA,CAAAA;EAC/B;CACF,IAEM8B,WAAsE;EAC1EJ,WAAW;EACXH,MAAM;EACN,eAAe;EACfvB,OAAOe;EACPgB,UAAU,CAAClB;EACXF,UAAUW;CACZ;CAEA,OACE,gBAAC5B,GAAAA;EAAWgC,WAAU;aACpB,gBAAC5B,GAAAA;GAAQ,GAAG2B,EAAAA;aACTf,GAASsB,KAAK,EAAEC,gBAAab,oBAC5B,gBAACvB,GAAAA;IAAaG,OAAOoB;IAAYO,OAAOM;IAA8BC,eAAad;MAAzBA,CAAAA,CAAAA;MAG9D,gBAACzB,GAAAA;GAAU,GAAGmC,EAAAA;aACXb,GAAce,KAAKhC,MAClB,gBAACJ,GAAAA;IAAsBI;IAAmB2B,OAAO3B;IAAOkC,eAAalC;MAAlCA,CAAAA,CAAAA;;;AAK7C"}
1
+ {"version":3,"file":"FiltersInput-DxcyR6Bp.mjs","names":["Button","Pill","Stack","SelectedFilters","selectedFilters","onDelete","onClear","useLingui","gap","wrap","alignment","distribution","map","filter","closeable","pillKey","name","pillValue","value","onClose","length","size","label","t","onClick","useCallback","useState","InputGroup","ComboBox","ComboBoxOption","SelectOption","Select","isEmpty","value","Array","isArray","length","Map","Set","size","Object","keys","FiltersInput","filters","onChange","useLingui","selectedFilterName","setSelectedFilterName","selectedFilterValue","setSelectedFilterValue","filterValues","find","filter","filterName","values","handleValueChange","name","setTimeout","getSelectProps","className","label","t","String","getComboBoxProps","disabled","map","displayName","data-testid"],"sources":["../../src/client/components/ListToolbar/SelectedFilters.tsx","../../src/client/components/ListToolbar/FiltersInput.tsx"],"sourcesContent":["import { useLingui } from \"@lingui/react/macro\"\nimport { Button, Pill, Stack } from \"@cloudoperators/juno-ui-components\"\nimport { SelectedFilter } from \"./types\"\n\nexport type SelectedFiltersProps = {\n /**\n * Array of currently active filters to be displayed as closeable pills.\n */\n selectedFilters: SelectedFilter[]\n\n /**\n * Callback function invoked when a user removes an individual filter pill.\n */\n onDelete: (filter: SelectedFilter) => void\n\n /**\n * Callback function invoked when the \"Clear all\" button is clicked.\n */\n onClear: () => void\n}\n\n/**\n * SelectedFilters Component\n *\n * Displays currently active filters as closeable pill components with individual\n * remove buttons and an optional \"Clear all\" button (shown when 2+ filters are active).\n *\n * The pills are arranged in a flexible, wrapping layout that adapts to available space.\n */\nexport const SelectedFilters = ({ selectedFilters, onDelete, onClear }: SelectedFiltersProps) => {\n const { t } = useLingui()\n\n return (\n <Stack gap=\"2\" wrap={true} alignment=\"start\" distribution=\"start\">\n {/* Render a closeable pill for each selected filter */}\n {selectedFilters.map((filter) => (\n <Pill\n key={`${filter.name}:${filter.value}`}\n closeable\n pillKey={filter.name}\n pillValue={filter.value}\n onClose={() => onDelete(filter)}\n />\n ))}\n {selectedFilters.length > 1 && <Button size=\"small\" label={t`Clear all`} onClick={onClear} />}\n </Stack>\n )\n}\n","import { useCallback, useState } from \"react\"\nimport { useLingui } from \"@lingui/react/macro\"\nimport {\n InputGroup,\n ComboBox,\n ComboBoxProps,\n ComboBoxOption,\n SelectOption,\n Select,\n SelectProps,\n} from \"@cloudoperators/juno-ui-components\"\nimport { Filter, SelectedFilter } from \"./types\"\n\nexport type FiltersInputProps = {\n filters: Filter[]\n onChange: (filter: SelectedFilter) => void\n}\n\nfunction isEmpty(value: unknown) {\n if (value == null) return true\n if (typeof value === \"string\" || Array.isArray(value)) return value.length === 0\n if (value instanceof Map || value instanceof Set) return value.size === 0\n if (typeof value === \"object\") return Object.keys(value).length === 0\n return false\n}\n\nexport const FiltersInput = ({ filters, onChange }: FiltersInputProps) => {\n const { t } = useLingui()\n\n const [selectedFilterName, setSelectedFilterName] = useState<string>(\"\")\n const [selectedFilterValue, setSelectedFilterValue] = useState<string>(\"\")\n\n const filterValues: string[] | undefined = filters\n .find((filter) => filter.filterName === selectedFilterName)\n ?.values?.filter((value) => value)\n\n const handleValueChange = useCallback(\n (value: string) => {\n setSelectedFilterValue(value)\n if (!isEmpty(selectedFilterName) && !isEmpty(value)) {\n onChange({\n name: selectedFilterName,\n value: value,\n })\n }\n setTimeout(() => {\n setSelectedFilterValue(\"\")\n }, 0)\n },\n [selectedFilterName, setSelectedFilterValue, onChange]\n )\n\n const getSelectProps = (): SelectProps & { \"data-testid\"?: string } => ({\n className: \"w-full sm:flex-1 sm:min-w-0\",\n name: \"filter\",\n \"data-testid\": \"select-filterValue\",\n label: t`Filter by`,\n value: selectedFilterName,\n onChange: (value: string | number | string[] | undefined) => {\n setSelectedFilterName(String(value))\n },\n })\n\n const getComboBoxProps = (): ComboBoxProps & { \"data-testid\"?: string } => ({\n className: \"w-full sm:flex-1 sm:min-w-0\",\n name: \"filterValue\",\n \"data-testid\": \"combobox-filterValue\",\n value: selectedFilterValue,\n disabled: !selectedFilterName,\n onChange: handleValueChange,\n })\n\n return (\n <InputGroup className=\"flex w-full flex-col sm:w-auto sm:flex-row sm:items-end\">\n <Select {...getSelectProps()}>\n {filters?.map(({ displayName, filterName }) => (\n <SelectOption value={filterName} label={displayName} key={filterName} data-testid={filterName} />\n ))}\n </Select>\n <ComboBox {...getComboBoxProps()}>\n {filterValues?.map((value) => (\n <ComboBoxOption value={value} key={value} label={value} data-testid={value} />\n ))}\n </ComboBox>\n </InputGroup>\n )\n}\n"],"mappings":";;;;;AA6BA,IAAaG,KAAmB,EAAEC,oBAAiBC,aAAUC,iBAA+B;CAC1F,IAAM,EAAA,MAAA,GAAA,GAAA,MAAQC,EAAAA;CAEd,OACE,gBAACL,GAAAA;EAAMM,KAAI;EAAIC,MAAM;EAAMC,WAAU;EAAQC,cAAa;aAEvDP,EAAgBQ,KAAKC,MACpB,gBAACZ,GAAAA;GAECa,WAAS;GACTC,SAASF,EAAOG;GAChBC,WAAWJ,EAAOK;GAClBC,eAAed,EAASQ,CAAAA;KAJnB,GAAGA,EAAOG,KAAK,GAAGH,EAAOK,OAAO,CAAA,GAOxCd,EAAgBgB,SAAS,KAAK,gBAACpB,GAAAA;GAAOqB,MAAK;GAAQC,OAAOC,EAAAA,EAAC,EAAA,IAAA,SAAU,CAAA;GAAGC,SAASlB;;;AAGxF;;;AC7BA,SAAS0B,EAAQC,GAAc;CAK7B,OAJIA,KAAS,OAAa,KACtB,OAAOA,KAAU,YAAYC,MAAMC,QAAQF,CAAAA,IAAeA,EAAMG,WAAW,IAC3EH,aAAiBI,OAAOJ,aAAiBK,MAAYL,EAAMM,SAAS,IACpE,OAAON,KAAU,WAAiBO,OAAOC,KAAKR,CAAAA,EAAOG,WAAW,IAC7D;AACT;AAEA,IAAaM,KAAgB,EAAEC,YAASC,kBAA6B;CACnE,IAAM,EAAA,MAAA,GAAA,GAAA,MAAQC,EAAAA,GAER,CAACC,GAAoBC,KAAyBrB,EAAiB,EAAA,GAC/D,CAACsB,GAAqBC,KAA0BvB,EAAiB,EAAA,GAEjEwB,IAAqCP,EACxCQ,MAAMC,MAAWA,EAAOC,eAAeP,CAAAA,GACtCQ,QAAQF,QAAQnB,MAAUA,CAAAA,GAExBsB,IAAoB9B,GACvBQ,MAAAA;EAQCwB,AAPAR,EAAuBhB,CAAAA,GACnB,CAACD,EAAQc,CAAAA,KAAuB,CAACd,EAAQC,CAAAA,KAC3CW,EAAS;GACPY,MAAMV;GACCb;EACT,CAAA,GAEFwB,iBAAW;GACTR,EAAuB,EAAA;EACzB,GAAG,CAAA;CACL,GACA;EAACH;EAAoBG;EAAwBL;EAAS,GAGlDc,WAAkE;EACtEC,WAAW;EACXH,MAAM;EACN,eAAe;EACfI,OAAOC,EAAAA,EAAC,EAAA,IAAA,SAAU,CAAA;EAClB5B,OAAOa;EACPF,WAAWX,MAAAA;GACTc,EAAsBe,OAAO7B,CAAAA,CAAAA;EAC/B;CACF,IAEM8B,WAAsE;EAC1EJ,WAAW;EACXH,MAAM;EACN,eAAe;EACfvB,OAAOe;EACPgB,UAAU,CAAClB;EACXF,UAAUW;CACZ;CAEA,OACE,gBAAC5B,GAAAA;EAAWgC,WAAU;aACpB,gBAAC5B,GAAAA;GAAQ,GAAG2B,EAAAA;aACTf,GAASsB,KAAK,EAAEC,gBAAab,oBAC5B,gBAACvB,GAAAA;IAAaG,OAAOoB;IAAYO,OAAOM;IAA8BC,eAAad;MAAzBA,CAAAA,CAAAA;MAG9D,gBAACzB,GAAAA;GAAU,GAAGmC,EAAAA;aACXb,GAAce,KAAKhC,MAClB,gBAACJ,GAAAA;IAAsBI;IAAmB2B,OAAO3B;IAAOkC,eAAalC;MAAlCA,CAAAA,CAAAA;;;AAK7C"}