@cobaltcore-dev/aurora 0.4.0 → 0.5.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/README.md +73 -77
- package/dist/client/AuroraApp.d.ts +15 -0
- package/dist/client/{AuthProvider-D-5Jpa6F.mjs → AuthProvider-Co4d0WzB.mjs} +3 -3
- package/dist/client/{AuthProvider-D-5Jpa6F.mjs.map → AuthProvider-Co4d0WzB.mjs.map} +1 -1
- package/dist/client/{ContentHeader-BXZoN3B9.mjs → ContentHeader-xQVhO2yT.mjs} +20 -20
- package/dist/client/{ContentHeader-BXZoN3B9.mjs.map → ContentHeader-xQVhO2yT.mjs.map} +1 -1
- package/dist/client/{DeleteFlavorModal-BusYn32r.mjs → DeleteFlavorModal-CHTUZ3YV.mjs} +211 -202
- package/dist/client/DeleteFlavorModal-CHTUZ3YV.mjs.map +1 -0
- package/dist/client/{EditSecurityGroupModal-DK3WYikA.mjs → EditSecurityGroupModal-CWHHx2Xk.mjs} +22 -22
- package/dist/client/{EditSecurityGroupModal-DK3WYikA.mjs.map → EditSecurityGroupModal-CWHHx2Xk.mjs.map} +1 -1
- package/dist/client/{FiltersInput-OVeIJzIo.mjs → FiltersInput-UKJpNFdr.mjs} +10 -10
- package/dist/client/{FiltersInput-OVeIJzIo.mjs.map → FiltersInput-UKJpNFdr.mjs.map} +1 -1
- package/dist/client/{FloatingIpActionModals-Dok7fJss.mjs → FloatingIpActionModals-caXn6bYo.mjs} +54 -54
- package/dist/client/{FloatingIpActionModals-Dok7fJss.mjs.map → FloatingIpActionModals-caXn6bYo.mjs.map} +1 -1
- package/dist/client/{ImageToastNotifications-BG9LPnXf.mjs → ImageToastNotifications-BWimIzu_.mjs} +227 -227
- package/dist/client/{ImageToastNotifications-BG9LPnXf.mjs.map → ImageToastNotifications-BWimIzu_.mjs.map} +1 -1
- package/dist/client/{RouteError-pDEWC_k7.mjs → RouteError-CUj_m3gu.mjs} +6 -6
- package/dist/client/{RouteError-pDEWC_k7.mjs.map → RouteError-CUj_m3gu.mjs.map} +1 -1
- package/dist/client/{SortInput-DXWSqSny.mjs → SortInput-GQlQBlAj.mjs} +6 -6
- package/dist/client/{SortInput-DXWSqSny.mjs.map → SortInput-GQlQBlAj.mjs.map} +1 -1
- package/dist/client/{_auth-CJj1Cnbm.mjs → _auth-DXJkv9QO.mjs} +3 -3
- package/dist/client/{_auth-CJj1Cnbm.mjs.map → _auth-DXJkv9QO.mjs.map} +1 -1
- package/dist/client/_flavorId-C5dc1N_j.mjs +194 -0
- package/dist/client/_flavorId-C5dc1N_j.mjs.map +1 -0
- package/dist/client/{_flavorId-BoNcxYmF.mjs → _flavorId-sUWG0xuy.mjs} +15 -15
- package/dist/client/_flavorId-sUWG0xuy.mjs.map +1 -0
- package/dist/client/{_floatingIpId-DF_BSJN6.mjs → _floatingIpId-COK_TBrz2.mjs} +42 -42
- package/dist/client/_floatingIpId-COK_TBrz2.mjs.map +1 -0
- package/dist/client/{_floatingIpId-D33bOEmH.mjs → _floatingIpId-CT4y-60o.mjs} +3 -3
- package/dist/client/{_floatingIpId-D33bOEmH.mjs.map → _floatingIpId-CT4y-60o.mjs.map} +1 -1
- package/dist/client/_imageId-n3RcnhAR.mjs +534 -0
- package/dist/client/_imageId-n3RcnhAR.mjs.map +1 -0
- package/dist/client/{_pcaId-CbBhBrX1.mjs → _pcaId-B-f_6kqs.mjs} +99 -99
- package/dist/client/{_pcaId-CbBhBrX1.mjs.map → _pcaId-B-f_6kqs.mjs.map} +1 -1
- package/dist/client/{_pcaId-BYCoeK6_.mjs → _pcaId-ChnM_t-9.mjs} +3 -3
- package/dist/client/{_pcaId-BYCoeK6_.mjs.map → _pcaId-ChnM_t-9.mjs.map} +1 -1
- package/dist/client/_projectId-26bw-_rm.mjs +46 -0
- package/dist/client/_projectId-26bw-_rm.mjs.map +1 -0
- package/dist/client/{_projectId-BwLMEMGC.mjs → _projectId-BK9UqeYw.mjs} +14 -14
- package/dist/client/{_projectId-BwLMEMGC.mjs.map → _projectId-BK9UqeYw.mjs.map} +1 -1
- package/dist/client/{_projectId-D35MN1kY.mjs → _projectId-CCtpAQ8m.mjs} +78 -95
- package/dist/client/_projectId-CCtpAQ8m.mjs.map +1 -0
- package/dist/client/{_projectId-OW2xkK43.mjs → _projectId-Dhb4AyBD.mjs} +3 -3
- package/dist/client/{_projectId-OW2xkK43.mjs.map → _projectId-Dhb4AyBD.mjs.map} +1 -1
- package/dist/client/{_securityGroupId-B-Z-CzLp.mjs → _securityGroupId-CR1mKICQ.mjs} +3 -3
- package/dist/client/{_securityGroupId-B-Z-CzLp.mjs.map → _securityGroupId-CR1mKICQ.mjs.map} +1 -1
- package/dist/client/{_securityGroupId-B1bOYRbX.mjs → _securityGroupId-DroYG6cA.mjs} +254 -255
- package/dist/client/{_securityGroupId-B1bOYRbX.mjs.map → _securityGroupId-DroYG6cA.mjs.map} +1 -1
- package/dist/client/about-969pIiZ9.mjs +92 -0
- package/dist/client/{about-DLn1ShhF.mjs.map → about-969pIiZ9.mjs.map} +1 -1
- package/dist/client/aurora-DDzsst74.mjs +19 -0
- package/dist/client/{aurora-CRcxVUCo.mjs.map → aurora-DDzsst74.mjs.map} +1 -1
- package/dist/client/{build-BJDfnAyi.mjs → build-DracvfrJ.mjs} +5 -5
- package/dist/client/{build-BJDfnAyi.mjs.map → build-DracvfrJ.mjs.map} +1 -1
- package/dist/client/{buildFilterParams-TeyosGyK.mjs → buildFilterParams-DoZzMKX9.mjs} +1 -1
- package/dist/client/{buildFilterParams-TeyosGyK.mjs.map → buildFilterParams-DoZzMKX9.mjs.map} +1 -1
- package/dist/client/{cn-C3laVXMm.mjs → cn-DM4Cy3jv.mjs} +1 -1
- package/dist/client/{cn-C3laVXMm.mjs.map → cn-DM4Cy3jv.mjs.map} +1 -1
- package/dist/client/{constants-B-P2r5F1.mjs → constants-4lVQXort.mjs} +22 -22
- package/dist/client/{constants-B-P2r5F1.mjs.map → constants-4lVQXort.mjs.map} +1 -1
- package/dist/client/{containers-BjWqjNOx.mjs → containers-DGY2hoWw.mjs} +3 -3
- package/dist/client/{containers-BjWqjNOx.mjs.map → containers-DGY2hoWw.mjs.map} +1 -1
- package/dist/client/containers-ZMFTRaQL.mjs +3277 -0
- package/dist/client/containers-ZMFTRaQL.mjs.map +1 -0
- package/dist/client/{containers-DsRWc1L5.mjs → containers-xfsYgRyf.mjs} +2 -2
- package/dist/client/{containers-DsRWc1L5.mjs.map → containers-xfsYgRyf.mjs.map} +1 -1
- package/dist/client/{flavors-D8oElC2K.mjs → flavors-C4GtoybP.mjs} +2 -2
- package/dist/client/{flavors-D8oElC2K.mjs.map → flavors-C4GtoybP.mjs.map} +1 -1
- package/dist/client/{flavors-qvgPSI7J.mjs → flavors-CpirO_nr.mjs} +167 -148
- package/dist/client/flavors-CpirO_nr.mjs.map +1 -0
- package/dist/client/{flavors-BXPYAFyQ.mjs → flavors-DWMZ6TuJ.mjs} +2 -2
- package/dist/client/{flavors-BXPYAFyQ.mjs.map → flavors-DWMZ6TuJ.mjs.map} +1 -1
- package/dist/client/{floatingips-Fa6ocNUu.mjs → floatingips-BUf_oLRl.mjs} +74 -75
- package/dist/client/{floatingips-Fa6ocNUu.mjs.map → floatingips-BUf_oLRl.mjs.map} +1 -1
- package/dist/client/{formatBytes-tQBEnPoL.mjs → formatBytes-CZv_XyCY.mjs} +1 -1
- package/dist/client/{formatBytes-tQBEnPoL.mjs.map → formatBytes-CZv_XyCY.mjs.map} +1 -1
- package/dist/client/{helpers--JWXi40U.mjs → helpers-1PpYf-fC.mjs} +1 -1
- package/dist/client/{helpers--JWXi40U.mjs.map → helpers-1PpYf-fC.mjs.map} +1 -1
- package/dist/client/hooks-dSArr2Ca.mjs +2 -0
- package/dist/client/{images-tYfyOkX8.mjs → images-CsonlmFx.mjs} +3 -3
- package/dist/client/{images-tYfyOkX8.mjs.map → images-CsonlmFx.mjs.map} +1 -1
- package/dist/client/{images-CSFfefAu.mjs → images-Da1t5KPh.mjs} +507 -535
- package/dist/client/images-Da1t5KPh.mjs.map +1 -0
- package/dist/client/{images-DM9I8G0p.mjs → images-NBf2bV43.mjs} +2 -2
- package/dist/client/{images-DM9I8G0p.mjs.map → images-NBf2bV43.mjs.map} +1 -1
- package/dist/client/{images-CTLCY-yY.mjs → images-QnWf63uj.mjs} +2 -2
- package/dist/client/{images-CTLCY-yY.mjs.map → images-QnWf63uj.mjs.map} +1 -1
- package/dist/client/index.js +252 -258
- package/dist/client/index.js.map +1 -1
- package/dist/client/{md-BivyCkGC.mjs → md-sBiSNVSQ.mjs} +7 -7
- package/dist/client/{md-BivyCkGC.mjs.map → md-sBiSNVSQ.mjs.map} +1 -1
- package/dist/client/{network-rYLHyf15.mjs → network-DuZm76BZ.mjs} +2 -2
- package/dist/client/{network-rYLHyf15.mjs.map → network-DuZm76BZ.mjs.map} +1 -1
- package/dist/client/{objects-BciXwZ00.mjs → objects-B89dYCBq.mjs} +3 -3
- package/dist/client/{objects-BciXwZ00.mjs.map → objects-B89dYCBq.mjs.map} +1 -1
- package/dist/client/{objects-Cdew99tK.mjs → objects-CuFLUOe1.mjs} +2 -2
- package/dist/client/{objects-Cdew99tK.mjs.map → objects-CuFLUOe1.mjs.map} +1 -1
- package/dist/client/objects-H0NN_Sja.mjs +5460 -0
- package/dist/client/objects-H0NN_Sja.mjs.map +1 -0
- package/dist/client/{pca-oc7J0_Xd.mjs → pca-C-UFjicP.mjs} +42 -42
- package/dist/client/{pca-oc7J0_Xd.mjs.map → pca-C-UFjicP.mjs.map} +1 -1
- package/dist/client/{pca-COmKvp3J.mjs → pca-CtU6REww.mjs} +2 -2
- package/dist/client/{pca-COmKvp3J.mjs.map → pca-CtU6REww.mjs.map} +1 -1
- package/dist/client/{projects-Dl5XkXUP.mjs → projects-C-sjd9T5.mjs} +3 -3
- package/dist/client/{projects-Dl5XkXUP.mjs.map → projects-C-sjd9T5.mjs.map} +1 -1
- package/dist/client/{projects-BUabCzvw.mjs → projects-DNXsDnJM.mjs} +25 -21
- package/dist/client/projects-DNXsDnJM.mjs.map +1 -0
- package/dist/client/{projects-DI_L4oDw.mjs → projects-dhnQkuvV.mjs} +2 -2
- package/dist/client/{projects-DI_L4oDw.mjs.map → projects-dhnQkuvV.mjs.map} +1 -1
- package/dist/client/{projects-HoQ0gE5Y.mjs → projects-yiK0HGSA.mjs} +2 -2
- package/dist/client/{projects-HoQ0gE5Y.mjs.map → projects-yiK0HGSA.mjs.map} +1 -1
- package/dist/client/{securitygroups-BjkmHk2J.mjs → securitygroups-wHdrxZXd.mjs} +72 -73
- package/dist/client/{securitygroups-BjkmHk2J.mjs.map → securitygroups-wHdrxZXd.mjs.map} +1 -1
- package/dist/client/{trpcClient-BxguzNYF.mjs → trpcClient-BzPUgiM2.mjs} +1 -1
- package/dist/client/{trpcClient-BxguzNYF.mjs.map → trpcClient-BzPUgiM2.mjs.map} +1 -1
- package/dist/client/{useErrorTranslation-TZVwIAzq.mjs → useErrorTranslation-Dc0eE8Zt.mjs} +1 -1
- package/dist/client/{useErrorTranslation-TZVwIAzq.mjs.map → useErrorTranslation-Dc0eE8Zt.mjs.map} +1 -1
- package/dist/client/useListWithFiltering-DrgUwXef.mjs +157 -0
- package/dist/client/useListWithFiltering-DrgUwXef.mjs.map +1 -0
- package/dist/client/{useModal-DxxlilRm.mjs → useModal-DCs1OJh7.mjs} +1 -1
- package/dist/client/{useModal-DxxlilRm.mjs.map → useModal-DCs1OJh7.mjs.map} +1 -1
- package/dist/client/{useProjectId-OQv2KBbG.mjs → useProjectId-DBc5lpoU.mjs} +1 -1
- package/dist/client/{useProjectId-OQv2KBbG.mjs.map → useProjectId-DBc5lpoU.mjs.map} +1 -1
- package/dist/server/index.js +1281 -432
- package/package.json +6 -5
- package/dist/client/DeleteFlavorModal-BusYn32r.mjs.map +0 -1
- package/dist/client/ListToolbar-BojRTNbo.mjs +0 -129
- package/dist/client/ListToolbar-BojRTNbo.mjs.map +0 -1
- package/dist/client/_flavorId-BRonXvCo.mjs +0 -188
- package/dist/client/_flavorId-BRonXvCo.mjs.map +0 -1
- package/dist/client/_flavorId-BoNcxYmF.mjs.map +0 -1
- package/dist/client/_floatingIpId-DF_BSJN6.mjs.map +0 -1
- package/dist/client/_imageId-BL0I5_pv.mjs +0 -527
- package/dist/client/_imageId-BL0I5_pv.mjs.map +0 -1
- package/dist/client/_projectId-5NiasyXm.mjs +0 -26
- package/dist/client/_projectId-5NiasyXm.mjs.map +0 -1
- package/dist/client/_projectId-D35MN1kY.mjs.map +0 -1
- package/dist/client/about-DLn1ShhF.mjs +0 -92
- package/dist/client/aurora-CRcxVUCo.mjs +0 -19
- package/dist/client/containers-J7WFA18U.mjs +0 -3120
- package/dist/client/containers-J7WFA18U.mjs.map +0 -1
- package/dist/client/flavors-qvgPSI7J.mjs.map +0 -1
- package/dist/client/hooks-DEjb9d1F.mjs +0 -2
- package/dist/client/images-CSFfefAu.mjs.map +0 -1
- package/dist/client/objects-DaElrban.mjs +0 -5340
- package/dist/client/objects-DaElrban.mjs.map +0 -1
- package/dist/client/overview-BMhjFMIV.mjs +0 -15
- package/dist/client/overview-BMhjFMIV.mjs.map +0 -1
- package/dist/client/overview-BYIRj7_X.mjs +0 -15
- package/dist/client/overview-BYIRj7_X.mjs.map +0 -1
- package/dist/client/overview-DRCKNBH2.mjs +0 -15
- package/dist/client/overview-DRCKNBH2.mjs.map +0 -1
- package/dist/client/overview-urYLOVQE.mjs +0 -173
- package/dist/client/overview-urYLOVQE.mjs.map +0 -1
- package/dist/client/projects-BUabCzvw.mjs.map +0 -1
- package/dist/client/useListWithFiltering-CbhHJO4V.mjs +0 -32
- package/dist/client/useListWithFiltering-CbhHJO4V.mjs.map +0 -1
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@cobaltcore-dev/aurora",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.5.0",
|
|
4
4
|
"private": false,
|
|
5
5
|
"description": "Aurora OpenStack dashboard — server and client library",
|
|
6
6
|
"license": "Apache-2.0",
|
|
@@ -64,6 +64,7 @@
|
|
|
64
64
|
"fastify-plugin": "^5.1.0",
|
|
65
65
|
"focus-trap-react": "^12.0.0",
|
|
66
66
|
"node-fetch": "^3.3.2",
|
|
67
|
+
"prom-client": "^15.1.3",
|
|
67
68
|
"react-error-boundary": "^6.1.0",
|
|
68
69
|
"react-icons": "^5.6.0",
|
|
69
70
|
"tailwind-merge": "^3.2.0",
|
|
@@ -99,18 +100,18 @@
|
|
|
99
100
|
"prettier": "^3.4.2",
|
|
100
101
|
"tailwindcss": "^4.1.7",
|
|
101
102
|
"tsc-alias": "^1.8.16",
|
|
103
|
+
"tsconfig-paths": "^4.2.0",
|
|
102
104
|
"tsup": "^8.5.1",
|
|
103
105
|
"tsx": "^4.21.0",
|
|
104
|
-
"tsconfig-paths": "^4.2.0",
|
|
105
106
|
"typescript": "^6.0.2",
|
|
106
|
-
"vite": "^8.0.
|
|
107
|
+
"vite": "^8.0.16",
|
|
107
108
|
"vite-plugin-dts": "^5.0.1",
|
|
108
109
|
"vite-plugin-svgr": "^5.0.0",
|
|
109
110
|
"vite-tsconfig-paths": "^6.1.1",
|
|
110
111
|
"vitest": "^4.1.2",
|
|
111
112
|
"@cobaltcore-dev/aurora-config": "0.0.1",
|
|
112
|
-
"@cobaltcore-dev/
|
|
113
|
-
"@cobaltcore-dev/
|
|
113
|
+
"@cobaltcore-dev/signal-openstack": "1.0.0",
|
|
114
|
+
"@cobaltcore-dev/policy-engine": "2.0.0"
|
|
114
115
|
},
|
|
115
116
|
"scripts": {
|
|
116
117
|
"build": "pnpm build:server && pnpm build:client",
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"DeleteFlavorModal-BusYn32r.mjs","names":["React","DataGridRow","DataGridCell","TextInput","ButtonRow","Button","SpecFormRow","specKey","value","errors","isLoading","onKeyChange","onValueChange","onSave","onCancel","useLingui","className","onChange","e","target","placeholder","t","errortext","key","required","icon","onClick","variant","title","disabled","React","useState","useEffect","DataGridRow","DataGridCell","Button","Stack","Spinner","SpecRow","specKey","value","isDeleting","onDelete","canDelete","useLingui","confirm","setConfirm","timer","setTimeout","clearTimeout","handleConfirmDelete","button","variant","onClick","title","t","aria-label","data-testid","disabled","icon","distribution","alignment","React","use","Suspense","useState","startTransition","useErrorTranslation","Modal","Message","DataGrid","DataGridRow","DataGridHeadCell","DataGridCell","Stack","Button","Spinner","SpecFormRow","SpecRow","createPermissionsPromise","client","project","compute","canUser","query","project_id","permission","then","canCreate","canDelete","createExtraSpecsPromise","flavorId","getExtraSpecs","SpecsLoading","colSpan","distribution","alignment","variant","EditSpecContent","permissionsPromise","extraSpecsPromise","flavor","onSpecsUpdate","isAddingSpec","setIsAddingSpec","setMessage","useLingui","translateError","permissions","initialExtraSpecs","extraSpecs","setExtraSpecs","key","setKey","value","setValue","errors","setErrors","isDeleting","setIsDeleting","validateForm","trimmedKey","trim","trimmedValue","newErrors","Object","keys","includes","length","resetForm","handleSave","text","t","type","createExtraSpecs","mutate","id","extra_specs","newSpecs","error","Error","message","handleDelete","keyToDelete","deleteExtraSpec","handleKeyChange","newKey","prev","undefined","handleValueChange","newValue","shouldShowEmptyState","direction","className","label","data-testid","onClick","disabled","columns","specKey","isLoading","onKeyChange","onValueChange","onSave","onCancel","entries","map","specValue","onDelete","EditSpecModal","isOpen","onClose","setExtraSpecsPromise","useMemo","useEffect","handleClose","handleSpecsUpdate","specs","Promise","resolve","title","open","size","div","onDismiss","fallback","React","DataGridRow","DataGridCell","TextInput","ButtonRow","Button","TenantAccessFormRow","tenantId","flavorId","errors","isLoading","onTenantIdChange","onSave","onCancel","useLingui","className","value","onChange","e","target","placeholder","t","errortext","required","icon","onClick","variant","title","disabled","React","useState","useEffect","DataGridRow","DataGridCell","Button","Stack","Spinner","TenantAccessRow","access","isDeleting","onDelete","canDelete","useLingui","confirm","setConfirm","timer","setTimeout","clearTimeout","handleConfirmDelete","button","variant","onClick","title","t","aria-label","data-testid","disabled","tenantId","tenant_id","icon","flavor_id","className","distribution","alignment","React","use","Suspense","useState","startTransition","useEffect","useMemo","useErrorTranslation","Modal","Message","DataGrid","DataGridRow","DataGridHeadCell","DataGridCell","Stack","Spinner","Button","TenantAccessFormRow","TenantAccessRow","createPermissionsPromise","client","project","compute","canUser","query","project_id","permission","then","canAdd","canRemove","createFlavorAccessPromise","flavorId","getFlavorAccess","AccessLoading","colSpan","distribution","alignment","variant","AccessContent","permissionsPromise","flavorAccessPromise","flavor","onAccessUpdate","isAddingAccess","setIsAddingAccess","setMessage","useLingui","translateError","permissions","flavorAccess","tenantId","setTenantId","errors","setErrors","deletingTenants","setDeletingTenants","Set","isLoading","setIsLoading","isPublicFlavor","shouldShowEmptyState","length","validateForm","trimmedTenantId","trim","newErrors","some","access","tenant_id","Object","keys","resetForm","handleSave","text","t","type","updatedAccess","addTenantAccess","mutate","id","targetProjectId","error","errorMessage","message","handleRemoveTenant","tenantIdToRemove","prev","add","removeTenantAccess","newSet","delete","handleTenantIdChange","newTenantId","undefined","columns","className","direction","label","data-testid","onClick","disabled","onTenantIdChange","onSave","onCancel","map","isDeleting","has","onDelete","canDelete","ManageAccessModal","isOpen","onClose","filter","entry","idx","arr","findIndex","e","catch","msg","flavorAccessOverride","setFlavorAccessOverride","accessKey","activeFlavorAccessPromise","key","promise","handleClose","handleAccessUpdate","deduplicated","Promise","resolve","flavorName","name","title","open","size","div","onDismiss","dismissible","fallback","React","useState","Modal","Message","Spinner","ModalFooter","Button","ButtonRow","DataGrid","DataGridRow","DataGridHeadCell","DataGridCell","Stack","useErrorTranslation","DeleteFlavorModal","client","isOpen","onClose","project","flavor","onSuccess","useLingui","translateError","isLoading","setIsLoading","generalError","setGeneralError","handleDelete","id","t","compute","deleteFlavor","mutate","project_id","flavorId","handleClose","error","errorMessage","message","dismissError","onCancel","title","open","onConfirm","modalFooter","className","variant","onClick","disabled","size","distribution","alignment","div","onDismiss","text","columns","name","vcpus","ram","disk","swap"],"sources":["../../src/client/routes/_auth/projects/$projectId/compute/-components/Flavors/-components/SpecFormRow.tsx","../../src/client/routes/_auth/projects/$projectId/compute/-components/Flavors/-components/SpecRow.tsx","../../src/client/routes/_auth/projects/$projectId/compute/-components/Flavors/-components/EditSpecModal.tsx","../../src/client/routes/_auth/projects/$projectId/compute/-components/Flavors/-components/TenantAccessFormRow.tsx","../../src/client/routes/_auth/projects/$projectId/compute/-components/Flavors/-components/TenantAccessRow.tsx","../../src/client/routes/_auth/projects/$projectId/compute/-components/Flavors/-components/ManageAccessModal.tsx","../../src/client/routes/_auth/projects/$projectId/compute/-components/Flavors/-components/DeleteFlavorModal.tsx"],"sourcesContent":["import React from \"react\"\nimport { useLingui } from \"@lingui/react/macro\"\nimport { DataGridRow, DataGridCell, TextInput, ButtonRow, Button } from \"@cloudoperators/juno-ui-components\"\n\ninterface SpecFormRowProps {\n specKey: string\n value: string\n errors: { key?: string; value?: string }\n isLoading: boolean\n onKeyChange: (key: string) => void\n onValueChange: (value: string) => void\n onSave: () => void\n onCancel: () => void\n}\n\nexport const SpecFormRow: React.FC<SpecFormRowProps> = ({\n specKey,\n value,\n errors,\n isLoading,\n onKeyChange,\n onValueChange,\n onSave,\n onCancel,\n}) => {\n const { t } = useLingui()\n\n return (\n <DataGridRow>\n <DataGridCell className=\"pl-0\">\n <TextInput\n value={specKey}\n onChange={(e) => onKeyChange(e.target.value)}\n placeholder={t`Enter key`}\n errortext={errors.key}\n required\n />\n </DataGridCell>\n <DataGridCell className=\"pl-0\">\n <TextInput\n value={value}\n onChange={(e) => onValueChange(e.target.value)}\n placeholder={t`Enter value`}\n errortext={errors.value}\n required\n />\n </DataGridCell>\n <DataGridCell>\n <ButtonRow>\n <Button icon=\"check\" onClick={onSave} variant=\"primary\" title={t`Save Metadata`} disabled={isLoading} />\n <Button icon=\"cancel\" onClick={onCancel} title={t`Cancel`} disabled={isLoading} />\n </ButtonRow>\n </DataGridCell>\n </DataGridRow>\n )\n}\n","import React, { useState, useEffect } from \"react\"\nimport { useLingui } from \"@lingui/react/macro\"\nimport { DataGridRow, DataGridCell, Button, Stack, Spinner } from \"@cloudoperators/juno-ui-components\"\n\ninterface SpecRowProps {\n specKey: string\n value: string\n isDeleting: boolean\n onDelete: () => void\n canDelete?: boolean\n}\n\nexport const SpecRow: React.FC<SpecRowProps> = ({ specKey, value, isDeleting, onDelete, canDelete }) => {\n const { t } = useLingui()\n const [confirm, setConfirm] = useState(false)\n useEffect(() => {\n if (confirm) {\n const timer = setTimeout(() => {\n setConfirm(false)\n }, 3000)\n\n return () => clearTimeout(timer)\n }\n }, [confirm])\n\n const handleConfirmDelete = () => {\n setConfirm(false)\n onDelete()\n }\n\n const button = () => {\n if (!canDelete) {\n return <></>\n }\n if (confirm) {\n return (\n <Button\n variant=\"primary-danger\"\n onClick={handleConfirmDelete}\n title={t`Delete`}\n aria-label={t`Delete`}\n data-testid=\"confirm-deletion\"\n disabled={isDeleting}\n >\n {t`Delete`}\n </Button>\n )\n } else {\n return (\n <Button\n icon=\"deleteForever\"\n onClick={() => setConfirm(true)}\n title={t`Delete ${specKey}`}\n aria-label={t`Delete ${specKey}`}\n data-testid={`delete-${specKey}`}\n disabled={isDeleting}\n />\n )\n }\n }\n\n return (\n <DataGridRow>\n <DataGridCell>{specKey}</DataGridCell>\n <DataGridCell>{value}</DataGridCell>\n <DataGridCell>\n {isDeleting ? (\n <Stack distribution=\"center\" alignment=\"center\">\n <Spinner variant=\"primary\" />\n </Stack>\n ) : (\n <Stack distribution=\"end\" alignment=\"end\">\n {button()}\n </Stack>\n )}\n </DataGridCell>\n </DataGridRow>\n )\n}\n","import React, { use, Suspense, useState, startTransition } from \"react\"\nimport { TrpcClient } from \"@/client/trpcClient\"\nimport { useLingui } from \"@lingui/react/macro\"\nimport { useErrorTranslation } from \"@/client/utils/useErrorTranslation\"\nimport {\n Modal,\n Message,\n DataGrid,\n DataGridRow,\n DataGridHeadCell,\n DataGridCell,\n Stack,\n Button,\n Spinner,\n} from \"@cloudoperators/juno-ui-components\"\nimport { Flavor } from \"@/server/Compute/types/flavor\"\nimport { SpecFormRow } from \"./SpecFormRow\"\nimport { SpecRow } from \"./SpecRow\"\n\ninterface EditSpecModalProps {\n client: TrpcClient\n isOpen: boolean\n onClose: () => void\n project: string\n flavor: Flavor | null\n}\n\nconst createPermissionsPromise = (client: TrpcClient, project: string) => {\n return client.compute.canUser\n .query({\n project_id: project,\n permission: [\"flavor_specs:create\", \"flavor_specs:delete\"],\n })\n .then(([canCreate, canDelete]) => ({ canCreate, canDelete }))\n}\n\nconst createExtraSpecsPromise = (client: TrpcClient, project: string, flavorId: string) => {\n return client.compute.getExtraSpecs.query({\n project_id: project,\n flavorId: flavorId,\n })\n}\n\nfunction SpecsLoading() {\n return (\n <DataGridRow>\n <DataGridCell colSpan={3}>\n <Stack distribution=\"center\" alignment=\"center\">\n <Spinner variant=\"primary\" />\n </Stack>\n </DataGridCell>\n </DataGridRow>\n )\n}\n\nfunction EditSpecContent({\n permissionsPromise,\n extraSpecsPromise,\n client,\n project,\n flavor,\n onSpecsUpdate,\n isAddingSpec,\n setIsAddingSpec,\n setMessage,\n}: {\n permissionsPromise: Promise<{ canCreate: boolean; canDelete: boolean }>\n extraSpecsPromise: Promise<Record<string, string>>\n client: TrpcClient\n project: string\n flavor: Flavor\n onSpecsUpdate: (specs: Record<string, string>) => void\n isAddingSpec: boolean\n setIsAddingSpec: (adding: boolean) => void\n message: { text: string; type: \"error\" | \"info\" } | null\n setMessage: (msg: { text: string; type: \"error\" | \"info\" } | null) => void\n}) {\n const { t } = useLingui()\n const { translateError } = useErrorTranslation()\n\n const permissions = use(permissionsPromise)\n const initialExtraSpecs = use(extraSpecsPromise)\n\n const [extraSpecs, setExtraSpecs] = useState(initialExtraSpecs)\n const [key, setKey] = useState(\"\")\n const [value, setValue] = useState(\"\")\n const [errors, setErrors] = useState<{ key?: string; value?: string }>({})\n const [isDeleting, setIsDeleting] = useState<string | null>(null)\n\n const validateForm = () => {\n const trimmedKey = key.trim()\n const trimmedValue = value.trim()\n const newErrors: { key?: string; value?: string } = {}\n\n if (!trimmedKey) {\n newErrors.key = \"Key is required.\"\n } else if (Object.keys(extraSpecs).includes(trimmedKey)) {\n newErrors.key = \"Key already exists.\"\n }\n\n if (!trimmedValue) {\n newErrors.value = \"Value is required.\"\n }\n\n setErrors(newErrors)\n return Object.keys(newErrors).length === 0\n }\n\n const resetForm = () => {\n setKey(\"\")\n setValue(\"\")\n setErrors({})\n }\n\n const handleSave = async () => {\n if (!validateForm()) {\n setMessage({ text: t`Please fix the validation errors below.`, type: \"error\" })\n return\n }\n\n try {\n const trimmedKey = key.trim()\n const trimmedValue = value.trim()\n\n await client.compute.createExtraSpecs.mutate({\n project_id: project,\n flavorId: flavor.id,\n extra_specs: { [trimmedKey]: trimmedValue },\n })\n\n const newSpecs = { [trimmedKey]: trimmedValue, ...extraSpecs }\n setExtraSpecs(newSpecs)\n onSpecsUpdate(newSpecs)\n\n setMessage({\n text: t`Metadata \"${trimmedKey}\" has been added successfully.`,\n type: \"info\",\n })\n resetForm()\n setIsAddingSpec(false)\n } catch (error) {\n setMessage({\n text: translateError(error instanceof Error ? error.message : \"Failed to create extra spec\"),\n type: \"error\",\n })\n }\n }\n\n const handleDelete = async (keyToDelete: string) => {\n try {\n setIsDeleting(keyToDelete)\n await client.compute.deleteExtraSpec.mutate({\n project_id: project,\n flavorId: flavor.id,\n key: keyToDelete,\n })\n\n const newSpecs = { ...extraSpecs }\n delete newSpecs[keyToDelete]\n setExtraSpecs(newSpecs)\n onSpecsUpdate(newSpecs)\n\n setMessage({\n text: t`Metadata \"${keyToDelete}\" has been deleted successfully.`,\n type: \"info\",\n })\n } catch (error) {\n setMessage({\n text: translateError(error instanceof Error ? error.message : `Failed to delete extra spec \"${keyToDelete}\"`),\n type: \"error\",\n })\n } finally {\n setIsDeleting(null)\n }\n }\n\n const handleKeyChange = (newKey: string) => {\n setKey(newKey)\n if (errors.key) setErrors((prev) => ({ ...prev, key: undefined }))\n }\n\n const handleValueChange = (newValue: string) => {\n setValue(newValue)\n if (errors.value) setErrors((prev) => ({ ...prev, value: undefined }))\n }\n\n const shouldShowEmptyState = Object.keys(extraSpecs).length === 0 && !isAddingSpec\n\n return (\n <>\n {permissions.canCreate && (\n <Stack direction=\"horizontal\" className=\"bg-theme-background-lvl-1 justify-end p-2\">\n <Button\n label={t`Add Metadata`}\n data-testid=\"addExtraButton\"\n onClick={() => setIsAddingSpec(true)}\n variant=\"primary\"\n disabled={isAddingSpec}\n />\n </Stack>\n )}\n\n <DataGrid columns={3}>\n <DataGridRow>\n <DataGridHeadCell>{t`Key`}</DataGridHeadCell>\n <DataGridHeadCell>{t`Value`}</DataGridHeadCell>\n <DataGridHeadCell></DataGridHeadCell>\n </DataGridRow>\n\n {isAddingSpec && (\n <SpecFormRow\n specKey={key}\n value={value}\n errors={errors}\n isLoading={false}\n onKeyChange={handleKeyChange}\n onValueChange={handleValueChange}\n onSave={handleSave}\n onCancel={() => {\n resetForm()\n setIsAddingSpec(false)\n setMessage(null)\n }}\n />\n )}\n\n {Object.entries(extraSpecs).map(([specKey, specValue]) => (\n <SpecRow\n key={specKey}\n specKey={specKey}\n value={specValue}\n isDeleting={isDeleting === specKey}\n onDelete={() => handleDelete(specKey)}\n canDelete={permissions.canDelete}\n />\n ))}\n\n {shouldShowEmptyState && (\n <DataGridRow>\n <DataGridCell colSpan={3} className=\"text-theme-default py-4 text-center\">\n {t`No extra specs found. Click \"Add Metadata\" to create one.`}\n </DataGridCell>\n </DataGridRow>\n )}\n </DataGrid>\n </>\n )\n}\n\nexport const EditSpecModal: React.FC<EditSpecModalProps> = ({ client, isOpen, onClose, project, flavor }) => {\n const { t } = useLingui()\n\n const [message, setMessage] = useState<{ text: string; type: \"error\" | \"info\" } | null>(null)\n const [isAddingSpec, setIsAddingSpec] = useState(false)\n const [extraSpecsPromise, setExtraSpecsPromise] = useState<Promise<Record<string, string>> | null>(null)\n\n const permissionsPromise = React.useMemo(\n () => (isOpen ? createPermissionsPromise(client, project) : null),\n [client, project, isOpen]\n )\n\n React.useEffect(() => {\n if (isOpen && flavor?.id) {\n startTransition(() => {\n setExtraSpecsPromise(createExtraSpecsPromise(client, project, flavor.id))\n })\n }\n }, [isOpen, flavor?.id, client, project])\n\n const handleClose = () => {\n setMessage(null)\n setIsAddingSpec(false)\n setExtraSpecsPromise(null)\n onClose()\n }\n\n const handleSpecsUpdate = (specs: Record<string, string>) => {\n startTransition(() => {\n setExtraSpecsPromise(Promise.resolve(specs))\n })\n }\n\n if (!isOpen || !flavor || !permissionsPromise || !extraSpecsPromise) {\n return null\n }\n\n return (\n <Modal onCancel={handleClose} title={t`Edit Metadata`} open={isOpen} size=\"large\">\n <div>\n {message && (\n <Message onDismiss={() => setMessage(null)} text={message.text} variant={message.type} className=\"mb-4\" />\n )}\n\n <Suspense fallback={<SpecsLoading />}>\n <EditSpecContent\n permissionsPromise={permissionsPromise}\n extraSpecsPromise={extraSpecsPromise}\n client={client}\n project={project}\n flavor={flavor}\n onSpecsUpdate={handleSpecsUpdate}\n isAddingSpec={isAddingSpec}\n setIsAddingSpec={setIsAddingSpec}\n message={message}\n setMessage={setMessage}\n />\n </Suspense>\n </div>\n </Modal>\n )\n}\n","import React from \"react\"\nimport { useLingui } from \"@lingui/react/macro\"\nimport { DataGridRow, DataGridCell, TextInput, ButtonRow, Button } from \"@cloudoperators/juno-ui-components\"\n\ninterface TenantAccessFormRowProps {\n tenantId: string\n flavorId: string\n errors: { tenantId?: string }\n isLoading: boolean\n onTenantIdChange: (tenantId: string) => void\n onSave: () => void\n onCancel: () => void\n}\n\nexport const TenantAccessFormRow: React.FC<TenantAccessFormRowProps> = ({\n tenantId,\n flavorId,\n errors,\n isLoading,\n onTenantIdChange,\n onSave,\n onCancel,\n}) => {\n const { t } = useLingui()\n\n return (\n <DataGridRow>\n <DataGridCell>{flavorId}</DataGridCell>\n <DataGridCell className=\"pl-0\">\n <TextInput\n value={tenantId}\n onChange={(e) => onTenantIdChange(e.target.value)}\n placeholder={t`Enter tenant ID`}\n errortext={errors.tenantId}\n required\n />\n </DataGridCell>\n <DataGridCell>\n <ButtonRow>\n <Button icon=\"check\" onClick={onSave} variant=\"primary\" title={t`Add Tenant Access`} disabled={isLoading} />\n <Button icon=\"cancel\" onClick={onCancel} title={t`Cancel`} disabled={isLoading} />\n </ButtonRow>\n </DataGridCell>\n </DataGridRow>\n )\n}\n","import React, { useState, useEffect } from \"react\"\nimport { useLingui } from \"@lingui/react/macro\"\nimport { DataGridRow, DataGridCell, Button, Stack, Spinner } from \"@cloudoperators/juno-ui-components\"\n\ninterface FlavorAccess {\n flavor_id: string\n tenant_id: string\n}\n\ninterface TenantAccessRowProps {\n access: FlavorAccess\n isDeleting: boolean\n onDelete: () => void\n canDelete: boolean\n}\n\nexport const TenantAccessRow: React.FC<TenantAccessRowProps> = ({ access, isDeleting, onDelete, canDelete }) => {\n const { t } = useLingui()\n const [confirm, setConfirm] = useState(false)\n\n useEffect(() => {\n if (confirm) {\n const timer = setTimeout(() => {\n setConfirm(false)\n }, 3000)\n\n return () => clearTimeout(timer)\n }\n }, [confirm])\n\n const handleConfirmDelete = () => {\n setConfirm(false)\n onDelete()\n }\n\n const button = () => {\n if (!canDelete) {\n return <></>\n }\n if (confirm) {\n return (\n <Button\n variant=\"primary-danger\"\n onClick={handleConfirmDelete}\n title={t`Remove tenant access`}\n aria-label={t`Remove tenant access`}\n data-testid=\"confirm-removal\"\n disabled={isDeleting}\n >\n {t`Remove`}\n </Button>\n )\n } else {\n const tenantId = access.tenant_id\n\n return (\n <Button\n icon=\"deleteForever\"\n onClick={() => setConfirm(true)}\n title={t`Remove access for ${tenantId}`}\n aria-label={t`Remove access for ${tenantId}`}\n data-testid={`remove-${tenantId}`}\n disabled={isDeleting}\n />\n )\n }\n }\n\n return (\n <DataGridRow>\n <DataGridCell>{access.flavor_id}</DataGridCell>\n <DataGridCell className=\"break-all\">{access.tenant_id}</DataGridCell>\n <DataGridCell>\n {isDeleting ? (\n <Stack distribution=\"center\" alignment=\"center\">\n <Spinner variant=\"primary\" />\n </Stack>\n ) : (\n <Stack distribution=\"end\" alignment=\"end\">\n {button()}\n </Stack>\n )}\n </DataGridCell>\n </DataGridRow>\n )\n}\n","import React, { use, Suspense, useState, startTransition, useEffect, useMemo } from \"react\"\nimport { TrpcClient } from \"@/client/trpcClient\"\nimport { useLingui } from \"@lingui/react/macro\"\nimport { useErrorTranslation } from \"@/client/utils/useErrorTranslation\"\nimport {\n Modal,\n Message,\n DataGrid,\n DataGridRow,\n DataGridHeadCell,\n DataGridCell,\n Stack,\n Spinner,\n Button,\n} from \"@cloudoperators/juno-ui-components\"\nimport { Flavor } from \"@/server/Compute/types/flavor\"\nimport { TenantAccessFormRow } from \"./TenantAccessFormRow\"\nimport { TenantAccessRow } from \"./TenantAccessRow\"\n\ninterface ManageAccessProps {\n client: TrpcClient\n isOpen: boolean\n onClose: () => void\n project: string\n flavor: Flavor | null\n}\n\ninterface FlavorAccess {\n flavor_id: string\n tenant_id: string\n}\n\nconst createPermissionsPromise = (client: TrpcClient, project: string) => {\n return client.compute.canUser\n .query({\n project_id: project,\n permission: [\"flavors:add_project\", \"flavors:remove_project\"],\n })\n .then(([canAdd, canRemove]) => ({ canAdd, canRemove }))\n}\n\nconst createFlavorAccessPromise = (client: TrpcClient, project: string, flavorId: string) => {\n return client.compute.getFlavorAccess.query({\n project_id: project,\n flavorId: flavorId,\n })\n}\n\nfunction AccessLoading() {\n return (\n <DataGridRow>\n <DataGridCell colSpan={3}>\n <Stack distribution=\"center\" alignment=\"center\">\n <Spinner variant=\"primary\" />\n </Stack>\n </DataGridCell>\n </DataGridRow>\n )\n}\n\nfunction AccessContent({\n permissionsPromise,\n flavorAccessPromise,\n client,\n project,\n flavor,\n onAccessUpdate,\n isAddingAccess,\n setIsAddingAccess,\n setMessage,\n}: {\n permissionsPromise: Promise<{ canAdd: boolean; canRemove: boolean }>\n flavorAccessPromise: Promise<FlavorAccess[]>\n client: TrpcClient\n project: string\n flavor: Flavor\n onAccessUpdate: (access: FlavorAccess[]) => void\n isAddingAccess: boolean\n setIsAddingAccess: (adding: boolean) => void\n setMessage: (msg: { text: string; type: \"error\" | \"info\" } | null) => void\n}) {\n const { t } = useLingui()\n const { translateError } = useErrorTranslation()\n\n const permissions = use(permissionsPromise)\n const flavorAccess = use(flavorAccessPromise) // Direkt verwenden - React 19 macht es reaktiv\n\n const [tenantId, setTenantId] = useState(\"\")\n const [errors, setErrors] = useState<{ tenantId?: string }>({})\n const [deletingTenants, setDeletingTenants] = useState<Set<string>>(new Set())\n const [isLoading, setIsLoading] = useState(false)\n\n const isPublicFlavor = flavor[\"os-flavor-access:is_public\"] !== false\n const shouldShowEmptyState = flavorAccess.length === 0 && !isAddingAccess\n\n const validateForm = () => {\n const trimmedTenantId = tenantId.trim()\n const newErrors: { tenantId?: string } = {}\n\n if (!trimmedTenantId) {\n newErrors.tenantId = \"Tenant ID is required.\"\n } else if (flavorAccess.some((access) => access.tenant_id === trimmedTenantId)) {\n newErrors.tenantId = \"This tenant already has access to this flavor.\"\n }\n\n setErrors(newErrors)\n return Object.keys(newErrors).length === 0\n }\n\n const resetForm = () => {\n setTenantId(\"\")\n setErrors({})\n }\n\n const handleSave = async () => {\n if (!validateForm()) {\n setMessage({ text: t`Please fix the validation errors below.`, type: \"error\" })\n return\n }\n\n setIsLoading(true)\n try {\n const trimmedTenantId = tenantId.trim()\n\n const updatedAccess = await client.compute.addTenantAccess.mutate({\n project_id: project,\n flavorId: flavor.id,\n targetProjectId: trimmedTenantId,\n })\n\n onAccessUpdate(updatedAccess)\n\n setMessage({\n text: t`Tenant access for \"${trimmedTenantId}\" has been added successfully.`,\n type: \"info\",\n })\n resetForm()\n setIsAddingAccess(false)\n } catch (error) {\n const errorMessage = (error as Error)?.message || \"Failed to add tenant access\"\n\n setMessage({\n text: translateError(errorMessage || \"Failed to add tenant access\"),\n type: \"error\",\n })\n } finally {\n setIsLoading(false)\n }\n }\n\n const handleRemoveTenant = async (tenantIdToRemove: string) => {\n setDeletingTenants((prev) => new Set(prev).add(tenantIdToRemove))\n\n try {\n const updatedAccess = await client.compute.removeTenantAccess.mutate({\n project_id: project,\n flavorId: flavor.id,\n targetProjectId: tenantIdToRemove,\n })\n\n onAccessUpdate(updatedAccess)\n setMessage({\n text: t`Tenant access for \"${tenantIdToRemove}\" has been removed successfully.`,\n type: \"info\",\n })\n } catch (error) {\n const errorMessage = (error as Error)?.message || \"Failed to remove tenant access\"\n\n setMessage({\n text: translateError(errorMessage || `Failed to remove tenant access for \"${tenantIdToRemove}\"`),\n type: \"error\",\n })\n } finally {\n setDeletingTenants((prev) => {\n const newSet = new Set(prev)\n newSet.delete(tenantIdToRemove)\n return newSet\n })\n }\n }\n\n const handleTenantIdChange = (newTenantId: string) => {\n setTenantId(newTenantId)\n if (errors.tenantId) setErrors((prev) => ({ ...prev, tenantId: undefined }))\n }\n\n if (isPublicFlavor) {\n return (\n <DataGrid columns={3}>\n <DataGridRow>\n <DataGridHeadCell>{t`Flavor ID`}</DataGridHeadCell>\n <DataGridHeadCell>{t`Tenant ID`}</DataGridHeadCell>\n <DataGridHeadCell> </DataGridHeadCell>\n </DataGridRow>\n <DataGridRow>\n <DataGridCell colSpan={3} className=\"text-theme-default py-4 text-center\">\n {t`This is a public flavor. All tenants have access to it.`}\n </DataGridCell>\n </DataGridRow>\n </DataGrid>\n )\n }\n\n return (\n <>\n {permissions.canAdd && (\n <Stack direction=\"horizontal\" className=\"bg-theme-background-lvl-1 justify-end p-2\">\n <Button\n label={t`Add Tenant Access`}\n data-testid=\"addTenantButton\"\n onClick={() => setIsAddingAccess(true)}\n variant=\"primary\"\n disabled={isAddingAccess}\n />\n </Stack>\n )}\n\n <DataGrid columns={3}>\n <DataGridRow>\n <DataGridHeadCell>{t`Flavor ID`}</DataGridHeadCell>\n <DataGridHeadCell>{t`Tenant ID`}</DataGridHeadCell>\n <DataGridHeadCell></DataGridHeadCell>\n </DataGridRow>\n\n {isAddingAccess && (\n <TenantAccessFormRow\n tenantId={tenantId}\n flavorId={flavor.id}\n errors={errors}\n isLoading={isLoading}\n onTenantIdChange={handleTenantIdChange}\n onSave={handleSave}\n onCancel={() => {\n resetForm()\n setIsAddingAccess(false)\n setMessage(null)\n }}\n />\n )}\n\n {flavorAccess.map((access) => (\n <TenantAccessRow\n key={access.tenant_id}\n access={access}\n isDeleting={deletingTenants.has(access.tenant_id)}\n onDelete={() => handleRemoveTenant(access.tenant_id)}\n canDelete={permissions.canRemove}\n />\n ))}\n\n {shouldShowEmptyState && (\n <DataGridRow>\n <DataGridCell colSpan={3} className=\"text-theme-default py-4 text-center\">\n {t`No specific tenant access configured for this private flavor. Click \"Add Tenant Access\" to grant access.`}\n </DataGridCell>\n </DataGridRow>\n )}\n </DataGrid>\n </>\n )\n}\n\nexport const ManageAccessModal: React.FC<ManageAccessProps> = ({ client, isOpen, onClose, project, flavor }) => {\n const { t } = useLingui()\n const { translateError } = useErrorTranslation()\n\n const [message, setMessage] = useState<{ text: string; type: \"error\" | \"info\" } | null>(null)\n const [isAddingAccess, setIsAddingAccess] = useState(false)\n\n const permissionsPromise = useMemo(\n () => (isOpen ? createPermissionsPromise(client, project) : null),\n [client, project, isOpen]\n )\n\n const flavorAccessPromise = useMemo(() => {\n if (!isOpen || !flavor?.id) return null\n return createFlavorAccessPromise(client, project, flavor.id)\n .then((access) =>\n access.filter((entry, idx, arr) => arr.findIndex((e) => e.tenant_id === entry.tenant_id) === idx)\n )\n .catch((error) => {\n const msg = translateError((error as Error)?.message || \"GET_FLAVOR_ACCESS_FAILED\")\n setMessage({ text: msg, type: \"error\" })\n return [] as FlavorAccess[]\n })\n }, [isOpen, flavor?.id, client, project])\n\n useEffect(() => {\n if (isOpen) setMessage(null)\n }, [isOpen, flavor?.id])\n\n // After add/remove, the server returns the updated list. We store it as an override so\n // the UI reflects the change immediately without refetching. The key prevents a stale\n // override from a previously opened flavor from leaking into the current modal session.\n const [flavorAccessOverride, setFlavorAccessOverride] = useState<{\n key: string\n promise: Promise<FlavorAccess[]>\n } | null>(null)\n\n const accessKey = `${isOpen}-${flavor?.id}`\n const activeFlavorAccessPromise =\n flavorAccessOverride?.key === accessKey ? flavorAccessOverride.promise : flavorAccessPromise\n\n const handleClose = () => {\n setMessage(null)\n setIsAddingAccess(false)\n setFlavorAccessOverride(null)\n onClose()\n }\n\n const handleAccessUpdate = (access: FlavorAccess[]) => {\n const deduplicated = access.filter(\n (entry, idx, arr) => arr.findIndex((e) => e.tenant_id === entry.tenant_id) === idx\n )\n startTransition(() => {\n setFlavorAccessOverride({ key: accessKey, promise: Promise.resolve(deduplicated) })\n })\n }\n\n if (!isOpen || !flavor || !permissionsPromise || !activeFlavorAccessPromise) {\n return null\n }\n const flavorName = flavor.name\n\n return (\n <Modal onCancel={handleClose} title={t`Manage Access - ${flavorName}`} open={isOpen} size=\"xl\">\n <div>\n {message && (\n <Message\n onDismiss={() => setMessage(null)}\n text={message.text}\n variant={message.type}\n className=\"mb-4\"\n dismissible\n />\n )}\n\n <Suspense fallback={<AccessLoading />}>\n <AccessContent\n permissionsPromise={permissionsPromise}\n flavorAccessPromise={activeFlavorAccessPromise}\n client={client}\n project={project}\n flavor={flavor}\n onAccessUpdate={handleAccessUpdate}\n isAddingAccess={isAddingAccess}\n setIsAddingAccess={setIsAddingAccess}\n setMessage={setMessage}\n />\n </Suspense>\n </div>\n </Modal>\n )\n}\n","import React, { useState } from \"react\"\nimport { useLingui } from \"@lingui/react/macro\"\nimport { TrpcClient } from \"@/client/trpcClient\"\nimport {\n Modal,\n Message,\n Spinner,\n ModalFooter,\n Button,\n ButtonRow,\n DataGrid,\n DataGridRow,\n DataGridHeadCell,\n DataGridCell,\n Stack,\n} from \"@cloudoperators/juno-ui-components\"\nimport { Flavor } from \"@/server/Compute/types/flavor\"\nimport { Trans } from \"@lingui/react/macro\"\nimport { useErrorTranslation } from \"@/client/utils/useErrorTranslation\"\n\ninterface DeleteFlavorModalProps {\n client: TrpcClient\n isOpen: boolean\n onClose: () => void\n project: string\n flavor: Flavor | null\n onSuccess: () => void\n}\n\nexport const DeleteFlavorModal: React.FC<DeleteFlavorModalProps> = ({\n client,\n isOpen,\n onClose,\n project,\n flavor,\n onSuccess,\n}) => {\n const { t } = useLingui()\n const { translateError } = useErrorTranslation()\n const [isLoading, setIsLoading] = useState(false)\n const [generalError, setGeneralError] = useState<string | null>(null)\n\n const handleDelete = async () => {\n if (!flavor?.id) {\n setGeneralError(t`No flavor selected for deletion.`)\n return\n }\n\n setGeneralError(null)\n\n try {\n setIsLoading(true)\n\n await client.compute.deleteFlavor.mutate({\n project_id: project,\n flavorId: flavor.id,\n })\n onSuccess()\n handleClose()\n } catch (error) {\n const errorMessage = (error as Error)?.message\n ? translateError((error as Error).message)\n : t`Failed to delete flavor. Please try again.`\n setGeneralError(errorMessage)\n } finally {\n setIsLoading(false)\n }\n }\n\n const handleClose = () => {\n setGeneralError(null)\n onClose()\n }\n\n const dismissError = () => {\n setGeneralError(null)\n }\n\n return (\n <Modal\n onCancel={handleClose}\n title={t`Delete Flavor`}\n open={isOpen}\n onConfirm={handleDelete}\n modalFooter={\n <ModalFooter className=\"flex justify-end\">\n <ButtonRow>\n <Button variant=\"primary-danger\" onClick={handleDelete} disabled={isLoading}>\n {isLoading ? <Spinner size=\"small\" /> : <Trans>Delete</Trans>}\n </Button>\n <Button variant=\"default\" onClick={handleClose}>\n <Trans>Cancel</Trans>\n </Button>\n </ButtonRow>\n </ModalFooter>\n }\n >\n {isLoading && (\n <Stack distribution=\"center\" alignment=\"center\">\n <Spinner variant=\"primary\" />\n </Stack>\n )}\n {!isLoading && (\n <div>\n {generalError && <Message onDismiss={dismissError} text={generalError} variant=\"error\" className=\"mb-4\" />}\n\n <Message\n text={t`This action cannot be undone. The flavor will be permanently deleted.`}\n variant=\"danger\"\n className=\"mb-4\"\n />\n\n {flavor && (\n <DataGrid columns={2}>\n <DataGridRow>\n <DataGridHeadCell>{t`Name`}</DataGridHeadCell>\n <DataGridCell>{flavor.name}</DataGridCell>\n </DataGridRow>\n <DataGridRow>\n <DataGridHeadCell>{t`ID`}</DataGridHeadCell>\n <DataGridCell>{flavor.id}</DataGridCell>\n </DataGridRow>\n <DataGridRow>\n <DataGridHeadCell>{t`VCPUs`}</DataGridHeadCell>\n <DataGridCell>{flavor.vcpus}</DataGridCell>\n </DataGridRow>\n <DataGridRow>\n <DataGridHeadCell>{t`RAM`}</DataGridHeadCell>\n <DataGridCell>{flavor.ram} MiB</DataGridCell>\n </DataGridRow>\n <DataGridRow>\n <DataGridHeadCell>{t`Disk`}</DataGridHeadCell>\n <DataGridCell>{flavor.disk} GiB</DataGridCell>\n </DataGridRow>\n {flavor.swap && (\n <DataGridRow>\n <DataGridHeadCell>{t`Swap`}</DataGridHeadCell>\n <DataGridCell>{flavor.swap} MiB</DataGridCell>\n </DataGridRow>\n )}\n </DataGrid>\n )}\n </div>\n )}\n </Modal>\n )\n}\n"],"mappings":";;;;;;AAeA,IAAaM,KAA2C,EACtDC,YACAC,UACAC,WACAC,cACAC,gBACAC,kBACAC,WACAC,kBACD;CACC,IAAM,EAAA,MAAA,GAAA,GAAA,MAAQC,GAAAA;AAEd,QACE,kBAACd,GAAAA,EAAAA,UAAAA;EACC,kBAACC,GAAAA;GAAac,WAAU;aACtB,kBAACb,GAAAA;IACCK,OAAOD;IACPU,WAAWC,MAAMP,EAAYO,EAAEC,OAAOX,MAAK;IAC3CY,aAAaC,EAAAA,EAAC,EAAA,IAAA,UAAU,CAAA;IACxBC,WAAWb,EAAOc;IAClBC,UAAQ;;;EAGZ,kBAACtB,GAAAA;GAAac,WAAU;aACtB,kBAACb,GAAAA;IACQK;IACPS,WAAWC,MAAMN,EAAcM,EAAEC,OAAOX,MAAK;IAC7CY,aAAaC,EAAAA,EAAC,EAAA,IAAA,UAAY,CAAA;IAC1BC,WAAWb,EAAOD;IAClBgB,UAAQ;;;EAGZ,kBAACtB,GAAAA,EAAAA,UACC,kBAACE,GAAAA,EAAAA,UAAAA,CACC,kBAACC,GAAAA;GAAOoB,MAAK;GAAQC,SAASb;GAAQc,SAAQ;GAAUC,OAAOP,EAAAA,EAAC,EAAA,IAAA,UAAc,CAAA;GAAGQ,UAAUnB;MAC3F,kBAACL,GAAAA;GAAOoB,MAAK;GAASC,SAASZ;GAAUc,OAAOP,EAAAA,EAAC,EAAA,IAAA,UAAO,CAAA;GAAGQ,UAAUnB;;;GCtClE4B,KAAmC,EAAEC,YAASC,UAAOC,eAAYC,aAAUC,mBAAW;CACjG,IAAM,EAAA,MAAA,GAAA,GAAA,MAAQC,GAAAA,EACR,CAACC,GAASC,KAAcf,EAAS,GAAA;AA+CvC,QA9CAC,QAAU;AACR,MAAIa,GAAS;GACX,IAAME,IAAQC,iBAAW;AACvBF,MAAW,GAAA;MACV,IAAA;AAEH,gBAAaG,aAAaF,EAAAA;;IAE3B,CAACF,EAAQ,CAAA,EAuCV,kBAACZ,GAAAA,EAAAA,UAAAA;EACC,kBAACC,GAAAA,EAAAA,UAAcK,GAAAA,CAAAA;EACf,kBAACL,GAAAA,EAAAA,UAAcM,GAAAA,CAAAA;EACf,kBAACN,GAAAA,EAAAA,UACEO,IACC,kBAACL,GAAAA;GAAMwB,cAAa;GAASC,WAAU;aACrC,kBAACxB,GAAAA,EAAQe,SAAQ,WAAA,CAAA;OAGnB,kBAAChB,GAAAA;GAAMwB,cAAa;GAAMC,WAAU;aAxCrClB,IAGDE,IAEA,kBAACV,GAAAA;IACCiB,SAAQ;IACRC,eAboB;AAE1BX,KADAI,EAAW,GAAA,EACXJ,GAAAA;;IAYMY,OAAOC,EAAAA,EAAC,EAAA,IAAA,UAAO,CAAA;IACfC,cAAYD,EAAAA,EAAC,EAAA,IAAA,UAAO,CAAA;IACpBE,eAAY;IACZC,UAAUjB;cAETc,EAAAA,EAAC,EAAA,IAAA,UAAO,CAAA;QAKX,kBAACpB,GAAAA;IACCwB,MAAK;IACLN,eAAeP,EAAW,GAAA;IAC1BQ,OAAOC,EAAAA,EAAC;;eAAUhB,YAAAA;KAAQ,CAAA;IAC1BiB,cAAYD,EAAAA,EAAC;;eAAUhB,YAAAA;KAAQ,CAAA;IAC/BkB,eAAa,UAAUlB;IACvBmB,UAAUjB;QAvBP,kBAAA,GAAA,EAAA,CAAA;;;GCLPsC,KAA4BC,GAAoBC,MAC7CD,EAAOE,QAAQC,QACnBC,MAAM;CACLC,YAAYJ;CACZK,YAAY,CAAC,uBAAuB,sBAAsB;CAC5D,CAAA,CACCC,MAAM,CAACC,GAAWC,QAAgB;CAAED;CAAWC;CAAU,EAAA,EAGxDC,KAA2BV,GAAoBC,GAAiBU,MAC7DX,EAAOE,QAAQU,cAAcR,MAAM;CACxCC,YAAYJ;CACFU;CACZ,CAAA;AAGF,SAASE,IAAAA;AACP,QACE,kBAACtB,GAAAA,EAAAA,UACC,kBAACE,GAAAA;EAAaqB,SAAS;YACrB,kBAACpB,GAAAA;GAAMqB,cAAa;GAASC,WAAU;aACrC,kBAACpB,GAAAA,EAAQqB,SAAQ,WAAA,CAAA;;;;AAO3B,SAASC,EAAgB,EACvBC,uBACAC,sBACApB,WACAC,YACAoB,WACAC,kBACAC,iBACAC,oBACAC,iBAYD;CACC,IAAM,EAAA,MAAA,GAAA,GAAA,MAAQC,GAAAA,EACR,EAAEC,sBAAmBxC,GAAAA,EAErByC,IAAc7C,EAAIoC,EAAAA,EAGlB,CAACW,GAAYC,KAAiB9C,EAFVF,EAAIqC,EAAAA,CAEeS,EACvC,CAACG,GAAKC,KAAUhD,EAAS,GAAA,EACzB,CAACiD,GAAOC,KAAYlD,EAAS,GAAA,EAC7B,CAACmD,GAAQC,KAAapD,EAA2C,EAAC,CAAA,EAClE,CAACqD,GAAYC,KAAiBtD,EAAwB,KAAA,EAEtDuD,UAAe;EACnB,IAAMC,IAAaT,EAAIU,MAAI,EACrBC,IAAeT,EAAMQ,MAAI,EACzBE,IAA8C,EAAC;AAarD,SAXKH,IAEMI,OAAOC,KAAKhB,EAAAA,CAAYiB,SAASN,EAAAA,KAC1CG,EAAUZ,MAAM,yBAFhBY,EAAUZ,MAAM,oBAKbW,MACHC,EAAUV,QAAQ,uBAGpBG,EAAUO,EAAAA,EACHC,OAAOC,KAAKF,EAAAA,CAAWI,WAAW;IAGrCC,UAAY;AAGhBZ,EAFAJ,EAAO,GAAA,EACPE,EAAS,GAAA,EACTE,EAAU,EAAC,CAAA;IAGPa,IAAa,YAAA;AACjB,MAAI,CAACV,GAAAA,EAAgB;AACnBf,KAAW;IAAE0B,MAAMC,EAAAA,EAAC,EAAA,IAAA,UAAwC,CAAA;IAAGC,MAAM;IAAQ,CAAA;AAC7E;;AAGF,MAAI;GACF,IAAMZ,IAAaT,EAAIU,MAAI,EACrBC,IAAeT,EAAMQ,MAAI;AAE/B,SAAM1C,EAAOE,QAAQoD,iBAAiBC,OAAO;IAC3ClD,YAAYJ;IACZU,UAAUU,EAAOmC;IACjBC,aAAa,GAAGhB,IAAaE,GAAa;IAC5C,CAAA;GAEA,IAAMe,IAAW;KAAGjB,IAAaE;IAAc,GAAGb;IAAW;AAS7DN,GARAO,EAAc2B,EAAAA,EACdpC,EAAcoC,EAAAA,EAEdjC,EAAW;IACT0B,MAAMC,EAAAA,EAAC;;eAAaX,eAAAA;KAAyC,CAAA;IAC7DY,MAAM;IACR,CAAA,EACAJ,GAAAA,EACAzB,EAAgB,GAAA;WACTmC,GAAO;AACdlC,KAAW;IACT0B,MAAMxB,EAAegC,aAAiBC,QAAQD,EAAME,UAAU,8BAAA;IAC9DR,MAAM;IACR,CAAA;;IAIES,IAAe,OAAOC,MAAAA;AAC1B,MAAI;AAEF,GADAxB,EAAcwB,EAAAA,EACd,MAAM/D,EAAOE,QAAQ8D,gBAAgBT,OAAO;IAC1ClD,YAAYJ;IACZU,UAAUU,EAAOmC;IACjBxB,KAAK+B;IACP,CAAA;GAEA,IAAML,IAAW,EAAE,GAAG5B,GAAW;AAKjCL,GAJA,OAAOiC,EAASK,IAChBhC,EAAc2B,EAAAA,EACdpC,EAAcoC,EAAAA,EAEdjC,EAAW;IACT0B,MAAMC,EAAAA,EAAC;;eAAaW,gBAAAA;KAA4C,CAAA;IAChEV,MAAM;IACR,CAAA;WACOM,GAAO;AACdlC,KAAW;IACT0B,MAAMxB,EAAegC,aAAiBC,QAAQD,EAAME,UAAU,gCAAgCE,EAAY,GAAE;IAC5GV,MAAM;IACR,CAAA;YACQ;AACRd,KAAc,KAAA;;IAIZ0B,KAAmBC,MAAAA;AAEvB,EADAjC,EAAOiC,EAAAA,EACH9B,EAAOJ,OAAKK,GAAW8B,OAAU;GAAE,GAAGA;GAAMnC,KAAKoC,KAAAA;GAAU,EAAA;IAG3DC,KAAqBC,MAAAA;AAEzB,EADAnC,EAASmC,EAAAA,EACLlC,EAAOF,SAAOG,GAAW8B,OAAU;GAAE,GAAGA;GAAMjC,OAAOkC,KAAAA;GAAU,EAAA;IAG/DG,IAAuB1B,OAAOC,KAAKhB,EAAAA,CAAYkB,WAAW,KAAK,CAACzB;AAEtE,QACE,kBAAA,GAAA,EAAA,UAAA,CACGK,EAAYpB,aACX,kBAACd,GAAAA;EAAM8E,WAAU;EAAaC,WAAU;YACtC,kBAAC9E,GAAAA;GACC+E,OAAOtB,EAAAA,EAAC,EAAA,IAAA,UAAa,CAAA;GACrBuB,eAAY;GACZC,eAAepD,EAAgB,GAAA;GAC/BP,SAAQ;GACR4D,UAAUtD;;KAKhB,kBAACjC,GAAAA;EAASwF,SAAS;;GACjB,kBAACvF,GAAAA,EAAAA,UAAAA;IACC,kBAACC,GAAAA,EAAAA,UAAkB4D,EAAAA,EAAC,EAAA,IAAA,UAAI,CAAA,EAAA,CAAA;IACxB,kBAAC5D,GAAAA,EAAAA,UAAkB4D,EAAAA,EAAC,EAAA,IAAA,UAAM,CAAA,EAAA,CAAA;IAC1B,kBAAC5D,GAAAA,EAAAA,CAAAA;;GAGF+B,KACC,kBAAC1B,GAAAA;IACCkF,SAAS/C;IACFE;IACCE;IACR4C,WAAW;IACXC,aAAahB;IACbiB,eAAeb;IACfc,QAAQjC;IACRkC,gBAAU;AAGR3D,KAFAwB,GAAAA,EACAzB,EAAgB,GAAA,EAChBC,EAAW,KAAA;;;GAKhBoB,OAAOwC,QAAQvD,EAAAA,CAAYwD,KAAK,CAACP,GAASQ,OACzC,kBAACzF,GAAAA;IAEUiF;IACT7C,OAAOqD;IACPjD,YAAYA,MAAeyC;IAC3BS,gBAAgB1B,EAAaiB,EAAAA;IAC7BtE,WAAWmB,EAAYnB;MALlBsE,EAAAA,CAAAA;GASRR,KACC,kBAAChF,GAAAA,EAAAA,UACC,kBAACE,GAAAA;IAAaqB,SAAS;IAAG2D,WAAU;cACjCrB,EAAAA,EAAC,EAAA,IAAA,UAA0D,CAAA;;;;;AAS1E,IAAaqC,KAA+C,EAAEzF,WAAQ0F,WAAQC,YAAS1F,YAASoB,gBAAQ;CACtG,IAAM,EAAA,MAAA,GAAA,GAAA,MAAQK,GAAAA,EAER,CAACmC,GAASpC,KAAcxC,EAA0D,KAAA,EAClF,CAACsC,GAAcC,KAAmBvC,EAAS,GAAA,EAC3C,CAACmC,GAAmBwE,KAAwB3G,EAAiD,KAAA,EAE7FkC,IAAqBrC,EAAM+G,cACxBH,IAAS3F,EAAyBC,GAAQC,EAAAA,GAAW,MAC5D;EAACD;EAAQC;EAASyF;EAAO,CAAA;AA4B3B,QAzBA5G,EAAMgH,gBAAU;AACd,EAAIJ,KAAUrE,GAAQmC,MACpBtE,QAAgB;AACd0G,KAAqBlF,EAAwBV,GAAQC,GAASoB,EAAOmC,GAAE,CAAA;IACzE;IAED;EAACkC;EAAQrE,GAAQmC;EAAIxD;EAAQC;EAAQ,CAAA,EAepC,CAACyF,KAAU,CAACrE,KAAU,CAACF,KAAsB,CAACC,IACzC,OAIP,kBAAChC,GAAAA;EAAMgG,gBAlBW;AAIlBO,GAHAlE,EAAW,KAAA,EACXD,EAAgB,GAAA,EAChBoE,EAAqB,KAAA,EACrBD,GAAAA;;EAc8BS,OAAOhD,EAAAA,EAAC,EAAA,IAAA,UAAc,CAAA;EAAGiD,MAAMX;EAAQY,MAAK;YACxE,kBAACC,OAAAA,EAAAA,UAAAA,CACE1C,KACC,kBAACxE,GAAAA;GAAQmH,iBAAiB/E,EAAW,KAAA;GAAO0B,MAAMU,EAAQV;GAAMlC,SAAS4C,EAAQR;GAAMoB,WAAU;MAGnG,kBAACzF,GAAAA;GAASyH,UAAU,kBAAC5F,GAAAA,EAAAA,CAAAA;aACnB,kBAACK,GAAAA;IACqBC;IACDC;IACXpB;IACCC;IACDoB;IACRC,gBAxBiB2E,MAAAA;AACzB/G,aAAgB;AACd0G,QAAqBM,QAAQC,QAAQF,EAAAA,CAAAA;OACvC;;IAsBsB1E;IACGC;IACRqC;IACGpC;;;;GClSXuF,KAA2D,EACtEC,aACAC,aACAC,WACAC,cACAC,qBACAC,WACAC,kBACD;CACC,IAAM,EAAA,MAAA,GAAA,GAAA,MAAQC,GAAAA;AAEd,QACE,kBAACb,GAAAA,EAAAA,UAAAA;EACC,kBAACC,GAAAA,EAAAA,UAAcM,GAAAA,CAAAA;EACf,kBAACN,GAAAA;GAAaa,WAAU;aACtB,kBAACZ,GAAAA;IACCa,OAAOT;IACPU,WAAWC,MAAMP,EAAiBO,EAAEC,OAAOH,MAAK;IAChDI,aAAaC,EAAAA,EAAC,EAAA,IAAA,UAAgB,CAAA;IAC9BC,WAAWb,EAAOF;IAClBgB,UAAQ;;;EAGZ,kBAACrB,GAAAA,EAAAA,UACC,kBAACE,GAAAA,EAAAA,UAAAA,CACC,kBAACC,GAAAA;GAAOmB,MAAK;GAAQC,SAASb;GAAQc,SAAQ;GAAUC,OAAON,EAAAA,EAAC,EAAA,IAAA,UAAkB,CAAA;GAAGO,UAAUlB;MAC/F,kBAACL,GAAAA;GAAOmB,MAAK;GAASC,SAASZ;GAAUc,OAAON,EAAAA,EAAC,EAAA,IAAA,UAAO,CAAA;GAAGO,UAAUlB;;;GCxBlE2B,KAAmD,EAAEC,WAAQC,eAAYC,aAAUC,mBAAW;CACzG,IAAM,EAAA,MAAA,GAAA,GAAA,MAAQC,GAAAA,EACR,CAACC,GAASC,KAAcd,EAAS,GAAA;AAEvCC,SAAU;AACR,MAAIY,GAAS;GACX,IAAME,IAAQC,iBAAW;AACvBF,MAAW,GAAA;MACV,IAAA;AAEH,gBAAaG,aAAaF,EAAAA;;IAE3B,CAACF,EAAQ,CAAA;CAEZ,IAAMK,UAAsB;AAE1BR,EADAI,EAAW,GAAA,EACXJ,GAAAA;;AAoCF,QACE,kBAACR,GAAAA,EAAAA,UAAAA;EACC,kBAACC,GAAAA,EAAAA,UAAcK,EAAOsB,WAAAA,CAAAA;EACtB,kBAAC3B,GAAAA;GAAa4B,WAAU;aAAavB,EAAOoB;;EAC5C,kBAACzB,GAAAA,EAAAA,UACEM,IACC,kBAACJ,GAAAA;GAAM2B,cAAa;GAASC,WAAU;aACrC,kBAAC3B,GAAAA,EAAQc,SAAQ,WAAA,CAAA;OAGnB,kBAACf,GAAAA;GAAM2B,cAAa;GAAMC,WAAU;oBA3C7B;AACb,QAAI,CAACtB,EACH,QAAO,kBAAA,GAAA,EAAA,CAAA;AAET,QAAIE,EACF,QACE,kBAACT,GAAAA;KACCgB,SAAQ;KACRC,SAASH;KACTI,OAAOC,EAAAA,EAAC,EAAA,IAAA,UAAqB,CAAA;KAC7BC,cAAYD,EAAAA,EAAC,EAAA,IAAA,UAAqB,CAAA;KAClCE,eAAY;KACZC,UAAUjB;eAETc,EAAAA,EAAC,EAAA,IAAA,UAAO,CAAA;;IAGR;KACL,IAAMI,IAAWnB,EAAOoB;AAExB,YACE,kBAACxB,GAAAA;MACCyB,MAAK;MACLR,eAAeP,EAAW,GAAA;MAC1BQ,OAAOC,EAAAA,EAAC;;iBAAqBI,aAAAA;OAAS,CAAA;MACtCH,cAAYD,EAAAA,EAAC;;iBAAqBI,aAAAA;OAAS,CAAA;MAC3CF,eAAa,UAAUE;MACvBD,UAAUjB;;;OAiBPU;;;GC/CPkC,KAA4BC,GAAoBC,MAC7CD,EAAOE,QAAQC,QACnBC,MAAM;CACLC,YAAYJ;CACZK,YAAY,CAAC,uBAAuB,yBAAyB;CAC/D,CAAA,CACCC,MAAM,CAACC,GAAQC,QAAgB;CAAED;CAAQC;CAAU,EAAA,EAGlDC,KAA6BV,GAAoBC,GAAiBU,MAC/DX,EAAOE,QAAQU,gBAAgBR,MAAM;CAC1CC,YAAYJ;CACFU;CACZ,CAAA;AAGF,SAASE,IAAAA;AACP,QACE,kBAACtB,GAAAA,EAAAA,UACC,kBAACE,GAAAA;EAAaqB,SAAS;YACrB,kBAACpB,GAAAA;GAAMqB,cAAa;GAASC,WAAU;aACrC,kBAACrB,GAAAA,EAAQsB,SAAQ,WAAA,CAAA;;;;AAO3B,SAASC,EAAc,EACrBC,uBACAC,wBACApB,WACAC,YACAoB,WACAC,mBACAC,mBACAC,sBACAC,iBAWD;CACC,IAAM,EAAA,MAAA,GAAA,GAAA,MAAQC,GAAAA,EACR,EAAEC,sBAAmBxC,GAAAA,EAErByC,IAAc/C,EAAIsC,EAAAA,EAClBU,IAAehD,EAAIuC,EAAAA,EAEnB,CAACU,GAAUC,KAAehD,EAAS,GAAA,EACnC,CAACiD,GAAQC,KAAalD,EAAgC,EAAC,CAAA,EACvD,CAACmD,GAAiBC,KAAsBpD,kBAAsB,IAAIqD,KAAAA,CAAAA,EAClE,CAACC,GAAWC,KAAgBvD,EAAS,GAAA,EAErCwD,IAAiBlB,EAAO,kCAAkC,IAC1DmB,IAAuBX,EAAaY,WAAW,KAAK,CAAClB,GAErDmB,UAAe;EACnB,IAAMC,IAAkBb,EAASc,MAAI,EAC/BC,IAAmC,EAAC;AAS1C,SAPKF,IAEMd,EAAaiB,MAAMC,MAAWA,EAAOC,cAAcL,EAAAA,KAC5DE,EAAUf,WAAW,oDAFrBe,EAAUf,WAAW,0BAKvBG,EAAUY,EAAAA,EACHI,OAAOC,KAAKL,EAAAA,CAAWJ,WAAW;IAGrCU,UAAY;AAEhBlB,EADAF,EAAY,GAAA,EACZE,EAAU,EAAC,CAAA;IAGPmB,IAAa,YAAA;AACjB,MAAI,CAACV,GAAAA,EAAgB;AACnBjB,KAAW;IAAE4B,MAAMC,EAAAA,EAAC,EAAA,IAAA,UAAwC,CAAA;IAAGC,MAAM;IAAQ,CAAA;AAC7E;;AAGFjB,IAAa,GAAA;AACb,MAAI;GACF,IAAMK,IAAkBb,EAASc,MAAI;AAerCpB,GAPAF,EANsB,MAAMtB,EAAOE,QAAQuD,gBAAgBC,OAAO;IAChErD,YAAYJ;IACZU,UAAUU,EAAOsC;IACjBC,iBAAiBjB;IACnB,CAAA,CAEea,EAEf/B,EAAW;IACT4B,MAAMC,EAAAA,EAAC;;eAAsBX,oBAAAA;KAA8C,CAAA;IAC3EY,MAAM;IACR,CAAA,EACAJ,GAAAA,EACA3B,EAAkB,GAAA;WACXqC,GAAO;AAGdpC,KAAW;IACT4B,MAAM1B,EAHa,GAAkBoC,WAAW,8BAGX;IACrCR,MAAM;IACR,CAAA;YACQ;AACRjB,KAAa,GAAA;;IAIX0B,IAAqB,OAAOC,MAAAA;AAChC9B,KAAoB+B,MAAS,IAAI9B,IAAI8B,EAAAA,CAAMC,IAAIF,EAAAA,CAAAA;AAE/C,MAAI;AAQFxC,GADAH,EANsB,MAAMtB,EAAOE,QAAQkE,mBAAmBV,OAAO;IACnErD,YAAYJ;IACZU,UAAUU,EAAOsC;IACjBC,iBAAiBK;IACnB,CAAA,CAEeT,EACf/B,EAAW;IACT4B,MAAMC,EAAAA,EAAC;;eAAsBW,qBAAAA;KAAiD,CAAA;IAC9EV,MAAM;IACR,CAAA;WACOM,GAAO;AAGdpC,KAAW;IACT4B,MAAM1B,EAHa,GAAkBoC,WAAW,iCAG+C;IAC/FR,MAAM;IACR,CAAA;YACQ;AACRpB,MAAoB+B,MAAAA;IAClB,IAAMG,IAAS,IAAIjC,IAAI8B,EAAAA;AAEvB,WADAG,EAAOC,OAAOL,EAAAA,EACPI;KACT;;;AA0BJ,QAjBI9B,IAEA,kBAACjD,GAAAA;EAASoF,SAAS;aACjB,kBAACnF,GAAAA,EAAAA,UAAAA;GACC,kBAACC,GAAAA,EAAAA,UAAkB8D,EAAAA,EAAC,EAAA,IAAA,UAAU,CAAA,EAAA,CAAA;GAC9B,kBAAC9D,GAAAA,EAAAA,UAAkB8D,EAAAA,EAAC,EAAA,IAAA,UAAU,CAAA,EAAA,CAAA;GAC9B,kBAAC9D,GAAAA,EAAAA,UAAiB,KAAA,CAAA;QAEpB,kBAACD,GAAAA,EAAAA,UACC,kBAACE,GAAAA;GAAaqB,SAAS;GAAG6D,WAAU;aACjCrB,EAAAA,EAAC,EAAA,IAAA,UAAwD,CAAA;;MAQlE,kBAAA,GAAA,EAAA,UAAA,CACG1B,EAAYpB,UACX,kBAACd,GAAAA;EAAMkF,WAAU;EAAaD,WAAU;YACtC,kBAAC/E,GAAAA;GACCiF,OAAOvB,EAAAA,EAAC,EAAA,IAAA,UAAkB,CAAA;GAC1BwB,eAAY;GACZC,eAAevD,EAAkB,GAAA;GACjCP,SAAQ;GACR+D,UAAUzD;;KAKhB,kBAACjC,GAAAA;EAASoF,SAAS;;GACjB,kBAACnF,GAAAA,EAAAA,UAAAA;IACC,kBAACC,GAAAA,EAAAA,UAAkB8D,EAAAA,EAAC,EAAA,IAAA,UAAU,CAAA,EAAA,CAAA;IAC9B,kBAAC9D,GAAAA,EAAAA,UAAkB8D,EAAAA,EAAC,EAAA,IAAA,UAAU,CAAA,EAAA,CAAA;IAC9B,kBAAC9D,GAAAA,EAAAA,CAAAA;;GAGF+B,KACC,kBAAC1B,GAAAA;IACWiC;IACVnB,UAAUU,EAAOsC;IACT3B;IACGK;IACX4C,mBAjDoBT,MAAAA;AAE5B,KADAzC,EAAYyC,EAAAA,EACRxC,EAAOF,YAAUG,GAAWiC,OAAU;MAAE,GAAGA;MAAMpC,UAAU2C,KAAAA;MAAU,EAAA;;IAgDjES,QAAQ9B;IACR+B,gBAAU;AAGR1D,KAFA0B,GAAAA,EACA3B,EAAkB,GAAA,EAClBC,EAAW,KAAA;;;GAKhBI,EAAauD,KAAKrC,MACjB,kBAACjD,GAAAA;IAESiD;IACRsC,YAAYnD,EAAgBoD,IAAIvC,EAAOC,UAAS;IAChDuC,gBAAgBvB,EAAmBjB,EAAOC,UAAS;IACnDwC,WAAW5D,EAAYnB;MAJlBsC,EAAOC,UAAS,CAAA;GAQxBR,KACC,kBAACjD,GAAAA,EAAAA,UACC,kBAACE,GAAAA;IAAaqB,SAAS;IAAG6D,WAAU;cACjCrB,EAAAA,EAAC,EAAA,IAAA,UAAyG,CAAA;;;;;AASzH,IAAamC,KAAkD,EAAEzF,WAAQ0F,WAAQC,YAAS1F,YAASoB,gBAAQ;CACzG,IAAM,EAAA,MAAA,GAAA,GAAA,MAAQK,GAAAA,EACR,EAAEC,sBAAmBxC,GAAAA,EAErB,CAAC4E,GAAStC,KAAc1C,EAA0D,KAAA,EAClF,CAACwC,GAAgBC,KAAqBzC,EAAS,GAAA,EAE/CoC,IAAqBjC,QAClBwG,IAAS3F,EAAyBC,GAAQC,EAAAA,GAAW,MAC5D;EAACD;EAAQC;EAASyF;EAAO,CAAA,EAGrBtE,IAAsBlC,QACtB,CAACwG,KAAU,CAACrE,GAAQsC,KAAW,OAC5BjD,EAA0BV,GAAQC,GAASoB,EAAOsC,GAAE,CACxDpD,MAAMwC,MACLA,EAAO6C,QAAQC,GAAOC,GAAKC,MAAQA,EAAIC,WAAWC,MAAMA,EAAEjD,cAAc6C,EAAM7C,UAAS,KAAM8C,EAAAA,CAAAA,CAE9FI,OAAOrC,OAENpC,EAAW;EAAE4B,MADD1B,EAAe,GAAkBoC,WAAW,2BAAA;EAChCR,MAAM;EAAQ,CAAA,EAC/B,EAAE,EACX,EACD;EAACmC;EAAQrE,GAAQsC;EAAI3D;EAAQC;EAAQ,CAAA;AAExChB,SAAU;AACR,EAAIyG,KAAQjE,EAAW,KAAA;IACtB,CAACiE,GAAQrE,GAAQsC,GAAG,CAAA;CAKvB,IAAM,CAACyC,GAAsBC,KAA2BtH,EAG9C,KAAA,EAEJuH,IAAY,GAAGZ,EAAO,GAAGrE,GAAQsC,MACjC4C,IACJH,GAAsBI,QAAQF,IAAYF,EAAqBK,UAAUrF,GAErEsF,UAAc;AAIlBf,EAHAlE,EAAW,KAAA,EACXD,EAAkB,GAAA,EAClB6E,EAAwB,KAAA,EACxBV,GAAAA;IAGIgB,KAAsB5D,MAAAA;EAC1B,IAAM6D,IAAe7D,EAAO6C,QACzBC,GAAOC,GAAKC,MAAQA,EAAIC,WAAWC,MAAMA,EAAEjD,cAAc6C,EAAM7C,UAAS,KAAM8C,EAAAA;AAEjF9G,UAAgB;AACdqH,KAAwB;IAAEG,KAAKF;IAAWG,SAASI,QAAQC,QAAQF,EAAAA;IAAc,CAAA;IACnF;;AAGF,KAAI,CAAClB,KAAU,CAACrE,KAAU,CAACF,KAAsB,CAACoF,EAChD,QAAO;CAET,IAAMQ,IAAa1F,EAAO2F;AAE1B,QACE,kBAAC5H,GAAAA;EAAM+F,UAAUuB;EAAaO,OAAO3D,EAAAA,EAAC;;aAAmByD,eAAAA;GAAW,CAAA;EAAGG,MAAMxB;EAAQyB,MAAK;YACxF,kBAACC,OAAAA,EAAAA,UAAAA,CACErD,KACC,kBAAC1E,GAAAA;GACCgI,iBAAiB5F,EAAW,KAAA;GAC5B4B,MAAMU,EAAQV;GACdpC,SAAS8C,EAAQR;GACjBoB,WAAU;GACV2C,aAAW;MAIf,kBAACxI,GAAAA;GAASyI,UAAU,kBAAC1G,GAAAA,EAAAA,CAAAA;aACnB,kBAACK,GAAAA;IACqBC;IACpBC,qBAAqBmF;IACbvG;IACCC;IACDoB;IACRC,gBAAgBqF;IACApF;IACGC;IACPC;;;;GC9TX6G,KAAuD,EAClEC,WACAC,WACAC,YACAC,YACAC,WACAC,mBACD;CACC,IAAM,EAAA,MAAA,GAAA,GAAA,MAAQC,GAAAA,EACR,EAAEC,sBAAmBT,GAAAA,EACrB,CAACU,GAAWC,KAAgBvB,EAAS,GAAA,EACrC,CAACwB,GAAcC,KAAmBzB,EAAwB,KAAA,EAE1D0B,IAAe,YAAA;AACnB,MAAI,CAACR,GAAQS,IAAI;AACfF,KAAgBG,EAAAA,EAAC,EAAA,IAAA,UAAiC,CAAA,CAAA;AAClD;;AAGFH,IAAgB,KAAA;AAEhB,MAAI;AAQFS,GAPAX,EAAa,GAAA,EAEb,MAAMT,EAAOe,QAAQC,aAAaC,OAAO;IACvCC,YAAYf;IACZgB,UAAUf,EAAOS;IACnB,CAAA,EACAR,GAAAA,EACAe,GAAAA;WACOC,GAAO;AAIdV,KAHqB,GAAkBY,UACnChB,EAAe,EAAiBgB,QAAO,GACvCT,EAAAA,EAAC,EAAA,IAAA,UAA2C,CAAA,CAChCQ;YACR;AACRb,KAAa,GAAA;;IAIXW,UAAc;AAElBlB,EADAS,EAAgB,KAAA,EAChBT,GAAAA;;AAOF,QACE,kBAACf,GAAAA;EACCsC,UAAUL;EACVM,OAAOZ,EAAAA,EAAC,EAAA,IAAA,UAAc,CAAA;EACtBa,MAAM1B;EACN2B,WAAWhB;EACXiB,aACE,kBAACvC,GAAAA;GAAYwC,WAAU;aACrB,kBAACtC,GAAAA,EAAAA,UAAAA,CACC,kBAACD,GAAAA;IAAOwC,SAAQ;IAAiBC,SAASpB;IAAcqB,UAAUzB;cAC/DA,IAAY,kBAACnB,GAAAA,EAAQ6C,MAAK,SAAA,CAAA,GAAa,kBAAA,GAAA,EAAA,IAAA,UAAA,CAAA;OAE1C,kBAAC3C,GAAAA;IAAOwC,SAAQ;IAAUC,SAASZ;cACjC,kBAAA,GAAA,EAAA,IAAA,UAAA,CAAA;;;aAMPZ,KACC,kBAACX,GAAAA;GAAMsC,cAAa;GAASC,WAAU;aACrC,kBAAC/C,GAAAA,EAAQ0C,SAAQ,WAAA,CAAA;MAGpB,CAACvB,KACA,kBAAC6B,OAAAA,EAAAA,UAAAA;GACE3B,KAAgB,kBAACtB,GAAAA;IAAQkD,iBA9Bb;AACnB3B,OAAgB,KAAA;;IA6ByC4B,MAAM7B;IAAcqB,SAAQ;IAAQD,WAAU;;GAEjG,kBAAC1C,GAAAA;IACCmD,MAAMzB,EAAAA,EAAC,EAAA,IAAA,UAAsE,CAAA;IAC7EiB,SAAQ;IACRD,WAAU;;GAGX1B,KACC,kBAACX,GAAAA;IAAS+C,SAAS;;KACjB,kBAAC9C,GAAAA,EAAAA,UAAAA,CACC,kBAACC,GAAAA,EAAAA,UAAkBmB,EAAAA,EAAC,EAAA,IAAA,UAAK,CAAA,EAAA,CAAA,EACzB,kBAAClB,GAAAA,EAAAA,UAAcQ,EAAOqC,MAAAA,CAAAA,CAAAA,EAAAA,CAAAA;KAExB,kBAAC/C,GAAAA,EAAAA,UAAAA,CACC,kBAACC,GAAAA,EAAAA,UAAkBmB,EAAAA,EAAC,EAAA,IAAA,UAAG,CAAA,EAAA,CAAA,EACvB,kBAAClB,GAAAA,EAAAA,UAAcQ,EAAOS,IAAAA,CAAAA,CAAAA,EAAAA,CAAAA;KAExB,kBAACnB,GAAAA,EAAAA,UAAAA,CACC,kBAACC,GAAAA,EAAAA,UAAkBmB,EAAAA,EAAC,EAAA,IAAA,UAAM,CAAA,EAAA,CAAA,EAC1B,kBAAClB,GAAAA,EAAAA,UAAcQ,EAAOsC,OAAAA,CAAAA,CAAAA,EAAAA,CAAAA;KAExB,kBAAChD,GAAAA,EAAAA,UAAAA,CACC,kBAACC,GAAAA,EAAAA,UAAkBmB,EAAAA,EAAC,EAAA,IAAA,UAAI,CAAA,EAAA,CAAA,EACxB,kBAAClB,GAAAA,EAAAA,UAAAA,CAAcQ,EAAOuC,KAAI,OAAA,EAAA,CAAA,CAAA,EAAA,CAAA;KAE5B,kBAACjD,GAAAA,EAAAA,UAAAA,CACC,kBAACC,GAAAA,EAAAA,UAAkBmB,EAAAA,EAAC,EAAA,IAAA,UAAK,CAAA,EAAA,CAAA,EACzB,kBAAClB,GAAAA,EAAAA,UAAAA,CAAcQ,EAAOwC,MAAK,OAAA,EAAA,CAAA,CAAA,EAAA,CAAA;KAE5BxC,EAAOyC,QACN,kBAACnD,GAAAA,EAAAA,UAAAA,CACC,kBAACC,GAAAA,EAAAA,UAAkBmB,EAAAA,EAAC,EAAA,IAAA,UAAK,CAAA,EAAA,CAAA,EACzB,kBAAClB,GAAAA,EAAAA,UAAAA,CAAcQ,EAAOyC,MAAK,OAAA,EAAA,CAAA,CAAA,EAAA,CAAA"}
|
|
@@ -1,129 +0,0 @@
|
|
|
1
|
-
import { _ as e, f as t, nt as n, x as r } from "./build-BJDfnAyi.mjs";
|
|
2
|
-
import { t as i } from "./SortInput-DXWSqSny.mjs";
|
|
3
|
-
import { n as a, t as o } from "./FiltersInput-OVeIJzIo.mjs";
|
|
4
|
-
import { Fragment as s, jsx as c, jsxs as l } from "react/jsx-runtime";
|
|
5
|
-
import { useCallback as u, useEffect as d, useRef as f } from "react";
|
|
6
|
-
import { Trans as p, useLingui as m } from "@lingui/react";
|
|
7
|
-
//#region src/client/components/ListToolbar/index.tsx
|
|
8
|
-
var h = ({ filterSettings: h, onFilter: g, sortSettings: _, onSort: v, searchTerm: y, onSearch: b, searchInputProps: x = {}, actions: S, tabs: C, totalCount: w, filteredCount: T, itemName: E = "items", lastUpdated: D }) => {
|
|
9
|
-
let { i18n: O, _: k } = m(), A = f(void 0);
|
|
10
|
-
d(() => () => {
|
|
11
|
-
A.current && clearTimeout(A.current);
|
|
12
|
-
}, []);
|
|
13
|
-
let j = (e) => e ? (typeof e == "string" ? new Date(e) : e).toLocaleString() : "", M = w !== void 0 && T !== void 0, N = u((e) => {
|
|
14
|
-
!g || !h || g({
|
|
15
|
-
...h,
|
|
16
|
-
selectedFilters: h.selectedFilters?.filter((t) => !(t.name === e.name && t.value === e.value))
|
|
17
|
-
});
|
|
18
|
-
}, [h, g]), P = (e) => {
|
|
19
|
-
if (!g || !h || h.selectedFilters?.some((t) => t.name === e.name && t.value === e.value)) return;
|
|
20
|
-
let t = h.filters.find((t) => e.name === t.filterName)?.supportsMultiValue ? [...h.selectedFilters || [], e] : [...(h.selectedFilters || []).filter((t) => t.name !== e.name), e];
|
|
21
|
-
g({
|
|
22
|
-
...h,
|
|
23
|
-
selectedFilters: t
|
|
24
|
-
});
|
|
25
|
-
}, F = u((e) => {
|
|
26
|
-
let t = typeof e == "string" ? e : "";
|
|
27
|
-
A.current && clearTimeout(A.current), b?.(t);
|
|
28
|
-
}, [b]), I = u((e) => {
|
|
29
|
-
let t = e.currentTarget.value;
|
|
30
|
-
A.current && clearTimeout(A.current), A.current = window.setTimeout(() => b?.(t), 500);
|
|
31
|
-
}, [b]), L = u(() => {
|
|
32
|
-
A.current && clearTimeout(A.current), b?.("");
|
|
33
|
-
}, [b]), R = h && g ? {
|
|
34
|
-
filters: h.filters,
|
|
35
|
-
onChange: P
|
|
36
|
-
} : null, z = _ && v ? {
|
|
37
|
-
options: _.options,
|
|
38
|
-
sortBy: _.sortBy,
|
|
39
|
-
sortDirection: _.sortDirection || "asc",
|
|
40
|
-
onSortByChange: (e) => v({
|
|
41
|
-
..._,
|
|
42
|
-
sortBy: e,
|
|
43
|
-
sortDirection: _.sortDirection || "asc"
|
|
44
|
-
}),
|
|
45
|
-
onSortDirectionChange: (e) => v({
|
|
46
|
-
..._,
|
|
47
|
-
sortDirection: e
|
|
48
|
-
})
|
|
49
|
-
} : null, B = b ? {
|
|
50
|
-
placeholder: O._({ id: "YIix5Y" }),
|
|
51
|
-
"data-testid": "searchbar",
|
|
52
|
-
value: y,
|
|
53
|
-
onInput: I,
|
|
54
|
-
onClear: L,
|
|
55
|
-
onSearch: F,
|
|
56
|
-
...x
|
|
57
|
-
} : null;
|
|
58
|
-
return /* @__PURE__ */ l(s, { children: [C && /* @__PURE__ */ c("div", {
|
|
59
|
-
className: "w-full",
|
|
60
|
-
children: /* @__PURE__ */ c(e, {
|
|
61
|
-
activeItem: C.activeItem,
|
|
62
|
-
onActiveItemChange: C.onActiveItemChange,
|
|
63
|
-
children: C.items.map((e) => /* @__PURE__ */ c(r, {
|
|
64
|
-
label: e.label,
|
|
65
|
-
value: e.value
|
|
66
|
-
}, e.value))
|
|
67
|
-
})
|
|
68
|
-
}), /* @__PURE__ */ l(n, {
|
|
69
|
-
alignment: "center",
|
|
70
|
-
gap: "6",
|
|
71
|
-
className: "bg-theme-background-lvl-1 flex w-full flex-col p-4",
|
|
72
|
-
children: [
|
|
73
|
-
S && /* @__PURE__ */ c(n, {
|
|
74
|
-
direction: "horizontal",
|
|
75
|
-
className: "w-full justify-end",
|
|
76
|
-
children: S
|
|
77
|
-
}),
|
|
78
|
-
/* @__PURE__ */ l("div", {
|
|
79
|
-
className: "flex w-full flex-col items-stretch gap-4 md:flex-row md:items-center",
|
|
80
|
-
children: [
|
|
81
|
-
R && /* @__PURE__ */ c("div", {
|
|
82
|
-
className: "w-full md:w-auto md:min-w-37.5",
|
|
83
|
-
children: /* @__PURE__ */ c(o, { ...R })
|
|
84
|
-
}),
|
|
85
|
-
z && /* @__PURE__ */ c("div", {
|
|
86
|
-
className: "w-full md:w-auto md:min-w-45",
|
|
87
|
-
children: /* @__PURE__ */ c(i, { ...z })
|
|
88
|
-
}),
|
|
89
|
-
B && /* @__PURE__ */ c("div", {
|
|
90
|
-
className: "w-full md:ml-auto md:w-auto md:min-w-25",
|
|
91
|
-
children: /* @__PURE__ */ c(t, { ...B })
|
|
92
|
-
})
|
|
93
|
-
]
|
|
94
|
-
}),
|
|
95
|
-
h?.selectedFilters && h.selectedFilters.length > 0 && g && /* @__PURE__ */ c("div", {
|
|
96
|
-
className: "w-full",
|
|
97
|
-
children: /* @__PURE__ */ c(a, {
|
|
98
|
-
selectedFilters: h.selectedFilters,
|
|
99
|
-
onDelete: N,
|
|
100
|
-
onClear: () => g({
|
|
101
|
-
...h,
|
|
102
|
-
selectedFilters: []
|
|
103
|
-
})
|
|
104
|
-
})
|
|
105
|
-
}),
|
|
106
|
-
(M || D) && /* @__PURE__ */ c("div", {
|
|
107
|
-
className: "text-theme-secondary flex w-full items-center justify-between text-sm",
|
|
108
|
-
children: /* @__PURE__ */ l("div", {
|
|
109
|
-
className: "flex items-center gap-2",
|
|
110
|
-
children: [M && /* @__PURE__ */ c("span", { children: /* @__PURE__ */ c(p, {
|
|
111
|
-
id: "Vg0k6h",
|
|
112
|
-
values: {
|
|
113
|
-
filteredCount: T,
|
|
114
|
-
totalCount: w,
|
|
115
|
-
itemName: E
|
|
116
|
-
}
|
|
117
|
-
}) }), D && /* @__PURE__ */ c("span", { children: /* @__PURE__ */ c(p, {
|
|
118
|
-
id: "wlUDbB",
|
|
119
|
-
values: { formattedDate: j(D) }
|
|
120
|
-
}) })]
|
|
121
|
-
})
|
|
122
|
-
})
|
|
123
|
-
]
|
|
124
|
-
})] });
|
|
125
|
-
};
|
|
126
|
-
//#endregion
|
|
127
|
-
export { h as t };
|
|
128
|
-
|
|
129
|
-
//# sourceMappingURL=ListToolbar-BojRTNbo.mjs.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"ListToolbar-BojRTNbo.mjs","names":["useCallback","useRef","useEffect","SearchInput","Stack","TabNavigation","TabNavigationItem","SelectedFilters","FiltersInput","SortInput","ListToolbar","filterSettings","onFilter","sortSettings","onSort","searchTerm","onSearch","searchInputProps","actions","tabs","totalCount","filteredCount","itemName","lastUpdated","useLingui","debounceTimerRef","undefined","current","clearTimeout","formatLastUpdated","date","dateObj","Date","toLocaleString","showCountInfo","handleFilterDelete","filterToRemove","selectedFilters","filter","name","value","handleSelect","selectedFilter","filterExists","some","supportsMultiValue","filters","find","filterName","newSelected","handleSearch","searchValue","handleSearchInput","event","currentTarget","window","setTimeout","handleSearchClear","filtersProps","onChange","sortProps","options","sortBy","sortDirection","onSortByChange","param","onSortDirectionChange","direction","searchProps","placeholder","t","onInput","onClear","div","className","activeItem","onActiveItemChange","items","map","item","label","alignment","gap","length","onDelete","span","formattedDate"],"sources":["../../src/client/components/ListToolbar/index.tsx"],"sourcesContent":["import { ReactNode, useCallback, useRef, useEffect } from \"react\"\nimport { Trans, useLingui } from \"@lingui/react/macro\"\nimport {\n SearchInput,\n SearchInputProps,\n Stack,\n TabNavigation,\n TabNavigationItem,\n} from \"@cloudoperators/juno-ui-components\"\nimport { SelectedFilters } from \"./SelectedFilters\"\nimport { FiltersInput } from \"./FiltersInput\"\nimport { SortInput } from \"./SortInput\"\nimport { FilterSettings, SelectedFilter, SortSettings } from \"./types\"\n\nexport type ListToolbarProps = {\n filterSettings?: FilterSettings\n onFilter?: (filterSettings: FilterSettings) => void\n sortSettings?: SortSettings\n onSort?: (sortSettings: SortSettings) => void\n searchTerm?: string\n onSearch?: (searchTerm: string) => void\n searchInputProps?: Omit<SearchInputProps, \"value\" | \"onSearch\" | \"onClear\" | \"onInput\">\n actions?: ReactNode\n tabs?: {\n items: Array<{ label: string; value: string }>\n activeItem: string\n onActiveItemChange: (value: ReactNode) => void\n }\n // Count information\n totalCount?: number\n itemName?: string // e.g. \"items\", \"users\", \"projects\" - used in count display\n filteredCount?: number\n // Last updated timestamp\n lastUpdated?: Date | string\n}\n\nexport const ListToolbar = ({\n filterSettings,\n onFilter,\n sortSettings,\n onSort,\n searchTerm,\n onSearch,\n searchInputProps = {},\n actions,\n tabs,\n totalCount,\n filteredCount,\n itemName = \"items\",\n lastUpdated,\n}: ListToolbarProps) => {\n const { t } = useLingui()\n\n const debounceTimerRef = useRef<number | undefined>(undefined)\n\n useEffect(() => {\n return () => {\n if (debounceTimerRef.current) {\n clearTimeout(debounceTimerRef.current)\n }\n }\n }, [])\n\n // Format last updated time\n const formatLastUpdated = (date: Date | string | undefined): string => {\n if (!date) return \"\"\n const dateObj = typeof date === \"string\" ? new Date(date) : date\n return dateObj.toLocaleString()\n }\n\n const showCountInfo = totalCount !== undefined && filteredCount !== undefined\n\n const handleFilterDelete = useCallback(\n (filterToRemove: SelectedFilter) => {\n if (!onFilter || !filterSettings) return\n onFilter({\n ...filterSettings,\n selectedFilters: filterSettings.selectedFilters?.filter(\n (filter) => !(filter.name === filterToRemove.name && filter.value === filterToRemove.value)\n ),\n })\n },\n [filterSettings, onFilter]\n )\n\n const handleSelect = (selectedFilter: SelectedFilter) => {\n if (!onFilter || !filterSettings) return\n const filterExists = filterSettings.selectedFilters?.some(\n (filter) => filter.name === selectedFilter.name && filter.value === selectedFilter.value\n )\n if (filterExists) return\n\n const supportsMultiValue = filterSettings.filters.find(\n (filter) => selectedFilter.name === filter.filterName\n )?.supportsMultiValue\n\n const newSelected = supportsMultiValue\n ? [...(filterSettings.selectedFilters || []), selectedFilter]\n : [\n ...(filterSettings.selectedFilters || []).filter((filter) => filter.name !== selectedFilter.name),\n selectedFilter,\n ]\n\n onFilter({ ...filterSettings, selectedFilters: newSelected })\n }\n\n const handleSearch = useCallback(\n (value: string | number | string[] | undefined) => {\n const searchValue = typeof value === \"string\" ? value : \"\"\n\n if (debounceTimerRef.current) {\n clearTimeout(debounceTimerRef.current)\n }\n\n onSearch?.(searchValue)\n },\n [onSearch]\n )\n\n const handleSearchInput = useCallback(\n (event: React.FormEvent<HTMLInputElement>) => {\n const searchValue = event.currentTarget.value\n if (debounceTimerRef.current) clearTimeout(debounceTimerRef.current)\n debounceTimerRef.current = window.setTimeout(() => onSearch?.(searchValue), 500)\n },\n [onSearch]\n )\n\n const handleSearchClear = useCallback(() => {\n if (debounceTimerRef.current) clearTimeout(debounceTimerRef.current)\n onSearch?.(\"\")\n }, [onSearch])\n\n const filtersProps = filterSettings && onFilter ? { filters: filterSettings.filters, onChange: handleSelect } : null\n const sortProps =\n sortSettings && onSort\n ? {\n options: sortSettings.options,\n sortBy: sortSettings.sortBy,\n sortDirection: sortSettings.sortDirection || \"asc\",\n onSortByChange: (param: string | number | string[] | undefined) =>\n onSort({ ...sortSettings, sortBy: param, sortDirection: sortSettings.sortDirection || \"asc\" }),\n onSortDirectionChange: (direction: \"asc\" | \"desc\") => onSort({ ...sortSettings, sortDirection: direction }),\n }\n : null\n\n const searchProps: (SearchInputProps & { \"data-testid\"?: string }) | null = onSearch\n ? {\n placeholder: t`Search...`,\n \"data-testid\": \"searchbar\",\n value: searchTerm,\n onInput: handleSearchInput,\n onClear: handleSearchClear,\n onSearch: handleSearch,\n ...searchInputProps,\n }\n : null\n\n return (\n <>\n {tabs && (\n <div className=\"w-full\">\n <TabNavigation activeItem={tabs.activeItem} onActiveItemChange={tabs.onActiveItemChange}>\n {tabs.items.map((item) => (\n <TabNavigationItem key={item.value} label={item.label} value={item.value} />\n ))}\n </TabNavigation>\n </div>\n )}\n <Stack alignment=\"center\" gap=\"6\" className=\"bg-theme-background-lvl-1 flex w-full flex-col p-4\">\n {actions && (\n <Stack direction=\"horizontal\" className=\"w-full justify-end\">\n {actions}\n </Stack>\n )}\n\n <div className=\"flex w-full flex-col items-stretch gap-4 md:flex-row md:items-center\">\n {filtersProps && (\n <div className=\"w-full md:w-auto md:min-w-37.5\">\n <FiltersInput {...filtersProps} />\n </div>\n )}\n {sortProps && (\n <div className=\"w-full md:w-auto md:min-w-45\">\n <SortInput {...sortProps} />\n </div>\n )}\n {searchProps && (\n <div className=\"w-full md:ml-auto md:w-auto md:min-w-25\">\n <SearchInput {...searchProps} />\n </div>\n )}\n </div>\n\n {filterSettings?.selectedFilters && filterSettings.selectedFilters.length > 0 && onFilter && (\n <div className=\"w-full\">\n <SelectedFilters\n selectedFilters={filterSettings.selectedFilters}\n onDelete={handleFilterDelete}\n onClear={() => onFilter({ ...filterSettings, selectedFilters: [] })}\n />\n </div>\n )}\n {/* Count and Last Updated Info */}\n {(showCountInfo || lastUpdated) && (\n <div className=\"text-theme-secondary flex w-full items-center justify-between text-sm\">\n <div className=\"flex items-center gap-2\">\n {showCountInfo && (\n <span>\n <Trans>\n Showing {filteredCount} of {totalCount} {itemName}\n </Trans>\n </span>\n )}\n {lastUpdated &&\n (() => {\n const formattedDate = formatLastUpdated(lastUpdated)\n return (\n <span>\n <Trans>Last updated: {formattedDate}</Trans>\n </span>\n )\n })()}\n </div>\n </div>\n )}\n </Stack>\n </>\n )\n}\n"],"mappings":"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"}
|
|
@@ -1,188 +0,0 @@
|
|
|
1
|
-
import { E as e, L as t, N as n, Q as r, R as i, W as a, Y as o, c as s, et as c, h as l, j as u, nt as d } from "./build-BJDfnAyi.mjs";
|
|
2
|
-
import { r as f } from "./trpcClient-BxguzNYF.mjs";
|
|
3
|
-
import { n as p, t as m } from "./_flavorId-BoNcxYmF.mjs";
|
|
4
|
-
import { t as h } from "./useErrorTranslation-TZVwIAzq.mjs";
|
|
5
|
-
import { n as g, r as _, t as v } from "./DeleteFlavorModal-BusYn32r.mjs";
|
|
6
|
-
import { t as y } from "./useModal-DxxlilRm.mjs";
|
|
7
|
-
import { t as b } from "./ContentHeader-BXZoN3B9.mjs";
|
|
8
|
-
import { Fragment as x, jsx as S, jsxs as C } from "react/jsx-runtime";
|
|
9
|
-
import w from "react";
|
|
10
|
-
import { useNavigate as T, useParams as E } from "@tanstack/react-router";
|
|
11
|
-
import { Trans as D, useLingui as O } from "@lingui/react";
|
|
12
|
-
//#region src/client/routes/_auth/projects/$projectId/compute/flavors/-components/FlavorDetailsView.tsx
|
|
13
|
-
function k({ flavor: e }) {
|
|
14
|
-
let r = (e, t = "MB") => e === 0 ? `0 ${t}` : `${e} ${t}`;
|
|
15
|
-
return /* @__PURE__ */ C(d, {
|
|
16
|
-
direction: "vertical",
|
|
17
|
-
gap: "6",
|
|
18
|
-
className: "mt-6",
|
|
19
|
-
children: [
|
|
20
|
-
/* @__PURE__ */ C(d, {
|
|
21
|
-
direction: "vertical",
|
|
22
|
-
gap: "2",
|
|
23
|
-
children: [/* @__PURE__ */ S(u, { children: /* @__PURE__ */ S(D, { id: "jIPNJG" }) }), /* @__PURE__ */ C(a, {
|
|
24
|
-
alignTerms: "right",
|
|
25
|
-
children: [
|
|
26
|
-
/* @__PURE__ */ S(n, { children: /* @__PURE__ */ S(D, { id: "S0kLOH" }) }),
|
|
27
|
-
/* @__PURE__ */ S(t, { children: e.id }),
|
|
28
|
-
/* @__PURE__ */ S(n, { children: /* @__PURE__ */ S(D, { id: "6YtxFj" }) }),
|
|
29
|
-
/* @__PURE__ */ S(t, { children: e.name }),
|
|
30
|
-
/* @__PURE__ */ S(n, { children: /* @__PURE__ */ S(D, { id: "Nu4oKW" }) }),
|
|
31
|
-
/* @__PURE__ */ S(t, { children: e?.description }),
|
|
32
|
-
/* @__PURE__ */ S(n, { children: /* @__PURE__ */ S(D, { id: "7d1a0d" }) }),
|
|
33
|
-
/* @__PURE__ */ S(t, { children: e["os-flavor-access:is_public"] ? /* @__PURE__ */ S(D, { id: "l75CjT" }) : /* @__PURE__ */ S(D, { id: "1UzENP" }) }),
|
|
34
|
-
/* @__PURE__ */ S(n, { children: /* @__PURE__ */ S(D, { id: "E/QGRL" }) }),
|
|
35
|
-
/* @__PURE__ */ S(t, { children: e["OS-FLV-DISABLED:disabled"] ? /* @__PURE__ */ S(D, { id: "l75CjT" }) : /* @__PURE__ */ S(D, { id: "1UzENP" }) })
|
|
36
|
-
]
|
|
37
|
-
})]
|
|
38
|
-
}),
|
|
39
|
-
/* @__PURE__ */ C(d, {
|
|
40
|
-
direction: "vertical",
|
|
41
|
-
gap: "2",
|
|
42
|
-
children: [/* @__PURE__ */ S(u, { children: /* @__PURE__ */ S(D, { id: "qQ1QBh" }) }), /* @__PURE__ */ C(a, {
|
|
43
|
-
alignTerms: "right",
|
|
44
|
-
children: [
|
|
45
|
-
/* @__PURE__ */ S(n, { children: /* @__PURE__ */ S(D, { id: "MZGbkp" }) }),
|
|
46
|
-
/* @__PURE__ */ S(t, { children: e.vcpus }),
|
|
47
|
-
/* @__PURE__ */ S(n, { children: /* @__PURE__ */ S(D, { id: "RGhYAo" }) }),
|
|
48
|
-
/* @__PURE__ */ S(t, { children: r(e.ram, "MiB") }),
|
|
49
|
-
/* @__PURE__ */ S(n, { children: /* @__PURE__ */ S(D, { id: "sPFHpI" }) }),
|
|
50
|
-
/* @__PURE__ */ S(t, { children: r(e.disk, "GiB") }),
|
|
51
|
-
/* @__PURE__ */ S(n, { children: /* @__PURE__ */ S(D, { id: "r9Aac8" }) }),
|
|
52
|
-
/* @__PURE__ */ S(t, { children: r(e["OS-FLV-EXT-DATA:ephemeral"] || 0, "GiB") }),
|
|
53
|
-
/* @__PURE__ */ S(n, { children: /* @__PURE__ */ S(D, { id: "vH2C/2" }) }),
|
|
54
|
-
/* @__PURE__ */ S(t, { children: e.swap === 0 || e.swap === "" ? /* @__PURE__ */ S(D, { id: "EdQY6l" }) : r(Number(e.swap), "MiB") }),
|
|
55
|
-
/* @__PURE__ */ S(n, { children: /* @__PURE__ */ S(D, { id: "u5HztT" }) }),
|
|
56
|
-
/* @__PURE__ */ S(t, { children: e.rxtx_factor })
|
|
57
|
-
]
|
|
58
|
-
})]
|
|
59
|
-
}),
|
|
60
|
-
e.extra_specs && Object.keys(e.extra_specs).length > 0 && /* @__PURE__ */ C(d, {
|
|
61
|
-
direction: "vertical",
|
|
62
|
-
gap: "2",
|
|
63
|
-
children: [/* @__PURE__ */ S(u, { children: /* @__PURE__ */ S(D, { id: "DKkOPx" }) }), /* @__PURE__ */ S(a, {
|
|
64
|
-
alignTerms: "right",
|
|
65
|
-
children: Object.entries(e.extra_specs).map(([e, r]) => /* @__PURE__ */ C(w.Fragment, { children: [/* @__PURE__ */ S(n, { children: e }), /* @__PURE__ */ S(t, { children: r })] }, e))
|
|
66
|
-
})]
|
|
67
|
-
})
|
|
68
|
-
]
|
|
69
|
-
});
|
|
70
|
-
}
|
|
71
|
-
//#endregion
|
|
72
|
-
//#region src/client/routes/_auth/projects/$projectId/compute/flavors/$flavorId.tsx?tsr-split=component
|
|
73
|
-
function A() {
|
|
74
|
-
let { projectId: t, flavorId: n } = E({ from: "/_auth/projects/$projectId/compute/flavors/$flavorId" }), { trpcClient: a } = m.useRouteContext(), u = T(), { i18n: w, _: A } = O(), { translateError: j, isRetryableError: M } = h(), { data: N, status: P, error: F, refetch: I } = f.compute.getFlavorById.useQuery({
|
|
75
|
-
project_id: t,
|
|
76
|
-
flavorId: n
|
|
77
|
-
}), { data: L } = f.compute.canUser.useQuery({
|
|
78
|
-
project_id: t,
|
|
79
|
-
permission: [
|
|
80
|
-
"flavors:delete",
|
|
81
|
-
"flavors:list_projects",
|
|
82
|
-
"flavor_specs:create",
|
|
83
|
-
"flavor_specs:delete"
|
|
84
|
-
]
|
|
85
|
-
}), R = L?.[0] ?? !1, z = L?.[1] ?? !1, B = (L?.[2] ?? !1) || (L?.[3] ?? !1), [V, H] = y(), [U, W] = y(), [G, K] = y(), q = () => {
|
|
86
|
-
u({
|
|
87
|
-
to: "/projects/$projectId/compute/flavors",
|
|
88
|
-
params: { projectId: t }
|
|
89
|
-
});
|
|
90
|
-
}, J = () => {
|
|
91
|
-
u({
|
|
92
|
-
to: "/projects/$projectId",
|
|
93
|
-
params: { projectId: t }
|
|
94
|
-
});
|
|
95
|
-
}, Y = () => {
|
|
96
|
-
I();
|
|
97
|
-
};
|
|
98
|
-
if (P === "pending") return /* @__PURE__ */ C(d, {
|
|
99
|
-
className: "fixed inset-0",
|
|
100
|
-
distribution: "center",
|
|
101
|
-
alignment: "center",
|
|
102
|
-
direction: "vertical",
|
|
103
|
-
children: [/* @__PURE__ */ S(r, {
|
|
104
|
-
variant: "primary",
|
|
105
|
-
size: "large",
|
|
106
|
-
className: "mb-2"
|
|
107
|
-
}), /* @__PURE__ */ S(D, { id: "YNgcgc" })]
|
|
108
|
-
});
|
|
109
|
-
if (P === "error") {
|
|
110
|
-
let e = F?.message || "UNKNOWN_ERROR", t = j(e), n = M(e);
|
|
111
|
-
return /* @__PURE__ */ S(p, {
|
|
112
|
-
message: t,
|
|
113
|
-
statusCode: ((e) => {
|
|
114
|
-
if (e.includes("UNAUTHORIZED")) return 401;
|
|
115
|
-
if (e.includes("FORBIDDEN")) return 403;
|
|
116
|
-
if (e.includes("NOT_FOUND")) return 404;
|
|
117
|
-
if (e.includes("SERVER_ERROR")) return 500;
|
|
118
|
-
})(e),
|
|
119
|
-
title: w._({ id: "FjONW3" }),
|
|
120
|
-
onBackClick: q,
|
|
121
|
-
onHomeClick: J,
|
|
122
|
-
reset: n ? Y : void 0
|
|
123
|
-
});
|
|
124
|
-
}
|
|
125
|
-
if (!N) return /* @__PURE__ */ S(p, {
|
|
126
|
-
message: w._({ id: "y0u86k" }),
|
|
127
|
-
statusCode: 404,
|
|
128
|
-
title: w._({ id: "bpme7e" }),
|
|
129
|
-
onBackClick: q,
|
|
130
|
-
onHomeClick: J
|
|
131
|
-
});
|
|
132
|
-
let X = z || R, Z = X || B ? /* @__PURE__ */ C(l, { children: [X && /* @__PURE__ */ C(c, { children: [/* @__PURE__ */ S(i, {
|
|
133
|
-
as: "div",
|
|
134
|
-
children: /* @__PURE__ */ S(s, {
|
|
135
|
-
icon: "moreVert",
|
|
136
|
-
children: /* @__PURE__ */ S(D, { id: "PgNNGl" })
|
|
137
|
-
})
|
|
138
|
-
}), /* @__PURE__ */ C(e, { children: [z && /* @__PURE__ */ S(o, {
|
|
139
|
-
label: w._({ id: "cWbW6w" }),
|
|
140
|
-
onClick: W
|
|
141
|
-
}), R && /* @__PURE__ */ S(o, {
|
|
142
|
-
label: w._({ id: "JT3I1g" }),
|
|
143
|
-
onClick: K
|
|
144
|
-
})] })] }), B && /* @__PURE__ */ S(s, {
|
|
145
|
-
onClick: H,
|
|
146
|
-
variant: "primary",
|
|
147
|
-
children: /* @__PURE__ */ S(D, { id: "6GBt0m" })
|
|
148
|
-
})] }) : void 0;
|
|
149
|
-
return /* @__PURE__ */ C(x, { children: [
|
|
150
|
-
/* @__PURE__ */ S(b, {
|
|
151
|
-
title: N.name,
|
|
152
|
-
projectId: t,
|
|
153
|
-
actions: Z
|
|
154
|
-
}),
|
|
155
|
-
/* @__PURE__ */ S(d, {
|
|
156
|
-
direction: "vertical",
|
|
157
|
-
children: /* @__PURE__ */ S(k, { flavor: N })
|
|
158
|
-
}),
|
|
159
|
-
a && /* @__PURE__ */ C(x, { children: [
|
|
160
|
-
V && /* @__PURE__ */ S(_, {
|
|
161
|
-
client: a,
|
|
162
|
-
isOpen: V,
|
|
163
|
-
onClose: H,
|
|
164
|
-
project: t,
|
|
165
|
-
flavor: N
|
|
166
|
-
}),
|
|
167
|
-
U && /* @__PURE__ */ S(g, {
|
|
168
|
-
client: a,
|
|
169
|
-
isOpen: U,
|
|
170
|
-
onClose: W,
|
|
171
|
-
project: t,
|
|
172
|
-
flavor: N
|
|
173
|
-
}),
|
|
174
|
-
G && /* @__PURE__ */ S(v, {
|
|
175
|
-
client: a,
|
|
176
|
-
isOpen: G,
|
|
177
|
-
onClose: K,
|
|
178
|
-
project: t,
|
|
179
|
-
flavor: N,
|
|
180
|
-
onSuccess: q
|
|
181
|
-
})
|
|
182
|
-
] })
|
|
183
|
-
] });
|
|
184
|
-
}
|
|
185
|
-
//#endregion
|
|
186
|
-
export { A as component };
|
|
187
|
-
|
|
188
|
-
//# sourceMappingURL=_flavorId-BRonXvCo.mjs.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"_flavorId-BRonXvCo.mjs","names":["React","Stack","DescriptionList","DescriptionTerm","DescriptionDefinition","ContentHeading","FlavorDetailsView","flavor","formatBytes","bytes","unit","direction","gap","className","alignTerms","id","name","description","vcpus","ram","disk","swap","Number","rxtx_factor","extra_specs","Object","keys","length","entries","map","key","value","Fragment","Button","ButtonRow","Stack","Spinner","PopupMenu","PopupMenuToggle","PopupMenuOptions","PopupMenuItem","useNavigate","useParams","Trans","useLingui","trpcReact","FlavorDetailsView","StatusError","useErrorTranslation","EditSpecModal","ManageAccessModal","DeleteFlavorModal","useModal","ContentHeader","Route","RouteComponent","projectId","flavorId","from","trpcClient","useRouteContext","navigate","t","translateError","isRetryableError","data","flavor","status","error","refetch","compute","getFlavorById","useQuery","project_id","permissionsData","canUser","permission","canDeleteFlavor","canManageAccess","canManageSpecs","specModalOpen","toggleSpecModal","accessModalOpen","toggleAccessModal","deleteModalOpen","toggleDeleteModal","handleBack","to","params","handleHome","handleRetry","errorCode","message","translatedError","canRetry","getStatusCode","code","includes","undefined","hasMoreActions","headerActions","name","component"],"sources":["../../src/client/routes/_auth/projects/$projectId/compute/flavors/-components/FlavorDetailsView.tsx","../../src/client/routes/_auth/projects/$projectId/compute/flavors/$flavorId.tsx?tsr-split=component"],"sourcesContent":["import React from \"react\"\nimport {\n Stack,\n DescriptionList,\n DescriptionTerm,\n DescriptionDefinition,\n ContentHeading,\n} from \"@cloudoperators/juno-ui-components/index\"\nimport { Trans } from \"@lingui/react/macro\"\nimport type { Flavor } from \"@/server/Compute/types/flavor\"\n\ninterface FlavorDetailsViewProps {\n flavor: Flavor\n}\n\nexport function FlavorDetailsView({ flavor }: FlavorDetailsViewProps) {\n const formatBytes = (bytes: number, unit: string = \"MB\") => {\n if (bytes === 0) return `0 ${unit}`\n return `${bytes} ${unit}`\n }\n\n return (\n <Stack direction=\"vertical\" gap=\"6\" className=\"mt-6\">\n <Stack direction=\"vertical\" gap=\"2\">\n <ContentHeading>\n <Trans>Basic Information</Trans>\n </ContentHeading>\n <DescriptionList alignTerms=\"right\">\n <DescriptionTerm>\n <Trans>ID</Trans>\n </DescriptionTerm>\n <DescriptionDefinition>{flavor.id}</DescriptionDefinition>\n\n <DescriptionTerm>\n <Trans>Name</Trans>\n </DescriptionTerm>\n <DescriptionDefinition>{flavor.name}</DescriptionDefinition>\n\n <DescriptionTerm>\n <Trans>Description</Trans>\n </DescriptionTerm>\n <DescriptionDefinition>{flavor?.description}</DescriptionDefinition>\n\n <DescriptionTerm>\n <Trans>Public</Trans>\n </DescriptionTerm>\n <DescriptionDefinition>\n {flavor[\"os-flavor-access:is_public\"] ? <Trans>Yes</Trans> : <Trans>No</Trans>}\n </DescriptionDefinition>\n\n <DescriptionTerm>\n <Trans>Disabled</Trans>\n </DescriptionTerm>\n <DescriptionDefinition>\n {flavor[\"OS-FLV-DISABLED:disabled\"] ? <Trans>Yes</Trans> : <Trans>No</Trans>}\n </DescriptionDefinition>\n </DescriptionList>\n </Stack>\n\n <Stack direction=\"vertical\" gap=\"2\">\n <ContentHeading>\n <Trans>Hardware Specifications</Trans>\n </ContentHeading>\n <DescriptionList alignTerms=\"right\">\n <DescriptionTerm>\n <Trans>VCPUs</Trans>\n </DescriptionTerm>\n <DescriptionDefinition>{flavor.vcpus}</DescriptionDefinition>\n\n <DescriptionTerm>\n <Trans>RAM</Trans>\n </DescriptionTerm>\n <DescriptionDefinition>{formatBytes(flavor.ram, \"MiB\")}</DescriptionDefinition>\n\n <DescriptionTerm>\n <Trans>Disk</Trans>\n </DescriptionTerm>\n <DescriptionDefinition>{formatBytes(flavor.disk, \"GiB\")}</DescriptionDefinition>\n\n <DescriptionTerm>\n <Trans>Ephemeral Disk</Trans>\n </DescriptionTerm>\n <DescriptionDefinition>{formatBytes(flavor[\"OS-FLV-EXT-DATA:ephemeral\"] || 0, \"GiB\")}</DescriptionDefinition>\n\n <DescriptionTerm>\n <Trans>Swap</Trans>\n </DescriptionTerm>\n <DescriptionDefinition>\n {flavor.swap === 0 || flavor.swap === \"\" ? <Trans>None</Trans> : formatBytes(Number(flavor.swap), \"MiB\")}\n </DescriptionDefinition>\n\n <DescriptionTerm>\n <Trans>RX/TX Factor</Trans>\n </DescriptionTerm>\n <DescriptionDefinition>{flavor.rxtx_factor}</DescriptionDefinition>\n </DescriptionList>\n </Stack>\n\n {flavor.extra_specs && Object.keys(flavor.extra_specs).length > 0 && (\n <Stack direction=\"vertical\" gap=\"2\">\n <ContentHeading>\n <Trans>Extra Specs</Trans>\n </ContentHeading>\n <DescriptionList alignTerms=\"right\">\n {Object.entries(flavor.extra_specs).map(([key, value]) => (\n <React.Fragment key={key}>\n <DescriptionTerm>{key}</DescriptionTerm>\n <DescriptionDefinition>{value}</DescriptionDefinition>\n </React.Fragment>\n ))}\n </DescriptionList>\n </Stack>\n )}\n </Stack>\n )\n}\n","import {\n Button,\n ButtonRow,\n Stack,\n Spinner,\n PopupMenu,\n PopupMenuToggle,\n PopupMenuOptions,\n PopupMenuItem,\n} from \"@cloudoperators/juno-ui-components/index\"\nimport { createFileRoute, redirect, useNavigate, useParams } from \"@tanstack/react-router\"\nimport type { RouteInfo } from \"@/client/routes/routeInfo\"\nimport { Trans, useLingui } from \"@lingui/react/macro\"\nimport { getServiceIndex } from \"@/server/Authentication/helpers\"\nimport { trpcReact } from \"@/client/trpcClient\"\nimport { FlavorDetailsView } from \"./-components/FlavorDetailsView\"\nimport { StatusError } from \"@/client/components/Error/StatusError\"\nimport { useErrorTranslation } from \"@/client/utils/useErrorTranslation\"\nimport { EditSpecModal } from \"../-components/Flavors/-components/EditSpecModal\"\nimport { ManageAccessModal } from \"../-components/Flavors/-components/ManageAccessModal\"\nimport { DeleteFlavorModal } from \"../-components/Flavors/-components/DeleteFlavorModal\"\nimport { useModal } from \"@/client/utils/useModal\"\nimport { ContentHeader } from \"@/client/components/ContentHeader/ContentHeader\"\n\nexport const Route = createFileRoute(\"/_auth/projects/$projectId/compute/flavors/$flavorId\")({\n staticData: {\n section: \"compute\",\n service: \"flavors\",\n isDetail: true,\n sectionCrumb: { labelKey: \"Compute\" },\n crumb: { labelKey: \"Flavors\", to: \"/projects/$projectId/compute/flavors\" },\n } satisfies RouteInfo,\n loader: async ({ context, params }) => {\n const flavor = await context.trpcClient?.compute.getFlavorById.query({\n project_id: params.projectId,\n flavorId: params.flavorId,\n })\n return { flavorName: flavor?.name ?? null }\n },\n head: ({ loaderData }) => ({\n meta: [{ title: loaderData?.flavorName ?? \"Flavor Details\" }],\n }),\n component: RouteComponent,\n beforeLoad: async ({ context, params }) => {\n const { trpcClient } = context\n const { projectId } = params\n\n const availableServices = (await trpcClient?.auth.getAvailableServices.query()) || []\n\n const serviceIndex = getServiceIndex(availableServices)\n\n if (!serviceIndex[\"flavor\"] && !serviceIndex[\"compute\"]) {\n throw redirect({\n to: \"/projects/$projectId\",\n params: { projectId },\n })\n }\n },\n})\n\nfunction RouteComponent() {\n const { projectId, flavorId } = useParams({\n from: \"/_auth/projects/$projectId/compute/flavors/$flavorId\",\n })\n const { trpcClient } = Route.useRouteContext()\n const navigate = useNavigate()\n const { t } = useLingui()\n const { translateError, isRetryableError } = useErrorTranslation()\n\n const {\n data: flavor,\n status,\n error,\n refetch,\n } = trpcReact.compute.getFlavorById.useQuery({\n project_id: projectId,\n flavorId,\n })\n\n const { data: permissionsData } = trpcReact.compute.canUser.useQuery({\n project_id: projectId,\n permission: [\"flavors:delete\", \"flavors:list_projects\", \"flavor_specs:create\", \"flavor_specs:delete\"],\n })\n\n const canDeleteFlavor = permissionsData?.[0] ?? false\n const canManageAccess = permissionsData?.[1] ?? false\n const canManageSpecs = (permissionsData?.[2] ?? false) || (permissionsData?.[3] ?? false)\n\n const [specModalOpen, toggleSpecModal] = useModal()\n const [accessModalOpen, toggleAccessModal] = useModal()\n const [deleteModalOpen, toggleDeleteModal] = useModal()\n\n const handleBack = () => {\n navigate({\n to: \"/projects/$projectId/compute/flavors\",\n params: { projectId },\n })\n }\n\n const handleHome = () => {\n navigate({\n to: \"/projects/$projectId\",\n params: { projectId },\n })\n }\n\n const handleRetry = () => {\n refetch()\n }\n\n if (status === \"pending\") {\n return (\n <Stack className=\"fixed inset-0\" distribution=\"center\" alignment=\"center\" direction=\"vertical\">\n <Spinner variant=\"primary\" size=\"large\" className=\"mb-2\" />\n <Trans>Loading Flavor Details...</Trans>\n </Stack>\n )\n }\n\n if (status === \"error\") {\n const errorCode = error?.message || \"UNKNOWN_ERROR\"\n const translatedError = translateError(errorCode)\n const canRetry = isRetryableError(errorCode)\n\n const getStatusCode = (code: string): number | undefined => {\n if (code.includes(\"UNAUTHORIZED\")) return 401\n if (code.includes(\"FORBIDDEN\")) return 403\n if (code.includes(\"NOT_FOUND\")) return 404\n if (code.includes(\"SERVER_ERROR\")) return 500\n return undefined\n }\n\n return (\n <StatusError\n message={translatedError}\n statusCode={getStatusCode(errorCode)}\n title={t`Error Loading Flavor`}\n onBackClick={handleBack}\n onHomeClick={handleHome}\n reset={canRetry ? handleRetry : undefined}\n />\n )\n }\n\n if (!flavor) {\n return (\n <StatusError\n message={t`The requested flavor could not be found. It may have been deleted or you may not have access to it.`}\n statusCode={404}\n title={t`Flavor Not Found`}\n onBackClick={handleBack}\n onHomeClick={handleHome}\n />\n )\n }\n\n const hasMoreActions = canManageAccess || canDeleteFlavor\n\n const headerActions =\n hasMoreActions || canManageSpecs ? (\n <ButtonRow>\n {hasMoreActions && (\n <PopupMenu>\n <PopupMenuToggle as=\"div\">\n <Button icon=\"moreVert\">\n <Trans>More Actions</Trans>\n </Button>\n </PopupMenuToggle>\n <PopupMenuOptions>\n {canManageAccess && <PopupMenuItem label={t`Manage Access`} onClick={toggleAccessModal} />}\n {canDeleteFlavor && <PopupMenuItem label={t`Delete Flavor`} onClick={toggleDeleteModal} />}\n </PopupMenuOptions>\n </PopupMenu>\n )}\n {canManageSpecs && (\n <Button onClick={toggleSpecModal} variant=\"primary\">\n <Trans>Metadata</Trans>\n </Button>\n )}\n </ButtonRow>\n ) : undefined\n\n return (\n <>\n <ContentHeader title={flavor.name} projectId={projectId} actions={headerActions} />\n <Stack direction=\"vertical\">\n <FlavorDetailsView flavor={flavor} />\n </Stack>\n\n {trpcClient && (\n <>\n {specModalOpen && (\n <EditSpecModal\n client={trpcClient}\n isOpen={specModalOpen}\n onClose={toggleSpecModal}\n project={projectId}\n flavor={flavor}\n />\n )}\n\n {accessModalOpen && (\n <ManageAccessModal\n client={trpcClient}\n isOpen={accessModalOpen}\n onClose={toggleAccessModal}\n project={projectId}\n flavor={flavor}\n />\n )}\n\n {deleteModalOpen && (\n <DeleteFlavorModal\n client={trpcClient}\n isOpen={deleteModalOpen}\n onClose={toggleDeleteModal}\n project={projectId}\n flavor={flavor}\n onSuccess={handleBack}\n />\n )}\n </>\n )}\n </>\n )\n}\n"],"mappings":"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"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"_flavorId-BoNcxYmF.mjs","names":["Button","ButtonRow","Container","ContentHeading","StatusError","message","statusCode","onHomeClick","onBackClick","title","reset","className","div","p","onClick","variant","createFileRoute","redirect","getServiceIndex","Route","staticData","section","service","isDetail","sectionCrumb","labelKey","crumb","to","RouteInfo","loader","context","params","flavor","trpcClient","compute","getFlavorById","query","project_id","projectId","flavorId","flavorName","name","head","loaderData","meta","title","component","lazyRouteComponent","$$splitComponentImporter","beforeLoad","availableServices","auth","getAvailableServices","serviceIndex"],"sources":["../../src/client/components/Error/StatusError.tsx","../../src/client/routes/_auth/projects/$projectId/compute/flavors/$flavorId.tsx"],"sourcesContent":["import { Button, ButtonRow, Container, ContentHeading } from \"@cloudoperators/juno-ui-components/index\"\nimport { Trans } from \"@lingui/react/macro\"\n\ninterface StatusErrorProps {\n message: string\n statusCode?: number\n onHomeClick?: () => void\n onBackClick?: () => void\n title: string\n showHeader?: boolean\n reset?: () => void\n}\n\nexport function StatusError({ message, statusCode, onHomeClick, onBackClick, title, reset }: StatusErrorProps) {\n return (\n <Container className=\"mx-auto flex min-h-full max-w-3xl flex-col items-center justify-center px-6 py-12 sm:px-12 md:px-20\">\n {statusCode && <div className=\"text-theme-high text-6xl font-bold\">{statusCode}</div>}\n <ContentHeading>{title}</ContentHeading>\n <p>{message}</p>\n {(onBackClick || onHomeClick || reset) && (\n <ButtonRow className=\"mt-6\">\n {onBackClick && (\n <Button onClick={onBackClick} variant=\"primary\">\n <Trans>Back</Trans>\n </Button>\n )}\n {onHomeClick && (\n <Button onClick={onHomeClick}>\n <Trans>Home</Trans>\n </Button>\n )}\n\n {reset && (\n <Button onClick={reset}>\n <Trans>Try Again</Trans>\n </Button>\n )}\n </ButtonRow>\n )}\n </Container>\n )\n}\n","import {\n Button,\n ButtonRow,\n Stack,\n Spinner,\n PopupMenu,\n PopupMenuToggle,\n PopupMenuOptions,\n PopupMenuItem,\n} from \"@cloudoperators/juno-ui-components/index\"\nimport { createFileRoute, redirect, useNavigate, useParams } from \"@tanstack/react-router\"\nimport type { RouteInfo } from \"@/client/routes/routeInfo\"\nimport { Trans, useLingui } from \"@lingui/react/macro\"\nimport { getServiceIndex } from \"@/server/Authentication/helpers\"\nimport { trpcReact } from \"@/client/trpcClient\"\nimport { FlavorDetailsView } from \"./-components/FlavorDetailsView\"\nimport { StatusError } from \"@/client/components/Error/StatusError\"\nimport { useErrorTranslation } from \"@/client/utils/useErrorTranslation\"\nimport { EditSpecModal } from \"../-components/Flavors/-components/EditSpecModal\"\nimport { ManageAccessModal } from \"../-components/Flavors/-components/ManageAccessModal\"\nimport { DeleteFlavorModal } from \"../-components/Flavors/-components/DeleteFlavorModal\"\nimport { useModal } from \"@/client/utils/useModal\"\nimport { ContentHeader } from \"@/client/components/ContentHeader/ContentHeader\"\n\nexport const Route = createFileRoute(\"/_auth/projects/$projectId/compute/flavors/$flavorId\")({\n staticData: {\n section: \"compute\",\n service: \"flavors\",\n isDetail: true,\n sectionCrumb: { labelKey: \"Compute\" },\n crumb: { labelKey: \"Flavors\", to: \"/projects/$projectId/compute/flavors\" },\n } satisfies RouteInfo,\n loader: async ({ context, params }) => {\n const flavor = await context.trpcClient?.compute.getFlavorById.query({\n project_id: params.projectId,\n flavorId: params.flavorId,\n })\n return { flavorName: flavor?.name ?? null }\n },\n head: ({ loaderData }) => ({\n meta: [{ title: loaderData?.flavorName ?? \"Flavor Details\" }],\n }),\n component: RouteComponent,\n beforeLoad: async ({ context, params }) => {\n const { trpcClient } = context\n const { projectId } = params\n\n const availableServices = (await trpcClient?.auth.getAvailableServices.query()) || []\n\n const serviceIndex = getServiceIndex(availableServices)\n\n if (!serviceIndex[\"flavor\"] && !serviceIndex[\"compute\"]) {\n throw redirect({\n to: \"/projects/$projectId\",\n params: { projectId },\n })\n }\n },\n})\n\nfunction RouteComponent() {\n const { projectId, flavorId } = useParams({\n from: \"/_auth/projects/$projectId/compute/flavors/$flavorId\",\n })\n const { trpcClient } = Route.useRouteContext()\n const navigate = useNavigate()\n const { t } = useLingui()\n const { translateError, isRetryableError } = useErrorTranslation()\n\n const {\n data: flavor,\n status,\n error,\n refetch,\n } = trpcReact.compute.getFlavorById.useQuery({\n project_id: projectId,\n flavorId,\n })\n\n const { data: permissionsData } = trpcReact.compute.canUser.useQuery({\n project_id: projectId,\n permission: [\"flavors:delete\", \"flavors:list_projects\", \"flavor_specs:create\", \"flavor_specs:delete\"],\n })\n\n const canDeleteFlavor = permissionsData?.[0] ?? false\n const canManageAccess = permissionsData?.[1] ?? false\n const canManageSpecs = (permissionsData?.[2] ?? false) || (permissionsData?.[3] ?? false)\n\n const [specModalOpen, toggleSpecModal] = useModal()\n const [accessModalOpen, toggleAccessModal] = useModal()\n const [deleteModalOpen, toggleDeleteModal] = useModal()\n\n const handleBack = () => {\n navigate({\n to: \"/projects/$projectId/compute/flavors\",\n params: { projectId },\n })\n }\n\n const handleHome = () => {\n navigate({\n to: \"/projects/$projectId\",\n params: { projectId },\n })\n }\n\n const handleRetry = () => {\n refetch()\n }\n\n if (status === \"pending\") {\n return (\n <Stack className=\"fixed inset-0\" distribution=\"center\" alignment=\"center\" direction=\"vertical\">\n <Spinner variant=\"primary\" size=\"large\" className=\"mb-2\" />\n <Trans>Loading Flavor Details...</Trans>\n </Stack>\n )\n }\n\n if (status === \"error\") {\n const errorCode = error?.message || \"UNKNOWN_ERROR\"\n const translatedError = translateError(errorCode)\n const canRetry = isRetryableError(errorCode)\n\n const getStatusCode = (code: string): number | undefined => {\n if (code.includes(\"UNAUTHORIZED\")) return 401\n if (code.includes(\"FORBIDDEN\")) return 403\n if (code.includes(\"NOT_FOUND\")) return 404\n if (code.includes(\"SERVER_ERROR\")) return 500\n return undefined\n }\n\n return (\n <StatusError\n message={translatedError}\n statusCode={getStatusCode(errorCode)}\n title={t`Error Loading Flavor`}\n onBackClick={handleBack}\n onHomeClick={handleHome}\n reset={canRetry ? handleRetry : undefined}\n />\n )\n }\n\n if (!flavor) {\n return (\n <StatusError\n message={t`The requested flavor could not be found. It may have been deleted or you may not have access to it.`}\n statusCode={404}\n title={t`Flavor Not Found`}\n onBackClick={handleBack}\n onHomeClick={handleHome}\n />\n )\n }\n\n const hasMoreActions = canManageAccess || canDeleteFlavor\n\n const headerActions =\n hasMoreActions || canManageSpecs ? (\n <ButtonRow>\n {hasMoreActions && (\n <PopupMenu>\n <PopupMenuToggle as=\"div\">\n <Button icon=\"moreVert\">\n <Trans>More Actions</Trans>\n </Button>\n </PopupMenuToggle>\n <PopupMenuOptions>\n {canManageAccess && <PopupMenuItem label={t`Manage Access`} onClick={toggleAccessModal} />}\n {canDeleteFlavor && <PopupMenuItem label={t`Delete Flavor`} onClick={toggleDeleteModal} />}\n </PopupMenuOptions>\n </PopupMenu>\n )}\n {canManageSpecs && (\n <Button onClick={toggleSpecModal} variant=\"primary\">\n <Trans>Metadata</Trans>\n </Button>\n )}\n </ButtonRow>\n ) : undefined\n\n return (\n <>\n <ContentHeader title={flavor.name} projectId={projectId} actions={headerActions} />\n <Stack direction=\"vertical\">\n <FlavorDetailsView flavor={flavor} />\n </Stack>\n\n {trpcClient && (\n <>\n {specModalOpen && (\n <EditSpecModal\n client={trpcClient}\n isOpen={specModalOpen}\n onClose={toggleSpecModal}\n project={projectId}\n flavor={flavor}\n />\n )}\n\n {accessModalOpen && (\n <ManageAccessModal\n client={trpcClient}\n isOpen={accessModalOpen}\n onClose={toggleAccessModal}\n project={projectId}\n flavor={flavor}\n />\n )}\n\n {deleteModalOpen && (\n <DeleteFlavorModal\n client={trpcClient}\n isOpen={deleteModalOpen}\n onClose={toggleDeleteModal}\n project={projectId}\n flavor={flavor}\n onSuccess={handleBack}\n />\n )}\n </>\n )}\n </>\n )\n}\n"],"mappings":";;;;;;AAaA,SAAgBI,EAAY,EAAEC,YAASC,eAAYC,gBAAaC,gBAAaC,UAAOC,YAAyB;AAC3G,QACE,kBAACR,GAAAA;EAAUS,WAAU;;GAClBL,KAAc,kBAACM,OAAAA;IAAID,WAAU;cAAsCL;;GACpE,kBAACH,GAAAA,EAAAA,UAAgBM,GAAAA,CAAAA;GACjB,kBAACI,KAAAA,EAAAA,UAAGR,GAAAA,CAAAA;IACFG,KAAeD,KAAeG,MAC9B,kBAACT,GAAAA;IAAUU,WAAU;;KAClBH,KACC,kBAACR,GAAAA;MAAOc,SAASN;MAAaO,SAAQ;gBACpC,kBAAA,GAAA,EAAA,IAAA,UAAA,CAAA;;KAGHR,KACC,kBAACP,GAAAA;MAAOc,SAASP;gBACf,kBAAA,GAAA,EAAA,IAAA,UAAA,CAAA;;KAIHG,KACC,kBAACV,GAAAA;MAAOc,SAASJ;gBACf,kBAAA,GAAA,EAAA,IAAA,UAAA,CAAA;;;;;;;ACVd,IAAaS,IAAQH,EAAgB,uDAAA,CAAwD;CAC3FI,YAAY;EACVC,SAAS;EACTC,SAAS;EACTC,UAAU;EACVC,cAAc,EAAEC,UAAU,WAAU;EACpCC,OAAO;GAAED,UAAU;GAAWE,IAAI;GAAuC;EAC3E;CACAE,QAAQ,OAAO,EAAEC,YAASC,iBAKjB,EAAES,aAJM,MAAMV,EAAQG,YAAYC,QAAQC,cAAcC,MAAM;EACnEC,YAAYN,EAAOO;EACnBC,UAAUR,EAAOQ;EACnB,CAAA,GAC6BE,QAAQ,MAAK;CAE5CC,OAAO,EAAEC,qBAAkB,EACzBC,MAAM,CAAC,EAAEC,OAAOF,GAAYH,cAAc,kBAAiB,CAAC,EAC9D;CACAM,WAASC,4CAAA,YAAA;CACTE,YAAY,OAAO,EAAEnB,YAASC,gBAAQ;EACpC,IAAM,EAAEE,kBAAeH,GACjB,EAAEQ,iBAAcP,GAIhBsB,IAAenC,EAFK,MAAOe,GAAYkB,KAAKC,qBAAqBhB,OAAAA,IAAY,EAAE,CAEhDc;AAErC,MAAI,CAACG,EAAa,UAAa,CAACA,EAAa,QAC3C,OAAMpC,EAAS;GACbU,IAAI;GACJI,QAAQ,EAAEO,cAAU;GACtB,CAAA;;CAGN,CAAA"}
|