@cobaltcore-dev/aurora 1.0.0 → 1.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/client/App.d.ts +2 -1
- package/dist/client/AuroraApp.d.ts +25 -0
- package/dist/client/{AuthProvider-5TyZKZkx.mjs → AuthProvider-BS5OVv8n.mjs} +2 -2
- package/dist/client/AuthProvider-BS5OVv8n.mjs.map +1 -0
- package/dist/client/{ContentHeader-D64NtKvo.mjs → ContentHeader-BHMUzd9H.mjs} +16 -16
- package/dist/client/{ContentHeader-D64NtKvo.mjs.map → ContentHeader-BHMUzd9H.mjs.map} +1 -1
- package/dist/client/{DeleteFlavorModal-C2K43ABZ.mjs → DeleteFlavorModal-BP83t9zX.mjs} +283 -294
- package/dist/client/DeleteFlavorModal-BP83t9zX.mjs.map +1 -0
- package/dist/client/{FiltersInput-Bw8TFfwb.mjs → FiltersInput-B8CNBg1L.mjs} +23 -23
- package/dist/client/{FiltersInput-Bw8TFfwb.mjs.map → FiltersInput-B8CNBg1L.mjs.map} +1 -1
- package/dist/client/{FloatingIpActionModals-BfEDfYg9.mjs → FloatingIpActionModals-BraiJWBi.mjs} +48 -48
- package/dist/client/{FloatingIpActionModals-BfEDfYg9.mjs.map → FloatingIpActionModals-BraiJWBi.mjs.map} +1 -1
- package/dist/client/ImageToastNotifications-BXMHJaIH.mjs +1131 -0
- package/dist/client/ImageToastNotifications-BXMHJaIH.mjs.map +1 -0
- package/dist/client/{RouteError-B-NPGIv7.mjs → RouteError-hAF8_jbe.mjs} +2 -2
- package/dist/client/{RouteError-B-NPGIv7.mjs.map → RouteError-hAF8_jbe.mjs.map} +1 -1
- package/dist/client/{SortInput-DysAXpB3.mjs → SortInput-Cqs2poV3.mjs} +7 -7
- package/dist/client/{SortInput-DysAXpB3.mjs.map → SortInput-Cqs2poV3.mjs.map} +1 -1
- package/dist/client/{StatusError-DX-GvLjq.mjs → StatusError-C5KodQOq.mjs} +4 -4
- package/dist/client/{StatusError-DX-GvLjq.mjs.map → StatusError-C5KodQOq.mjs.map} +1 -1
- package/dist/client/{TwoColumnDescriptionList-B3xunXmz.mjs → TwoColumnDescriptionList-DiDx3PnH.mjs} +6 -6
- package/dist/client/{TwoColumnDescriptionList-B3xunXmz.mjs.map → TwoColumnDescriptionList-DiDx3PnH.mjs.map} +1 -1
- package/dist/client/{_auth-R5H2yKFf.mjs → _auth-DJ9wHZaj.mjs} +2 -2
- package/dist/client/{_auth-R5H2yKFf.mjs.map → _auth-DJ9wHZaj.mjs.map} +1 -1
- package/dist/client/{_flavorId-Zj7LNL-R.mjs → _flavorId-BN_qessZ.mjs} +2 -2
- package/dist/client/{_flavorId-Zj7LNL-R.mjs.map → _flavorId-BN_qessZ.mjs.map} +1 -1
- package/dist/client/{_flavorId-Dit5mM8I.mjs → _flavorId-CJjEB_Ao.mjs} +34 -34
- package/dist/client/{_flavorId-Dit5mM8I.mjs.map → _flavorId-CJjEB_Ao.mjs.map} +1 -1
- package/dist/client/{_floatingIpId-DCQQpNO-.mjs → _floatingIpId-CwDGHkWm.mjs} +2 -2
- package/dist/client/{_floatingIpId-DCQQpNO-.mjs.map → _floatingIpId-CwDGHkWm.mjs.map} +1 -1
- package/dist/client/{_floatingIpId-B0MCoqE3.mjs → _floatingIpId-foMIwbE4.mjs} +23 -23
- package/dist/client/{_floatingIpId-B0MCoqE3.mjs.map → _floatingIpId-foMIwbE4.mjs.map} +1 -1
- package/dist/client/_imageId-BtJ7GmYB.mjs +558 -0
- package/dist/client/{_imageId-CZYzBAVx.mjs.map → _imageId-BtJ7GmYB.mjs.map} +1 -1
- package/dist/client/{_projectId-DhSWowQo.mjs → _projectId-BmtCuzJu.mjs} +4 -4
- package/dist/client/{_projectId-DhSWowQo.mjs.map → _projectId-BmtCuzJu.mjs.map} +1 -1
- package/dist/client/_projectId-Byt3GQDW.mjs +99 -0
- package/dist/client/_projectId-Byt3GQDW.mjs.map +1 -0
- package/dist/client/_projectId-NYk1IN_a.mjs +291 -0
- package/dist/client/_projectId-NYk1IN_a.mjs.map +1 -0
- package/dist/client/{_projectId-D2pFfYIs.mjs → _projectId-QueiFczy.mjs} +3 -3
- package/dist/client/{_projectId-D2pFfYIs.mjs.map → _projectId-QueiFczy.mjs.map} +1 -1
- package/dist/client/{_securityGroupId-Mj8NJT2-.mjs → _securityGroupId-BcbkRhsN.mjs} +2 -2
- package/dist/client/{_securityGroupId-Mj8NJT2-.mjs.map → _securityGroupId-BcbkRhsN.mjs.map} +1 -1
- package/dist/client/{_securityGroupId-DZ4D4WwB.mjs → _securityGroupId-pPtJsCoe.mjs} +438 -442
- package/dist/client/{_securityGroupId-DZ4D4WwB.mjs.map → _securityGroupId-pPtJsCoe.mjs.map} +1 -1
- package/dist/client/_storageType-BmqrU06i.mjs +2202 -0
- package/dist/client/_storageType-BmqrU06i.mjs.map +1 -0
- package/dist/client/{about-WLyShNgE.mjs → about-_73VmpTB.mjs} +2 -2
- package/dist/client/{about-WLyShNgE.mjs.map → about-_73VmpTB.mjs.map} +1 -1
- package/dist/client/assets/{objectDownload.worker-BXFQIIU_.js.map → objectDownload.worker-CWWLPDyb.js.map} +1 -1
- package/dist/client/assets/{objectDownload.worker-ECvFtmOF.js.map → objectDownload.worker-kZlQuo3F.js.map} +1 -1
- package/dist/client/{aurora-IMO9HhqJ.mjs → aurora-EbwGRLLf.mjs} +2 -2
- package/dist/client/{aurora-IMO9HhqJ.mjs.map → aurora-EbwGRLLf.mjs.map} +1 -1
- package/dist/client/{build-DnD-T35u.mjs → build-C_4vRMCq.mjs} +2233 -2662
- package/dist/client/{build-DnD-T35u.mjs.map → build-C_4vRMCq.mjs.map} +1 -1
- package/dist/client/{flavors-Cp0LEGOH.mjs → flavors-CiHCYrtZ.mjs} +2 -2
- package/dist/client/{flavors-Cp0LEGOH.mjs.map → flavors-CiHCYrtZ.mjs.map} +1 -1
- package/dist/client/{flavors-CwMbDRHm2.mjs → flavors-DY-bDc8l.mjs} +164 -164
- package/dist/client/flavors-DY-bDc8l.mjs.map +1 -0
- package/dist/client/{floatingips-ICwo-rV_.mjs → floatingips-Ci4jHkaG.mjs} +177 -177
- package/dist/client/{floatingips-ICwo-rV_.mjs.map → floatingips-Ci4jHkaG.mjs.map} +1 -1
- package/dist/client/{hooks-CrriowRk.mjs → hooks-LutR2Yg3.mjs} +2 -2
- package/dist/client/{hooks-CrriowRk.mjs.map → hooks-LutR2Yg3.mjs.map} +1 -1
- package/dist/client/images-91U7tr9Y2.mjs +1976 -0
- package/dist/client/images-91U7tr9Y2.mjs.map +1 -0
- package/dist/client/{images-DWiM_72I.mjs → images-CS4kZQyu.mjs} +2 -2
- package/dist/client/{images-DWiM_72I.mjs.map → images-CS4kZQyu.mjs.map} +1 -1
- package/dist/client/index.d.ts +4 -1
- package/dist/client/index.js +444 -586
- package/dist/client/index.js.map +1 -1
- package/dist/client/{md-DNzcRhmz.mjs → md-kvaGCNAK.mjs} +4 -22
- package/dist/client/{md-DNzcRhmz.mjs.map → md-kvaGCNAK.mjs.map} +1 -1
- package/dist/client/{objects-DeK2WD5K.mjs → objects-C3azvW8m.mjs} +2019 -2023
- package/dist/client/{objects-DeK2WD5K.mjs.map → objects-C3azvW8m.mjs.map} +1 -1
- package/dist/client/{objects-DI1-tnKr.mjs → objects-CM265S6b.mjs} +2 -2
- package/dist/client/{objects-DI1-tnKr.mjs.map → objects-CM265S6b.mjs.map} +1 -1
- package/dist/client/{objects-D2MKUCxc.mjs → objects-EE9Cd1wI.mjs} +2 -2
- package/dist/client/{objects-D2MKUCxc.mjs.map → objects-EE9Cd1wI.mjs.map} +1 -1
- package/dist/client/{routeInfo-CdTRlSxv.mjs → routeInfo-DXqB2HCf.mjs} +3 -3
- package/dist/client/routeInfo-DXqB2HCf.mjs.map +1 -0
- package/dist/client/router.d.ts +2 -1
- package/dist/client/{routes-DOJr5onJ.mjs → routes-CBd8CCuM.mjs} +13 -13
- package/dist/client/{routes-DOJr5onJ.mjs.map → routes-CBd8CCuM.mjs.map} +1 -1
- package/dist/client/{routes-B05u5bk4.mjs → routes-CdDm-hhO.mjs} +2 -2
- package/dist/client/{routes-B05u5bk4.mjs.map → routes-CdDm-hhO.mjs.map} +1 -1
- package/dist/client/{securitygroups-Be2Qgmew.mjs → securitygroups-Bd_uV4S9.mjs} +198 -198
- package/dist/client/{securitygroups-Be2Qgmew.mjs.map → securitygroups-Bd_uV4S9.mjs.map} +1 -1
- package/dist/client/{securitygroups-_7SYN2jN.mjs → securitygroups-Byte-iSp.mjs} +2 -2
- package/dist/client/{securitygroups-_7SYN2jN.mjs.map → securitygroups-Byte-iSp.mjs.map} +1 -1
- package/dist/client/services-D1PbooD1.mjs +6 -0
- package/dist/client/services-D1PbooD1.mjs.map +1 -0
- package/dist/client/services-DEMVtFyn.mjs +9 -0
- package/dist/client/services-DEMVtFyn.mjs.map +1 -0
- package/dist/client/trpcClient.d.ts +18 -367
- package/dist/client/{useSecurityGroupPermissions-qPwm4mFt.mjs → useSecurityGroupPermissions-C29mzb3b.mjs} +15 -15
- package/dist/client/{useSecurityGroupPermissions-qPwm4mFt.mjs.map → useSecurityGroupPermissions-C29mzb3b.mjs.map} +1 -1
- package/dist/server/index.d.ts +43 -369
- package/dist/server/index.js +71 -276
- package/package.json +1 -3
- package/dist/client/AuthProvider-5TyZKZkx.mjs.map +0 -1
- package/dist/client/DeleteFlavorModal-C2K43ABZ.mjs.map +0 -1
- package/dist/client/DeletePcaModal-D9v8E0Ki.mjs +0 -92
- package/dist/client/DeletePcaModal-D9v8E0Ki.mjs.map +0 -1
- package/dist/client/DetailsInfo-h7rPJ4Jf.mjs +0 -61
- package/dist/client/DetailsInfo-h7rPJ4Jf.mjs.map +0 -1
- package/dist/client/ImageToastNotifications-C0Tluzq-.mjs +0 -1125
- package/dist/client/ImageToastNotifications-C0Tluzq-.mjs.map +0 -1
- package/dist/client/_imageId-CZYzBAVx.mjs +0 -558
- package/dist/client/_pcaId-CHRRsWmO.mjs +0 -605
- package/dist/client/_pcaId-CHRRsWmO.mjs.map +0 -1
- package/dist/client/_projectId-B8wWSxPu.mjs +0 -98
- package/dist/client/_projectId-B8wWSxPu.mjs.map +0 -1
- package/dist/client/_projectId-C5DUYIjt.mjs +0 -291
- package/dist/client/_projectId-C5DUYIjt.mjs.map +0 -1
- package/dist/client/_storageType-C-9bNkmZ.mjs +0 -2211
- package/dist/client/_storageType-C-9bNkmZ.mjs.map +0 -1
- package/dist/client/flavors-CwMbDRHm2.mjs.map +0 -1
- package/dist/client/images-DOGZmr3D.mjs +0 -1937
- package/dist/client/images-DOGZmr3D.mjs.map +0 -1
- package/dist/client/pca-BokFv4Gz.mjs +0 -239
- package/dist/client/pca-BokFv4Gz.mjs.map +0 -1
- package/dist/client/pca-D5jHAl0b.mjs +0 -26
- package/dist/client/pca-D5jHAl0b.mjs.map +0 -1
- package/dist/client/pcaAccess-Br4kVjLQ.mjs +0 -9
- package/dist/client/pcaAccess-Br4kVjLQ.mjs.map +0 -1
- package/dist/client/routeInfo-CdTRlSxv.mjs.map +0 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"floatingips-ICwo-rV_.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","ContentHeading","Stack","Spinner","FloatingIpTableRow","TABLE_COLUMNS","FloatingIpListContainer","floatingIps","isLoading","isError","error","useLingui","columns","columnCount","length","className","distribution","alignment","direction","variant","size","message","t","data-testid","colSpan","p","map","label","ip","floatingIp","id","z","useForm","useStore","Modal","Form","FormSection","Spinner","Message","Textarea","TextInput","Select","SelectOption","trpcReact","useProjectId","ipv4Regex","ipv6Regex","isValidIpAddress","value","test","dnsNameRegex","AllocateFloatingIpModal","open","onClose","useLingui","projectId","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","mutateAsync","tenant_id","handleClose","reset","currentPortId","store","state","values","currentFloatingNetworkId","selectedPort","find","port","id","portFixedIps","fixed_ips","formErrorMessage","size","title","onCancel","cancelButtonLabel","confirmButtonLabel","onConfirm","handleSubmit","disableConfirmButton","dismissible","variant","className","div","span","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","SortInput","SelectedFilters","FiltersInput","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","className","distribution","alignment","direction","message","div","variant","gap","selectClassName","onSortByChange","v","onSortDirectionChange","dir","onClick","comboboxClassName","onChange","selected","newSelected","placeholder","data-testid","onInput","e","currentTarget","window","setTimeout","onSearch","onClear","onDelete","filterToRemove","filter","f","name","open","onClose","useLingui","FloatingIpsList","ContentHeading","RouteComponent","t","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 \"Preview\", \"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>{floatingIp.description || \"—\"}</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`Preview`} 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 { Trans, useLingui } from \"@lingui/react/macro\"\nimport {\n DataGrid,\n DataGridHeadCell,\n DataGridRow,\n DataGridCell,\n ContentHeading,\n Stack,\n Spinner,\n} 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 (\n <Stack className=\"py-8\" distribution=\"center\" alignment=\"center\" direction=\"vertical\">\n <Spinner variant=\"primary\" size=\"large\" className=\"mb-2\" />\n <Trans>Loading...</Trans>\n </Stack>\n )\n }\n\n if (isError) {\n return (\n <Stack className=\"py-8\" distribution=\"center\" alignment=\"center\" direction=\"vertical\">\n {error?.message ?? t`Failed to load Floating IPs`}\n </Stack>\n )\n }\n\n if (floatingIps.length === 0) {\n return (\n <DataGrid columns={columnCount} className=\"floating-ips\" data-testid=\"no-floating-ips\">\n <DataGridRow>\n <DataGridCell colSpan={columnCount}>\n <ContentHeading>\n <Trans>No Floating IPs found</Trans>\n </ContentHeading>\n <p>\n <Trans>\n There are no Floating IPs available for this project. Floating IPs allow you to map public IP addresses\n to instances.\n </Trans>\n </p>\n </DataGridCell>\n </DataGridRow>\n </DataGrid>\n )\n }\n\n return (\n <DataGrid columns={columnCount}>\n <DataGridRow>\n {columns.map((label) => (\n <DataGridHeadCell key={label}>{label}</DataGridHeadCell>\n ))}\n </DataGridRow>\n {floatingIps.map((ip) => (\n <FloatingIpTableRow key={ip.id} floatingIp={ip} />\n ))}\n </DataGrid>\n )\n}\n","import { z } from \"zod\"\nimport { useForm, useStore } from \"@tanstack/react-form\"\nimport { Trans, useLingui } from \"@lingui/react/macro\"\nimport {\n Modal,\n Form,\n FormSection,\n Spinner,\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 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 await createFloatingIpMutation.mutateAsync({\n project_id: projectId,\n tenant_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 },\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 >\n {formErrorMessage && (\n <Message dismissible={false} variant=\"error\" className=\"mb-4\">\n {formErrorMessage}\n </Message>\n )}\n\n {isPending && (\n <div className=\"mb-4 flex items-center justify-center gap-2\">\n <Spinner variant=\"primary\" />\n <span className=\"text-theme-high text-sm\">\n <Trans>Allocating Floating IP...</Trans>\n </span>\n </div>\n )}\n\n {!isPending && (\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 } 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 { 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 = \"fixed_ip_address\"\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: [\n { label: t`Fixed IP Address`, value: \"fixed_ip_address\" },\n { label: t`Floating IP Address`, value: \"floating_ip_address\" },\n { label: t`Floating Network ID`, value: \"floating_network_id\" },\n { label: t`ID`, value: \"id\" },\n { label: t`Router ID`, value: \"router_id\" },\n { label: t`Status`, value: \"status\" },\n { label: t`Tenant ID`, value: \"tenant_id\" },\n { label: t`Project ID`, value: \"project_id\" },\n ],\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 {\n project_id: projectId,\n permission: [\"network:floatingips:create\"],\n },\n {\n select: ([canCreate]) => ({\n canCreate,\n }),\n }\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 {\n placeholderData: (prev) => prev,\n }\n )\n\n if (isLoading && !floatingIps.length) {\n return (\n <Stack className=\"py-8\" distribution=\"center\" alignment=\"center\" direction=\"vertical\">\n <Trans>Loading...</Trans>\n </Stack>\n )\n }\n\n if (isError && !floatingIps.length) {\n return (\n <Stack className=\"py-8\" distribution=\"center\" alignment=\"center\" direction=\"vertical\">\n {error?.message ?? t`Failed to load Floating IPs`}\n </Stack>\n )\n }\n\n return (\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-40\"\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","import { createFileRoute } from \"@tanstack/react-router\"\nimport { z } from \"zod\"\nimport { t } from \"@lingui/core/macro\"\nimport { useLingui } from \"@lingui/react/macro\"\nimport { FloatingIpsList } from \"./-components/FloatingIpsList\"\nimport type { RouteInfo } from \"@/client/routes/routeInfo\"\nimport { ContentHeading } from \"@cloudoperators/juno-ui-components\"\nimport { FloatingIpQueryParametersSchema, FloatingIpStatusSchema } from \"@/server/Network/types/floatingIp\"\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.object(floatingIpsSearchFields).passthrough()\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 sectionCrumb: { labelKey: \"Network\" },\n crumb: { labelKey: \"Floating IPs\" },\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 const { t } = useLingui()\n return (\n <>\n <ContentHeading>{t`Floating IPs`}</ContentHeading>\n <FloatingIpsList />\n </>\n )\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"floatingips-Ci4jHkaG.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","ContentHeading","Stack","Spinner","FloatingIpTableRow","TABLE_COLUMNS","FloatingIpListContainer","floatingIps","isLoading","isError","error","useLingui","columns","columnCount","length","className","distribution","alignment","direction","variant","size","message","t","data-testid","colSpan","p","map","label","ip","floatingIp","id","z","useForm","useStore","Modal","Form","FormSection","Spinner","Message","Textarea","TextInput","Select","SelectOption","trpcReact","useProjectId","ipv4Regex","ipv6Regex","isValidIpAddress","value","test","dnsNameRegex","AllocateFloatingIpModal","open","onClose","useLingui","projectId","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","mutateAsync","tenant_id","handleClose","reset","currentPortId","store","state","values","currentFloatingNetworkId","selectedPort","find","port","id","portFixedIps","fixed_ips","formErrorMessage","size","title","onCancel","cancelButtonLabel","confirmButtonLabel","onConfirm","handleSubmit","disableConfirmButton","dismissible","variant","className","div","span","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","SortInput","SelectedFilters","FiltersInput","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","className","distribution","alignment","direction","message","div","variant","gap","selectClassName","onSortByChange","v","onSortDirectionChange","dir","onClick","comboboxClassName","onChange","selected","newSelected","placeholder","data-testid","onInput","e","currentTarget","window","setTimeout","onSearch","onClear","onDelete","filterToRemove","filter","f","name","open","onClose","useLingui","FloatingIpsList","ContentHeading","RouteComponent","t","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 \"Preview\", \"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>{floatingIp.description || \"—\"}</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`Preview`} 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 { Trans, useLingui } from \"@lingui/react/macro\"\nimport {\n DataGrid,\n DataGridHeadCell,\n DataGridRow,\n DataGridCell,\n ContentHeading,\n Stack,\n Spinner,\n} 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 (\n <Stack className=\"py-8\" distribution=\"center\" alignment=\"center\" direction=\"vertical\">\n <Spinner variant=\"primary\" size=\"large\" className=\"mb-2\" />\n <Trans>Loading...</Trans>\n </Stack>\n )\n }\n\n if (isError) {\n return (\n <Stack className=\"py-8\" distribution=\"center\" alignment=\"center\" direction=\"vertical\">\n {error?.message ?? t`Failed to load Floating IPs`}\n </Stack>\n )\n }\n\n if (floatingIps.length === 0) {\n return (\n <DataGrid columns={columnCount} className=\"floating-ips\" data-testid=\"no-floating-ips\">\n <DataGridRow>\n <DataGridCell colSpan={columnCount}>\n <ContentHeading>\n <Trans>No Floating IPs found</Trans>\n </ContentHeading>\n <p>\n <Trans>\n There are no Floating IPs available for this project. Floating IPs allow you to map public IP addresses\n to instances.\n </Trans>\n </p>\n </DataGridCell>\n </DataGridRow>\n </DataGrid>\n )\n }\n\n return (\n <DataGrid columns={columnCount}>\n <DataGridRow>\n {columns.map((label) => (\n <DataGridHeadCell key={label}>{label}</DataGridHeadCell>\n ))}\n </DataGridRow>\n {floatingIps.map((ip) => (\n <FloatingIpTableRow key={ip.id} floatingIp={ip} />\n ))}\n </DataGrid>\n )\n}\n","import { z } from \"zod\"\nimport { useForm, useStore } from \"@tanstack/react-form\"\nimport { Trans, useLingui } from \"@lingui/react/macro\"\nimport {\n Modal,\n Form,\n FormSection,\n Spinner,\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 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 await createFloatingIpMutation.mutateAsync({\n project_id: projectId,\n tenant_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 },\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 >\n {formErrorMessage && (\n <Message dismissible={false} variant=\"error\" className=\"mb-4\">\n {formErrorMessage}\n </Message>\n )}\n\n {isPending && (\n <div className=\"mb-4 flex items-center justify-center gap-2\">\n <Spinner variant=\"primary\" />\n <span className=\"text-theme-high text-sm\">\n <Trans>Allocating Floating IP...</Trans>\n </span>\n </div>\n )}\n\n {!isPending && (\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 } 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 { 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 = \"fixed_ip_address\"\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: [\n { label: t`Fixed IP Address`, value: \"fixed_ip_address\" },\n { label: t`Floating IP Address`, value: \"floating_ip_address\" },\n { label: t`Floating Network ID`, value: \"floating_network_id\" },\n { label: t`ID`, value: \"id\" },\n { label: t`Router ID`, value: \"router_id\" },\n { label: t`Status`, value: \"status\" },\n { label: t`Tenant ID`, value: \"tenant_id\" },\n { label: t`Project ID`, value: \"project_id\" },\n ],\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 {\n project_id: projectId,\n permission: [\"network:floatingips:create\"],\n },\n {\n select: ([canCreate]) => ({\n canCreate,\n }),\n }\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 {\n placeholderData: (prev) => prev,\n }\n )\n\n if (isLoading && !floatingIps.length) {\n return (\n <Stack className=\"py-8\" distribution=\"center\" alignment=\"center\" direction=\"vertical\">\n <Trans>Loading...</Trans>\n </Stack>\n )\n }\n\n if (isError && !floatingIps.length) {\n return (\n <Stack className=\"py-8\" distribution=\"center\" alignment=\"center\" direction=\"vertical\">\n {error?.message ?? t`Failed to load Floating IPs`}\n </Stack>\n )\n }\n\n return (\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-40\"\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","import { createFileRoute } from \"@tanstack/react-router\"\nimport { z } from \"zod\"\nimport { t } from \"@lingui/core/macro\"\nimport { useLingui } from \"@lingui/react/macro\"\nimport { FloatingIpsList } from \"./-components/FloatingIpsList\"\nimport type { RouteInfo } from \"@/client/routes/routeInfo\"\nimport { ContentHeading } from \"@cloudoperators/juno-ui-components\"\nimport { FloatingIpQueryParametersSchema, FloatingIpStatusSchema } from \"@/server/Network/types/floatingIp\"\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.object(floatingIpsSearchFields).passthrough()\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 sectionCrumb: { labelKey: \"Network\" },\n crumb: { labelKey: \"Floating IPs\" },\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 const { t } = useLingui()\n return (\n <>\n <ContentHeading>{t`Floating IPs`}</ContentHeading>\n <FloatingIpsList />\n </>\n )\n}\n"],"mappings":";;;;;;;;;;;;;;;;;AASA,IAAaG,IAAmE;CAC9EC,QAAQ;EACNC,MAAM;EACNC,MAAM,gBAACJ,GAAAA;GAAcK,MAAM;GAAIC,OAAM;GAAQC,MAAK;;CACpD;CACAC,MAAM;EACJL,MAAM;EACNC,MAAM,gBAACL,GAAAA;GAAeM,MAAM;GAAIC,OAAM;GAAQC,MAAK;;CACrD;CACAE,OAAO;EACLN,MAAM;EACNC,MAAM,gBAACN,GAAAA;GAAQO,MAAM;GAAIC,OAAM;GAAQC,MAAK;;CAC9C;AACF,GAEaG,UACX;CACEC,EAAAA,EAAC,EAAA,IAAA,SAAO,CAAA;CACRA,EAAAA,EAAC,EAAA,IAAA,SAAoB,CAAA;CACrBA,EAAAA,EAAC,EAAA,IAAA,SAAiB,CAAA;CAClBA,EAAAA,EAAC,EAAA,IAAA,SAAO,CAAA;CACRA,EAAAA,EAAC,EAAA,IAAA,SAAY,CAAA;CACb;AACD,GCdUU,KAAsB,EAAEC,oBAAqC;CACxE,IAAM,EAAA,MAAA,GAAA,GAAA,MAAQC,EAAAA,GACRC,IAAWZ,EAAAA,GACXa,IAAYL,EAAAA,GAEZM,UAAwB;EAC5BF,EAAS;GACPG,IAAI;GACJC,QAAQ;IAAEH;IAAWI,cAAcP,EAAWQ;GAAG;EACnD,CAAA;CACF;CAEA,OACE,gBAAChB,GAAAA;EAAgCiB,eAAa,mBAAmBT,EAAWQ;EAAME,SAASN;;GACzF,gBAACb,GAAAA,EACC,UAAA,gBAACoB,OAAAA;IAAIC,WAAU;IACZhB,UAAAA,CAAAA,EAAcI,EAAWa,OAAO,CAACC,MACjClB,EAAcI,EAAWa,OAAO,CAACE,IAAAA;;GAGtC,gBAACxB,GAAAA,EAAcS,UAAAA,EAAWgB,oBAAAA,CAAAA;GAC1B,gBAACzB,GAAAA,EAAcS,UAAAA,EAAWiB,oBAAoB,IAAA,CAAA;GAC9C,gBAAC1B,GAAAA,EAAcS,UAAAA,EAAWkB,oBAAAA,CAAAA;GAC1B,gBAAC3B,GAAAA,EAAcS,UAAAA,EAAWmB,eAAe,IAAA,CAAA;GACzC,gBAAC5B,GAAAA;IAAamB,UAAUU,MAAMA,EAAEC,gBAAe;IAAIT,WAAU;IAC3D,UAAA,gBAACf,GAAAA;KAAmCG;KACjC,WAAC,EAAEsB,oBAAiBC,sBAAmBC,sBAAmBC,4BACzD,gBAAChC,GAAAA,EACC,UAAA,gBAACE,GAAAA,EAAAA,UAAAA;MACC,gBAACD,GAAAA;OAAcgC,OAAOC,EAAAA,EAAC,EAAA,IAAA,SAAQ,CAAA;OAAGjB,SAASN;;MAC3C,gBAACV,GAAAA;OAAcgC,OAAOC,EAAAA,EAAC,EAAA,IAAA,SAAiB,CAAA;OAAGjB,SAASY;;MACpD,gBAAC5B,GAAAA;OAAcgC,OAAOC,EAAAA,EAAC,EAAA,IAAA,SAAO,CAAA;OAAGjB,SAASa;;MAC1C,gBAAC7B,GAAAA;OAAcgC,OAAOC,EAAAA,EAAC,EAAA,IAAA,SAAO,CAAA;OAAGjB,SAASc;;MAC1C,gBAAC9B,GAAAA;OAAcgC,OAAOC,EAAAA,EAAC,EAAA,IAAA,SAAQ,CAAA;OAAGjB,SAASe;;;;;;CApBrCzB,GAAAA,EAAWQ,EAAE;AA4BnC,GCtCa6B,KAA2B,EAAEC,gBAAaC,cAAWC,YAASC,eAAqC;CAC9G,IAAM,EAAA,MAAA,GAAA,GAAA,MAAQC,EAAAA,GACRC,IAAUP,EAAAA,GACVQ,IAAcD,EAAQE;CAuC5B,OArCIN,IAEA,gBAACN,GAAAA;EAAMa,WAAU;EAAOC,cAAa;EAASC,WAAU;EAASC,WAAU;EACzE,UAAA,CAAA,gBAACf,GAAAA;GAAQgB,SAAQ;GAAUC,MAAK;GAAQL,WAAU;EAClD,CAAA,GAAA,gBAAA,GAAA,EAAA,IAAA,SAAA,CAAA,CAAA;MAKFN,IAEA,gBAACP,GAAAA;EAAMa,WAAU;EAAOC,cAAa;EAASC,WAAU;EAASC,WAAU;EACxER,UAAAA,GAAOW,WAAWC,EAAAA,EAAC,EAAA,IAAA,SAA4B,CAAA;MAKlDf,EAAYO,WAAW,IAEvB,gBAACjB,GAAAA;EAASe,SAASC;EAAaE,WAAU;EAAeQ,eAAY;EACnE,UAAA,gBAACxB,GAAAA,EACC,UAAA,gBAACC,GAAAA;GAAawB,SAASX;GACrB,UAAA,CAAA,gBAACZ,GAAAA,EACC,UAAA,gBAAA,GAAA,EAAA,IAAA,SAAA,CAAA,EAAA,CAAA,GAEF,gBAACwB,KAAAA,EACC,UAAA,gBAAA,GAAA,EAAA,IAAA,SAAA,CAAA,EAAA,CAAA,CAAA;;MAYV,gBAAC5B,GAAAA;EAASe,SAASC;EACjB,UAAA,CAAA,gBAACd,GAAAA,EACEa,UAAAA,EAAQc,KAAKC,MACZ,gBAAC7B,GAAAA,EAA8B6B,UAAAA,EAARA,GAAAA,CAAAA,CAAAA,EAAAA,CAAAA,GAG1BpB,EAAYmB,KAAKE,MAChB,gBAACxB,GAAAA,EAA+ByB,YAAYD,EAAnBA,GAAAA,EAAGE,EAAE,CAAA,CAAA;;AAItC,GCrDMe,IAAY,+EACZC,IACJ,4lBACIC,MAAoBC,MAAkBH,EAAUI,KAAKD,CAAAA,KAAUF,EAAUG,KAAKD,CAAAA,GAC9EE,KAAe,iGAERC,MAA2B,EAAEC,SAAMC,iBAAuC;CACrF,IAAM,EAAA,MAAA,GAAA,GAAA,MAAQC,EAAAA,GACRC,IAAYX,EAAAA,GACZY,IAAQb,EAAUc,SAAQ,GAE1B,EAAEC,cAAW,GAAGC,MAA6BhB,EAAUiB,QAAQC,WAAWC,OAAOC,YAAY,EACjGC,iBAAiBR,EAAMI,QAAQC,WAAWI,KAAKC,WAAU,EAC3D,CAAA,GAEM,EACJC,MAAMC,IAAmB,CAAA,GACzBC,WAAWC,GACXC,OAAOC,MACL7B,EAAUiB,QAAQC,WAAWY,qBAAqBC,SAAS,EAAEC,YAAYpB,EAAU,CAAA,GAEjF,EACJY,MAAMS,IAAa,CAAA,GACnBP,WAAWQ,GACXN,OAAOO,MACLnC,EAAUiB,QAAQC,WAAWkB,eAAeL,SAAS,EAAEC,YAAYpB,EAAU,CAAA,GAE3E,EACJY,MAAMa,IAAiB,CAAA,GACvBX,WAAWY,GACXV,OAAOW,MACLvC,EAAUiB,QAAQC,WAAWsB,mBAAmBT,SAAS,EAAEC,YAAYpB,EAAU,CAAA,GAE/E6B,IAAarD,EAAEsD,OAAO;EAC1BC,qBAAqBvD,EAAEwD,OAAM;EAC7BC,YAAYzD,EAAEwD,OAAM;EACpBE,UAAU1D,EACPwD,OAAM,CAAA,CACNG,KAAI,CAAA,CACJC,IAAI,IAAIC,EAAAA,EAAC,EAAA,IAAA,SAAwC,CAAA,CAAA,CAAA,CACjDC,QAAQ7C,MAAUA,MAAU,MAAME,GAAaD,KAAKD,CAAAA,GAAQ,EAC3D8C,SAASF,EAAAA,EAAC,EAAA,IAAA,SAA+F,CAAA,EAC3G,CAAA;EACFG,aAAahE,EACVwD,OAAM,CAAA,CACNG,KAAI,CAAA,CACJC,IAAI,KAAKC,EAAAA,EAAC,EAAA,IAAA,SAA4C,CAAA,CAAA;EACzDI,qBAAqBjE,EAClBwD,OAAM,CAAA,CACNG,KAAI,CAAA,CACJG,QAAQ7C,MAAUA,MAAU,MAAMD,GAAiBC,CAAAA,GAAQ,EAC1D8C,SAASF,EAAAA,EAAC,EAAA,IAAA,SAAiF,CAAA,EAC7F,CAAA;EACFK,SAASlE,EAAEwD,OAAM;EACjBW,kBAAkBnE,EAAEwD,OAAM;CAC5B,CAAA,GAEMY,IAAOnE,EAAQ;EACnBoE,eAAe;GACbd,qBAAqB;GACrBE,YAAY;GACZC,UAAU;GACVM,aAAa;GACbC,qBAAqB;GACrBC,SAAS;GACTC,kBAAkB;EACpB;EACAG,YAAY,EACVC,UAAUlB,EACZ;EACAkB,UAAU,OAAO,EAAEtD,eAAO;GACpBU,MAEJ,MAAMC,EAAyB4C,YAAY;IACzC5B,YAAYpB;IACZiD,WAAWjD;IACX+B,qBAAqBtC,EAAMsC;IAC3B,GAAItC,EAAMwC,cAAc,EAAEA,YAAYxC,EAAMwC,WAAW;IACvD,GAAIxC,EAAMyC,YAAY,EAAEA,UAAUzC,EAAMyC,SAAS;IACjD,GAAIzC,EAAM+C,eAAe,EAAEA,aAAa/C,EAAM+C,YAAY;IAC1D,GAAI/C,EAAMgD,uBAAuB,EAAEA,qBAAqBhD,EAAMgD,oBAAoB;IAClF,GAAIhD,EAAMiD,WAAW,EAAEA,SAASjD,EAAMiD,QAAQ;IAC9C,GAAIjD,EAAMkD,oBAAoB,EAAEA,kBAAkBlD,EAAMkD,iBAAiB;GAC3E,CAAA,GACAO,EAAAA;EACF;CACF,CAAA,GAEMA,UAAc;EACd/C,MAEJyC,EAAKO,MAAK,GACV/C,EAAyB+C,MAAK,GAC9BrD,EAAAA;CACF,GAEMsD,IAAgB1E,EAASkE,EAAKS,QAAQC,MAAUA,EAAMC,OAAOb,OAAO,GACpEc,IAA2B9E,EAASkE,EAAKS,QAAQC,MAAUA,EAAMC,OAAOxB,mBAAmB,GAE3F8B,IADepC,EAAeiC,MAAMC,MAASA,EAAKC,OAAOR,CAC1CK,CAAAA,EAAcK,aAAa,CAAA,GAE1CC,KACH9C,GAAuBsB,WAAWhB,GAAiBgB,WAAWZ,GAAYY,YAC3EnC,EAAyBY,OAAOuB,WAChC;CAEF,OACE,gBAAC5D,GAAAA;EACOkB;EACNmE,MAAK;EACLC,OAAO5B,EAAAA,EAAC,EAAA,IAAA,SAAqB,CAAA;EAC7B6B,UAAUhB;EACViB,mBAAmB9B,EAAAA,EAAC,EAAA,IAAA,SAAO,CAAA;EAC3B+B,oBAAoB/B,EAAAA,EAAC,EAAA,IAAA,SAAS,CAAA;EAC9BgC,WAAWzB,EAAK0B;EAChBC,sBAAsBpE,KAAa,CAACqD;;GAEnCO,KACC,gBAAChF,GAAAA;IAAQyF,aAAa;IAAOC,SAAQ;IAAQC,WAAU;IACpDX,UAAAA;;GAIJ5D,KACC,gBAACwE,OAAAA;IAAID,WAAU;IACb,UAAA,CAAA,gBAAC5F,GAAAA,EAAQ2F,SAAQ,UAAA,CAAA,GACjB,gBAACG,QAAAA;KAAKF,WAAU;KACd,UAAA,gBAAA,GAAA,EAAA,IAAA,SAAA,CAAA;;;GAKL,CAACvE,KACA,gBAACvB,GAAAA;IACC8F,WAAU;IACVd,IAAG;IACHb,WAAW8B,MAAAA;KAETjC,AADAiC,EAAEC,eAAc,GAChBlC,EAAK0B,aAAY;IACnB;;KAEA,gBAACzF,GAAAA;MAAY6F,WAAU;MACrB,UAAA,gBAAC9B,EAAKmC,OAAK;OACTC,MAAK;OACLC,WAAWC,MACT,gBAAChG,GAAAA;QACC0E,IAAIsB,EAAMF;QACVA,MAAME,EAAMF;QACZvF,OAAOyF,EAAM5B,MAAM7D;QACnB0F,WAAW1F,MAAUyF,EAAME,aAAa,OAAO3F,KAAU,WAAWA,IAAQ,EAAA;QAC5E4F,OAAOhD,EAAAA,EAAC,EAAA,IAAA,SAAiB,CAAA;QACzBiD,UAAUjD,EAAAA,EAAC,EAAA,IAAA,SAAuD,CAAA;QAClEkD,aAAalD,EAAAA,EAAC,EAAA,IAAA,SAA2B,CAAA;QACzCmD,UAAUrF,KAAaY;QACvB0E,UAAQ;QACRC,SAAS3E;QAERF,UAAAA,EAAiB8E,KAAK,EAAE/B,OAAIoB,cAC3B,gBAAC7F,GAAAA;SAAsBM,OAAOmE;SAAIyB,OAAOL,IAAO,GAAGA,EAAK,IAAIpB,EAAG,KAAKA;QAAjDA,GAAAA,CAAAA,CAAAA;;;;KAM7B,gBAAC/E,GAAAA;MAAY6F,WAAU;MACrB,UAAA,gBAAC9B,EAAKmC,OAAK;OACTC,MAAK;OACLC,WAAWC,MACT,gBAAChG,GAAAA;QACC0E,IAAIsB,EAAMF;QACVA,MAAME,EAAMF;QACZvF,OAAOyF,EAAM5B,MAAM7D;QACnB0F,WAAW1F,MAAUyF,EAAME,aAAa,OAAO3F,KAAU,WAAWA,IAAQ,EAAA;QAC5E4F,OAAOhD,EAAAA,EAAC,EAAA,IAAA,SAAW,CAAA;QACnBiD,UAAUjD,EAAAA,EAAC,EAAA,IAAA,SAAqB,CAAA;QAChCmD,UAAUrF,KAAamB;QACvBoE,SAASpE;QAERD,UAAAA,EAAWsE,KAAK,EAAE/B,OAAIoB,cACrB,gBAAC7F,GAAAA;SAAsBM,OAAOuF;SAAMK,OAAOL;QAAxBpB,GAAAA,CAAAA,CAAAA;;;;KAM7B,gBAAC/E,GAAAA;MAAY6F,WAAU;MACrB,UAAA,gBAAC9B,EAAKmC,OAAK;OACTC,MAAK;OACLC,WAAWC,MACT,gBAACjG,GAAAA;QACC2E,IAAIsB,EAAMF;QACVA,MAAME,EAAMF;QACZvF,OAAOyF,EAAM5B,MAAM7D;QACnBmG,QAAQV,EAAMW;QACdV,WAAWN,MAAMK,EAAME,aAAaP,EAAEiB,OAAOrG,KAAK;QAClD4F,OAAOhD,EAAAA,EAAC,EAAA,IAAA,SAAS,CAAA;QACjBkD,aAAalD,EAAAA,EAAC,EAAA,IAAA,SAAe,CAAA;QAC7BiD,UAAUjD,EAAAA,EAAC,EAAA,IAAA,SAA+H,CAAA;QAC1I0D,WAAWb,EAAM5B,MAAM0C,KAAKC,OAAON,KAAKd,MAAMA,GAAGtC,OAAAA,CAAAA,CAAS2D,KAAK,IAAA;QAC/DV,UAAUrF;;;;KAKlB,gBAACtB,GAAAA;MAAY6F,WAAU;MACrB,UAAA,gBAAC9B,EAAKmC,OAAK;OACTC,MAAK;OACLC,WAAWC,MACT,gBAAClG,GAAAA;QACC4E,IAAIsB,EAAMF;QACVA,MAAME,EAAMF;QACZvF,OAAOyF,EAAM5B,MAAM7D;QACnBmG,QAAQV,EAAMW;QACdV,WAAWN,MAAMK,EAAME,aAAaP,EAAEiB,OAAOrG,KAAK;QAClD8F,aAAalD,EAAAA,EAAC,EAAA,IAAA,SAAY,CAAA;QAC1B0D,WAAWb,EAAM5B,MAAM0C,KAAKC,OAAON,KAAKd,MAAMA,GAAGtC,OAAAA,CAAAA,CAAS2D,KAAK,IAAA;QAC/DV,UAAUrF;;;;KAKlB,gBAACtB,GAAAA;MAAY6F,WAAU;MACrB,UAAA,gBAAC9B,EAAKmC,OAAK;OACTC,MAAK;OACLC,WAAWC,MACT,gBAACjG,GAAAA;QACC2E,IAAIsB,EAAMF;QACVA,MAAME,EAAMF;QACZvF,OAAOyF,EAAM5B,MAAM7D;QACnBmG,QAAQV,EAAMW;QACdV,WAAWN,MAAMK,EAAME,aAAaP,EAAEiB,OAAOrG,KAAK;QAClD4F,OAAOhD,EAAAA,EAAC,EAAA,IAAA,SAAoB,CAAA;QAC5BkD,aAAalD,EAAAA,EAAC,EAAA,IAAA,SAAoB,CAAA;QAClCiD,UAAUjD,EAAAA,EAAC,EAAA,IAAA,SAAsD,CAAA;QACjE0D,WAAWb,EAAM5B,MAAM0C,KAAKC,OAAON,KAAKd,MAAMA,GAAGtC,OAAAA,CAAAA,CAAS2D,KAAK,IAAA;QAC/DV,UAAUrF;;;;KAKlB,gBAACtB,GAAAA;MAAY6F,WAAU;MACrB,UAAA,gBAAC9B,EAAKmC,OAAK;OACTC,MAAK;OACLC,WAAWC,MACT,gBAAChG,GAAAA;QACC0E,IAAIsB,EAAMF;QACVA,MAAME,EAAMF;QACZvF,OAAOyF,EAAM5B,MAAM7D;QACnB0F,WAAW1F,MAAAA;SACT,IAAM0G,IAAS,OAAO1G,KAAU,WAAWA,IAAQ;SACnDyF,EAAME,aAAae,CAAAA;SAEnB,IAAME,IADO5E,EAAeiC,MAAM0C,MAAMA,EAAExC,OAAOuC,CACrCxC,CAAAA,EAAMG,aAAa,CAAA;SAC/BlB,EAAK0D,cAAc,oBAAoBD,EAAIE,WAAW,IAAIF,EAAI,EAAE,CAACG,aAAa,EAAA;QAChF;QACAnB,OAAOhD,EAAAA,EAAC,EAAA,IAAA,SAAQ,CAAA;QAChBkD,aAAalD,EAAAA,EAAC,EAAA,IAAA,SAAyB,CAAA;QACvC0D,WAAWb,EAAM5B,MAAM0C,KAAKC,OAAON,KAAKd,MAAMA,GAAGtC,OAAAA,CAAAA,CAAS2D,KAAK,IAAA;QAC/DV,UAAUrF,KAAauB;QACvBgE,SAAShE;QAERD,UAAAA,EAAekE,KAAKhC,MACnB,gBAACxE,GAAAA;SAECM,OAAOkE,EAAKC;SACZyB,OAAO1B,EAAKqB,OAAO,GAAGrB,EAAKqB,KAAK,IAAIrB,EAAKC,GAAG,KAAKD,EAAKC;QAFjDD,GAAAA,EAAKC,EAAE,CAAA;;;;KASxB,gBAAC/E,GAAAA,EACC,UAAA,gBAAC+D,EAAKmC,OAAK;MACTC,MAAK;MACLC,WAAWC,MACT,gBAAChG,GAAAA;OACC0E,IAAIsB,EAAMF;OACVA,MAAME,EAAMF;OACZvF,OAAOyF,EAAM5B,MAAM7D;OACnBmG,QAAQV,EAAMW;OACdV,WAAW1F,MAAUyF,EAAME,aAAa,OAAO3F,KAAU,WAAWA,IAAQ,EAAA;OAC5E4F,OAAOhD,EAAAA,EAAC,EAAA,IAAA,SAAiB,CAAA;OACzBkD,aAAalD,EAAAA,EAAC,EAAA,IAAA,SAA0B,CAAA;OACxCiD,UAAUjD,EAAAA,EAAC,EAAA,IAAA,SAAoG,CAAA;OAC/G0D,WAAWb,EAAM5B,MAAM0C,KAAKC,OAAON,KAAKd,MAAMA,GAAGtC,OAAAA,CAAAA,CAAS2D,KAAK,IAAA;OAC/DV,UAAUrF,KAAa0D,EAAa0C,WAAW;OAE9C1C,UAAAA,EAAa8B,KAAK,EAAEa,oBACnB,gBAACrH,GAAAA;QAA8BM,OAAO+G;QAAYnB,OAAOmB;OAAtCA,GAAAA,CAAAA,CAAAA;;;;;;;AAUvC,GCrTaC,KAAuBC,MAAAA;CAClC,IAAMC,IAA4B,CAAA;CAOlC,OAJID,EAAaE,UACfD,EAAQE,KAAK;EAAEC,MAAM;EAAUC,OAAOL,EAAaE;CAAO,CAAA,GAGrDD;AACT,GAKaK,MACXC,GACAC,MAAAA;CAEA,IAAMC,IAAiC,CAAC;CAExC,IAAI,CAACF,GAAiBG,QAAQ,OAAOD;CAGrC,IAAME,IAAeJ,EAClBK,QAAQC,MAAO,CAACA,EAAGC,QAAQ,CAAA,CAC3BC,QACEC,GAAKH,OACCG,EAAIH,EAAGT,UAAOY,EAAIH,EAAGT,QAAQ,CAAA,IAClCY,EAAIH,EAAGT,KAAK,CAACD,KAAKU,EAAGR,KAAK,GACnBW,IAET,CAAC,CAAA;CAcL,OAVAC,OAAOC,QAAQP,CAAAA,CAAAA,CAAcQ,SAAS,CAACC,GAAYC,OAAO;EAGxD,AAFkBb,EAAkBe,MAAMC,MAAMA,EAAEJ,eAAeA,CAE7DE,CAAAA,EAAWG,sBAAsBJ,EAAOX,SAAS,IACnDD,EAAOW,KAAc,MAAMC,EAAOK,KAAK,GAAA,MAEvCjB,EAAOW,KAAcC,EAAO;CAEhC,CAAA,GAEOZ;AACT,GAQakB,MACXC,GACAC,GACArB,MAEwBoB,EAAQG,MAAMP,MAAMA,EAAEpB,SAASyB,EAASzB,QAAQoB,EAAEnB,UAAUwB,EAASxB,KACzFyB,IAAwBF,IAENpB,EAAkBe,MAAMC,MAAMA,EAAEJ,eAAeS,EAASzB,IAAI,CAAA,EAAGqB,qBAC9D,CAAIG,GAAAA,GAASC,CAAS,IAAG,CAAID,GAAAA,EAAQhB,QAAQY,MAAMA,EAAEpB,SAASyB,EAASzB,IAAI,GAAGyB,CAAS,GAMnGI,MACX1B,GACAC,GACA0B,MAAAA;CAMA,IAAMC,IAAqC;EACzCC,QAAQF,EAAWE;EACnBC,QAAQH,EAAWG;EACnBC,eAAeJ,EAAWI;CAC5B;CAEA,IAAI,CAAC/B,GAAiBG,QAAQ,OAAOyB;CAErC,IAAMxB,IAAeJ,EAClBK,QAAQC,MAAO,CAACA,EAAGC,QAAQ,CAAA,CAC3BC,QACEC,GAAKH,OACCG,EAAIH,EAAGT,UAAOY,EAAIH,EAAGT,QAAQ,CAAA,IAClCY,EAAIH,EAAGT,KAAK,CAACD,KAAKU,EAAGR,KAAK,GACnBW,IAET,CAAC,CAAA;CAcL,OAXAC,OAAOC,QAAQP,CAAAA,CAAAA,CAAcQ,SAAS,CAACC,GAAYC,OAAO;EAGxD,AAFkBb,EAAkBe,MAAMC,MAAMA,EAAEJ,eAAeA,CAE7DE,CAAAA,EAAWG,sBAAsBJ,EAAOX,SAAS,IAEjDyB,EAAqCf,KAAc,MAAMC,EAAOK,KAAK,GAAA,MAErES,EAAqCf,KAAcC,EAAO;CAEhE,CAAA,GAEOc;AACT,GCzGM0B,IAAmB,oBACnBC,IAAmB,OAgBZC,WAAkB;CAC7B,IAAM,EAAA,MAAA,GAAA,GAAA,MAAQC,EAAAA,GACRC,IAAWvB,EAAAA,GACXwB,IAAevB,EAAU,EAAEwB,QAAQ,GAAM,CAAA,GACzCC,IAAYd,EAAAA,GACZ,CAACe,GAAmBC,KAAuBjB,EAAS,EAAA,GACpD,CAACkB,GAAiBC,KAAsBjC,EAAS2B,EAAaO,UAAU,EAAA,GACxEC,IAAgBlC,EAA2BmC,KAAAA,CAAAA;CAEjDlC,cAAsBmC,aAAaF,EAAcG,OAAO,GAAG,CAAA,CAAE;CAE7D,IAAM,CAACC,GAAcC,KAAmBxC,EAA+B;EACrEyC,SAAS;GACP;IAAEC,OAAOC,EAAAA,EAAC,EAAA,IAAA,SAAiB,CAAA;IAAGC,OAAO;GAAmB;GACxD;IAAEF,OAAOC,EAAAA,EAAC,EAAA,IAAA,SAAoB,CAAA;IAAGC,OAAO;GAAsB;GAC9D;IAAEF,OAAOC,EAAAA,EAAC,EAAA,IAAA,SAAoB,CAAA;IAAGC,OAAO;GAAsB;GAC9D;IAAEF,OAAOC,EAAAA,EAAC,EAAA,IAAA,SAAG,CAAA;IAAGC,OAAO;GAAK;GAC5B;IAAEF,OAAOC,EAAAA,EAAC,EAAA,IAAA,SAAU,CAAA;IAAGC,OAAO;GAAY;GAC1C;IAAEF,OAAOC,EAAAA,EAAC,EAAA,IAAA,SAAO,CAAA;IAAGC,OAAO;GAAS;GACpC;IAAEF,OAAOC,EAAAA,EAAC,EAAA,IAAA,SAAU,CAAA;IAAGC,OAAO;GAAY;GAC1C;IAAEF,OAAOC,EAAAA,EAAC,EAAA,IAAA,SAAW,CAAA;IAAGC,OAAO;GAAa;EAC7C;EACDC,QAAQlB,EAAakB,UAAUvB;EAC/BwB,eAAenB,EAAamB,iBAAiBvB;CAC/C,CAAA,GAEM,CAACwB,GAAgBC,KAAqBhD,EAAyB;EACnEiD,SAAS,CACP;GACEC,aAAaP,EAAAA,EAAC,EAAA,IAAA,SAAO,CAAA;GACrBQ,YAAY;GACZC,QAAQ;IAAC;IAAU;IAAQ;GAAQ;GACnCC,oBAAoB;EACtB,CACD;EACDC,iBAAiBpC,EAAoBS,CAAAA;CACvC,CAAA,GAEM4B,IAAa5B,EAAaO,UAAU,IAEpC,EAAEsB,MAAMC,MAAgB5C,EAAU6C,QAAQC,QAAQC,SACtD;EACEC,YAAYhC;EACZiC,YAAY,CAAC,4BAA6B;CAC5C,GACA,EACEC,SAAS,CAACC,QAAgB,EACxBA,aACF,GACF,CAAA;CAGF9D,QAAU;EACR,IAAM+D,IAAa/C,EAAoBS,CAAAA,GACjCuC,IAAYvC,EAAakB,UAAUvB,GACnC6C,IAAmBxC,EAAamB,iBAAiBvB,GACjD6C,IAAgBzC,EAAaO,UAAU;EAI7CD,AAFAe,GAAmBqB,OAAU;GAAE,GAAGA;GAAMf,iBAAiBW;EAAW,EAAA,GACpEzB,GAAiB6B,OAAU;GAAE,GAAGA;GAAMxB,QAAQqB;GAAWpB,eAAeqB;EAAiB,EAAA,GACzFlC,EAAmBmC,CAAAA;CACrB,GAAG;EAACzC,EAAa2C;EAAQ3C,EAAakB;EAAQlB,EAAamB;EAAenB,EAAaO;CAAO,CAAA;CAE9F,IAAMqC,KAAoBC,MAAAA;EACxB,IAAMC,IAAiC;GACrChC,SAAS+B,EAAgB/B;GACzBI,QAAQ2B,EAAgB3B,QAAQ6B,SAAAA,KAAcpD;GAC9CwB,eAAe0B,EAAgB1B,iBAAiBvB;EAClD;EAEAG,AADAc,EAAgBiC,CAAAA,GAChB/C,EAAS;GACPQ,SAAUmC,OAAmC;IAC3C,GAAGA;IACHxB,QAAQ4B,EAAS5B;IACjBC,eAAe2B,EAAS3B;GAC1B;GACA6B,SAAS;EACX,CAAA;CACF,GAEMC,KAAsBC,MAAAA;EAE1BnD,AADAsB,EAAkB6B,CAAAA,GAClBnD,EAAS;GACPQ,SAAUmC,MACRjD,GAAqByD,EAAkBvB,mBAAmB,CAAA,GAAIuB,EAAkB5B,SAAS;IACvFf,QAAQmC,EAAKnC;IACbW,QAAQwB,EAAKxB;IACbC,eAAeuB,EAAKvB;GACtB,CAAA;GACF6B,SAAS;EACX,CAAA;CACF,GAEMG,KAAsBC,GAAcJ,IAAU,OAAK;EACvDjD,EAAS;GACPQ,SAAUmC,OAAmC;IAC3C,GAAGA;IACHnC,QAAQ6C,KAAQ3C,KAAAA;GAClB;GACAuC;EACF,CAAA;CACF,GAEM,EACJnB,MAAMwB,IAAc,CAAA,GACpBC,cACAC,YACAC,aACEtE,EAAU6C,QAAQ0B,WAAWC,KAAKzB,SACpC;EACEC,YAAYhC;EACZyD,UAAU/C,EAAaM;EACvB0C,UAAUhD,EAAaO;EACvB,GAAG3B,GAAkB4B,EAAeO,mBAAmB,CAAA,GAAIP,EAAeE,OAAO;EACjF,GAAIM,IAAa,EAAEA,cAAW,IAAI,CAAC;CACrC,GACA,EACEiC,kBAAkBnB,MAASA,EAC7B,CAAA;CAmBF,OAhBIY,KAAa,CAACD,EAAYS,SAE1B,gBAACnF,GAAAA;EAAMoF,WAAU;EAAOC,cAAa;EAASC,WAAU;EAASC,WAAU;EACzE,UAAA,gBAAA,GAAA,EAAA,IAAA,SAAA,CAAA;MAKFX,KAAW,CAACF,EAAYS,SAExB,gBAACnF,GAAAA;EAAMoF,WAAU;EAAOC,cAAa;EAASC,WAAU;EAASC,WAAU;EACxEV,UAAAA,GAAOW,WAAWnD,EAAAA,EAAC,EAAA,IAAA,SAA4B,CAAA;MAMpD,gBAACoD,OAAAA;EAAIL,WAAU;;GAEZR,KAAWF,EAAYS,SAAS,KAC/B,gBAAChF,GAAAA;IAAQuF,SAAQ;IAAQN,WAAU;IAChCP,UAAAA,GAAOW,WAAWnD,EAAAA,EAAC,EAAA,IAAA,SAAqD,CAAA;;GAK7E,gBAACrC,GAAAA;IAAMqF,cAAa;IAAMC,WAAU;IAASK,KAAI;IAAIP,WAAU;IAC7D,UAAA,gBAACpF,GAAAA;KAAM2F,KAAI;KACT,UAAA,CAAA,gBAACvF,GAAAA;MACC+B,SAASF,EAAaE;MACtBI,QAAQN,EAAaM;MACrBC,eAAeP,EAAaO,iBAAiB;MAC7CoD,iBAAgB;MAChBC,iBAAiBC,MACf7B,EAAiB;OAAE,GAAGhC;OAAcM,QAAQuD;OAAGtD,eAAeP,EAAaO;MAAc,CAAA;MAE3FuD,wBAAwBC,MAAQ/B,EAAiB;OAAE,GAAGhC;OAAcO,eAAewD;MAAI,CAAA;KAExF7C,CAAAA,GAAAA,GAAaO,aACZ,gBAAC3D,GAAAA;MAAOkG,SAASxE;MAAqBiE,SAAQ;MAAUN,WAAU;MAChE,UAAA,gBAAA,GAAA,EAAA,IAAA,SAAA,CAAA;;;;GAOR,gBAACnF,GAAAA,EACC,UAAA,gBAACD,GAAAA;IAAMuF,WAAU;IAAWI,KAAI;IAC9B,UAAA,CAAA,gBAAC3F,GAAAA;KAAMqF,cAAa;KAAUC,WAAU;KACtC,UAAA,CAAA,gBAAChF,GAAAA;MACCqC,SAASF,EAAeE;MACxBiD,iBAAgB;MAChBM,mBAAkB;MAClBC,WAAWC,MAAAA;OACT,IAAMC,IAActF,GAClB0B,EAAeO,mBAAmB,CAAA,GAClCoD,GACA3D,EAAeE,OAAO;OAEpB0D,OAAiB5D,EAAeO,mBAAmB,CAAA,MACvDsB,EAAmB;QAAE,GAAG7B;QAAgBO,iBAAiBqD;OAAY,CAAA;MACvE;KAEF,CAAA,GAAA,gBAACnG,GAAAA;MACCoG,aAAajE,EAAAA,EAAC,EAAA,IAAA,SAAuB,CAAA;MACrCkE,eAAY;MACZjE,OAAOZ;MACP8E,UAAUC,MAAAA;OACR,IAAMX,IAAIW,EAAEC,cAAcpE;OAG1BT,AAFAF,EAAmBmE,CAAAA,GACnB/D,aAAaF,EAAcG,OAAO,GAClCH,EAAcG,UAAU2E,OAAOC,iBAAiBpC,EAAmBsB,GAAG,EAAA,GAAO,GAAA;MAC/E;MACAe,WAAWf,MAAAA;OAETtB,AADAzC,aAAaF,EAAcG,OAAO,GAClCwC,EAAmB,OAAOsB,KAAM,WAAWA,IAAI,IAAI,EAAA;MACrD;MACAgB,eAAS;OAGPtC,AAFAzC,aAAaF,EAAcG,OAAO,GAClCL,EAAmB,EAAA,GACnB6C,EAAmB,IAAI,EAAA;MACzB;;IAGH/B,CAAAA,GAAAA,EAAeO,mBAAmBP,EAAeO,gBAAgBmC,SAAS,KACzE,gBAAC9E,GAAAA;KACC2C,iBAAiBP,EAAeO;KAChC+D,WAAWC,MACT1C,EAAmB;MACjB,GAAG7B;MACHO,kBAAkBP,EAAeO,mBAAmB,CAAA,EAAA,CAAIiE,QACrDC,MAAQA,EAAEC,SAASH,EAAeG,QAAQD,EAAE5E,UAAU0E,EAAe1E,KAAI;KAE9E,CAAA;KAEFwE,eAAexC,EAAmB;MAAE,GAAG7B;MAAgBO,iBAAiB,CAAA;KAAG,CAAA;;;GAMnF,gBAACtC,GAAAA;IACcgE;IACFC;IACXC,SAASA,KAAW,CAACF,EAAYS;IAC1BN;;GAGRrD,KAAqB,gBAACb,IAAAA;IAAwByG,MAAM5F;IAAmB6F,SAAS5F;;;;AAGvF;;;AC7NA,SAASgG,KAAAA;CACP,IAAM,EAAA,MAAA,GAAA,GAAA,MAAQH,EAAAA;CACd,OACE,gBAAA,GAAA,EAAA,UAAA,CACE,gBAAC,GAAA,EAAgBI,UAAAA,EAAAA,EAAC,EAAA,IAAA,SAAA,CAAA,EAAA,CAAA,GAClB,gBAAC,IAAA,CAAA,CAAA,CAAA,EAAA,CAAA;AAGP"}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { n as e } from "./AuthProvider-
|
|
1
|
+
import { n as e } from "./AuthProvider-BS5OVv8n.mjs";
|
|
2
2
|
import "./useProjectId-DBc5lpoU.mjs";
|
|
3
3
|
import { useParams as t } from "@tanstack/react-router";
|
|
4
4
|
//#region src/client/hooks/useDomainId.ts
|
|
@@ -19,4 +19,4 @@ function r() {
|
|
|
19
19
|
//#endregion
|
|
20
20
|
export { n, r as t };
|
|
21
21
|
|
|
22
|
-
//# sourceMappingURL=hooks-
|
|
22
|
+
//# sourceMappingURL=hooks-LutR2Yg3.mjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"hooks-
|
|
1
|
+
{"version":3,"file":"hooks-LutR2Yg3.mjs","names":["useAuth","useDomainId","user","domainId","domain","id","Error","useParams","useAuth","useScope","auth","projectId","strict","userDomainId","user","domain","id"],"sources":["../../src/client/hooks/useDomainId.ts","../../src/client/hooks/useScope.ts"],"sourcesContent":["import { useAuth } from \"@/client/store/AuthProvider\"\n\n/**\n * Get the current user's domain ID from the authentication context.\n *\n * This hook provides access to the domain ID of the currently authenticated user.\n * The domain ID is obtained from the user's session, not from URL parameters.\n *\n * @throws {Error} If user is not authenticated or domain ID is not available\n * @returns {string} The current domain ID from the user's session\n *\n * @example\n * ```tsx\n * function UsersList() {\n * const domainId = useDomainId()\n *\n * const { data } = trpc.identity.users.list.useQuery({\n * domain_id: domainId\n * })\n * }\n * ```\n */\nexport function useDomainId(): string {\n const { user } = useAuth()\n\n const domainId = user?.domain?.id\n\n if (!domainId) {\n throw new Error(\n \"useDomainId() requires an authenticated user with a domain. \" +\n \"This is likely an authentication error. \" +\n \"Ensure the user is logged in and has a domain assigned.\"\n )\n }\n\n return domainId\n}\n","import { useParams } from \"@tanstack/react-router\"\nimport { useAuth } from \"../store/AuthProvider\"\n\nexport function useScope() {\n const auth = useAuth()\n const { projectId } = useParams({ strict: false })\n\n const userDomainId = auth.user?.domain?.id\n return {\n userDomainId,\n projectId,\n }\n}\n"],"mappings":";;;;AAsBA,SAAgBC,IAAAA;CACd,IAAM,EAAEC,YAASF,EAAAA,GAEXG,IAAWD,GAAME,QAAQC;CAE/B,IAAI,CAACF,GACH,MAAUG,MACR,6JAEE;CAIN,OAAOH;AACT;;;ACjCA,SAAgBM,IAAAA;CACd,IAAMC,IAAOF,EAAAA,GACP,EAAEG,iBAAcJ,EAAU,EAAEK,QAAQ,GAAM,CAAA;CAGhD,OAAO;EACLC,cAFmBH,EAAKI,MAAMC,QAAQC;EAGtCL;CACF;AACF"}
|