@cobaltcore-dev/aurora 1.3.0 → 2.0.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 (122) hide show
  1. package/dist/client/DeleteFlavorModal-C2MqUgGR.mjs +801 -0
  2. package/dist/client/DeleteFlavorModal-C2MqUgGR.mjs.map +1 -0
  3. package/dist/client/{FiltersInput-CKI6zWnm.mjs → FiltersInput-Becwxo_J.mjs} +36 -33
  4. package/dist/client/FiltersInput-Becwxo_J.mjs.map +1 -0
  5. package/dist/client/{FloatingIpActionModals-Ch8uozH9.mjs → FloatingIpActionModals-Cq10WljB.mjs} +2 -2
  6. package/dist/client/{FloatingIpActionModals-Ch8uozH9.mjs.map → FloatingIpActionModals-Cq10WljB.mjs.map} +1 -1
  7. package/dist/client/ImageToastNotifications-BWfzOUMc.mjs +1135 -0
  8. package/dist/client/ImageToastNotifications-BWfzOUMc.mjs.map +1 -0
  9. package/dist/client/RouteIdLevelDefaultError-CSseJ1yG.mjs +26 -0
  10. package/dist/client/RouteIdLevelDefaultError-CSseJ1yG.mjs.map +1 -0
  11. package/dist/client/{_flavorId-Dg7MS0Af.mjs → _flavorId-CaA4-Pnf.mjs} +4 -3
  12. package/dist/client/_flavorId-CaA4-Pnf.mjs.map +1 -0
  13. package/dist/client/_flavorId-DYv_StX22.mjs +276 -0
  14. package/dist/client/_flavorId-DYv_StX22.mjs.map +1 -0
  15. package/dist/client/_flavorId-YV3jCS5g.mjs +22 -0
  16. package/dist/client/_flavorId-YV3jCS5g.mjs.map +1 -0
  17. package/dist/client/{_floatingIpId-C9xfRWot.mjs → _floatingIpId-BeYElanB.mjs} +2 -2
  18. package/dist/client/{_floatingIpId-C9xfRWot.mjs.map → _floatingIpId-BeYElanB.mjs.map} +1 -1
  19. package/dist/client/{_floatingIpId-DNn6ABCB.mjs → _floatingIpId-Dpsc7GU4.mjs} +5 -5
  20. package/dist/client/{_floatingIpId-DNn6ABCB.mjs.map → _floatingIpId-Dpsc7GU4.mjs.map} +1 -1
  21. package/dist/client/_imageId-mfKp3JHn.mjs +558 -0
  22. package/dist/client/_imageId-mfKp3JHn.mjs.map +1 -0
  23. package/dist/client/_imageId-mpXUMCh_.mjs +22 -0
  24. package/dist/client/_imageId-mpXUMCh_.mjs.map +1 -0
  25. package/dist/client/{_imageId-8JIbFmGB.mjs → _imageId-pBSS0YcC.mjs} +4 -3
  26. package/dist/client/_imageId-pBSS0YcC.mjs.map +1 -0
  27. package/dist/client/{_projectId-B3wmSala.mjs → _projectId-AjgJX6Gl.mjs} +2 -2
  28. package/dist/client/_projectId-AjgJX6Gl.mjs.map +1 -0
  29. package/dist/client/{_projectId-DPzv0CCp.mjs → _projectId-BnTBxKfp.mjs} +4 -4
  30. package/dist/client/_projectId-BnTBxKfp.mjs.map +1 -0
  31. package/dist/client/{_projectId-DfeVJy0G.mjs → _projectId-CVrdJ52s.mjs} +2 -2
  32. package/dist/client/_projectId-CVrdJ52s.mjs.map +1 -0
  33. package/dist/client/_projectId-DgciZslU.mjs +92 -0
  34. package/dist/client/_projectId-DgciZslU.mjs.map +1 -0
  35. package/dist/client/{_securityGroupId-C6eHmrx_.mjs → _securityGroupId-AO3wnH8g.mjs} +2 -2
  36. package/dist/client/_securityGroupId-AO3wnH8g.mjs.map +1 -0
  37. package/dist/client/{_securityGroupId-DmplhDgt.mjs → _securityGroupId-Bq0ZyG6z.mjs} +750 -741
  38. package/dist/client/_securityGroupId-Bq0ZyG6z.mjs.map +1 -0
  39. package/dist/client/_storageType-c-DAu8qr.mjs +858 -0
  40. package/dist/client/_storageType-c-DAu8qr.mjs.map +1 -0
  41. package/dist/client/components/{Error → Errors}/RouteError.d.ts +5 -0
  42. package/dist/client/components/Errors/RouteIdLevelDefaultError.d.ts +17 -0
  43. package/dist/client/components/Errors/ServiceLevelDefaultError.d.ts +9 -0
  44. package/dist/client/components/ListToolbar/SelectedFilters.d.ts +7 -2
  45. package/dist/client/components/ListToolbar/types.d.ts +6 -0
  46. package/dist/client/components/ListToolbar/valueLabels.d.ts +11 -0
  47. package/dist/client/flavors-Bgq3KZmx.mjs +659 -0
  48. package/dist/client/flavors-Bgq3KZmx.mjs.map +1 -0
  49. package/dist/client/{flavors-B1SDOPDu.mjs → flavors-ZudiAiTU.mjs} +2 -2
  50. package/dist/client/{flavors-B1SDOPDu.mjs.map → flavors-ZudiAiTU.mjs.map} +1 -1
  51. package/dist/client/{floatingips-DrCvtXtT.mjs → floatingips-B1oLH8z6.mjs} +6 -6
  52. package/dist/client/{floatingips-DrCvtXtT.mjs.map → floatingips-B1oLH8z6.mjs.map} +1 -1
  53. package/dist/client/floatingips-BeQEkVH8.mjs +14 -0
  54. package/dist/client/floatingips-BeQEkVH8.mjs.map +1 -0
  55. package/dist/client/floatingips-BtLg3yEQ.mjs +22 -0
  56. package/dist/client/floatingips-BtLg3yEQ.mjs.map +1 -0
  57. package/dist/client/floatingips-Cz9k80cc.mjs.map +1 -1
  58. package/dist/client/{images-BGQv9kKT.mjs → images-CnTW3bpy.mjs} +810 -770
  59. package/dist/client/images-CnTW3bpy.mjs.map +1 -0
  60. package/dist/client/{images-CPmMa4SQ.mjs → images-DZHDYDQu.mjs} +2 -2
  61. package/dist/client/{images-CPmMa4SQ.mjs.map → images-DZHDYDQu.mjs.map} +1 -1
  62. package/dist/client/index.js +412 -409
  63. package/dist/client/index.js.map +1 -1
  64. package/dist/client/{objects-DVccbrL1.mjs → objects-25xsh4Ia.mjs} +2 -2
  65. package/dist/client/objects-25xsh4Ia.mjs.map +1 -0
  66. package/dist/client/objects-KXY6dgwq.mjs +82 -0
  67. package/dist/client/objects-KXY6dgwq.mjs.map +1 -0
  68. package/dist/client/objects-QryuClU3.mjs +82 -0
  69. package/dist/client/objects-QryuClU3.mjs.map +1 -0
  70. package/dist/client/{objects-BR3eeSNH.mjs → objects-jYQBFzwg.mjs} +4668 -4699
  71. package/dist/client/objects-jYQBFzwg.mjs.map +1 -0
  72. package/dist/client/projects-yiK0HGSA.mjs.map +1 -1
  73. package/dist/client/securitygroups--0PS2wbM.mjs +580 -0
  74. package/dist/client/securitygroups--0PS2wbM.mjs.map +1 -0
  75. package/dist/client/{securitygroups-DEJQBcxm.mjs → securitygroups-BRndk7wh.mjs} +2 -2
  76. package/dist/client/{securitygroups-DEJQBcxm.mjs.map → securitygroups-BRndk7wh.mjs.map} +1 -1
  77. package/dist/client/securitygroups-CdN4yAAw.mjs +14 -0
  78. package/dist/client/securitygroups-CdN4yAAw.mjs.map +1 -0
  79. package/dist/client/securitygroups-Cs2Op-tu.mjs +22 -0
  80. package/dist/client/securitygroups-Cs2Op-tu.mjs.map +1 -0
  81. package/dist/client/securitygroups-CtKne8UQ.mjs.map +1 -1
  82. package/dist/client/trpcClient.d.ts +6 -1
  83. package/dist/client/useModalTracking-BYd37pXm.mjs +37 -0
  84. package/dist/client/useModalTracking-BYd37pXm.mjs.map +1 -0
  85. package/dist/client/useSecurityGroupPermissions--hK4aR8Y.mjs +294 -0
  86. package/dist/client/useSecurityGroupPermissions--hK4aR8Y.mjs.map +1 -0
  87. package/dist/server/index.d.ts +6 -1
  88. package/dist/server/index.js +96 -30
  89. package/package.json +4 -4
  90. package/dist/client/DeleteFlavorModal-V44QCJBd.mjs +0 -773
  91. package/dist/client/DeleteFlavorModal-V44QCJBd.mjs.map +0 -1
  92. package/dist/client/FiltersInput-CKI6zWnm.mjs.map +0 -1
  93. package/dist/client/ImageToastNotifications-m6c3tVPb.mjs +0 -1152
  94. package/dist/client/ImageToastNotifications-m6c3tVPb.mjs.map +0 -1
  95. package/dist/client/_flavorId-Dg7MS0Af.mjs.map +0 -1
  96. package/dist/client/_flavorId-kHl-b8rI.mjs +0 -232
  97. package/dist/client/_flavorId-kHl-b8rI.mjs.map +0 -1
  98. package/dist/client/_imageId-8JIbFmGB.mjs.map +0 -1
  99. package/dist/client/_imageId-BBAlRioC.mjs +0 -574
  100. package/dist/client/_imageId-BBAlRioC.mjs.map +0 -1
  101. package/dist/client/_projectId-7Nl1MQTJ.mjs +0 -99
  102. package/dist/client/_projectId-7Nl1MQTJ.mjs.map +0 -1
  103. package/dist/client/_projectId-B3wmSala.mjs.map +0 -1
  104. package/dist/client/_projectId-DPzv0CCp.mjs.map +0 -1
  105. package/dist/client/_projectId-DfeVJy0G.mjs.map +0 -1
  106. package/dist/client/_securityGroupId-C6eHmrx_.mjs.map +0 -1
  107. package/dist/client/_securityGroupId-DmplhDgt.mjs.map +0 -1
  108. package/dist/client/_storageType-C5gS9eut.mjs +0 -845
  109. package/dist/client/_storageType-C5gS9eut.mjs.map +0 -1
  110. package/dist/client/flavors-D8_PzQUB.mjs +0 -628
  111. package/dist/client/flavors-D8_PzQUB.mjs.map +0 -1
  112. package/dist/client/images-BGQv9kKT.mjs.map +0 -1
  113. package/dist/client/objects-AERkhfiM.mjs +0 -66
  114. package/dist/client/objects-AERkhfiM.mjs.map +0 -1
  115. package/dist/client/objects-BR3eeSNH.mjs.map +0 -1
  116. package/dist/client/objects-DVccbrL1.mjs.map +0 -1
  117. package/dist/client/securitygroups-BjhgLBHm.mjs +0 -620
  118. package/dist/client/securitygroups-BjhgLBHm.mjs.map +0 -1
  119. package/dist/client/useModalTracking-BcOKTYRN.mjs +0 -33
  120. package/dist/client/useModalTracking-BcOKTYRN.mjs.map +0 -1
  121. package/dist/client/useSecurityGroupPermissions-BOyLQLdC.mjs +0 -227
  122. package/dist/client/useSecurityGroupPermissions-BOyLQLdC.mjs.map +0 -1
@@ -0,0 +1 @@
1
+ {"version":3,"file":"flavors-Bgq3KZmx.mjs","names":["DataGrid","DataGridHeadCell","DataGridRow","DataGridCell","PopupMenu","PopupMenuOptions","PopupMenuItem","PopupMenuSectionSeparator","Status","Pagination","DeleteFlavorModal","useEffect","useState","EditSpecModal","ManageAccessModal","useParams","useNavigate","FlavorListContainer","flavors","isLoading","client","project","onFlavorDeleted","canDeleteFlavor","canMangageAccess","canManageSpecs","currentPage","totalPages","onPageChange","useLingui","navigate","deleteModalOpen","setDeleteModalOpen","specModalOpen","setSpecModalOpen","accessModalOpen","setAccessModalOpen","selectedFlavor","setSelectedFlavor","inputPage","setInputPage","toString","projectId","from","openDeleteModal","flavor","openSpecModal","openAccessModal","closeDeleteModal","handleDeleteSuccess","name","updateCurrentPage","newPage","status","title","t","columns","minContentColumns","className","data-testid","length","map","id","onClick","to","params","flavorId","vcpus","ram","disk","swap","e","stopPropagation","label","colSpan","body","div","variant","pages","onPressPrevious","Math","max","onPressNext","min","onSelectChange","selectedPage","onInputChange","newInputPage","undefined","String","onKeyDown","key","parseInt","isNaN","isOpen","onClose","onSuccess","validateField","field","value","t","undefined","idStr","String","trim","idRegex","test","msg","nameStr","length","vcpus","Number","isNaN","ram","disk","swap","rxtx","str","ephemeral","cleanFlavorData","flavor","result","name","isValidValue","isValidNumber","id","description","rxtx_factor","Boolean","React","useState","Modal","Form","FormRow","FormSection","TextInput","Message","Status","Checkbox","validateField","cleanFlavorData","useErrorTranslation","CreateFlavorModal","client","isOpen","onClose","project","onSuccess","useLingui","translateError","newFlavor","setNewFlavor","errors","setErrors","isLoading","setIsLoading","generalError","setGeneralError","handleInputChange","e","name","value","type","checked","target","prev","newState","undefined","handleNumericInputChange","handleBlur","error","handleSubmit","preventDefault","newErrors","requiredFields","forEach","key","optionalFields","Object","keys","length","t","flavorData","compute","createFlavor","mutate","project_id","flavor","handleClose","errorMessage","message","dismissError","isFormValid","field","onCancel","size","title","open","onConfirm","cancelButtonLabel","confirmButtonLabel","disableConfirmButton","disableCancelButton","disableCloseButton","status","className","onDismiss","text","variant","id","label","onChange","onBlur","errortext","helptext","required","description","String","vcpus","Number","ram","disk","swap","defaultValue","rxtx_factor","use","Suspense","useState","useRef","startTransition","useEffect","useCallback","ErrorBoundary","useSearch","useNavigate","TRPCClientError","toast","Message","Button","Stack","DataGridToolbar","SearchInput","Status","SortInput","FlavorListContainer","CreateFlavorModal","getFlavorCreatedToast","getFlavorDeletedToast","PAGE_SIZE","createFlavorsPromise","client","project","sortBy","sortDirection","searchTerm","compute","getFlavorsByProjectId","query","project_id","then","res","listError","undefined","catch","err","data","code","flavors","privateFlavorError","message","createPermissionsPromise","canUser","permission","canCreate","canDelete","canAddProject","canRemoveProject","canCreateSpecs","canDeleteSpecs","canManageAccess","canManageSpecs","FlavorsContent","flavorsPromise","permissionsPromise","onFlavorDeleted","onFlavorCreated","setSearchTerm","sortSettings","handleSortChange","createModalOpen","setCreateModalOpen","currentPage","onPageChange","useLingui","permissions","localSearchTerm","setLocalSearchTerm","debounceTimer","clearTimeout","current","p","totalPages","Math","max","ceil","length","safePage","min","paginatedFlavors","slice","isOpen","onClose","onSuccess","className","text","t","variant","distribution","alignment","gap","options","selectClassName","selectWidth","onSortByChange","v","onSortDirectionChange","dir","label","onClick","placeholder","data-testid","value","onInput","e","currentTarget","window","setTimeout","onSearch","onClear","isLoading","canDeleteFlavor","canMangageAccess","Flavors","navigate","searchParams","strict","setSortSettings","search","page","setFlavorsPromise","refetchFlavors","handleFlavorDeleted","flavorName","success","handleFlavorCreated","newSortSettings","settings","toString","prev","replace","handleSearchChange","term","searchValue","handlePageChange","div","fallbackRender","error","status","title","body","Error","fallback","useLingui","Flavors","ContentHeader","Route","RouteComponent","t","projectId","useParams","trpcClient","useRouteContext","component"],"sources":["../../src/client/routes/_auth/projects/$projectId/compute/flavors/-components/FlavorListContainer.tsx","../../src/client/routes/_auth/projects/$projectId/compute/flavors/-components/flavorValidation.ts","../../src/client/routes/_auth/projects/$projectId/compute/flavors/-components/CreateFlavorModal.tsx","../../src/client/routes/_auth/projects/$projectId/compute/flavors/-components/List.tsx","../../src/client/routes/_auth/projects/$projectId/compute/flavors/index.tsx?tsr-split=component"],"sourcesContent":["import { Flavor } from \"@/server/Compute/types/flavor\"\nimport {\n DataGrid,\n DataGridHeadCell,\n DataGridRow,\n DataGridCell,\n PopupMenu,\n PopupMenuOptions,\n PopupMenuItem,\n PopupMenuSectionSeparator,\n Status,\n Pagination,\n} from \"@cloudoperators/juno-ui-components\"\nimport { Trans, useLingui } from \"@lingui/react/macro\"\nimport { DeleteFlavorModal } from \"./DeleteFlavorModal\"\nimport { useEffect, useState } from \"react\"\nimport { TrpcClient } from \"@/client/trpcClient\"\nimport { EditSpecModal } from \"./EditSpecModal\"\nimport { ManageAccessModal } from \"./ManageAccessModal\"\nimport { useParams, useNavigate } from \"@tanstack/react-router\"\n\ninterface FlavorListContainerProps {\n flavors?: Flavor[]\n isLoading: boolean\n client: TrpcClient\n project: string\n onFlavorDeleted?: (flavorName: string) => void\n canDeleteFlavor?: boolean\n canMangageAccess?: boolean\n canManageSpecs?: boolean\n currentPage?: number\n totalPages?: number\n onPageChange?: (page: number) => void\n}\n\nexport const FlavorListContainer = ({\n flavors,\n isLoading,\n client,\n project,\n onFlavorDeleted,\n canDeleteFlavor,\n canMangageAccess,\n canManageSpecs,\n currentPage = 1,\n totalPages = 1,\n onPageChange,\n}: FlavorListContainerProps) => {\n const { t } = useLingui()\n const navigate = useNavigate()\n const [deleteModalOpen, setDeleteModalOpen] = useState(false)\n const [specModalOpen, setSpecModalOpen] = useState(false)\n const [accessModalOpen, setAccessModalOpen] = useState(false)\n const [selectedFlavor, setSelectedFlavor] = useState<Flavor | null>(null)\n const [inputPage, setInputPage] = useState<string>(currentPage.toString())\n\n useEffect(() => {\n setInputPage(currentPage.toString())\n }, [currentPage])\n\n const { projectId } = useParams({\n from: \"/_auth/projects/$projectId/compute/flavors/\",\n })\n\n const openDeleteModal = (flavor: Flavor) => {\n setSelectedFlavor(flavor)\n setDeleteModalOpen(true)\n }\n\n const openSpecModal = (flavor: Flavor) => {\n setSelectedFlavor(flavor)\n setSpecModalOpen(true)\n }\n\n const openAccessModal = (flavor: Flavor) => {\n setSelectedFlavor(flavor)\n setAccessModalOpen(true)\n }\n\n const closeDeleteModal = () => {\n setDeleteModalOpen(false)\n setSelectedFlavor(null)\n }\n\n const handleDeleteSuccess = () => {\n if (selectedFlavor && onFlavorDeleted) {\n onFlavorDeleted(selectedFlavor.name || \"\")\n }\n closeDeleteModal()\n }\n\n const updateCurrentPage = (newPage: number) => {\n if (newPage >= 1 && newPage <= totalPages) {\n onPageChange?.(newPage)\n setInputPage(newPage.toString())\n }\n }\n\n if (isLoading) {\n return <Status status=\"progress\" title={t`Loading...`} />\n }\n\n return (\n <>\n <DataGrid columns={7} minContentColumns={[6]} className=\"flavors\" data-testid=\"flavors-table\">\n <DataGridRow>\n <DataGridHeadCell>\n <Trans>Name</Trans>\n </DataGridHeadCell>\n <DataGridHeadCell>\n <Trans>vCPU</Trans>\n </DataGridHeadCell>\n <DataGridHeadCell>\n <Trans>RAM (MiB)</Trans>\n </DataGridHeadCell>\n <DataGridHeadCell>\n <Trans>Root Disk (GiB)</Trans>\n </DataGridHeadCell>\n <DataGridHeadCell>\n <Trans>Swap (MiB)</Trans>\n </DataGridHeadCell>\n <DataGridHeadCell>\n <Trans>Access Type</Trans>\n </DataGridHeadCell>\n <DataGridHeadCell></DataGridHeadCell>\n </DataGridRow>\n\n {flavors && flavors.length > 0 ? (\n flavors.map((flavor) => (\n <DataGridRow\n key={flavor.id}\n data-testid={`flavor-row-${flavor.id}`}\n onClick={() =>\n navigate({\n to: \"/projects/$projectId/compute/flavors/$flavorId\",\n params: { projectId, flavorId: flavor.id },\n })\n }\n >\n <DataGridCell>{flavor.name || flavor.id}</DataGridCell>\n <DataGridCell>{flavor.vcpus || \"–\"}</DataGridCell>\n <DataGridCell>{flavor.ram || \"–\"}</DataGridCell>\n <DataGridCell>{flavor.disk || \"–\"}</DataGridCell>\n <DataGridCell>{flavor.swap || \"–\"}</DataGridCell>\n <DataGridCell>{flavor[\"os-flavor-access:is_public\"] === false ? t`Private` : t`Public`}</DataGridCell>\n <DataGridCell onClick={(e) => e.stopPropagation()}>\n <PopupMenu>\n <PopupMenuOptions>\n {canManageSpecs && <PopupMenuItem label={t`Edit Metadata`} onClick={() => openSpecModal(flavor)} />}\n {canMangageAccess && flavor[\"os-flavor-access:is_public\"] === false && (\n <PopupMenuItem label={t`Manage Access`} onClick={() => openAccessModal(flavor)} />\n )}\n <PopupMenuItem\n label={t`Show Details`}\n onClick={() =>\n navigate({\n to: \"/projects/$projectId/compute/flavors/$flavorId\",\n params: { projectId, flavorId: flavor.id },\n })\n }\n />\n {canDeleteFlavor && (\n <>\n <PopupMenuSectionSeparator />\n <PopupMenuItem label={t`Delete Flavor`} onClick={() => openDeleteModal(flavor)} />\n </>\n )}\n </PopupMenuOptions>\n </PopupMenu>\n </DataGridCell>\n </DataGridRow>\n ))\n ) : (\n <DataGridRow>\n <DataGridCell colSpan={7}>\n <Status\n status=\"empty\"\n title={t`No flavors found`}\n body={t`There are no flavors available for this project with the current filters applied. Try adjusting your filter criteria or create a new flavor.`}\n />\n </DataGridCell>\n </DataGridRow>\n )}\n </DataGrid>\n {totalPages > 1 && (\n <div className=\"flex justify-center py-4\">\n <Pagination\n variant=\"input\"\n currentPage={currentPage}\n pages={totalPages}\n onPressPrevious={() => updateCurrentPage(Math.max(currentPage - 1, 1))}\n onPressNext={() => updateCurrentPage(Math.min(currentPage + 1, totalPages))}\n onSelectChange={(selectedPage: number) => {\n updateCurrentPage(selectedPage)\n }}\n onInputChange={(newInputPage?: number) => {\n setInputPage(newInputPage === undefined ? \"\" : String(newInputPage))\n }}\n onKeyDown={(e: React.KeyboardEvent<HTMLInputElement>) => {\n if (e.key === \"Enter\" && inputPage !== \"\") {\n const newPage = parseInt(inputPage, 10)\n if (!isNaN(newPage) && newPage >= 1 && newPage <= totalPages) {\n updateCurrentPage(newPage)\n }\n }\n }}\n />\n </div>\n )}\n <DeleteFlavorModal\n client={client}\n isOpen={deleteModalOpen}\n onClose={closeDeleteModal}\n project={project}\n flavor={selectedFlavor}\n onSuccess={handleDeleteSuccess}\n />\n <EditSpecModal\n client={client}\n isOpen={specModalOpen}\n onClose={() => setSpecModalOpen(false)}\n project={project}\n flavor={selectedFlavor}\n />\n\n <ManageAccessModal\n client={client}\n isOpen={accessModalOpen}\n onClose={() => setAccessModalOpen(false)}\n project={project}\n flavor={selectedFlavor}\n />\n </>\n )\n}\n","import { msg } from \"@lingui/core/macro\"\nimport { MessageDescriptor } from \"@lingui/core\"\nimport { Flavor } from \"@/server/Compute/types/flavor\"\n\nexport const validateField = (\n field: FlavorFormField,\n value: string | number | boolean | null | undefined,\n t: (descriptor: MessageDescriptor) => string\n): string | undefined => {\n switch (field) {\n case \"id\":\n if (!value) return undefined\n {\n const idStr = String(value).trim()\n const idRegex = /^[a-zA-Z0-9.\\-_]*$/\n return idRegex.test(idStr)\n ? undefined\n : t(msg`ID must only contain alphanumeric characters, hyphens, underscores, and dots.`)\n }\n\n case \"name\": {\n const nameStr = String(value || \"\").trim()\n return nameStr.length >= 2 && nameStr.length <= 50 ? undefined : t(msg`Name must be 2-50 characters long.`)\n }\n\n case \"vcpus\": {\n const vcpus = Number(value)\n return !isNaN(vcpus) && vcpus >= 1 ? undefined : t(msg`VCPUs must be an integer ≥ 1.`)\n }\n\n case \"ram\": {\n const ram = Number(value)\n return !isNaN(ram) && ram >= 128 ? undefined : t(msg`RAM must be an integer ≥ 128 MB.`)\n }\n\n case \"disk\": {\n const disk = Number(value)\n return !isNaN(disk) && disk >= 0 ? undefined : t(msg`Root Disk must be an integer ≥ 0.`)\n }\n\n case \"swap\":\n if (value === \"\" || value === undefined || value === null) return undefined\n {\n const swap = Number(value)\n return !isNaN(swap) && swap >= 0 ? undefined : t(msg`Swap Disk must be an integer ≥ 0.`)\n }\n\n case \"rxtx_factor\": {\n const rxtx = Number(value)\n return !isNaN(rxtx) && rxtx >= 1 ? undefined : t(msg`RX/TX Factor must be an integer ≥ 1.`)\n }\n\n case \"description\":\n if (!value) return undefined\n {\n const str = String(value)\n return str.length < 65535 ? undefined : t(msg`Description must be less than 65535 characters.`)\n }\n\n case \"OS-FLV-EXT-DATA:ephemeral\": {\n const ephemeral = Number(value)\n return !isNaN(ephemeral) && ephemeral >= 0 ? undefined : t(msg`Ephemeral Disk must be an integer ≥ 0.`)\n }\n\n case \"os-flavor-access:is_public\": {\n if (value === undefined || value === null) {\n return undefined\n }\n if (typeof value === \"boolean\") {\n return undefined\n }\n if (typeof value === \"string\" && (value === \"true\" || value === \"false\")) {\n return undefined\n }\n return t(msg`Invalid value for public flavor setting.`)\n }\n\n default:\n return undefined\n }\n}\n\nexport type FlavorFormField =\n | \"id\"\n | \"name\"\n | \"vcpus\"\n | \"ram\"\n | \"disk\"\n | \"swap\"\n | \"description\"\n | \"rxtx_factor\"\n | \"OS-FLV-EXT-DATA:ephemeral\"\n | \"os-flavor-access:is_public\"\n\nexport interface FieldErrors {\n id?: string\n name?: string\n vcpus?: string\n ram?: string\n disk?: string\n swap?: string\n rxtx_factor?: string\n description?: string\n \"OS-FLV-EXT-DATA:ephemeral\"?: string\n \"os-flavor-access:is_public\"?: string\n}\n\nexport const cleanFlavorData = (flavor: Partial<Flavor>) => {\n const result: {\n name: string\n vcpus: number\n ram: number\n disk: number\n \"OS-FLV-EXT-DATA:ephemeral\"?: number\n id?: string\n swap?: number\n rxtx_factor?: number\n description?: string\n \"os-flavor-access:is_public\"?: boolean\n } = {\n name: String(flavor.name),\n vcpus: Number(flavor.vcpus),\n ram: Number(flavor.ram),\n disk: Number(flavor.disk),\n }\n\n const isValidValue = (value: string | undefined | null) => {\n return value !== undefined && value !== null && value !== \"\" && String(value).trim() !== \"\"\n }\n\n const isValidNumber = (value: string | number | undefined | null) => {\n return value !== undefined && value !== null && value !== \"\" && String(value).trim() !== \"\" && !isNaN(Number(value))\n }\n\n if (isValidValue(flavor.id)) {\n result.id = String(flavor.id).trim()\n }\n\n if (isValidValue(flavor.description)) {\n result.description = String(flavor.description).trim()\n }\n\n if (isValidNumber(flavor.swap)) {\n result.swap = Number(flavor.swap)\n }\n\n if (isValidNumber(flavor.rxtx_factor)) {\n result.rxtx_factor = Number(flavor.rxtx_factor)\n }\n\n if (isValidNumber(flavor[\"OS-FLV-EXT-DATA:ephemeral\"])) {\n result[\"OS-FLV-EXT-DATA:ephemeral\"] = Number(flavor[\"OS-FLV-EXT-DATA:ephemeral\"])\n }\n\n if (flavor[\"os-flavor-access:is_public\"] !== undefined) {\n result[\"os-flavor-access:is_public\"] = Boolean(flavor[\"os-flavor-access:is_public\"])\n }\n\n return result\n}\n","import React, { useState } from \"react\"\nimport { useLingui } from \"@lingui/react/macro\"\nimport { TrpcClient } from \"@/client/trpcClient\"\nimport {\n Modal,\n Form,\n FormRow,\n FormSection,\n TextInput,\n Message,\n Status,\n Checkbox,\n} from \"@cloudoperators/juno-ui-components\"\nimport { Flavor } from \"@/server/Compute/types/flavor\"\nimport { validateField, FlavorFormField, FieldErrors } from \"./flavorValidation\"\nimport { cleanFlavorData } from \"./flavorValidation\"\nimport { useErrorTranslation } from \"@/client/utils/useErrorTranslation\"\n\ninterface CreateFlavorModalProps {\n client: TrpcClient\n isOpen: boolean\n onClose: () => void\n project: string\n onSuccess: (name: string) => void\n}\n\nexport const CreateFlavorModal: React.FC<CreateFlavorModalProps> = ({\n client,\n isOpen,\n onClose,\n project,\n onSuccess,\n}) => {\n const { t } = useLingui()\n const { translateError } = useErrorTranslation()\n const [newFlavor, setNewFlavor] = useState<Partial<Flavor>>({\n \"os-flavor-access:is_public\": true,\n })\n const [errors, setErrors] = useState<FieldErrors>({})\n const [isLoading, setIsLoading] = useState(false)\n const [generalError, setGeneralError] = useState<string | null>(null)\n\n const handleInputChange = (e: React.ChangeEvent<HTMLInputElement>) => {\n const { name, value, type, checked } = e.target\n\n setNewFlavor((prev) => {\n const newState = {\n ...prev,\n [name]: type === \"checkbox\" ? checked : value,\n }\n\n return newState\n })\n // Clear error for this field when user changes the value\n setErrors((prev) => ({\n ...prev,\n [name]: undefined,\n }))\n if (generalError) setGeneralError(null)\n }\n\n const handleNumericInputChange = (name: FlavorFormField, value: number | undefined) => {\n setNewFlavor((prev) => ({\n ...prev,\n [name]: value,\n }))\n // Clear error for this field when user changes the value\n setErrors((prev) => ({\n ...prev,\n [name]: undefined,\n }))\n if (generalError) setGeneralError(null)\n }\n\n const handleBlur = (e: React.FocusEvent<HTMLInputElement>) => {\n const { name, value } = e.target\n const error = validateField(name as FlavorFormField, value, t)\n setErrors((prev) => ({\n ...prev,\n [name]: error,\n }))\n }\n\n const handleSubmit = async (e: React.FormEvent) => {\n e.preventDefault()\n setGeneralError(null)\n\n const newErrors: FieldErrors = {}\n\n const requiredFields: FlavorFormField[] = [\"name\", \"vcpus\", \"ram\", \"disk\"]\n requiredFields.forEach((key) => {\n const error = validateField(key, newFlavor[key], t)\n if (error) {\n newErrors[key] = error\n }\n })\n\n const optionalFields: FlavorFormField[] = [\n \"id\",\n \"swap\",\n \"OS-FLV-EXT-DATA:ephemeral\",\n \"rxtx_factor\",\n \"description\",\n \"os-flavor-access:is_public\",\n ]\n optionalFields.forEach((key) => {\n const value = newFlavor[key]\n\n if (value !== undefined && value !== \"\" && value !== null) {\n const error = validateField(key, value, t)\n if (error) {\n newErrors[key] = error\n }\n }\n })\n\n if (Object.keys(newErrors).length > 0) {\n setErrors(newErrors)\n setGeneralError(t`Please fix the validation errors below.`)\n return\n }\n\n try {\n setIsLoading(true)\n\n const flavorData = cleanFlavorData(newFlavor)\n\n await client.compute.createFlavor.mutate({\n project_id: project,\n flavor: flavorData,\n })\n\n onSuccess(flavorData.name)\n handleClose()\n } catch (error) {\n const errorMessage = (error as Error)?.message\n ? translateError((error as Error).message)\n : t`Failed to create flavor. Please try again.`\n setGeneralError(errorMessage)\n } finally {\n setIsLoading(false)\n }\n }\n\n const handleClose = () => {\n setNewFlavor({\n \"os-flavor-access:is_public\": true,\n })\n setErrors({})\n setGeneralError(null)\n onClose()\n }\n\n const dismissError = () => {\n setGeneralError(null)\n }\n\n const isFormValid = () => {\n // Check required fields are filled and have no errors\n const requiredFields: FlavorFormField[] = [\"name\", \"vcpus\", \"ram\", \"disk\"]\n\n for (const field of requiredFields) {\n const value = newFlavor[field]\n // Field must have a value\n if (value === undefined || value === \"\" || value === null) return false\n // Field must not have a validation error\n if (validateField(field, value, t)) return false\n }\n\n // Check optional fields for errors (if they have values)\n const optionalFields: FlavorFormField[] = [\"id\", \"swap\", \"OS-FLV-EXT-DATA:ephemeral\", \"rxtx_factor\", \"description\"]\n\n for (const field of optionalFields) {\n const value = newFlavor[field]\n // Skip empty optional fields\n if (value === undefined || value === \"\" || value === null) continue\n // Field must not have a validation error\n if (validateField(field, value, t)) return false\n }\n\n return true\n }\n\n return (\n <Modal\n onCancel={handleClose}\n size=\"large\"\n title={t`Create Flavor`}\n open={isOpen}\n onConfirm={handleSubmit}\n cancelButtonLabel={t`Cancel`}\n confirmButtonLabel={t`Create New Flavor`}\n disableConfirmButton={!isFormValid() || isLoading}\n disableCancelButton={isLoading}\n disableCloseButton={isLoading}\n >\n {isLoading && <Status status=\"progress\" title={t`Creating Flavor...`} className=\"mt-0\" />}\n {!isLoading && (\n <Form>\n {generalError && (\n <FormRow>\n <Message onDismiss={dismissError} text={generalError} variant=\"error\" />\n </FormRow>\n )}\n\n <FormSection title={t`Flavor Information`}>\n <FormRow>\n <TextInput\n id=\"id\"\n name=\"id\"\n label={t`Flavor ID`}\n value={newFlavor.id || \"\"}\n onChange={handleInputChange}\n onBlur={handleBlur}\n errortext={errors.id}\n helptext={t`Auto-generated if not provided. Only alphanumeric, hyphens, underscores, and dots allowed.`}\n />\n </FormRow>\n <FormRow>\n <TextInput\n id=\"name\"\n name=\"name\"\n label={t`Flavor Name`}\n value={newFlavor.name || \"\"}\n onChange={handleInputChange}\n onBlur={handleBlur}\n errortext={errors.name}\n helptext={t`2-50 characters.`}\n required\n />\n </FormRow>\n <FormRow>\n <TextInput\n id=\"description\"\n name=\"description\"\n label={t`Description`}\n value={newFlavor.description || \"\"}\n onChange={handleInputChange}\n onBlur={handleBlur}\n errortext={errors.description}\n />\n </FormRow>\n <FormRow>\n <Checkbox\n name=\"os-flavor-access:is_public\"\n label={t`Public Flavor`}\n helptext={t`When checked, all tenants can use this flavor. Otherwise, grant access explicitly.`}\n checked={!!newFlavor[\"os-flavor-access:is_public\"]}\n onChange={handleInputChange}\n />\n </FormRow>\n </FormSection>\n\n <FormSection title={t`Hardware Specifications`}>\n <FormRow>\n <TextInput\n id=\"vcpus\"\n name=\"vcpus\"\n label={t`vCPU`}\n value={String(newFlavor.vcpus || \"\")}\n onChange={(e) => handleNumericInputChange(\"vcpus\", Number(e.target.value))}\n onBlur={handleBlur}\n errortext={errors.vcpus}\n type=\"number\"\n required\n />\n </FormRow>\n <FormRow>\n <TextInput\n id=\"ram\"\n name=\"ram\"\n label={t`RAM (MiB)`}\n value={String(newFlavor.ram || \"\")}\n onChange={(e) => handleNumericInputChange(\"ram\", Number(e.target.value))}\n onBlur={handleBlur}\n errortext={errors.ram}\n helptext={t`Minimum 128 MB.`}\n type=\"number\"\n required\n />\n </FormRow>\n <FormRow>\n <TextInput\n id=\"disk\"\n name=\"disk\"\n label={t`Root Disk (GiB)`}\n value={String(newFlavor.disk || \"\")}\n onChange={(e) => handleNumericInputChange(\"disk\", Number(e.target.value))}\n onBlur={handleBlur}\n errortext={errors.disk}\n type=\"number\"\n required\n />\n </FormRow>\n <FormRow>\n <TextInput\n id=\"OS-FLV-EXT-DATA:ephemeral\"\n name=\"OS-FLV-EXT-DATA:ephemeral\"\n label={t`Ephemeral Disk (GiB)`}\n value={String(newFlavor[\"OS-FLV-EXT-DATA:ephemeral\"] || \"\")}\n onChange={(e) => handleNumericInputChange(\"OS-FLV-EXT-DATA:ephemeral\", Number(e.target.value))}\n onBlur={handleBlur}\n errortext={errors[\"OS-FLV-EXT-DATA:ephemeral\"]}\n type=\"number\"\n />\n </FormRow>\n <FormRow>\n <TextInput\n id=\"swap\"\n name=\"swap\"\n label={t`Swap (MiB)`}\n value={String(newFlavor.swap || \"\")}\n onChange={(e) => handleNumericInputChange(\"swap\", e.target.value ? Number(e.target.value) : undefined)}\n onBlur={handleBlur}\n errortext={errors.swap}\n type=\"number\"\n />\n </FormRow>\n <FormRow>\n <TextInput\n id=\"rxtx_factor\"\n name=\"rxtx_factor\"\n label={t`RX/TX Factor`}\n defaultValue={1}\n value={String(newFlavor.rxtx_factor || \"\")}\n onChange={(e) => handleNumericInputChange(\"rxtx_factor\", Number(e.target.value))}\n onBlur={handleBlur}\n errortext={errors.rxtx_factor}\n helptext={t`Defaults to 1.`}\n type=\"number\"\n />\n </FormRow>\n </FormSection>\n </Form>\n )}\n </Modal>\n )\n}\n","import { use, Suspense, useState, useRef, startTransition, useEffect, useCallback } from \"react\"\nimport { ErrorBoundary } from \"react-error-boundary\"\nimport { useLingui } from \"@lingui/react/macro\"\nimport { useSearch, useNavigate } from \"@tanstack/react-router\"\nimport { TrpcClient } from \"@/client/trpcClient\"\nimport { Flavor } from \"@/server/Compute/types/flavor\"\nimport { TRPCClientError } from \"@trpc/client\"\nimport { toast, Message, Button, Stack, DataGridToolbar, SearchInput, Status } from \"@cloudoperators/juno-ui-components\"\nimport { SortInput } from \"@/client/components/ListToolbar/SortInput\"\nimport { SortSettings } from \"@/client/components/ListToolbar/types\"\nimport { FlavorListContainer } from \"./FlavorListContainer\"\nimport { CreateFlavorModal } from \"./CreateFlavorModal\"\nimport { getFlavorCreatedToast, getFlavorDeletedToast } from \"./FlavorToastNotifications\"\nimport type { FlavorsSearchParams } from \"@/client/routes/_auth/projects/$projectId/compute/flavors\"\n\nconst PAGE_SIZE = 50\n\ninterface FlavorsProps {\n client: TrpcClient\n project: string\n}\n\ntype RequiredSortSettings = {\n options: SortSettings[\"options\"]\n sortBy: string\n sortDirection: \"asc\" | \"desc\"\n}\n\nconst createFlavorsPromise = (\n client: TrpcClient,\n project: string,\n sortBy: string,\n sortDirection: string,\n searchTerm: string\n) => {\n return client.compute.getFlavorsByProjectId\n .query({ project_id: project, sortBy, sortDirection, searchTerm })\n .then((res) => ({ ...res, listError: undefined as string | undefined }))\n .catch((err: unknown) => {\n if (err instanceof TRPCClientError && err.data?.code === \"FORBIDDEN\") {\n return { flavors: [] as Flavor[], privateFlavorError: undefined, listError: err.message }\n }\n throw err\n })\n}\n\nconst createPermissionsPromise = (client: TrpcClient, project: string) => {\n return client.compute.canUser\n .query({\n project_id: project,\n permission: [\n \"flavors:create\",\n \"flavors:delete\",\n \"flavors:add_project\",\n \"flavors:remove_project\",\n \"flavor_specs:create\",\n \"flavor_specs:delete\",\n ],\n })\n .then(([canCreate, canDelete, canAddProject, canRemoveProject, canCreateSpecs, canDeleteSpecs]) => ({\n canCreate,\n canDelete,\n canManageAccess: canAddProject || canRemoveProject,\n canManageSpecs: canCreateSpecs || canDeleteSpecs,\n }))\n}\n\nfunction FlavorsContent({\n flavorsPromise,\n permissionsPromise,\n client,\n project,\n onFlavorDeleted,\n onFlavorCreated,\n searchTerm,\n setSearchTerm,\n sortSettings,\n handleSortChange,\n createModalOpen,\n setCreateModalOpen,\n currentPage,\n onPageChange,\n}: {\n flavorsPromise: Promise<{ flavors: Flavor[]; privateFlavorError?: string; listError?: string }>\n permissionsPromise: Promise<{\n canCreate: boolean\n canDelete: boolean\n canManageAccess: boolean\n canManageSpecs: boolean\n }>\n client: TrpcClient\n project: string\n onFlavorDeleted: (name: string) => void\n onFlavorCreated: (name: string) => void\n searchTerm: string\n setSearchTerm: (term: string) => void\n sortSettings: SortSettings\n handleSortChange: (settings: SortSettings) => void\n createModalOpen: boolean\n setCreateModalOpen: (open: boolean) => void\n currentPage: number\n onPageChange: (page: number) => void\n}) {\n const { t } = useLingui()\n const { flavors, privateFlavorError, listError } = use(flavorsPromise)\n const permissions = use(permissionsPromise)\n const [localSearchTerm, setLocalSearchTerm] = useState(searchTerm)\n const debounceTimer = useRef<number | undefined>(undefined)\n\n useEffect(() => () => clearTimeout(debounceTimer.current), [])\n\n if (listError) {\n return <p>{listError}</p>\n }\n\n const totalPages = Math.max(1, Math.ceil(flavors.length / PAGE_SIZE))\n const safePage = Math.min(currentPage, totalPages)\n const paginatedFlavors = flavors.slice((safePage - 1) * PAGE_SIZE, safePage * PAGE_SIZE)\n\n useEffect(() => {\n if (currentPage > totalPages) onPageChange(1)\n }, [totalPages, currentPage, onPageChange])\n\n return (\n <>\n <CreateFlavorModal\n client={client}\n isOpen={createModalOpen}\n project={project}\n onClose={() => setCreateModalOpen(false)}\n onSuccess={onFlavorCreated}\n />\n\n {privateFlavorError && (\n <Message\n className=\"mb-4\"\n text={t`Private flavors could not be loaded. You may be seeing an incomplete list.`}\n variant=\"warning\"\n />\n )}\n\n {/* Zone 1 — sort + create action, no background */}\n <Stack distribution=\"end\" alignment=\"center\" gap=\"2\" className=\"pb-2\">\n <Stack gap=\"2\">\n <SortInput\n options={sortSettings.options}\n sortBy={sortSettings.sortBy}\n sortDirection={sortSettings.sortDirection ?? \"asc\"}\n selectClassName=\"min-w-45\"\n selectWidth=\"auto\"\n onSortByChange={(v) =>\n handleSortChange({ ...sortSettings, sortBy: v, sortDirection: sortSettings.sortDirection })\n }\n onSortDirectionChange={(dir) => handleSortChange({ ...sortSettings, sortDirection: dir })}\n />\n {permissions.canCreate && (\n <Button variant=\"primary\" label={t`Create Flavor`} onClick={() => setCreateModalOpen(true)} />\n )}\n </Stack>\n </Stack>\n\n {/* Zone 2 — search bar */}\n <DataGridToolbar>\n <Stack distribution=\"end\" alignment=\"center\">\n <SearchInput\n placeholder={t`Search flavors...`}\n data-testid=\"searchbar\"\n value={localSearchTerm}\n onInput={(e: React.FormEvent<HTMLInputElement>) => {\n const v = e.currentTarget.value\n setLocalSearchTerm(v)\n clearTimeout(debounceTimer.current)\n debounceTimer.current = window.setTimeout(() => setSearchTerm(v), 500)\n }}\n onSearch={(v) => {\n clearTimeout(debounceTimer.current)\n setSearchTerm(typeof v === \"string\" ? v : \"\")\n }}\n onClear={() => {\n clearTimeout(debounceTimer.current)\n setLocalSearchTerm(\"\")\n setSearchTerm(\"\")\n }}\n />\n </Stack>\n </DataGridToolbar>\n\n <FlavorListContainer\n flavors={paginatedFlavors}\n isLoading={false}\n client={client}\n project={project}\n onFlavorDeleted={onFlavorDeleted}\n canDeleteFlavor={permissions.canDelete}\n canMangageAccess={permissions.canManageAccess}\n canManageSpecs={permissions.canManageSpecs}\n currentPage={safePage}\n totalPages={totalPages}\n onPageChange={onPageChange}\n />\n </>\n )\n}\nexport const Flavors = ({ client, project }: FlavorsProps) => {\n const { t } = useLingui()\n const navigate = useNavigate()\n const searchParams = useSearch({ strict: false }) as FlavorsSearchParams\n\n const [sortSettings, setSortSettings] = useState<RequiredSortSettings>({\n options: [\n { label: t`Name`, value: \"name\" },\n { label: t`vCPU`, value: \"vcpus\" },\n { label: t`RAM (MiB)`, value: \"ram\" },\n { label: t`Root Disk (GiB)`, value: \"disk\" },\n { label: t`Swap (MiB)`, value: \"swap\" },\n ],\n sortBy: searchParams.sortBy || \"name\",\n sortDirection: searchParams.sortDirection || \"asc\",\n })\n\n const [searchTerm, setSearchTerm] = useState(searchParams.search || \"\")\n const currentPage = searchParams.page ?? 1\n const [createModalOpen, setCreateModalOpen] = useState(false)\n\n const [flavorsPromise, setFlavorsPromise] = useState(() =>\n createFlavorsPromise(client, project, sortSettings.sortBy, sortSettings.sortDirection, searchTerm)\n )\n const [permissionsPromise] = useState(() => createPermissionsPromise(client, project))\n\n const refetchFlavors = () => {\n startTransition(() => {\n setFlavorsPromise(\n createFlavorsPromise(client, project, sortSettings.sortBy, sortSettings.sortDirection, searchTerm)\n )\n })\n }\n\n const handleFlavorDeleted = (flavorName: string) => {\n const { message, ...options } = getFlavorDeletedToast(flavorName)\n toast.success(message, options)\n refetchFlavors()\n }\n\n const handleFlavorCreated = (flavorName: string) => {\n const { message, ...options } = getFlavorCreatedToast(flavorName)\n toast.success(message, options)\n refetchFlavors()\n }\n\n const handleSortChange = (newSortSettings: SortSettings) => {\n const settings: RequiredSortSettings = {\n options: newSortSettings.options,\n sortBy: newSortSettings.sortBy?.toString() || \"name\",\n sortDirection: newSortSettings.sortDirection || \"asc\",\n }\n\n setSortSettings(settings)\n navigate({\n search: ((prev: FlavorsSearchParams) => ({\n ...prev,\n sortBy: settings.sortBy,\n sortDirection: settings.sortDirection,\n page: undefined,\n })) as unknown as true,\n replace: true,\n })\n startTransition(() => {\n setFlavorsPromise(createFlavorsPromise(client, project, settings.sortBy, settings.sortDirection, searchTerm))\n })\n }\n\n const handleSearchChange = (term: string | number | string[] | undefined) => {\n const searchValue = typeof term === \"string\" ? term : \"\"\n setSearchTerm(searchValue)\n\n navigate({\n search: ((prev: FlavorsSearchParams) => ({\n ...prev,\n search: searchValue || undefined,\n page: undefined,\n })) as unknown as true,\n replace: true,\n })\n startTransition(() => {\n setFlavorsPromise(\n createFlavorsPromise(client, project, sortSettings.sortBy, sortSettings.sortDirection, searchValue)\n )\n })\n }\n\n const handlePageChange = useCallback(\n (page: number) => {\n navigate({\n search: ((prev: FlavorsSearchParams) => ({\n ...prev,\n page: page === 1 ? undefined : page,\n })) as unknown as true,\n })\n },\n [navigate]\n )\n\n return (\n <div className=\"relative\">\n <ErrorBoundary\n fallbackRender={({ error }) => (\n <Status\n status=\"error\"\n title={t`Failed to Load Flavors`}\n body={error instanceof Error ? error.message : t`An unexpected error occurred.`}\n />\n )}\n >\n <Suspense fallback={<Status status=\"progress\" title={t`Loading Flavors...`} />}>\n <FlavorsContent\n flavorsPromise={flavorsPromise}\n permissionsPromise={permissionsPromise}\n client={client}\n project={project}\n onFlavorDeleted={handleFlavorDeleted}\n onFlavorCreated={handleFlavorCreated}\n searchTerm={searchTerm}\n setSearchTerm={handleSearchChange}\n sortSettings={sortSettings}\n handleSortChange={handleSortChange}\n createModalOpen={createModalOpen}\n setCreateModalOpen={setCreateModalOpen}\n currentPage={currentPage}\n onPageChange={handlePageChange}\n />\n </Suspense>\n </ErrorBoundary>\n </div>\n )\n}\n","import { createFileRoute } from \"@tanstack/react-router\"\nimport { t } from \"@lingui/core/macro\"\nimport { useLingui } from \"@lingui/react/macro\"\nimport { Flavors } from \"./-components/List\"\nimport type { RouteInfo } from \"@/client/routes/routeInfo\"\nimport { ContentHeader } from \"@/client/components/ContentHeader/ContentHeader\"\n\nexport const Route = createFileRoute(\"/_auth/projects/$projectId/compute/flavors/\")({\n staticData: {\n section: \"compute\",\n service: \"flavors\",\n analytics: {\n name: \"compute.flavors.list\",\n },\n } satisfies RouteInfo,\n head: () => ({ meta: [{ title: t`Flavors` }] }),\n component: RouteComponent,\n})\n\nfunction RouteComponent() {\n const { t } = useLingui()\n const { projectId } = Route.useParams()\n const { trpcClient } = Route.useRouteContext()\n return (\n <>\n <ContentHeader title={t`Flavors`} projectId={projectId} />\n <Flavors project={projectId} client={trpcClient!} />\n </>\n )\n}\n"],"mappings":"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"}
@@ -7,9 +7,9 @@ var r = e("/_auth/projects/$projectId/compute/flavors/")({
7
7
  analytics: { name: "compute.flavors.list" }
8
8
  },
9
9
  head: () => ({ meta: [{ title: n._({ id: "neiJm0" }) }] }),
10
- component: t(() => import("./flavors-D8_PzQUB.mjs"), "component")
10
+ component: t(() => import("./flavors-Bgq3KZmx.mjs"), "component")
11
11
  });
12
12
  //#endregion
13
13
  export { r as t };
14
14
 
15
- //# sourceMappingURL=flavors-B1SDOPDu.mjs.map
15
+ //# sourceMappingURL=flavors-ZudiAiTU.mjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"flavors-B1SDOPDu.mjs","names":["createFileRoute","t","Route","staticData","section","service","analytics","name","RouteInfo","head","meta","title","component","lazyRouteComponent","$$splitComponentImporter"],"sources":["../../src/client/routes/_auth/projects/$projectId/compute/flavors/index.tsx"],"sourcesContent":["import { createFileRoute } from \"@tanstack/react-router\"\nimport { t } from \"@lingui/core/macro\"\nimport { useLingui } from \"@lingui/react/macro\"\nimport { Flavors } from \"./-components/List\"\nimport type { RouteInfo } from \"@/client/routes/routeInfo\"\nimport { ContentHeader } from \"@/client/components/ContentHeader/ContentHeader\"\n\nexport const Route = createFileRoute(\"/_auth/projects/$projectId/compute/flavors/\")({\n staticData: {\n section: \"compute\",\n service: \"flavors\",\n analytics: {\n name: \"compute.flavors.list\",\n },\n } satisfies RouteInfo,\n head: () => ({ meta: [{ title: t`Flavors` }] }),\n component: RouteComponent,\n})\n\nfunction RouteComponent() {\n const { t } = useLingui()\n const { projectId } = Route.useParams()\n const { trpcClient } = Route.useRouteContext()\n return (\n <>\n <ContentHeader title={t`Flavors`} projectId={projectId} />\n <Flavors project={projectId} client={trpcClient!} />\n </>\n )\n}\n"],"mappings":";;AAOA,IAAaE,IAAQF,EAAgB,6CAAA,CAAA,CAA+C;CAClFG,YAAY;EACVC,SAAS;EACTC,SAAS;EACTC,WAAW,EACTC,MAAM,uBACR;CACF;CACAE,aAAa,EAAEC,MAAM,CAAC,EAAEC,OAAOV,EAAAA,EAAC,EAAA,IAAA,SAAA,CAAA,EAAU,CAAC,EAAE;CAC7CW,WAASC,0CAAA,WAAA;AACX,CAAA"}
1
+ {"version":3,"file":"flavors-ZudiAiTU.mjs","names":["createFileRoute","t","Route","staticData","section","service","analytics","name","RouteInfo","head","meta","title","component","lazyRouteComponent","$$splitComponentImporter"],"sources":["../../src/client/routes/_auth/projects/$projectId/compute/flavors/index.tsx"],"sourcesContent":["import { createFileRoute } from \"@tanstack/react-router\"\nimport { t } from \"@lingui/core/macro\"\nimport { useLingui } from \"@lingui/react/macro\"\nimport { Flavors } from \"./-components/List\"\nimport type { RouteInfo } from \"@/client/routes/routeInfo\"\nimport { ContentHeader } from \"@/client/components/ContentHeader/ContentHeader\"\n\nexport const Route = createFileRoute(\"/_auth/projects/$projectId/compute/flavors/\")({\n staticData: {\n section: \"compute\",\n service: \"flavors\",\n analytics: {\n name: \"compute.flavors.list\",\n },\n } satisfies RouteInfo,\n head: () => ({ meta: [{ title: t`Flavors` }] }),\n component: RouteComponent,\n})\n\nfunction RouteComponent() {\n const { t } = useLingui()\n const { projectId } = Route.useParams()\n const { trpcClient } = Route.useRouteContext()\n return (\n <>\n <ContentHeader title={t`Flavors`} projectId={projectId} />\n <Flavors project={projectId} client={trpcClient!} />\n </>\n )\n}\n"],"mappings":";;AAOA,IAAaE,IAAQF,EAAgB,6CAAA,CAAA,CAA+C;CAClFG,YAAY;EACVC,SAAS;EACTC,SAAS;EACTC,WAAW,EACTC,MAAM,uBACR;CACF;CACAE,aAAa,EAAEC,MAAM,CAAC,EAAEC,OAAOV,EAAAA,EAAC,EAAA,IAAA,SAAA,CAAA,EAAU,CAAC,EAAE;CAC7CW,WAASC,0CAAA,WAAA;AACX,CAAA"}
@@ -6,8 +6,8 @@ import { d as C, n as w, o as T } from "./md-kvaGCNAK.mjs";
6
6
  import { t as E } from "./ContentHeader-CPJbgYWn.mjs";
7
7
  import "./hooks-D0yKIumu.mjs";
8
8
  import { t as D } from "./useModal-DCs1OJh7.mjs";
9
- import { n as O, t as k } from "./FiltersInput-CKI6zWnm.mjs";
10
- import { t as A } from "./FloatingIpActionModals-Ch8uozH9.mjs";
9
+ import { n as O, t as k } from "./FiltersInput-Becwxo_J.mjs";
10
+ import { t as A } from "./FloatingIpActionModals-Cq10WljB.mjs";
11
11
  import { Fragment as j, jsx as M, jsxs as N } from "react/jsx-runtime";
12
12
  import { useEffect as P, useRef as F, useState as I } from "react";
13
13
  import { useNavigate as L, useSearch as R } from "@tanstack/react-router";
@@ -111,7 +111,7 @@ var G = {
111
111
  title: i._({ id: "odksI6" })
112
112
  }) : n ? /*#__PURE__*/ M(_, {
113
113
  status: "error",
114
- title: r?.message ?? i._({ id: "+Nx1wc" })
114
+ title: r?.message ?? i._({ id: "/sdjzP" })
115
115
  }) : /*#__PURE__*/ N(h, {
116
116
  columns: l,
117
117
  minContentColumns: [l - 1],
@@ -119,7 +119,7 @@ var G = {
119
119
  colSpan: l,
120
120
  children: /*#__PURE__*/ M(_, {
121
121
  status: "empty",
122
- title: i._({ id: "WCLyHI" }),
122
+ title: i._({ id: "JiQKPG" }),
123
123
  body: i._({ id: "0eY8Mz" })
124
124
  })
125
125
  }) })]
@@ -442,7 +442,7 @@ var G = {
442
442
  }, { placeholderData: (e) => e });
443
443
  return W && !H.length ? /*#__PURE__*/ M(_, {
444
444
  status: "error",
445
- title: G?.message ?? t._({ id: "+Nx1wc" })
445
+ title: G?.message ?? t._({ id: "/sdjzP" })
446
446
  }) : /*#__PURE__*/ N(j, { children: [/*#__PURE__*/ M(E, {
447
447
  title: t._({ id: "u77/s4" }),
448
448
  projectId: s
@@ -548,4 +548,4 @@ function se() {
548
548
  //#endregion
549
549
  export { se as component };
550
550
 
551
- //# sourceMappingURL=floatingips-DrCvtXtT.mjs.map
551
+ //# sourceMappingURL=floatingips-B1oLH8z6.mjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"floatingips-DrCvtXtT.mjs","names":["MdError","MdRemoveCircle","MdCheckCircle","STATUS_CONFIG","ACTIVE","text","icon","size","color","fill","DOWN","ERROR","TABLE_COLUMNS","t","useNavigate","DataGridCell","DataGridRow","PopupMenu","PopupMenuItem","PopupMenuOptions","STATUS_CONFIG","FloatingIpActionModals","useProjectId","FloatingIpTableRow","floatingIp","useLingui","navigate","projectId","navigateToDetailsPage","to","params","floatingIpId","id","data-testid","onClick","div","className","status","icon","text","floating_ip_address","fixed_ip_address","floating_network_id","description","e","stopPropagation","toggleEditModal","toggleAttachModal","toggleDetachModal","toggleReleaseModal","label","t","DataGrid","DataGridHeadCell","DataGridRow","DataGridCell","Status","FloatingIpTableRow","TABLE_COLUMNS","FloatingIpListContainer","floatingIps","isLoading","isError","error","useLingui","columns","columnCount","length","status","title","t","message","minContentColumns","map","label","ip","floatingIp","id","colSpan","body","z","useForm","useStore","useNavigate","Modal","Form","FormSection","Status","Message","Textarea","TextInput","Select","SelectOption","trpcReact","useProjectId","ipv4Regex","ipv6Regex","isValidIpAddress","value","test","dnsNameRegex","AllocateFloatingIpModal","open","onClose","useLingui","projectId","navigate","utils","useUtils","isPending","createFloatingIpMutation","network","floatingIp","create","useMutation","onSettled","list","invalidate","data","externalNetworks","isLoading","isExternalNetworksLoading","error","externalNetworksError","listExternalNetworks","useQuery","project_id","dnsDomains","isDnsDomainsLoading","dnsDomainsError","listDnsDomains","availablePorts","isPortsLoading","portsError","listAvailablePorts","formSchema","object","floating_network_id","string","dns_domain","dns_name","trim","max","t","refine","message","description","floating_ip_address","port_id","fixed_ip_address","form","defaultValues","validators","onSubmit","created","mutateAsync","handleClose","to","params","floatingIpId","id","reset","currentPortId","store","state","values","currentFloatingNetworkId","selectedPort","find","port","portFixedIps","fixed_ips","formErrorMessage","size","title","onCancel","cancelButtonLabel","confirmButtonLabel","onConfirm","handleSubmit","disableConfirmButton","disableCancelButton","disableCloseButton","dismissible","variant","className","status","e","preventDefault","Field","name","children","field","onChange","handleChange","label","helptext","placeholder","disabled","required","loading","map","onBlur","handleBlur","target","errortext","meta","errors","join","portId","p","ips","setFieldValue","length","ip_address","parseFiltersFromUrl","searchParams","filters","status","push","name","value","buildFilterParams","selectedFilters","filterDefinitions","params","length","filterGroups","filter","sf","inactive","reduce","acc","Object","entries","forEach","filterName","values","filterDef","find","f","supportsMultiValue","join","applyFilterSelection","current","selected","alreadySelected","some","supportsMulti","buildUrlSearchParams","baseParams","newParams","search","sortBy","sortDirection","useState","useRef","useEffect","useNavigate","useSearch","Button","Stack","DataGridToolbar","SearchInput","Message","Status","SortInput","SelectedFilters","FiltersInput","ContentHeader","trpcReact","useModal","useProjectId","FloatingIpListContainer","AllocateFloatingIpModal","parseFiltersFromUrl","buildFilterParams","buildUrlSearchParams","applyFilterSelection","DEFAULT_SORT_KEY","DEFAULT_SORT_DIR","FloatingIpsList","useLingui","navigate","searchParams","strict","projectId","allocateModalOpen","toggleAllocateModal","localSearchTerm","setLocalSearchTerm","search","debounceTimer","undefined","clearTimeout","current","sortSettings","setSortSettings","options","label","t","value","sortBy","sortDirection","filterSettings","setFilterSettings","filters","displayName","filterName","values","supportsMultiValue","selectedFilters","searchTerm","data","permissions","network","canUser","useQuery","project_id","permission","select","canCreate","urlFilters","urlSortBy","urlSortDirection","urlSearchTerm","prev","status","handleSortChange","newSortSettings","settings","toString","replace","handleFilterChange","newFilterSettings","handleSearchChange","term","floatingIps","isLoading","isError","error","floatingIp","list","sort_key","sort_dir","placeholderData","length","title","message","div","className","variant","distribution","alignment","gap","selectClassName","onSortByChange","v","onSortDirectionChange","dir","onClick","direction","comboboxClassName","onChange","selected","newSelected","placeholder","data-testid","onInput","e","currentTarget","window","setTimeout","onSearch","onClear","onDelete","filterToRemove","filter","f","name","open","onClose","FloatingIpsList","RouteComponent","component"],"sources":["../../src/client/routes/_auth/projects/$projectId/network/floatingips/-components/-table/constants.tsx","../../src/client/routes/_auth/projects/$projectId/network/floatingips/-components/-table/FloatingIpTableRow.tsx","../../src/client/routes/_auth/projects/$projectId/network/floatingips/-components/-table/FloatingIpListContainer.tsx","../../src/client/routes/_auth/projects/$projectId/network/floatingips/-components/-modals/AllocateFloatingIpModal.tsx","../../src/client/routes/_auth/projects/$projectId/network/floatingips/urlHelpers.ts","../../src/client/routes/_auth/projects/$projectId/network/floatingips/-components/FloatingIpsList.tsx","../../src/client/routes/_auth/projects/$projectId/network/floatingips/index.tsx?tsr-split=component"],"sourcesContent":["import { MdError, MdRemoveCircle, MdCheckCircle } from \"react-icons/md\"\nimport { t } from \"@lingui/core/macro\"\nimport { FloatingIpStatus } from \"@/server/Network/types/floatingIp\"\n\ntype FloatingIpStatusDisplay = {\n text: string\n icon: React.ReactNode\n}\n\nexport const STATUS_CONFIG: Record<FloatingIpStatus, FloatingIpStatusDisplay> = {\n ACTIVE: {\n text: \"Active\",\n icon: <MdCheckCircle size={18} color=\"white\" fill=\"#4FB81C\" />,\n },\n DOWN: {\n text: \"Down\",\n icon: <MdRemoveCircle size={18} color=\"white\" fill=\"#969696\" />,\n },\n ERROR: {\n text: \"Error\",\n icon: <MdError size={18} color=\"white\" fill=\"#C70000\" />,\n },\n} as const\n\nexport const TABLE_COLUMNS = () =>\n [\n t`Status`,\n t`Floating IP Address`,\n t`Fixed IP Address`,\n t`Subnet`,\n t`Description`,\n \"\", // empty column for item-actions with context menu containing \"Show Details\", \"Edit Description\", \"Attach\", \"Detach\" and \"Release\"\n ] as const\n","import { useNavigate } from \"@tanstack/react-router\"\nimport { useLingui } from \"@lingui/react/macro\"\nimport {\n DataGridCell,\n DataGridRow,\n PopupMenu,\n PopupMenuItem,\n PopupMenuOptions,\n} from \"@cloudoperators/juno-ui-components\"\nimport { FloatingIp } from \"@/server/Network/types/floatingIp\"\nimport { STATUS_CONFIG } from \"./constants\"\nimport { FloatingIpActionModals } from \"../-modals/FloatingIpActionModals\"\nimport { useProjectId } from \"@/client/hooks\"\n\ninterface FloatingIpTableRowProps {\n floatingIp: FloatingIp\n}\n\nexport const FloatingIpTableRow = ({ floatingIp }: FloatingIpTableRowProps) => {\n const { t } = useLingui()\n const navigate = useNavigate()\n const projectId = useProjectId()\n\n const navigateToDetailsPage = () => {\n navigate({\n to: \"/projects/$projectId/network/floatingips/$floatingIpId\",\n params: { projectId, floatingIpId: floatingIp.id },\n })\n }\n\n return (\n <DataGridRow key={floatingIp.id} data-testid={`floating-ip-row-${floatingIp.id}`} onClick={navigateToDetailsPage}>\n <DataGridCell>\n <div className=\"flex items-center gap-2\">\n {STATUS_CONFIG[floatingIp.status].icon}\n {STATUS_CONFIG[floatingIp.status].text}\n </div>\n </DataGridCell>\n <DataGridCell>{floatingIp.floating_ip_address}</DataGridCell>\n <DataGridCell>{floatingIp.fixed_ip_address || \"—\"}</DataGridCell>\n <DataGridCell>{floatingIp.floating_network_id}</DataGridCell>\n <DataGridCell>\n <div className=\"truncate\">{floatingIp.description || \"—\"}</div>\n </DataGridCell>\n <DataGridCell onClick={(e) => e.stopPropagation()} className=\"items-end pr-0\">\n <FloatingIpActionModals floatingIp={floatingIp}>\n {({ toggleEditModal, toggleAttachModal, toggleDetachModal, toggleReleaseModal }) => (\n <PopupMenu>\n <PopupMenuOptions>\n <PopupMenuItem label={t`Show Details`} onClick={navigateToDetailsPage} />\n <PopupMenuItem label={t`Edit Description`} onClick={toggleEditModal} />\n <PopupMenuItem label={t`Attach`} onClick={toggleAttachModal} />\n <PopupMenuItem label={t`Detach`} onClick={toggleDetachModal} />\n <PopupMenuItem label={t`Release`} onClick={toggleReleaseModal} />\n </PopupMenuOptions>\n </PopupMenu>\n )}\n </FloatingIpActionModals>\n </DataGridCell>\n </DataGridRow>\n )\n}\n","import { useLingui } from \"@lingui/react/macro\"\nimport { DataGrid, DataGridHeadCell, DataGridRow, DataGridCell, Status } from \"@cloudoperators/juno-ui-components\"\nimport { FloatingIp } from \"@/server/Network/types/floatingIp\"\nimport { FloatingIpTableRow } from \"./FloatingIpTableRow\"\nimport { TABLE_COLUMNS } from \"./constants\"\n\ninterface FloatingIpListContainerProps {\n floatingIps: FloatingIp[]\n isLoading: boolean\n isError: boolean\n error: { message?: string } | null\n}\n\nexport const FloatingIpListContainer = ({ floatingIps, isLoading, isError, error }: FloatingIpListContainerProps) => {\n const { t } = useLingui()\n const columns = TABLE_COLUMNS()\n const columnCount = columns.length\n\n if (isLoading) {\n return <Status status=\"progress\" title={t`Loading Floating IPs...`} />\n }\n\n if (isError) {\n return <Status status=\"error\" title={error?.message ?? t`Failed to load Floating IPs`} />\n }\n\n return (\n <DataGrid columns={columnCount} minContentColumns={[columnCount - 1]}>\n <DataGridRow>\n {columns.map((label) => (\n <DataGridHeadCell key={label}>{label}</DataGridHeadCell>\n ))}\n </DataGridRow>\n {floatingIps.length > 0 ? (\n floatingIps.map((ip) => <FloatingIpTableRow key={ip.id} floatingIp={ip} />)\n ) : (\n <DataGridRow>\n <DataGridCell colSpan={columnCount}>\n <Status\n status=\"empty\"\n title={t`No Floating IPs found`}\n body={t`There are no Floating IPs available for this project. Floating IPs allow you to map public IP addresses to instances.`}\n />\n </DataGridCell>\n </DataGridRow>\n )}\n </DataGrid>\n )\n}\n","import { z } from \"zod\"\nimport { useForm, useStore } from \"@tanstack/react-form\"\nimport { useNavigate } from \"@tanstack/react-router\"\nimport { useLingui } from \"@lingui/react/macro\"\nimport {\n Modal,\n Form,\n FormSection,\n Status,\n Message,\n Textarea,\n TextInput,\n Select,\n SelectOption,\n} from \"@cloudoperators/juno-ui-components\"\nimport { trpcReact } from \"@/client/trpcClient\"\nimport { useProjectId } from \"@/client/hooks\"\n\nexport interface AllocateFloatingIpModalProps {\n open: boolean\n onClose: () => void\n}\n\nconst ipv4Regex = /^(25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)(\\.(25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)){3}$/\nconst ipv6Regex =\n /^(([0-9a-fA-F]{1,4}:){7}[0-9a-fA-F]{1,4}|(([0-9a-fA-F]{1,4}:){1,7}:)|(([0-9a-fA-F]{1,4}:){1,6}:[0-9a-fA-F]{1,4})|(([0-9a-fA-F]{1,4}:){1,5}(:[0-9a-fA-F]{1,4}){1,2})|(([0-9a-fA-F]{1,4}:){1,4}(:[0-9a-fA-F]{1,4}){1,3})|(([0-9a-fA-F]{1,4}:){1,3}(:[0-9a-fA-F]{1,4}){1,4})|(([0-9a-fA-F]{1,4}:){1,2}(:[0-9a-fA-F]{1,4}){1,5})|([0-9a-fA-F]{1,4}:((:[0-9a-fA-F]{1,4}){1,6}))|(:((:[0-9a-fA-F]{1,4}){1,7}|:))|(::([fF]{4}(:0{1,4})?:)?((25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)(\\.(25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)){3}))|(([0-9a-fA-F]{1,4}:){1,4}:((25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)(\\.(25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)){3})))$/\nconst isValidIpAddress = (value: string) => ipv4Regex.test(value) || ipv6Regex.test(value)\nconst dnsNameRegex = /^([a-zA-Z0-9]([a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?\\.)*[a-zA-Z0-9]([a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?$/\n\nexport const AllocateFloatingIpModal = ({ open, onClose }: AllocateFloatingIpModalProps) => {\n const { t } = useLingui()\n const projectId = useProjectId()\n const navigate = useNavigate()\n const utils = trpcReact.useUtils()\n\n const { isPending, ...createFloatingIpMutation } = trpcReact.network.floatingIp.create.useMutation({\n onSettled: () => utils.network.floatingIp.list.invalidate(),\n })\n\n const {\n data: externalNetworks = [],\n isLoading: isExternalNetworksLoading,\n error: externalNetworksError,\n } = trpcReact.network.floatingIp.listExternalNetworks.useQuery({ project_id: projectId })\n\n const {\n data: dnsDomains = [],\n isLoading: isDnsDomainsLoading,\n error: dnsDomainsError,\n } = trpcReact.network.floatingIp.listDnsDomains.useQuery({ project_id: projectId })\n\n const {\n data: availablePorts = [],\n isLoading: isPortsLoading,\n error: portsError,\n } = trpcReact.network.floatingIp.listAvailablePorts.useQuery({ project_id: projectId })\n\n const formSchema = z.object({\n floating_network_id: z.string(),\n dns_domain: z.string(),\n dns_name: z\n .string()\n .trim()\n .max(63, t`DNS name must be at most 63 characters.`)\n .refine((value) => value === \"\" || dnsNameRegex.test(value), {\n message: t`Must be a valid PQDN or FQDN (alphanumeric and hyphens only, cannot start or end with hyphen).`,\n }),\n description: z\n .string()\n .trim()\n .max(255, t`Description must be at most 255 characters.`),\n floating_ip_address: z\n .string()\n .trim()\n .refine((value) => value === \"\" || isValidIpAddress(value), {\n message: t`Must be a valid IPv4 or IPv6 address (for example: 172.24.4.228 or 2001:db8::1).`,\n }),\n port_id: z.string(),\n fixed_ip_address: z.string(),\n })\n\n const form = useForm({\n defaultValues: {\n floating_network_id: \"\",\n dns_domain: \"\",\n dns_name: \"\",\n description: \"\",\n floating_ip_address: \"\",\n port_id: \"\",\n fixed_ip_address: \"\",\n },\n validators: {\n onSubmit: formSchema,\n },\n onSubmit: async ({ value }) => {\n if (isPending) return\n\n const created = await createFloatingIpMutation.mutateAsync({\n project_id: projectId,\n floating_network_id: value.floating_network_id,\n ...(value.dns_domain && { dns_domain: value.dns_domain }),\n ...(value.dns_name && { dns_name: value.dns_name }),\n ...(value.description && { description: value.description }),\n ...(value.floating_ip_address && { floating_ip_address: value.floating_ip_address }),\n ...(value.port_id && { port_id: value.port_id }),\n ...(value.fixed_ip_address && { fixed_ip_address: value.fixed_ip_address }),\n })\n handleClose()\n navigate({\n to: \"/projects/$projectId/network/floatingips/$floatingIpId\",\n params: { projectId, floatingIpId: created.id },\n })\n },\n })\n\n const handleClose = () => {\n if (isPending) return\n\n form.reset()\n createFloatingIpMutation.reset()\n onClose()\n }\n\n const currentPortId = useStore(form.store, (state) => state.values.port_id)\n const currentFloatingNetworkId = useStore(form.store, (state) => state.values.floating_network_id)\n const selectedPort = availablePorts.find((port) => port.id === currentPortId)\n const portFixedIps = selectedPort?.fixed_ips ?? []\n\n const formErrorMessage =\n (externalNetworksError?.message || dnsDomainsError?.message || portsError?.message) ??\n createFloatingIpMutation.error?.message ??\n null\n\n return (\n <Modal\n open={open}\n size=\"large\"\n title={t`Allocate Floating IP`}\n onCancel={handleClose}\n cancelButtonLabel={t`Cancel`}\n confirmButtonLabel={t`Allocate`}\n onConfirm={form.handleSubmit}\n disableConfirmButton={isPending || !currentFloatingNetworkId}\n disableCancelButton={isPending}\n disableCloseButton={isPending}\n >\n {formErrorMessage && (\n <Message dismissible={false} variant=\"error\" className=\"mb-4\">\n {formErrorMessage}\n </Message>\n )}\n\n {isPending ? (\n <Status status=\"progress\" title={t`Allocating Floating IP...`} className=\"mt-0\" />\n ) : (\n <Form\n className=\"mb-0\"\n id=\"allocate-floating-ip-form\"\n onSubmit={(e) => {\n e.preventDefault()\n form.handleSubmit()\n }}\n >\n <FormSection className=\"mb-4\">\n <form.Field\n name=\"floating_network_id\"\n children={(field) => (\n <Select\n id={field.name}\n name={field.name}\n value={field.state.value}\n onChange={(value) => field.handleChange(typeof value === \"string\" ? value : \"\")}\n label={t`External Network`}\n helptext={t`The ID of the network associated with the floating IP.`}\n placeholder={t`Select an external network`}\n disabled={isPending || isExternalNetworksLoading}\n required\n loading={isExternalNetworksLoading}\n >\n {externalNetworks.map(({ id, name }) => (\n <SelectOption key={id} value={id} label={name ? `${name} (${id})` : id} />\n ))}\n </Select>\n )}\n />\n </FormSection>\n <FormSection className=\"mb-4\">\n <form.Field\n name=\"dns_domain\"\n children={(field) => (\n <Select\n id={field.name}\n name={field.name}\n value={field.state.value}\n onChange={(value) => field.handleChange(typeof value === \"string\" ? value : \"\")}\n label={t`DNS Domain`}\n helptext={t`Select a DNS domain.`}\n disabled={isPending || isDnsDomainsLoading}\n loading={isDnsDomainsLoading}\n >\n {dnsDomains.map(({ id, name }) => (\n <SelectOption key={id} value={name} label={name} />\n ))}\n </Select>\n )}\n />\n </FormSection>\n <FormSection className=\"mb-4\">\n <form.Field\n name=\"dns_name\"\n children={(field) => (\n <TextInput\n id={field.name}\n name={field.name}\n value={field.state.value}\n onBlur={field.handleBlur}\n onChange={(e) => field.handleChange(e.target.value)}\n label={t`DNS Name`}\n placeholder={t`Enter DNS name`}\n helptext={t`Enter a valid PQDN or FQDN (max 63 characters) to associate with the floating IP. A and PTR records are created automatically.`}\n errortext={field.state.meta.errors.map((e) => e?.message).join(\", \")}\n disabled={isPending}\n />\n )}\n />\n </FormSection>\n <FormSection className=\"mb-4\">\n <form.Field\n name=\"description\"\n children={(field) => (\n <Textarea\n id={field.name}\n name={field.name}\n value={field.state.value}\n onBlur={field.handleBlur}\n onChange={(e) => field.handleChange(e.target.value)}\n placeholder={t`Description`}\n errortext={field.state.meta.errors.map((e) => e?.message).join(\", \")}\n disabled={isPending}\n />\n )}\n />\n </FormSection>\n <FormSection className=\"mb-4\">\n <form.Field\n name=\"floating_ip_address\"\n children={(field) => (\n <TextInput\n id={field.name}\n name={field.name}\n value={field.state.value}\n onBlur={field.handleBlur}\n onChange={(e) => field.handleChange(e.target.value)}\n label={t`Floating IP Address`}\n placeholder={t`Enter a floating IP`}\n helptext={t`Enter a floating IP or leave blank to auto-assign one`}\n errortext={field.state.meta.errors.map((e) => e?.message).join(\", \")}\n disabled={isPending}\n />\n )}\n />\n </FormSection>\n <FormSection className=\"mb-4\">\n <form.Field\n name=\"port_id\"\n children={(field) => (\n <Select\n id={field.name}\n name={field.name}\n value={field.state.value}\n onChange={(value) => {\n const portId = typeof value === \"string\" ? value : \"\"\n field.handleChange(portId)\n const port = availablePorts.find((p) => p.id === portId)\n const ips = port?.fixed_ips ?? []\n form.setFieldValue(\"fixed_ip_address\", ips.length === 1 ? ips[0].ip_address : \"\")\n }}\n label={t`Port ID`}\n placeholder={t`Select port to associate`}\n errortext={field.state.meta.errors.map((e) => e?.message).join(\", \")}\n disabled={isPending || isPortsLoading}\n loading={isPortsLoading}\n >\n {availablePorts.map((port) => (\n <SelectOption\n key={port.id}\n value={port.id}\n label={port.name ? `${port.name} (${port.id})` : port.id}\n />\n ))}\n </Select>\n )}\n />\n </FormSection>\n <FormSection>\n <form.Field\n name=\"fixed_ip_address\"\n children={(field) => (\n <Select\n id={field.name}\n name={field.name}\n value={field.state.value}\n onBlur={field.handleBlur}\n onChange={(value) => field.handleChange(typeof value === \"string\" ? value : \"\")}\n label={t`Fixed IP Address`}\n placeholder={t`Select a fixed IP address`}\n helptext={t`Associates on the selected port. If the port has multiple IPs, select the desired fixed IP address.`}\n errortext={field.state.meta.errors.map((e) => e?.message).join(\", \")}\n disabled={isPending || portFixedIps.length === 0}\n >\n {portFixedIps.map(({ ip_address }) => (\n <SelectOption key={ip_address} value={ip_address} label={ip_address} />\n ))}\n </Select>\n )}\n />\n </FormSection>\n </Form>\n )}\n </Modal>\n )\n}\n","import { SelectedFilter, Filter } from \"@/client/components/ListToolbar/types\"\n\ntype FloatingIpsSearchParams = {\n status?: string\n search?: string\n sortBy?: string\n sortDirection?: \"asc\" | \"desc\"\n}\n\n/**\n * Parses URL search params into SelectedFilter array for ListToolbar\n */\nexport const parseFiltersFromUrl = (searchParams: FloatingIpsSearchParams): SelectedFilter[] => {\n const filters: SelectedFilter[] = []\n\n // Status filter\n if (searchParams.status) {\n filters.push({ name: \"status\", value: searchParams.status })\n }\n\n return filters\n}\n\n/**\n * Builds filter parameters for API request from SelectedFilter array\n */\nexport const buildFilterParams = (\n selectedFilters: SelectedFilter[],\n filterDefinitions: Filter[]\n): Record<string, string> => {\n const params: Record<string, string> = {}\n\n if (!selectedFilters?.length) return params\n\n // Group selected filters by filter name\n const filterGroups = selectedFilters\n .filter((sf) => !sf.inactive)\n .reduce(\n (acc, sf) => {\n if (!acc[sf.name]) acc[sf.name] = []\n acc[sf.name].push(sf.value)\n return acc\n },\n {} as Record<string, string[]>\n )\n\n // Build parameters based on whether filter supports multiple values\n Object.entries(filterGroups).forEach(([filterName, values]) => {\n const filterDef = filterDefinitions.find((f) => f.filterName === filterName)\n\n if (filterDef?.supportsMultiValue && values.length > 1) {\n params[filterName] = `in:${values.join(\",\")}`\n } else {\n params[filterName] = values[0]\n }\n })\n\n return params\n}\n\n/**\n * Merges a newly selected filter into the current list.\n * - Ignores duplicates (same name + value).\n * - For single-value filters, replaces any existing entry with the same name.\n * - For multi-value filters, appends.\n */\nexport const applyFilterSelection = (\n current: SelectedFilter[],\n selected: SelectedFilter,\n filterDefinitions: Filter[]\n): SelectedFilter[] => {\n const alreadySelected = current.some((f) => f.name === selected.name && f.value === selected.value)\n if (alreadySelected) return current\n\n const supportsMulti = filterDefinitions.find((f) => f.filterName === selected.name)?.supportsMultiValue\n return supportsMulti ? [...current, selected] : [...current.filter((f) => f.name !== selected.name), selected]\n}\n\n/**\n * Builds URL search params object from filter settings for navigation\n */\nexport const buildUrlSearchParams = (\n selectedFilters: SelectedFilter[],\n filterDefinitions: Filter[],\n baseParams: {\n search?: string\n sortBy?: string\n sortDirection?: \"asc\" | \"desc\"\n }\n): FloatingIpsSearchParams => {\n const newParams: FloatingIpsSearchParams = {\n search: baseParams.search,\n sortBy: baseParams.sortBy,\n sortDirection: baseParams.sortDirection,\n }\n\n if (!selectedFilters?.length) return newParams\n\n const filterGroups = selectedFilters\n .filter((sf) => !sf.inactive)\n .reduce(\n (acc, sf) => {\n if (!acc[sf.name]) acc[sf.name] = []\n acc[sf.name].push(sf.value)\n return acc\n },\n {} as Record<string, string[]>\n )\n\n Object.entries(filterGroups).forEach(([filterName, values]) => {\n const filterDef = filterDefinitions.find((f) => f.filterName === filterName)\n\n if (filterDef?.supportsMultiValue && values.length > 1) {\n // Type assertion needed because we're dynamically setting filter fields\n ;(newParams as Record<string, string>)[filterName] = `in:${values.join(\",\")}`\n } else {\n ;(newParams as Record<string, string>)[filterName] = values[0]\n }\n })\n\n return newParams\n}\n","import { useState, useRef, useEffect } from \"react\"\nimport { Trans, useLingui } from \"@lingui/react/macro\"\nimport { useNavigate, useSearch } from \"@tanstack/react-router\"\nimport { Button, Stack, DataGridToolbar, SearchInput, Message, Status } from \"@cloudoperators/juno-ui-components\"\nimport { FloatingIpQueryParameters } from \"@/server/Network/types/floatingIp\"\nimport { SortInput } from \"@/client/components/ListToolbar/SortInput\"\nimport { SelectedFilters } from \"@/client/components/ListToolbar/SelectedFilters\"\nimport { FiltersInput } from \"@/client/components/ListToolbar/FiltersInput\"\nimport { FilterSettings, SortSettings } from \"@/client/components/ListToolbar/types\"\nimport { ContentHeader } from \"@/client/components/ContentHeader/ContentHeader\"\nimport { trpcReact } from \"@/client/trpcClient\"\nimport { useModal } from \"@/client/utils/useModal\"\nimport { useProjectId } from \"@/client/hooks\"\nimport { FloatingIpListContainer } from \"./-table/FloatingIpListContainer\"\nimport { AllocateFloatingIpModal } from \"./-modals/AllocateFloatingIpModal\"\nimport { parseFiltersFromUrl, buildFilterParams, buildUrlSearchParams, applyFilterSelection } from \"../urlHelpers\"\n\nconst DEFAULT_SORT_KEY = \"status\"\nconst DEFAULT_SORT_DIR = \"asc\"\nexport type FloatingIpsSortKey = NonNullable<FloatingIpQueryParameters[\"sort_key\"]>\n\ntype FloatingIpsSearchParams = {\n status?: string\n search?: string\n sortBy?: string\n sortDirection?: \"asc\" | \"desc\"\n}\n\ntype RequiredSortSettings = {\n options: SortSettings[\"options\"]\n sortBy: string\n sortDirection: \"asc\" | \"desc\"\n}\n\nexport const FloatingIpsList = () => {\n const { t } = useLingui()\n const navigate = useNavigate()\n const searchParams = useSearch({ strict: false }) as FloatingIpsSearchParams\n const projectId = useProjectId()\n const [allocateModalOpen, toggleAllocateModal] = useModal(false)\n const [localSearchTerm, setLocalSearchTerm] = useState(searchParams.search || \"\")\n const debounceTimer = useRef<number | undefined>(undefined)\n\n useEffect(() => () => clearTimeout(debounceTimer.current), [])\n\n const [sortSettings, setSortSettings] = useState<RequiredSortSettings>({\n options: [{ label: t`Status`, value: \"status\" }],\n sortBy: searchParams.sortBy || DEFAULT_SORT_KEY,\n sortDirection: searchParams.sortDirection || DEFAULT_SORT_DIR,\n })\n\n const [filterSettings, setFilterSettings] = useState<FilterSettings>({\n filters: [\n {\n displayName: t`Status`,\n filterName: \"status\",\n values: [\"ACTIVE\", \"DOWN\", \"ERROR\"],\n supportsMultiValue: false,\n },\n ],\n selectedFilters: parseFiltersFromUrl(searchParams),\n })\n\n const searchTerm = searchParams.search || \"\"\n\n const { data: permissions } = trpcReact.network.canUser.useQuery(\n { project_id: projectId, permission: [\"network:floatingips:create\"] },\n { select: ([canCreate]) => ({ canCreate }) }\n )\n\n useEffect(() => {\n const urlFilters = parseFiltersFromUrl(searchParams)\n const urlSortBy = searchParams.sortBy || DEFAULT_SORT_KEY\n const urlSortDirection = searchParams.sortDirection || DEFAULT_SORT_DIR\n const urlSearchTerm = searchParams.search || \"\"\n\n setFilterSettings((prev) => ({ ...prev, selectedFilters: urlFilters }))\n setSortSettings((prev) => ({ ...prev, sortBy: urlSortBy, sortDirection: urlSortDirection }))\n setLocalSearchTerm(urlSearchTerm)\n }, [searchParams.status, searchParams.sortBy, searchParams.sortDirection, searchParams.search])\n\n const handleSortChange = (newSortSettings: SortSettings) => {\n const settings: RequiredSortSettings = {\n options: newSortSettings.options,\n sortBy: newSortSettings.sortBy?.toString() || DEFAULT_SORT_KEY,\n sortDirection: newSortSettings.sortDirection || DEFAULT_SORT_DIR,\n }\n setSortSettings(settings)\n navigate({\n search: ((prev: FloatingIpsSearchParams) => ({\n ...prev,\n sortBy: settings.sortBy,\n sortDirection: settings.sortDirection,\n })) as unknown as true,\n replace: false,\n })\n }\n\n const handleFilterChange = (newFilterSettings: FilterSettings) => {\n setFilterSettings(newFilterSettings)\n navigate({\n search: ((prev: FloatingIpsSearchParams) =>\n buildUrlSearchParams(newFilterSettings.selectedFilters || [], newFilterSettings.filters, {\n search: prev.search,\n sortBy: prev.sortBy,\n sortDirection: prev.sortDirection,\n })) as unknown as true,\n replace: false,\n })\n }\n\n const handleSearchChange = (term: string, replace = false) => {\n navigate({\n search: ((prev: FloatingIpsSearchParams) => ({\n ...prev,\n search: term || undefined,\n })) as unknown as true,\n replace,\n })\n }\n\n const {\n data: floatingIps = [],\n isLoading,\n isError,\n error,\n } = trpcReact.network.floatingIp.list.useQuery(\n {\n project_id: projectId,\n sort_key: sortSettings.sortBy as FloatingIpsSortKey,\n sort_dir: sortSettings.sortDirection,\n ...buildFilterParams(filterSettings.selectedFilters || [], filterSettings.filters),\n ...(searchTerm ? { searchTerm } : {}),\n },\n { placeholderData: (prev) => prev }\n )\n\n if (isError && !floatingIps.length) {\n return <Status status=\"error\" title={error?.message ?? t`Failed to load Floating IPs`} />\n }\n\n return (\n <>\n <ContentHeader title={t`Floating IPs`} projectId={projectId} />\n\n <div className=\"relative\">\n {/* Non-blocking error banner for refetch failures with cached data */}\n {isError && floatingIps.length > 0 && (\n <Message variant=\"error\" className=\"mb-4\">\n {error?.message ?? t`Failed to refresh Floating IPs. Showing cached data.`}\n </Message>\n )}\n\n {/* Zone 1 — sort + create button, no background */}\n <Stack distribution=\"end\" alignment=\"center\" gap=\"2\" className=\"pb-2\">\n <Stack gap=\"2\">\n <SortInput\n options={sortSettings.options}\n sortBy={sortSettings.sortBy}\n sortDirection={sortSettings.sortDirection ?? \"asc\"}\n selectClassName=\"min-w-52\"\n onSortByChange={(v) =>\n handleSortChange({ ...sortSettings, sortBy: v, sortDirection: sortSettings.sortDirection })\n }\n onSortDirectionChange={(dir) => handleSortChange({ ...sortSettings, sortDirection: dir })}\n />\n {permissions?.canCreate && (\n <Button onClick={toggleAllocateModal} variant=\"primary\" className=\"whitespace-nowrap\">\n <Trans>Allocate Floating IP</Trans>\n </Button>\n )}\n </Stack>\n </Stack>\n\n {/* Zone 2 — filter + search + active filter pills */}\n <DataGridToolbar>\n <Stack direction=\"vertical\" gap=\"2\">\n <Stack distribution=\"between\" alignment=\"center\">\n <FiltersInput\n filters={filterSettings.filters}\n selectClassName=\"sm:min-w-40\"\n comboboxClassName=\"sm:min-w-40\"\n onChange={(selected) => {\n const newSelected = applyFilterSelection(\n filterSettings.selectedFilters || [],\n selected,\n filterSettings.filters\n )\n if (newSelected === (filterSettings.selectedFilters || [])) return\n handleFilterChange({ ...filterSettings, selectedFilters: newSelected })\n }}\n />\n <SearchInput\n placeholder={t`Search floating IPs...`}\n data-testid=\"searchbar\"\n value={localSearchTerm}\n onInput={(e: React.FormEvent<HTMLInputElement>) => {\n const v = e.currentTarget.value\n setLocalSearchTerm(v)\n clearTimeout(debounceTimer.current)\n debounceTimer.current = window.setTimeout(() => handleSearchChange(v, true), 500)\n }}\n onSearch={(v) => {\n clearTimeout(debounceTimer.current)\n handleSearchChange(typeof v === \"string\" ? v : \"\", false)\n }}\n onClear={() => {\n clearTimeout(debounceTimer.current)\n setLocalSearchTerm(\"\")\n handleSearchChange(\"\", false)\n }}\n />\n </Stack>\n {filterSettings.selectedFilters && filterSettings.selectedFilters.length > 0 && (\n <SelectedFilters\n selectedFilters={filterSettings.selectedFilters}\n onDelete={(filterToRemove) =>\n handleFilterChange({\n ...filterSettings,\n selectedFilters: (filterSettings.selectedFilters || []).filter(\n (f) => !(f.name === filterToRemove.name && f.value === filterToRemove.value)\n ),\n })\n }\n onClear={() => handleFilterChange({ ...filterSettings, selectedFilters: [] })}\n />\n )}\n </Stack>\n </DataGridToolbar>\n\n <FloatingIpListContainer\n floatingIps={floatingIps}\n isLoading={isLoading}\n isError={isError && !floatingIps.length}\n error={error}\n />\n\n {allocateModalOpen && <AllocateFloatingIpModal open={allocateModalOpen} onClose={toggleAllocateModal} />}\n </div>\n </>\n )\n}\n","import { createFileRoute } from \"@tanstack/react-router\"\nimport { z } from \"zod\"\nimport { t } from \"@lingui/core/macro\"\nimport { FloatingIpQueryParametersSchema, FloatingIpStatusSchema } from \"@/server/Network/types/floatingIp\"\nimport type { RouteInfo } from \"@/client/routes/routeInfo\"\nimport { FloatingIpsList } from \"./-components/FloatingIpsList\"\n\nconst floatingIpsSearchFields = {\n status: FloatingIpStatusSchema.optional(),\n search: z.string().optional(),\n sortBy: FloatingIpQueryParametersSchema.shape.sort_key.unwrap().optional(),\n sortDirection: z.enum([\"asc\", \"desc\"]).optional(),\n}\n\nconst floatingIpsSearchSchema = z.looseObject(floatingIpsSearchFields)\n\nexport const Route = createFileRoute(\"/_auth/projects/$projectId/network/floatingips/\")({\n staticData: {\n section: \"network\",\n service: \"floatingips\",\n analytics: {\n name: \"network.floatingips.list\",\n },\n } satisfies RouteInfo,\n validateSearch: (search) => {\n const result = floatingIpsSearchSchema.safeParse(search)\n if (result.success) return result.data\n return {\n ...search,\n status: floatingIpsSearchFields.status.safeParse(search.status).success ? search.status : undefined,\n search: floatingIpsSearchFields.search.safeParse(search.search).success ? search.search : undefined,\n sortBy: floatingIpsSearchFields.sortBy.safeParse(search.sortBy).success ? search.sortBy : undefined,\n sortDirection: floatingIpsSearchFields.sortDirection.safeParse(search.sortDirection).success\n ? search.sortDirection\n : undefined,\n }\n },\n head: () => ({ meta: [{ title: t`Floating IPs` }] }),\n component: RouteComponent,\n})\n\nfunction RouteComponent() {\n return <FloatingIpsList />\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"floatingips-B1oLH8z6.mjs","names":["MdError","MdRemoveCircle","MdCheckCircle","STATUS_CONFIG","ACTIVE","text","icon","size","color","fill","DOWN","ERROR","TABLE_COLUMNS","t","useNavigate","DataGridCell","DataGridRow","PopupMenu","PopupMenuItem","PopupMenuOptions","STATUS_CONFIG","FloatingIpActionModals","useProjectId","FloatingIpTableRow","floatingIp","useLingui","navigate","projectId","navigateToDetailsPage","to","params","floatingIpId","id","data-testid","onClick","div","className","status","icon","text","floating_ip_address","fixed_ip_address","floating_network_id","description","e","stopPropagation","toggleEditModal","toggleAttachModal","toggleDetachModal","toggleReleaseModal","label","t","DataGrid","DataGridHeadCell","DataGridRow","DataGridCell","Status","FloatingIpTableRow","TABLE_COLUMNS","FloatingIpListContainer","floatingIps","isLoading","isError","error","useLingui","columns","columnCount","length","status","title","t","message","minContentColumns","map","label","ip","floatingIp","id","colSpan","body","z","useForm","useStore","useNavigate","Modal","Form","FormSection","Status","Message","Textarea","TextInput","Select","SelectOption","trpcReact","useProjectId","ipv4Regex","ipv6Regex","isValidIpAddress","value","test","dnsNameRegex","AllocateFloatingIpModal","open","onClose","useLingui","projectId","navigate","utils","useUtils","isPending","createFloatingIpMutation","network","floatingIp","create","useMutation","onSettled","list","invalidate","data","externalNetworks","isLoading","isExternalNetworksLoading","error","externalNetworksError","listExternalNetworks","useQuery","project_id","dnsDomains","isDnsDomainsLoading","dnsDomainsError","listDnsDomains","availablePorts","isPortsLoading","portsError","listAvailablePorts","formSchema","object","floating_network_id","string","dns_domain","dns_name","trim","max","t","refine","message","description","floating_ip_address","port_id","fixed_ip_address","form","defaultValues","validators","onSubmit","created","mutateAsync","handleClose","to","params","floatingIpId","id","reset","currentPortId","store","state","values","currentFloatingNetworkId","selectedPort","find","port","portFixedIps","fixed_ips","formErrorMessage","size","title","onCancel","cancelButtonLabel","confirmButtonLabel","onConfirm","handleSubmit","disableConfirmButton","disableCancelButton","disableCloseButton","dismissible","variant","className","status","e","preventDefault","Field","name","children","field","onChange","handleChange","label","helptext","placeholder","disabled","required","loading","map","onBlur","handleBlur","target","errortext","meta","errors","join","portId","p","ips","setFieldValue","length","ip_address","parseFiltersFromUrl","searchParams","filters","status","push","name","value","buildFilterParams","selectedFilters","filterDefinitions","params","length","filterGroups","filter","sf","inactive","reduce","acc","Object","entries","forEach","filterName","values","filterDef","find","f","supportsMultiValue","join","applyFilterSelection","current","selected","alreadySelected","some","supportsMulti","buildUrlSearchParams","baseParams","newParams","search","sortBy","sortDirection","useState","useRef","useEffect","useNavigate","useSearch","Button","Stack","DataGridToolbar","SearchInput","Message","Status","SortInput","SelectedFilters","FiltersInput","ContentHeader","trpcReact","useModal","useProjectId","FloatingIpListContainer","AllocateFloatingIpModal","parseFiltersFromUrl","buildFilterParams","buildUrlSearchParams","applyFilterSelection","DEFAULT_SORT_KEY","DEFAULT_SORT_DIR","FloatingIpsList","useLingui","navigate","searchParams","strict","projectId","allocateModalOpen","toggleAllocateModal","localSearchTerm","setLocalSearchTerm","search","debounceTimer","undefined","clearTimeout","current","sortSettings","setSortSettings","options","label","t","value","sortBy","sortDirection","filterSettings","setFilterSettings","filters","displayName","filterName","values","supportsMultiValue","selectedFilters","searchTerm","data","permissions","network","canUser","useQuery","project_id","permission","select","canCreate","urlFilters","urlSortBy","urlSortDirection","urlSearchTerm","prev","status","handleSortChange","newSortSettings","settings","toString","replace","handleFilterChange","newFilterSettings","handleSearchChange","term","floatingIps","isLoading","isError","error","floatingIp","list","sort_key","sort_dir","placeholderData","length","title","message","div","className","variant","distribution","alignment","gap","selectClassName","onSortByChange","v","onSortDirectionChange","dir","onClick","direction","comboboxClassName","onChange","selected","newSelected","placeholder","data-testid","onInput","e","currentTarget","window","setTimeout","onSearch","onClear","onDelete","filterToRemove","filter","f","name","open","onClose","FloatingIpsList","RouteComponent","component"],"sources":["../../src/client/routes/_auth/projects/$projectId/network/floatingips/-components/-table/constants.tsx","../../src/client/routes/_auth/projects/$projectId/network/floatingips/-components/-table/FloatingIpTableRow.tsx","../../src/client/routes/_auth/projects/$projectId/network/floatingips/-components/-table/FloatingIpListContainer.tsx","../../src/client/routes/_auth/projects/$projectId/network/floatingips/-components/-modals/AllocateFloatingIpModal.tsx","../../src/client/routes/_auth/projects/$projectId/network/floatingips/urlHelpers.ts","../../src/client/routes/_auth/projects/$projectId/network/floatingips/-components/FloatingIpsList.tsx","../../src/client/routes/_auth/projects/$projectId/network/floatingips/index.tsx?tsr-split=component"],"sourcesContent":["import { MdError, MdRemoveCircle, MdCheckCircle } from \"react-icons/md\"\nimport { t } from \"@lingui/core/macro\"\nimport { FloatingIpStatus } from \"@/server/Network/types/floatingIp\"\n\ntype FloatingIpStatusDisplay = {\n text: string\n icon: React.ReactNode\n}\n\nexport const STATUS_CONFIG: Record<FloatingIpStatus, FloatingIpStatusDisplay> = {\n ACTIVE: {\n text: \"Active\",\n icon: <MdCheckCircle size={18} color=\"white\" fill=\"#4FB81C\" />,\n },\n DOWN: {\n text: \"Down\",\n icon: <MdRemoveCircle size={18} color=\"white\" fill=\"#969696\" />,\n },\n ERROR: {\n text: \"Error\",\n icon: <MdError size={18} color=\"white\" fill=\"#C70000\" />,\n },\n} as const\n\nexport const TABLE_COLUMNS = () =>\n [\n t`Status`,\n t`Floating IP Address`,\n t`Fixed IP Address`,\n t`Subnet`,\n t`Description`,\n \"\", // empty column for item-actions with context menu containing \"Show Details\", \"Edit Description\", \"Attach\", \"Detach\" and \"Release\"\n ] as const\n","import { useNavigate } from \"@tanstack/react-router\"\nimport { useLingui } from \"@lingui/react/macro\"\nimport {\n DataGridCell,\n DataGridRow,\n PopupMenu,\n PopupMenuItem,\n PopupMenuOptions,\n} from \"@cloudoperators/juno-ui-components\"\nimport { FloatingIp } from \"@/server/Network/types/floatingIp\"\nimport { STATUS_CONFIG } from \"./constants\"\nimport { FloatingIpActionModals } from \"../-modals/FloatingIpActionModals\"\nimport { useProjectId } from \"@/client/hooks\"\n\ninterface FloatingIpTableRowProps {\n floatingIp: FloatingIp\n}\n\nexport const FloatingIpTableRow = ({ floatingIp }: FloatingIpTableRowProps) => {\n const { t } = useLingui()\n const navigate = useNavigate()\n const projectId = useProjectId()\n\n const navigateToDetailsPage = () => {\n navigate({\n to: \"/projects/$projectId/network/floatingips/$floatingIpId\",\n params: { projectId, floatingIpId: floatingIp.id },\n })\n }\n\n return (\n <DataGridRow key={floatingIp.id} data-testid={`floating-ip-row-${floatingIp.id}`} onClick={navigateToDetailsPage}>\n <DataGridCell>\n <div className=\"flex items-center gap-2\">\n {STATUS_CONFIG[floatingIp.status].icon}\n {STATUS_CONFIG[floatingIp.status].text}\n </div>\n </DataGridCell>\n <DataGridCell>{floatingIp.floating_ip_address}</DataGridCell>\n <DataGridCell>{floatingIp.fixed_ip_address || \"—\"}</DataGridCell>\n <DataGridCell>{floatingIp.floating_network_id}</DataGridCell>\n <DataGridCell>\n <div className=\"truncate\">{floatingIp.description || \"—\"}</div>\n </DataGridCell>\n <DataGridCell onClick={(e) => e.stopPropagation()} className=\"items-end pr-0\">\n <FloatingIpActionModals floatingIp={floatingIp}>\n {({ toggleEditModal, toggleAttachModal, toggleDetachModal, toggleReleaseModal }) => (\n <PopupMenu>\n <PopupMenuOptions>\n <PopupMenuItem label={t`Show Details`} onClick={navigateToDetailsPage} />\n <PopupMenuItem label={t`Edit Description`} onClick={toggleEditModal} />\n <PopupMenuItem label={t`Attach`} onClick={toggleAttachModal} />\n <PopupMenuItem label={t`Detach`} onClick={toggleDetachModal} />\n <PopupMenuItem label={t`Release`} onClick={toggleReleaseModal} />\n </PopupMenuOptions>\n </PopupMenu>\n )}\n </FloatingIpActionModals>\n </DataGridCell>\n </DataGridRow>\n )\n}\n","import { useLingui } from \"@lingui/react/macro\"\nimport { DataGrid, DataGridHeadCell, DataGridRow, DataGridCell, Status } from \"@cloudoperators/juno-ui-components\"\nimport { FloatingIp } from \"@/server/Network/types/floatingIp\"\nimport { FloatingIpTableRow } from \"./FloatingIpTableRow\"\nimport { TABLE_COLUMNS } from \"./constants\"\n\ninterface FloatingIpListContainerProps {\n floatingIps: FloatingIp[]\n isLoading: boolean\n isError: boolean\n error: { message?: string } | null\n}\n\nexport const FloatingIpListContainer = ({ floatingIps, isLoading, isError, error }: FloatingIpListContainerProps) => {\n const { t } = useLingui()\n const columns = TABLE_COLUMNS()\n const columnCount = columns.length\n\n if (isLoading) {\n return <Status status=\"progress\" title={t`Loading Floating IPs...`} />\n }\n\n if (isError) {\n return <Status status=\"error\" title={error?.message ?? t`Failed to Load Floating IPs`} />\n }\n\n return (\n <DataGrid columns={columnCount} minContentColumns={[columnCount - 1]}>\n <DataGridRow>\n {columns.map((label) => (\n <DataGridHeadCell key={label}>{label}</DataGridHeadCell>\n ))}\n </DataGridRow>\n {floatingIps.length > 0 ? (\n floatingIps.map((ip) => <FloatingIpTableRow key={ip.id} floatingIp={ip} />)\n ) : (\n <DataGridRow>\n <DataGridCell colSpan={columnCount}>\n <Status\n status=\"empty\"\n title={t`No Floating IPs Found`}\n body={t`There are no Floating IPs available for this project. Floating IPs allow you to map public IP addresses to instances.`}\n />\n </DataGridCell>\n </DataGridRow>\n )}\n </DataGrid>\n )\n}\n","import { z } from \"zod\"\nimport { useForm, useStore } from \"@tanstack/react-form\"\nimport { useNavigate } from \"@tanstack/react-router\"\nimport { useLingui } from \"@lingui/react/macro\"\nimport {\n Modal,\n Form,\n FormSection,\n Status,\n Message,\n Textarea,\n TextInput,\n Select,\n SelectOption,\n} from \"@cloudoperators/juno-ui-components\"\nimport { trpcReact } from \"@/client/trpcClient\"\nimport { useProjectId } from \"@/client/hooks\"\n\nexport interface AllocateFloatingIpModalProps {\n open: boolean\n onClose: () => void\n}\n\nconst ipv4Regex = /^(25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)(\\.(25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)){3}$/\nconst ipv6Regex =\n /^(([0-9a-fA-F]{1,4}:){7}[0-9a-fA-F]{1,4}|(([0-9a-fA-F]{1,4}:){1,7}:)|(([0-9a-fA-F]{1,4}:){1,6}:[0-9a-fA-F]{1,4})|(([0-9a-fA-F]{1,4}:){1,5}(:[0-9a-fA-F]{1,4}){1,2})|(([0-9a-fA-F]{1,4}:){1,4}(:[0-9a-fA-F]{1,4}){1,3})|(([0-9a-fA-F]{1,4}:){1,3}(:[0-9a-fA-F]{1,4}){1,4})|(([0-9a-fA-F]{1,4}:){1,2}(:[0-9a-fA-F]{1,4}){1,5})|([0-9a-fA-F]{1,4}:((:[0-9a-fA-F]{1,4}){1,6}))|(:((:[0-9a-fA-F]{1,4}){1,7}|:))|(::([fF]{4}(:0{1,4})?:)?((25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)(\\.(25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)){3}))|(([0-9a-fA-F]{1,4}:){1,4}:((25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)(\\.(25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)){3})))$/\nconst isValidIpAddress = (value: string) => ipv4Regex.test(value) || ipv6Regex.test(value)\nconst dnsNameRegex = /^([a-zA-Z0-9]([a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?\\.)*[a-zA-Z0-9]([a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?$/\n\nexport const AllocateFloatingIpModal = ({ open, onClose }: AllocateFloatingIpModalProps) => {\n const { t } = useLingui()\n const projectId = useProjectId()\n const navigate = useNavigate()\n const utils = trpcReact.useUtils()\n\n const { isPending, ...createFloatingIpMutation } = trpcReact.network.floatingIp.create.useMutation({\n onSettled: () => utils.network.floatingIp.list.invalidate(),\n })\n\n const {\n data: externalNetworks = [],\n isLoading: isExternalNetworksLoading,\n error: externalNetworksError,\n } = trpcReact.network.floatingIp.listExternalNetworks.useQuery({ project_id: projectId })\n\n const {\n data: dnsDomains = [],\n isLoading: isDnsDomainsLoading,\n error: dnsDomainsError,\n } = trpcReact.network.floatingIp.listDnsDomains.useQuery({ project_id: projectId })\n\n const {\n data: availablePorts = [],\n isLoading: isPortsLoading,\n error: portsError,\n } = trpcReact.network.floatingIp.listAvailablePorts.useQuery({ project_id: projectId })\n\n const formSchema = z.object({\n floating_network_id: z.string(),\n dns_domain: z.string(),\n dns_name: z\n .string()\n .trim()\n .max(63, t`DNS name must be at most 63 characters.`)\n .refine((value) => value === \"\" || dnsNameRegex.test(value), {\n message: t`Must be a valid PQDN or FQDN (alphanumeric and hyphens only, cannot start or end with hyphen).`,\n }),\n description: z\n .string()\n .trim()\n .max(255, t`Description must be at most 255 characters.`),\n floating_ip_address: z\n .string()\n .trim()\n .refine((value) => value === \"\" || isValidIpAddress(value), {\n message: t`Must be a valid IPv4 or IPv6 address (for example: 172.24.4.228 or 2001:db8::1).`,\n }),\n port_id: z.string(),\n fixed_ip_address: z.string(),\n })\n\n const form = useForm({\n defaultValues: {\n floating_network_id: \"\",\n dns_domain: \"\",\n dns_name: \"\",\n description: \"\",\n floating_ip_address: \"\",\n port_id: \"\",\n fixed_ip_address: \"\",\n },\n validators: {\n onSubmit: formSchema,\n },\n onSubmit: async ({ value }) => {\n if (isPending) return\n\n const created = await createFloatingIpMutation.mutateAsync({\n project_id: projectId,\n floating_network_id: value.floating_network_id,\n ...(value.dns_domain && { dns_domain: value.dns_domain }),\n ...(value.dns_name && { dns_name: value.dns_name }),\n ...(value.description && { description: value.description }),\n ...(value.floating_ip_address && { floating_ip_address: value.floating_ip_address }),\n ...(value.port_id && { port_id: value.port_id }),\n ...(value.fixed_ip_address && { fixed_ip_address: value.fixed_ip_address }),\n })\n handleClose()\n navigate({\n to: \"/projects/$projectId/network/floatingips/$floatingIpId\",\n params: { projectId, floatingIpId: created.id },\n })\n },\n })\n\n const handleClose = () => {\n if (isPending) return\n\n form.reset()\n createFloatingIpMutation.reset()\n onClose()\n }\n\n const currentPortId = useStore(form.store, (state) => state.values.port_id)\n const currentFloatingNetworkId = useStore(form.store, (state) => state.values.floating_network_id)\n const selectedPort = availablePorts.find((port) => port.id === currentPortId)\n const portFixedIps = selectedPort?.fixed_ips ?? []\n\n const formErrorMessage =\n (externalNetworksError?.message || dnsDomainsError?.message || portsError?.message) ??\n createFloatingIpMutation.error?.message ??\n null\n\n return (\n <Modal\n open={open}\n size=\"large\"\n title={t`Allocate Floating IP`}\n onCancel={handleClose}\n cancelButtonLabel={t`Cancel`}\n confirmButtonLabel={t`Allocate`}\n onConfirm={form.handleSubmit}\n disableConfirmButton={isPending || !currentFloatingNetworkId}\n disableCancelButton={isPending}\n disableCloseButton={isPending}\n >\n {formErrorMessage && (\n <Message dismissible={false} variant=\"error\" className=\"mb-4\">\n {formErrorMessage}\n </Message>\n )}\n\n {isPending ? (\n <Status status=\"progress\" title={t`Allocating Floating IP...`} className=\"mt-0\" />\n ) : (\n <Form\n className=\"mb-0\"\n id=\"allocate-floating-ip-form\"\n onSubmit={(e) => {\n e.preventDefault()\n form.handleSubmit()\n }}\n >\n <FormSection className=\"mb-4\">\n <form.Field\n name=\"floating_network_id\"\n children={(field) => (\n <Select\n id={field.name}\n name={field.name}\n value={field.state.value}\n onChange={(value) => field.handleChange(typeof value === \"string\" ? value : \"\")}\n label={t`External Network`}\n helptext={t`The ID of the network associated with the floating IP.`}\n placeholder={t`Select an external network`}\n disabled={isPending || isExternalNetworksLoading}\n required\n loading={isExternalNetworksLoading}\n >\n {externalNetworks.map(({ id, name }) => (\n <SelectOption key={id} value={id} label={name ? `${name} (${id})` : id} />\n ))}\n </Select>\n )}\n />\n </FormSection>\n <FormSection className=\"mb-4\">\n <form.Field\n name=\"dns_domain\"\n children={(field) => (\n <Select\n id={field.name}\n name={field.name}\n value={field.state.value}\n onChange={(value) => field.handleChange(typeof value === \"string\" ? value : \"\")}\n label={t`DNS Domain`}\n helptext={t`Select a DNS domain.`}\n disabled={isPending || isDnsDomainsLoading}\n loading={isDnsDomainsLoading}\n >\n {dnsDomains.map(({ id, name }) => (\n <SelectOption key={id} value={name} label={name} />\n ))}\n </Select>\n )}\n />\n </FormSection>\n <FormSection className=\"mb-4\">\n <form.Field\n name=\"dns_name\"\n children={(field) => (\n <TextInput\n id={field.name}\n name={field.name}\n value={field.state.value}\n onBlur={field.handleBlur}\n onChange={(e) => field.handleChange(e.target.value)}\n label={t`DNS Name`}\n placeholder={t`Enter DNS name`}\n helptext={t`Enter a valid PQDN or FQDN (max 63 characters) to associate with the floating IP. A and PTR records are created automatically.`}\n errortext={field.state.meta.errors.map((e) => e?.message).join(\", \")}\n disabled={isPending}\n />\n )}\n />\n </FormSection>\n <FormSection className=\"mb-4\">\n <form.Field\n name=\"description\"\n children={(field) => (\n <Textarea\n id={field.name}\n name={field.name}\n value={field.state.value}\n onBlur={field.handleBlur}\n onChange={(e) => field.handleChange(e.target.value)}\n placeholder={t`Description`}\n errortext={field.state.meta.errors.map((e) => e?.message).join(\", \")}\n disabled={isPending}\n />\n )}\n />\n </FormSection>\n <FormSection className=\"mb-4\">\n <form.Field\n name=\"floating_ip_address\"\n children={(field) => (\n <TextInput\n id={field.name}\n name={field.name}\n value={field.state.value}\n onBlur={field.handleBlur}\n onChange={(e) => field.handleChange(e.target.value)}\n label={t`Floating IP Address`}\n placeholder={t`Enter a floating IP`}\n helptext={t`Enter a floating IP or leave blank to auto-assign one`}\n errortext={field.state.meta.errors.map((e) => e?.message).join(\", \")}\n disabled={isPending}\n />\n )}\n />\n </FormSection>\n <FormSection className=\"mb-4\">\n <form.Field\n name=\"port_id\"\n children={(field) => (\n <Select\n id={field.name}\n name={field.name}\n value={field.state.value}\n onChange={(value) => {\n const portId = typeof value === \"string\" ? value : \"\"\n field.handleChange(portId)\n const port = availablePorts.find((p) => p.id === portId)\n const ips = port?.fixed_ips ?? []\n form.setFieldValue(\"fixed_ip_address\", ips.length === 1 ? ips[0].ip_address : \"\")\n }}\n label={t`Port ID`}\n placeholder={t`Select port to associate`}\n errortext={field.state.meta.errors.map((e) => e?.message).join(\", \")}\n disabled={isPending || isPortsLoading}\n loading={isPortsLoading}\n >\n {availablePorts.map((port) => (\n <SelectOption\n key={port.id}\n value={port.id}\n label={port.name ? `${port.name} (${port.id})` : port.id}\n />\n ))}\n </Select>\n )}\n />\n </FormSection>\n <FormSection>\n <form.Field\n name=\"fixed_ip_address\"\n children={(field) => (\n <Select\n id={field.name}\n name={field.name}\n value={field.state.value}\n onBlur={field.handleBlur}\n onChange={(value) => field.handleChange(typeof value === \"string\" ? value : \"\")}\n label={t`Fixed IP Address`}\n placeholder={t`Select a fixed IP address`}\n helptext={t`Associates on the selected port. If the port has multiple IPs, select the desired fixed IP address.`}\n errortext={field.state.meta.errors.map((e) => e?.message).join(\", \")}\n disabled={isPending || portFixedIps.length === 0}\n >\n {portFixedIps.map(({ ip_address }) => (\n <SelectOption key={ip_address} value={ip_address} label={ip_address} />\n ))}\n </Select>\n )}\n />\n </FormSection>\n </Form>\n )}\n </Modal>\n )\n}\n","import { SelectedFilter, Filter } from \"@/client/components/ListToolbar/types\"\n\ntype FloatingIpsSearchParams = {\n status?: string\n search?: string\n sortBy?: string\n sortDirection?: \"asc\" | \"desc\"\n}\n\n/**\n * Parses URL search params into SelectedFilter array for ListToolbar\n */\nexport const parseFiltersFromUrl = (searchParams: FloatingIpsSearchParams): SelectedFilter[] => {\n const filters: SelectedFilter[] = []\n\n // Status filter\n if (searchParams.status) {\n filters.push({ name: \"status\", value: searchParams.status })\n }\n\n return filters\n}\n\n/**\n * Builds filter parameters for API request from SelectedFilter array\n */\nexport const buildFilterParams = (\n selectedFilters: SelectedFilter[],\n filterDefinitions: Filter[]\n): Record<string, string> => {\n const params: Record<string, string> = {}\n\n if (!selectedFilters?.length) return params\n\n // Group selected filters by filter name\n const filterGroups = selectedFilters\n .filter((sf) => !sf.inactive)\n .reduce(\n (acc, sf) => {\n if (!acc[sf.name]) acc[sf.name] = []\n acc[sf.name].push(sf.value)\n return acc\n },\n {} as Record<string, string[]>\n )\n\n // Build parameters based on whether filter supports multiple values\n Object.entries(filterGroups).forEach(([filterName, values]) => {\n const filterDef = filterDefinitions.find((f) => f.filterName === filterName)\n\n if (filterDef?.supportsMultiValue && values.length > 1) {\n params[filterName] = `in:${values.join(\",\")}`\n } else {\n params[filterName] = values[0]\n }\n })\n\n return params\n}\n\n/**\n * Merges a newly selected filter into the current list.\n * - Ignores duplicates (same name + value).\n * - For single-value filters, replaces any existing entry with the same name.\n * - For multi-value filters, appends.\n */\nexport const applyFilterSelection = (\n current: SelectedFilter[],\n selected: SelectedFilter,\n filterDefinitions: Filter[]\n): SelectedFilter[] => {\n const alreadySelected = current.some((f) => f.name === selected.name && f.value === selected.value)\n if (alreadySelected) return current\n\n const supportsMulti = filterDefinitions.find((f) => f.filterName === selected.name)?.supportsMultiValue\n return supportsMulti ? [...current, selected] : [...current.filter((f) => f.name !== selected.name), selected]\n}\n\n/**\n * Builds URL search params object from filter settings for navigation\n */\nexport const buildUrlSearchParams = (\n selectedFilters: SelectedFilter[],\n filterDefinitions: Filter[],\n baseParams: {\n search?: string\n sortBy?: string\n sortDirection?: \"asc\" | \"desc\"\n }\n): FloatingIpsSearchParams => {\n const newParams: FloatingIpsSearchParams = {\n search: baseParams.search,\n sortBy: baseParams.sortBy,\n sortDirection: baseParams.sortDirection,\n }\n\n if (!selectedFilters?.length) return newParams\n\n const filterGroups = selectedFilters\n .filter((sf) => !sf.inactive)\n .reduce(\n (acc, sf) => {\n if (!acc[sf.name]) acc[sf.name] = []\n acc[sf.name].push(sf.value)\n return acc\n },\n {} as Record<string, string[]>\n )\n\n Object.entries(filterGroups).forEach(([filterName, values]) => {\n const filterDef = filterDefinitions.find((f) => f.filterName === filterName)\n\n if (filterDef?.supportsMultiValue && values.length > 1) {\n // Type assertion needed because we're dynamically setting filter fields\n ;(newParams as Record<string, string>)[filterName] = `in:${values.join(\",\")}`\n } else {\n ;(newParams as Record<string, string>)[filterName] = values[0]\n }\n })\n\n return newParams\n}\n","import { useState, useRef, useEffect } from \"react\"\nimport { Trans, useLingui } from \"@lingui/react/macro\"\nimport { useNavigate, useSearch } from \"@tanstack/react-router\"\nimport { Button, Stack, DataGridToolbar, SearchInput, Message, Status } from \"@cloudoperators/juno-ui-components\"\nimport { FloatingIpQueryParameters } from \"@/server/Network/types/floatingIp\"\nimport { SortInput } from \"@/client/components/ListToolbar/SortInput\"\nimport { SelectedFilters } from \"@/client/components/ListToolbar/SelectedFilters\"\nimport { FiltersInput } from \"@/client/components/ListToolbar/FiltersInput\"\nimport { FilterSettings, SortSettings } from \"@/client/components/ListToolbar/types\"\nimport { ContentHeader } from \"@/client/components/ContentHeader/ContentHeader\"\nimport { trpcReact } from \"@/client/trpcClient\"\nimport { useModal } from \"@/client/utils/useModal\"\nimport { useProjectId } from \"@/client/hooks\"\nimport { FloatingIpListContainer } from \"./-table/FloatingIpListContainer\"\nimport { AllocateFloatingIpModal } from \"./-modals/AllocateFloatingIpModal\"\nimport { parseFiltersFromUrl, buildFilterParams, buildUrlSearchParams, applyFilterSelection } from \"../urlHelpers\"\n\nconst DEFAULT_SORT_KEY = \"status\"\nconst DEFAULT_SORT_DIR = \"asc\"\nexport type FloatingIpsSortKey = NonNullable<FloatingIpQueryParameters[\"sort_key\"]>\n\ntype FloatingIpsSearchParams = {\n status?: string\n search?: string\n sortBy?: string\n sortDirection?: \"asc\" | \"desc\"\n}\n\ntype RequiredSortSettings = {\n options: SortSettings[\"options\"]\n sortBy: string\n sortDirection: \"asc\" | \"desc\"\n}\n\nexport const FloatingIpsList = () => {\n const { t } = useLingui()\n const navigate = useNavigate()\n const searchParams = useSearch({ strict: false }) as FloatingIpsSearchParams\n const projectId = useProjectId()\n const [allocateModalOpen, toggleAllocateModal] = useModal(false)\n const [localSearchTerm, setLocalSearchTerm] = useState(searchParams.search || \"\")\n const debounceTimer = useRef<number | undefined>(undefined)\n\n useEffect(() => () => clearTimeout(debounceTimer.current), [])\n\n const [sortSettings, setSortSettings] = useState<RequiredSortSettings>({\n options: [{ label: t`Status`, value: \"status\" }],\n sortBy: searchParams.sortBy || DEFAULT_SORT_KEY,\n sortDirection: searchParams.sortDirection || DEFAULT_SORT_DIR,\n })\n\n const [filterSettings, setFilterSettings] = useState<FilterSettings>({\n filters: [\n {\n displayName: t`Status`,\n filterName: \"status\",\n values: [\"ACTIVE\", \"DOWN\", \"ERROR\"],\n supportsMultiValue: false,\n },\n ],\n selectedFilters: parseFiltersFromUrl(searchParams),\n })\n\n const searchTerm = searchParams.search || \"\"\n\n const { data: permissions } = trpcReact.network.canUser.useQuery(\n { project_id: projectId, permission: [\"network:floatingips:create\"] },\n { select: ([canCreate]) => ({ canCreate }) }\n )\n\n useEffect(() => {\n const urlFilters = parseFiltersFromUrl(searchParams)\n const urlSortBy = searchParams.sortBy || DEFAULT_SORT_KEY\n const urlSortDirection = searchParams.sortDirection || DEFAULT_SORT_DIR\n const urlSearchTerm = searchParams.search || \"\"\n\n setFilterSettings((prev) => ({ ...prev, selectedFilters: urlFilters }))\n setSortSettings((prev) => ({ ...prev, sortBy: urlSortBy, sortDirection: urlSortDirection }))\n setLocalSearchTerm(urlSearchTerm)\n }, [searchParams.status, searchParams.sortBy, searchParams.sortDirection, searchParams.search])\n\n const handleSortChange = (newSortSettings: SortSettings) => {\n const settings: RequiredSortSettings = {\n options: newSortSettings.options,\n sortBy: newSortSettings.sortBy?.toString() || DEFAULT_SORT_KEY,\n sortDirection: newSortSettings.sortDirection || DEFAULT_SORT_DIR,\n }\n setSortSettings(settings)\n navigate({\n search: ((prev: FloatingIpsSearchParams) => ({\n ...prev,\n sortBy: settings.sortBy,\n sortDirection: settings.sortDirection,\n })) as unknown as true,\n replace: false,\n })\n }\n\n const handleFilterChange = (newFilterSettings: FilterSettings) => {\n setFilterSettings(newFilterSettings)\n navigate({\n search: ((prev: FloatingIpsSearchParams) =>\n buildUrlSearchParams(newFilterSettings.selectedFilters || [], newFilterSettings.filters, {\n search: prev.search,\n sortBy: prev.sortBy,\n sortDirection: prev.sortDirection,\n })) as unknown as true,\n replace: false,\n })\n }\n\n const handleSearchChange = (term: string, replace = false) => {\n navigate({\n search: ((prev: FloatingIpsSearchParams) => ({\n ...prev,\n search: term || undefined,\n })) as unknown as true,\n replace,\n })\n }\n\n const {\n data: floatingIps = [],\n isLoading,\n isError,\n error,\n } = trpcReact.network.floatingIp.list.useQuery(\n {\n project_id: projectId,\n sort_key: sortSettings.sortBy as FloatingIpsSortKey,\n sort_dir: sortSettings.sortDirection,\n ...buildFilterParams(filterSettings.selectedFilters || [], filterSettings.filters),\n ...(searchTerm ? { searchTerm } : {}),\n },\n { placeholderData: (prev) => prev }\n )\n\n if (isError && !floatingIps.length) {\n return <Status status=\"error\" title={error?.message ?? t`Failed to Load Floating IPs`} />\n }\n\n return (\n <>\n <ContentHeader title={t`Floating IPs`} projectId={projectId} />\n\n <div className=\"relative\">\n {/* Non-blocking error banner for refetch failures with cached data */}\n {isError && floatingIps.length > 0 && (\n <Message variant=\"error\" className=\"mb-4\">\n {error?.message ?? t`Failed to refresh Floating IPs. Showing cached data.`}\n </Message>\n )}\n\n {/* Zone 1 — sort + create button, no background */}\n <Stack distribution=\"end\" alignment=\"center\" gap=\"2\" className=\"pb-2\">\n <Stack gap=\"2\">\n <SortInput\n options={sortSettings.options}\n sortBy={sortSettings.sortBy}\n sortDirection={sortSettings.sortDirection ?? \"asc\"}\n selectClassName=\"min-w-52\"\n onSortByChange={(v) =>\n handleSortChange({ ...sortSettings, sortBy: v, sortDirection: sortSettings.sortDirection })\n }\n onSortDirectionChange={(dir) => handleSortChange({ ...sortSettings, sortDirection: dir })}\n />\n {permissions?.canCreate && (\n <Button onClick={toggleAllocateModal} variant=\"primary\" className=\"whitespace-nowrap\">\n <Trans>Allocate Floating IP</Trans>\n </Button>\n )}\n </Stack>\n </Stack>\n\n {/* Zone 2 — filter + search + active filter pills */}\n <DataGridToolbar>\n <Stack direction=\"vertical\" gap=\"2\">\n <Stack distribution=\"between\" alignment=\"center\">\n <FiltersInput\n filters={filterSettings.filters}\n selectClassName=\"sm:min-w-40\"\n comboboxClassName=\"sm:min-w-40\"\n onChange={(selected) => {\n const newSelected = applyFilterSelection(\n filterSettings.selectedFilters || [],\n selected,\n filterSettings.filters\n )\n if (newSelected === (filterSettings.selectedFilters || [])) return\n handleFilterChange({ ...filterSettings, selectedFilters: newSelected })\n }}\n />\n <SearchInput\n placeholder={t`Search floating IPs...`}\n data-testid=\"searchbar\"\n value={localSearchTerm}\n onInput={(e: React.FormEvent<HTMLInputElement>) => {\n const v = e.currentTarget.value\n setLocalSearchTerm(v)\n clearTimeout(debounceTimer.current)\n debounceTimer.current = window.setTimeout(() => handleSearchChange(v, true), 500)\n }}\n onSearch={(v) => {\n clearTimeout(debounceTimer.current)\n handleSearchChange(typeof v === \"string\" ? v : \"\", false)\n }}\n onClear={() => {\n clearTimeout(debounceTimer.current)\n setLocalSearchTerm(\"\")\n handleSearchChange(\"\", false)\n }}\n />\n </Stack>\n {filterSettings.selectedFilters && filterSettings.selectedFilters.length > 0 && (\n <SelectedFilters\n selectedFilters={filterSettings.selectedFilters}\n onDelete={(filterToRemove) =>\n handleFilterChange({\n ...filterSettings,\n selectedFilters: (filterSettings.selectedFilters || []).filter(\n (f) => !(f.name === filterToRemove.name && f.value === filterToRemove.value)\n ),\n })\n }\n onClear={() => handleFilterChange({ ...filterSettings, selectedFilters: [] })}\n />\n )}\n </Stack>\n </DataGridToolbar>\n\n <FloatingIpListContainer\n floatingIps={floatingIps}\n isLoading={isLoading}\n isError={isError && !floatingIps.length}\n error={error}\n />\n\n {allocateModalOpen && <AllocateFloatingIpModal open={allocateModalOpen} onClose={toggleAllocateModal} />}\n </div>\n </>\n )\n}\n","import { createFileRoute } from \"@tanstack/react-router\"\nimport { z } from \"zod\"\nimport { t } from \"@lingui/core/macro\"\nimport { FloatingIpQueryParametersSchema, FloatingIpStatusSchema } from \"@/server/Network/types/floatingIp\"\nimport type { RouteInfo } from \"@/client/routes/routeInfo\"\nimport { FloatingIpsList } from \"./-components/FloatingIpsList\"\n\nconst floatingIpsSearchFields = {\n status: FloatingIpStatusSchema.optional(),\n search: z.string().optional(),\n sortBy: FloatingIpQueryParametersSchema.shape.sort_key.unwrap().optional(),\n sortDirection: z.enum([\"asc\", \"desc\"]).optional(),\n}\n\nconst floatingIpsSearchSchema = z.looseObject(floatingIpsSearchFields)\n\nexport const Route = createFileRoute(\"/_auth/projects/$projectId/network/floatingips/\")({\n staticData: {\n section: \"network\",\n service: \"floatingips\",\n analytics: {\n name: \"network.floatingips.list\",\n },\n } satisfies RouteInfo,\n validateSearch: (search) => {\n const result = floatingIpsSearchSchema.safeParse(search)\n if (result.success) return result.data\n return {\n ...search,\n status: floatingIpsSearchFields.status.safeParse(search.status).success ? search.status : undefined,\n search: floatingIpsSearchFields.search.safeParse(search.search).success ? search.search : undefined,\n sortBy: floatingIpsSearchFields.sortBy.safeParse(search.sortBy).success ? search.sortBy : undefined,\n sortDirection: floatingIpsSearchFields.sortDirection.safeParse(search.sortDirection).success\n ? search.sortDirection\n : undefined,\n }\n },\n head: () => ({ meta: [{ title: t`Floating IPs` }] }),\n component: RouteComponent,\n})\n\nfunction RouteComponent() {\n return <FloatingIpsList />\n}\n"],"mappings":"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"}
@@ -0,0 +1,14 @@
1
+ import { createFileRoute as e, lazyRouteComponent as t } from "@tanstack/react-router";
2
+ var n = e("/_auth/projects/$projectId/network/floatingips")({
3
+ staticData: {
4
+ section: "network",
5
+ service: "floatingips",
6
+ crumb: { text: { id: "u77/s4" } }
7
+ },
8
+ component: t(() => import("./floatingips-Cz9k80cc.mjs"), "component"),
9
+ errorComponent: t(() => import("./floatingips-BtLg3yEQ.mjs"), "errorComponent")
10
+ });
11
+ //#endregion
12
+ export { n as t };
13
+
14
+ //# sourceMappingURL=floatingips-BeQEkVH8.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"floatingips-BeQEkVH8.mjs","names":["createFileRoute","msg","Route","staticData","section","service","crumb","text","RouteInfo","component","lazyRouteComponent","$$splitComponentImporter","errorComponent","$$splitErrorComponentImporter"],"sources":["../../src/client/routes/_auth/projects/$projectId/network/floatingips.tsx"],"sourcesContent":["import { createFileRoute, Outlet, useNavigate } from \"@tanstack/react-router\"\nimport { RouteIdLevelDefaultError } from \"@/client/components/Errors/RouteIdLevelDefaultError\"\nimport { Button } from \"@cloudoperators/juno-ui-components\"\nimport { msg } from \"@lingui/core/macro\"\nimport { useLingui } from \"@lingui/react/macro\"\nimport type { RouteInfo } from \"@/client/routes/routeInfo\"\n\nconst FloatingIpsErrorComponent = () => {\n const { t } = useLingui()\n const navigate = useNavigate()\n const { projectId } = Route.useParams()\n\n return (\n <RouteIdLevelDefaultError\n action={\n <Button\n variant=\"primary\"\n onClick={() => navigate({ to: \"/projects/$projectId/network/floatingips\", params: { projectId } })}\n >\n {t`Back to Floating IPs`}\n </Button>\n }\n />\n )\n}\n\nexport const Route = createFileRoute(\"/_auth/projects/$projectId/network/floatingips\")({\n staticData: {\n section: \"network\",\n service: \"floatingips\",\n crumb: { text: msg`Floating IPs` },\n } satisfies RouteInfo,\n component: () => <Outlet />,\n // Render errors from the floating IPs subtree inside the project layout\n // (side navigation, header, breadcrumbs) instead of the full-screen route error.\n errorComponent: FloatingIpsErrorComponent,\n})\n"],"mappings":";AA0BA,IAAaE,IAAQF,EAAgB,gDAAA,CAAA,CAAkD;CACrFG,YAAY;EACVC,SAAS;EACTC,SAAS;EACTC,OAAO,EAAEC,MAAMN,EAAAA,IAAAA,SAAG,EAAe;CACnC;CACAQ,WAASC,8CAAA,WAAA;CAGTE,gBAAcF,8CAAA,gBAAA;AAChB,CAAA"}
@@ -0,0 +1,22 @@
1
+ import { i as e } from "./build-WuxXRAqf.mjs";
2
+ import { t } from "./floatingips-BeQEkVH8.mjs";
3
+ import { t as n } from "./RouteIdLevelDefaultError-CSseJ1yG.mjs";
4
+ import { jsx as r } from "react/jsx-runtime";
5
+ import { useNavigate as i } from "@tanstack/react-router";
6
+ import { useLingui as a } from "@lingui/react";
7
+ //#region src/client/routes/_auth/projects/$projectId/network/floatingips.tsx?tsr-split=errorComponent
8
+ var o = () => {
9
+ let { i18n: o, _: s } = a(), c = i(), { projectId: l } = t.useParams();
10
+ return /*#__PURE__*/ r(n, { action: /*#__PURE__*/ r(e, {
11
+ variant: "primary",
12
+ onClick: () => c({
13
+ to: "/projects/$projectId/network/floatingips",
14
+ params: { projectId: l }
15
+ }),
16
+ children: o._({ id: "z1JceR" })
17
+ }) });
18
+ };
19
+ //#endregion
20
+ export { o as errorComponent };
21
+
22
+ //# sourceMappingURL=floatingips-BtLg3yEQ.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"floatingips-BtLg3yEQ.mjs","names":["useNavigate","RouteIdLevelDefaultError","Button","useLingui","FloatingIpsErrorComponent","t","navigate","projectId","Route","useParams","to","params","errorComponent"],"sources":["../../src/client/routes/_auth/projects/$projectId/network/floatingips.tsx?tsr-split=errorComponent"],"sourcesContent":["import { createFileRoute, Outlet, useNavigate } from \"@tanstack/react-router\"\nimport { RouteIdLevelDefaultError } from \"@/client/components/Errors/RouteIdLevelDefaultError\"\nimport { Button } from \"@cloudoperators/juno-ui-components\"\nimport { msg } from \"@lingui/core/macro\"\nimport { useLingui } from \"@lingui/react/macro\"\nimport type { RouteInfo } from \"@/client/routes/routeInfo\"\n\nconst FloatingIpsErrorComponent = () => {\n const { t } = useLingui()\n const navigate = useNavigate()\n const { projectId } = Route.useParams()\n\n return (\n <RouteIdLevelDefaultError\n action={\n <Button\n variant=\"primary\"\n onClick={() => navigate({ to: \"/projects/$projectId/network/floatingips\", params: { projectId } })}\n >\n {t`Back to Floating IPs`}\n </Button>\n }\n />\n )\n}\n\nexport const Route = createFileRoute(\"/_auth/projects/$projectId/network/floatingips\")({\n staticData: {\n section: \"network\",\n service: \"floatingips\",\n crumb: { text: msg`Floating IPs` },\n } satisfies RouteInfo,\n component: () => <Outlet />,\n // Render errors from the floating IPs subtree inside the project layout\n // (side navigation, header, breadcrumbs) instead of the full-screen route error.\n errorComponent: FloatingIpsErrorComponent,\n})\n"],"mappings":";;;;;;;AAOA,IAAMI,UAA4BA;CAChC,IAAM,EAAA,MAAA,GAAA,GAAA,MAAQD,EAAAA,GACRG,IAAWN,EAAAA,GACX,EAAEO,iBAAcC,EAAMC,UAAS;CAErC,OACE,gBAAC,GAAA,EACC,QACE,gBAAC,GAAA;EACC,SAAQ;EACR,eAAeH,EAAS;GAAEI,IAAI;GAA4CC,QAAQ,EAAEJ,aAAU;EAAE,CAAA;EAE/FF,UAAAA,EAAAA,EAAC,EAAA,IAAA,SAAA,CAAA;;AAKZ"}
@@ -1 +1 @@
1
- {"version":3,"file":"floatingips-Cz9k80cc.mjs","names":["Outlet","SplitComponent","component"],"sources":["../../src/client/routes/_auth/projects/$projectId/network/floatingips.tsx?tsr-split=component"],"sourcesContent":["import { createFileRoute, Outlet } from \"@tanstack/react-router\"\nimport { msg } from \"@lingui/core/macro\"\nimport type { RouteInfo } from \"@/client/routes/routeInfo\"\n\nexport const Route = createFileRoute(\"/_auth/projects/$projectId/network/floatingips\")({\n staticData: {\n section: \"network\",\n service: \"floatingips\",\n crumb: { text: msg`Floating IPs` },\n } satisfies RouteInfo,\n component: () => <Outlet />,\n})\n"],"mappings":";;;AAAgE,IAAAC,UAU7C,gBAAC,GAAA,CAAA,CAAA"}
1
+ {"version":3,"file":"floatingips-Cz9k80cc.mjs","names":["Outlet","SplitComponent","component"],"sources":["../../src/client/routes/_auth/projects/$projectId/network/floatingips.tsx?tsr-split=component"],"sourcesContent":["import { createFileRoute, Outlet, useNavigate } from \"@tanstack/react-router\"\nimport { RouteIdLevelDefaultError } from \"@/client/components/Errors/RouteIdLevelDefaultError\"\nimport { Button } from \"@cloudoperators/juno-ui-components\"\nimport { msg } from \"@lingui/core/macro\"\nimport { useLingui } from \"@lingui/react/macro\"\nimport type { RouteInfo } from \"@/client/routes/routeInfo\"\n\nconst FloatingIpsErrorComponent = () => {\n const { t } = useLingui()\n const navigate = useNavigate()\n const { projectId } = Route.useParams()\n\n return (\n <RouteIdLevelDefaultError\n action={\n <Button\n variant=\"primary\"\n onClick={() => navigate({ to: \"/projects/$projectId/network/floatingips\", params: { projectId } })}\n >\n {t`Back to Floating IPs`}\n </Button>\n }\n />\n )\n}\n\nexport const Route = createFileRoute(\"/_auth/projects/$projectId/network/floatingips\")({\n staticData: {\n section: \"network\",\n service: \"floatingips\",\n crumb: { text: msg`Floating IPs` },\n } satisfies RouteInfo,\n component: () => <Outlet />,\n // Render errors from the floating IPs subtree inside the project layout\n // (side navigation, header, breadcrumbs) instead of the full-screen route error.\n errorComponent: FloatingIpsErrorComponent,\n})\n"],"mappings":";;;AAA6E,IAAAC,UAgC1D,gBAAC,GAAA,CAAA,CAAA"}