@cobaltcore-dev/aurora 0.10.0 → 0.11.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 +2 -1
- package/dist/client/AuroraApp.d.ts +2 -0
- package/dist/client/AuthProvider-DZqOvceF.mjs +64 -0
- package/dist/client/AuthProvider-DZqOvceF.mjs.map +1 -0
- package/dist/client/ContentHeader-DsuZD8fa.mjs +110 -0
- package/dist/client/ContentHeader-DsuZD8fa.mjs.map +1 -0
- package/dist/client/{DeleteFlavorModal-C3m7bQJu.mjs → DeleteFlavorModal-RnbspW_2.mjs} +135 -135
- package/dist/client/{DeleteFlavorModal-C3m7bQJu.mjs.map → DeleteFlavorModal-RnbspW_2.mjs.map} +1 -1
- package/dist/client/{DeleteVersionsModal-CyYZfB8d.mjs → DeleteVersionsModal-CsBJzXoW.mjs} +57 -57
- package/dist/client/{DeleteVersionsModal-CyYZfB8d.mjs.map → DeleteVersionsModal-CsBJzXoW.mjs.map} +1 -1
- package/dist/client/{EditSecurityGroupModal-DKusxfta.mjs → EditSecurityGroupModal-BPv3d7am.mjs} +15 -15
- package/dist/client/{EditSecurityGroupModal-DKusxfta.mjs.map → EditSecurityGroupModal-BPv3d7am.mjs.map} +1 -1
- package/dist/client/{FiltersInput-GzR4D0q6.mjs → FiltersInput-CViamP59.mjs} +2 -2
- package/dist/client/{FiltersInput-GzR4D0q6.mjs.map → FiltersInput-CViamP59.mjs.map} +1 -1
- package/dist/client/{FloatingIpActionModals-CRvROJ3H.mjs → FloatingIpActionModals-DTn3HFei.mjs} +45 -45
- package/dist/client/{FloatingIpActionModals-CRvROJ3H.mjs.map → FloatingIpActionModals-DTn3HFei.mjs.map} +1 -1
- package/dist/client/{ImageToastNotifications-BuDXpTkl.mjs → ImageToastNotifications-CFKQZTgf.mjs} +261 -261
- package/dist/client/{ImageToastNotifications-BuDXpTkl.mjs.map → ImageToastNotifications-CFKQZTgf.mjs.map} +1 -1
- package/dist/client/{RouteError-DVAiT0mT.mjs → RouteError-BebIhFpQ.mjs} +2 -2
- package/dist/client/{RouteError-DVAiT0mT.mjs.map → RouteError-BebIhFpQ.mjs.map} +1 -1
- package/dist/client/{SortInput-DLcusjGZ.mjs → SortInput-D0Vb864D.mjs} +2 -2
- package/dist/client/{SortInput-DLcusjGZ.mjs.map → SortInput-D0Vb864D.mjs.map} +1 -1
- package/dist/client/{_auth-DXJkv9QO.mjs → _auth-DnImOqR-.mjs} +2 -2
- package/dist/client/_auth-DnImOqR-.mjs.map +1 -0
- package/dist/client/{_flavorId-Dy7EYQum.mjs → _flavorId-C9SZd1jL.mjs} +8 -8
- package/dist/client/{_flavorId-Dy7EYQum.mjs.map → _flavorId-C9SZd1jL.mjs.map} +1 -1
- package/dist/client/{_flavorId-DsD2VTKA.mjs → _flavorId-DINgWoeV.mjs} +38 -38
- package/dist/client/{_flavorId-DsD2VTKA.mjs.map → _flavorId-DINgWoeV.mjs.map} +1 -1
- package/dist/client/{_floatingIpId-j17rCQqG2.mjs → _floatingIpId-BACLbMzi2.mjs} +32 -32
- package/dist/client/{_floatingIpId-j17rCQqG2.mjs.map → _floatingIpId-BACLbMzi2.mjs.map} +1 -1
- package/dist/client/{_floatingIpId-BjVbeNw_.mjs → _floatingIpId-BzVMOv97.mjs} +2 -2
- package/dist/client/{_floatingIpId-BjVbeNw_.mjs.map → _floatingIpId-BzVMOv97.mjs.map} +1 -1
- package/dist/client/_imageId-DCvaU7-S.mjs +534 -0
- package/dist/client/_imageId-DCvaU7-S.mjs.map +1 -0
- package/dist/client/{_pcaId-Bo7yHkNW.mjs → _pcaId-B3PqECyO.mjs} +115 -115
- package/dist/client/{_pcaId-Bo7yHkNW.mjs.map → _pcaId-B3PqECyO.mjs.map} +1 -1
- package/dist/client/{_pcaId-CKkCVC7b.mjs → _pcaId-DAJEt3ZI.mjs} +2 -2
- package/dist/client/{_pcaId-CKkCVC7b.mjs.map → _pcaId-DAJEt3ZI.mjs.map} +1 -1
- package/dist/client/{_projectId-CARHuZTU.mjs → _projectId-B2hG5peP.mjs} +3 -3
- package/dist/client/_projectId-B2hG5peP.mjs.map +1 -0
- package/dist/client/{_projectId-CY8W0IF6.mjs → _projectId-BnWXWTBR.mjs} +3 -3
- package/dist/client/{_projectId-CY8W0IF6.mjs.map → _projectId-BnWXWTBR.mjs.map} +1 -1
- package/dist/client/{_projectId-Dbck_MFa.mjs → _projectId-DRr9rLST.mjs} +66 -66
- package/dist/client/{_projectId-Dbck_MFa.mjs.map → _projectId-DRr9rLST.mjs.map} +1 -1
- package/dist/client/{_projectId-B_2sZKk-.mjs → _projectId-DU8qRiZk.mjs} +2 -2
- package/dist/client/_projectId-DU8qRiZk.mjs.map +1 -0
- package/dist/client/{_securityGroupId-gSEZbBII.mjs → _securityGroupId-Cj9IotMJ.mjs} +2 -2
- package/dist/client/{_securityGroupId-gSEZbBII.mjs.map → _securityGroupId-Cj9IotMJ.mjs.map} +1 -1
- package/dist/client/{_securityGroupId-CkN0CGVg.mjs → _securityGroupId-ClJiFh4R.mjs} +267 -267
- package/dist/client/{_securityGroupId-CkN0CGVg.mjs.map → _securityGroupId-ClJiFh4R.mjs.map} +1 -1
- package/dist/client/_storageType-BrHDa2bD.mjs +3005 -0
- package/dist/client/_storageType-BrHDa2bD.mjs.map +1 -0
- package/dist/client/{_storageType-6k8lUnQo.mjs → _storageType-CSLH93js.mjs} +2 -2
- package/dist/client/{_storageType-6k8lUnQo.mjs.map → _storageType-CSLH93js.mjs.map} +1 -1
- package/dist/client/_storageType-zeSZe--V.mjs.map +1 -1
- package/dist/client/{about-Nsxkyh9U.mjs → about-BnU297yB.mjs} +2 -2
- package/dist/client/about-BnU297yB.mjs.map +1 -0
- package/dist/client/{aurora-DDzsst74.mjs → aurora-6RsAZtnz.mjs} +2 -2
- package/dist/client/aurora-6RsAZtnz.mjs.map +1 -0
- package/dist/client/{build-BdRRmNf5.mjs → build-DF7MTyXG.mjs} +3582 -3114
- package/dist/client/{build-BdRRmNf5.mjs.map → build-DF7MTyXG.mjs.map} +1 -1
- package/dist/client/{constants-PMXUGI4Q.mjs → constants-BskfpGYY.mjs} +16 -16
- package/dist/client/{constants-PMXUGI4Q.mjs.map → constants-BskfpGYY.mjs.map} +1 -1
- package/dist/client/{flavors-p2TKcqP-.mjs → flavors-DAbtRoep.mjs} +151 -151
- package/dist/client/{flavors-p2TKcqP-.mjs.map → flavors-DAbtRoep.mjs.map} +1 -1
- package/dist/client/{flavors-BclEwobO.mjs → flavors-DODudzrA.mjs} +2 -2
- package/dist/client/{flavors-BclEwobO.mjs.map → flavors-DODudzrA.mjs.map} +1 -1
- package/dist/client/flavors-DWMZ6TuJ.mjs.map +1 -1
- package/dist/client/{floatingips-ph0ZxJw8.mjs → floatingips-DJW9ftN_.mjs} +83 -83
- package/dist/client/floatingips-DJW9ftN_.mjs.map +1 -0
- package/dist/client/{hooks-dSArr2Ca.mjs → hooks-CMgoYcDG.mjs} +1 -1
- package/dist/client/{images-CXdghaMW.mjs → images-BbLnuYrL.mjs} +2 -2
- package/dist/client/{images-CXdghaMW.mjs.map → images-BbLnuYrL.mjs.map} +1 -1
- package/dist/client/{images-Dbjo4yKn.mjs → images-C3JyPwer.mjs} +2 -2
- package/dist/client/images-C3JyPwer.mjs.map +1 -0
- package/dist/client/{images-BblnyWJq.mjs → images-Cp6V1nF5.mjs} +455 -455
- package/dist/client/{images-BblnyWJq.mjs.map → images-Cp6V1nF5.mjs.map} +1 -1
- package/dist/client/images-NBf2bV43.mjs.map +1 -1
- package/dist/client/index.js +257 -257
- package/dist/client/index.js.map +1 -1
- package/dist/client/network-DuZm76BZ.mjs.map +1 -1
- package/dist/client/{objects-B9Jh3SMG.mjs → objects-Bw96WXOs.mjs} +2 -2
- package/dist/client/{objects-B9Jh3SMG.mjs.map → objects-Bw96WXOs.mjs.map} +1 -1
- package/dist/client/{objects-Bw25cE1m.mjs → objects-DUmK3WgA.mjs} +1458 -1430
- package/dist/client/objects-DUmK3WgA.mjs.map +1 -0
- package/dist/client/objects-o2Cj_ndZ.mjs.map +1 -1
- package/dist/client/{pca-DUrQ_tIg.mjs → pca-DKeGzbww.mjs} +2 -2
- package/dist/client/{pca-DUrQ_tIg.mjs.map → pca-DKeGzbww.mjs.map} +1 -1
- package/dist/client/{pca-CiLPHmK7.mjs → pca-Dc_tdh4-.mjs} +47 -47
- package/dist/client/{pca-CiLPHmK7.mjs.map → pca-Dc_tdh4-.mjs.map} +1 -1
- package/dist/client/{projects-DNd3UTas.mjs → projects-CRL37ftA.mjs} +16 -16
- package/dist/client/{projects-DNd3UTas.mjs.map → projects-CRL37ftA.mjs.map} +1 -1
- package/dist/client/{projects-B5topuei.mjs → projects-DUWOgB3m.mjs} +2 -2
- package/dist/client/{projects-B5topuei.mjs.map → projects-DUWOgB3m.mjs.map} +1 -1
- package/dist/client/{projects-CHYn7L5e.mjs → projects-DpXQYfKc.mjs} +2 -2
- package/dist/client/projects-DpXQYfKc.mjs.map +1 -0
- package/dist/client/{securitygroups-CcA2TpAt.mjs → securitygroups-CWWFSjjj.mjs} +94 -94
- package/dist/client/securitygroups-CWWFSjjj.mjs.map +1 -0
- package/dist/client/{useListWithFiltering-CVzhMyEA.mjs → useListWithFiltering-C9k7xWqz.mjs} +7 -7
- package/dist/client/{useListWithFiltering-CVzhMyEA.mjs.map → useListWithFiltering-C9k7xWqz.mjs.map} +1 -1
- package/dist/server/index.js +697 -406
- package/package.json +3 -3
- package/dist/client/AuthProvider-Co4d0WzB.mjs +0 -100
- package/dist/client/AuthProvider-Co4d0WzB.mjs.map +0 -1
- package/dist/client/ContentHeader-D4jlOG-9.mjs +0 -96
- package/dist/client/ContentHeader-D4jlOG-9.mjs.map +0 -1
- package/dist/client/_auth-DXJkv9QO.mjs.map +0 -1
- package/dist/client/_imageId-BjfhqAje.mjs +0 -534
- package/dist/client/_imageId-BjfhqAje.mjs.map +0 -1
- package/dist/client/_projectId-B_2sZKk-.mjs.map +0 -1
- package/dist/client/_projectId-CARHuZTU.mjs.map +0 -1
- package/dist/client/_storageType-CLTxXjQZ.mjs +0 -3048
- package/dist/client/_storageType-CLTxXjQZ.mjs.map +0 -1
- package/dist/client/about-Nsxkyh9U.mjs.map +0 -1
- package/dist/client/aurora-DDzsst74.mjs.map +0 -1
- package/dist/client/floatingips-ph0ZxJw8.mjs.map +0 -1
- package/dist/client/images-Dbjo4yKn.mjs.map +0 -1
- package/dist/client/objects-Bw25cE1m.mjs.map +0 -1
- package/dist/client/projects-CHYn7L5e.mjs.map +0 -1
- package/dist/client/securitygroups-CcA2TpAt.mjs.map +0 -1
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"_storageType-BrHDa2bD.mjs","names":["useState","trpcReact","Modal","TextInput","Stack","useProjectId","CreateContainerModal","isOpen","onClose","onSuccess","onError","maxContainerNameLength","useLingui","projectId","containerName","setContainerName","nameError","setNameError","utils","useUtils","createContainerMutation","storage","swift","createContainer","useMutation","listContainers","invalidate","name","trim","error","message","onSettled","handleClose","reset","validateName","t","length","includes","handleNameChange","e","value","target","handleSubmit","mutate","project_id","container","handleKeyDown","key","title","open","onCancel","confirmButtonLabel","onConfirm","cancelButtonLabel","size","disableConfirmButton","isPending","direction","gap","p","className","label","required","onChange","onKeyDown","invalid","errortext","undefined","disabled","autoFocus","placeholder","useState","useRef","trpcReact","useProjectId","Modal","ModalFooter","Button","ButtonRow","TextInput","Stack","Spinner","DataGrid","DataGridRow","DataGridHeadCell","DataGridCell","Icon","formatBytesBinary","EmptyContainerModal","isOpen","container","onClose","onSuccess","onError","useLingui","projectId","confirmName","setConfirmName","nameError","setNameError","copied","setCopied","containerNameRef","handleCopyName","navigator","clipboard","writeText","name","then","setTimeout","utils","useUtils","data","objects","isLoading","isLoadingObjects","error","objectsError","storage","swift","listObjects","useQuery","project_id","format","limit","enabled","emptyContainerMutation","emptyContainer","useMutation","deletedCount","listContainers","invalidate","current","message","onSettled","handleClose","reset","handleConfirmNameChange","e","value","target","handleSubmit","trim","t","mutate","handleKeyDown","key","actualObjectCount","length","isTrulyEmpty","count","isConsistencyDelay","showEmptyInfo","modalTitle","span","className","title","button","type","onClick","icon","size","open","onCancel","confirmButtonLabel","undefined","confirmButtonVariant","onConfirm","cancelButtonLabel","modalFooter","variant","data-testid","disableConfirmButton","isPending","p","errorMessage","direction","alignment","gap","br","strong","div","total","columns","map","obj","bytes","last_modified","Date","toLocaleString","label","required","onChange","onKeyDown","invalid","errortext","disabled","autoFocus","placeholder","useState","useEffect","trpcReact","Modal","ModalFooter","Button","ButtonRow","TextInput","Stack","Spinner","Checkbox","useProjectId","DeleteContainerModal","isOpen","container","onClose","onSuccess","onError","useLingui","projectId","confirmName","setConfirmName","nameError","setNameError","versionsConfirmed","setVersionsConfirmed","utils","useUtils","data","objects","isLoading","isLoadingObjects","error","objectsError","storage","swift","listObjects","useQuery","project_id","name","format","limit","enabled","containerMetadata","metaError","getContainerMetadata","isVersioned","versionsEnabled","versionsLocation","historyLocation","deleteContainerMutation","deleteContainer","useMutation","listContainers","invalidate","message","onSettled","handleClose","reset","handleConfirmNameChange","e","value","target","handleSubmit","trim","t","mutate","handleKeyDown","key","actualObjectCount","length","hasObjects","count","isConsistencyDelay","hasPreflightError","modalTitle","span","className","title","open","onCancel","confirmButtonLabel","undefined","confirmButtonVariant","onConfirm","cancelButtonLabel","modalFooter","variant","onClick","data-testid","size","disableConfirmButton","isPending","direction","gap","role","aria-live","p","errorMessage","alignment","br","strong","label","checked","onChange","invalid","required","onKeyDown","errortext","disabled","autoFocus","placeholder","useState","useEffect","useRef","useCallback","trpcReact","Modal","TextInput","Stack","Spinner","DataGrid","DataGridRow","DataGridHeadCell","DataGridCell","Button","Checkbox","Tooltip","TooltipTrigger","TooltipContent","Icon","ComboBox","ComboBoxOption","useProjectId","RESERVED_META_KEYS","Set","MAX_COMBO_OPTIONS","VALID_KEY_RE","EditContainerMetadataModal","isOpen","container","onClose","onSuccess","onError","useLingui","projectId","data","info","isLoading","isError","isMetaError","error","metaError","storage","swift","getContainerMetadata","useQuery","project_id","name","enabled","isPublicAccess","read","publicUrl","getContainerPublicUrl","containers","listContainers","containerSearch","setContainerSearch","debouncedSearch","setDebouncedSearch","debounceTimer","handleContainerSearch","e","value","target","current","clearTimeout","setTimeout","filteredContainers","trim","length","filter","c","toLowerCase","includes","visibleContainers","slice","hiddenCount","utils","useUtils","quotaBytes","setQuotaBytes","quotaBytesError","setQuotaBytesError","quotaCount","setQuotaCount","quotaCountError","setQuotaCountError","webIndex","setWebIndex","webListings","setWebListings","versionsEnabled","setVersionsEnabled","versionsLocation","setVersionsLocation","metadata","setMetadata","metaErrors","setMetaErrors","isAddingNew","setIsAddingNew","newKey","setNewKey","newValue","setNewValue","newKeyError","setNewKeyError","newValueError","setNewValueError","String","historyLocation","rawMetaForWeb","rawMeta","entries","Object","key","has","map","isNew","isEditing","originalKey","originalValue","resetForm","updateMutation","reset","updateContainerMetadata","useMutation","invalidate","handleClose","message","validateQuotas","valid","isNaN","Number","t","validateMetaKey","test","isDuplicate","some","handleAddNew","keyErr","handleCancelAdd","handleEdit","index","i","handleSaveEdit","entry","handleCancelEdit","handleDeleteMeta","_","handleKeyChange","prev","n","handleValueChange","handleSubmit","metadataToSet","removeMetadata","forEach","push","originalKeys","keys","k","currentOriginalKeys","Boolean","wasVersioned","previousLocation","mutate","undefined","removeVersionsLocation","isBusy","isPending","isMetaFailed","hasEditing","initialQuotaBytes","initialQuotaCount","initialVersionsEnabled","initialVersionsLocation","initialWebIndex","initialWebListings","initialMetadataKeys","metadataUnchanged","every","isUnchanged","displayedQuotaBytes","title","span","className","open","onCancel","confirmButtonLabel","onConfirm","cancelButtonLabel","size","disableConfirmButton","p","errorMessage","direction","alignment","gap","div","label","count","disabled","readOnly","bytesUsed","toLocaleString","bytes","onChange","placeholder","invalid","errortext","helptext","a","href","rel","checked","triggerEvent","icon","strong","onInputChange","maxOptions","totalCount","distribution","onClick","variant","columns","autoFocus","colSpan","useState","useEffect","useRef","Fragment","trpcReact","useProjectId","Modal","Textarea","Stack","Spinner","Checkbox","Badge","Button","Icon","Tooltip","TooltipTrigger","TooltipContent","Message","DescriptionList","DescriptionTerm","DescriptionDefinition","parseAclEntry","raw","entry","trim","type","description","requiresToken","startsWith","referrer","slice","isDeny","host","test","projectId","split","userId","includes","parseAclString","aclString","map","s","filter","Boolean","PUBLIC_READ_ENTRIES","isPublicRead","readAcl","entries","every","e","addPublicReadEntries","current","existing","merged","Set","join","removePublicReadEntries","aclEntryLabel","t","ManageContainerAccessModal","isOpen","container","onClose","onSuccess","onError","useLingui","setReadAcl","writeAcl","setWriteAcl","publicRead","setPublicRead","showPreview","setShowPreview","data","info","isLoading","isError","isMetaError","error","metaError","storage","swift","getContainerMetadata","useQuery","project_id","name","enabled","read","write","utils","useUtils","updateMutation","updateContainerMetadata","useMutation","invalidate","listContainers","handleClose","message","resetMutationRef","reset","handlePublicReadChange","checked","target","prev","handleReadAclChange","value","handleSubmit","mutate","isBusy","isPending","hasAnyAcl","length","parsedReadEntries","parsedWriteEntries","modalTitle","span","className","title","open","onCancel","confirmButtonLabel","onConfirm","cancelButtonLabel","size","disableConfirmButton","p","errorMessage","div","variant","direction","alignment","gap","AclFieldLabel","label","onChange","disabled","placeholder","rows","onClick","v","alignTerms","i","AclExample","code","a","href","rel","triggerEvent","icon","useRef","useEffect","useState","useVirtualizer","useNavigate","useParams","Checkbox","DataGrid","DataGridHeadCell","DataGridRow","DataGridCell","PopupMenu","PopupMenuItem","PopupMenuOptions","formatBytesBinary","CreateContainerModal","EmptyContainerModal","DeleteContainerModal","EditContainerMetadataModal","ManageContainerAccessModal","ContainerTableView","containers","createModalOpen","setCreateModalOpen","maxContainerNameLength","onCreateSuccess","onCreateError","onEmptySuccess","onEmptyError","onDeleteSuccess","onDeleteError","onPropertiesSuccess","onPropertiesError","onAclSuccess","onAclError","selectedContainers","setSelectedContainers","hasAnyBulkAction","projectId","provider","storageType","from","useLingui","navigate","parentRef","scrollbarWidth","setScrollbarWidth","emptyModalContainer","setEmptyModalContainer","deleteModalContainer","setDeleteModalContainer","propertiesModalContainer","setPropertiesModalContainer","accessControlModalContainer","setAccessControlModalContainer","current","width","offsetWidth","clientWidth","length","formatDate","dateString","date","Date","toLocaleString","t","rowVirtualizer","count","getScrollElement","estimateSize","overscan","handleSelectContainer","containerName","includes","filter","name","columns","className","data-testid","colSpan","div","h3","p","isOpen","onClose","onSuccess","onError","columnCount","gridColumnTemplate","style","paddingRight","marginRight","ref","height","getTotalSize","position","getVirtualItems","map","virtualRow","container","index","isSelected","handleRowNavigate","to","params","data-index","measureElement","top","left","transform","start","display","gridTemplateColumns","alignItems","role","tabIndex","onClick","onKeyDown","e","key","preventDefault","stopPropagation","checked","onChange","span","title","last_modified","bytes","label","Stack","NotificationText","title","description","direction","gap","span","className","getContainerCreatedToast","containerName","config","variant","children","onDismiss","getContainerCreateErrorToast","errorMessage","getContainerEmptiedToast","deletedCount","getContainerEmptyErrorToast","getContainerDeletedToast","getContainerDeleteErrorToast","getContainerUpdatedToast","getContainerUpdateErrorToast","getContainerAclUpdatedToast","getContainerAclUpdateErrorToast","getContainersEmptiedToast","emptiedCount","totalDeleted","getContainersEmptyErrorToast","getContainersEmptyCompleteToast","errors","hasErrors","length","hasSuccess","isPartial","errorDetails","join","Tooltip","TooltipTrigger","TooltipContent","Icon","formatBytesBinary","LimitItem","label","value","undefined","span","className","icon","size","CapabilityItem","Section","title","children","ContainerLimitsTooltip","serviceInfo","accountInfo","open","useLingui","swift","capabilityMap","account_quotas","t","container_quotas","bulk_delete","bulk_upload","slo","container_sync","tempurl","symlink","versioned_writes","capabilities","Object","entries","filter","key","map","triggerEvent","placement","asChild","containerCount","toLocaleString","objectCount","bytesUsed","quotaBytes","max_file_size","max_container_name_length","max_object_name_length","container_listing_limit","account_listing_limit","max_header_size","max_meta_count","max_meta_name_length","max_meta_value_length","max_meta_overall_size","max_deletes_per_request","max_containers_per_extraction","max_manifest_segments","length","cap","useState","Fragment","React","trpcReact","Modal","Spinner","Stack","Message","TextInput","DescriptionList","DescriptionTerm","DescriptionDefinition","useProjectId","MAX_VISIBLE","CONFIRM_WORD","EmptyContainersModal","isOpen","containers","onClose","onComplete","i18n","useLingui","projectId","progress","setProgress","confirmValue","setConfirmValue","isConfirmed","trim","utils","useUtils","emptyContainerMutation","storage","swift","emptyContainer","useMutation","handleClose","reset","handleConfirm","emptiedCount","totalDeleted","errors","total","length","i","current","container","deleted","mutateAsync","project_id","name","err","message","Error","String","push","listContainers","invalidate","totalCount","visibleContainers","slice","hiddenCount","isPending","progressCurrent","progressTotal","title","open","onCancel","confirmButtonLabel","t","confirmButtonVariant","cancelButtonLabel","onConfirm","disableConfirmButton","disableCancelButton","disableCloseButton","size","direction","distribution","alignment","gap","className","variant","p","div","strong","h3","alignTerms","map","count","span","_","plural","label","placeholder","value","onChange","e","target","useState","useEffect","useRef","startTransition","SortInput","trpcReact","Button","Checkbox","DataGridToolbar","PopupMenu","PopupMenuItem","PopupMenuOptions","PopupMenuToggle","SearchInput","Spinner","Stack","Toast","formatBytesBinary","ContainerTableView","getContainerCreatedToast","getContainerCreateErrorToast","getContainerEmptiedToast","getContainerEmptyErrorToast","getContainerDeletedToast","getContainerDeleteErrorToast","getContainerUpdatedToast","getContainerUpdateErrorToast","getContainerAclUpdatedToast","getContainerAclUpdateErrorToast","getContainersEmptyCompleteToast","ContainerLimitsTooltip","EmptyContainersModal","useNavigate","Route","useProjectId","SwiftContainers","i18n","useLingui","projectId","navigate","from","fullPath","sortBy","sortDirection","search","searchParam","useSearch","hasAnyBulkAction","createModalOpen","setCreateModalOpen","emptyAllModalOpen","setEmptyAllModalOpen","selectedContainers","setSelectedContainers","toastData","setToastData","localSearchTerm","setLocalSearchTerm","debounceTimer","undefined","clearTimeout","current","handleToastDismiss","handleCreateSuccess","containerName","onDismiss","handleCreateError","errorMessage","handleEmptySuccess","deletedCount","handleEmptyError","handleDeleteSuccess","handleDeleteError","handlePropertiesSuccess","handlePropertiesError","handleAclSuccess","handleAclError","handleEmptyAllComplete","emptiedCount","totalDeleted","errors","length","failedContainerNames","Set","map","e","split","prev","filter","name","has","sortSettings","options","label","t","value","data","containers","isLoading","error","storage","swift","listContainers","useQuery","project_id","format","accountInfo","getAccountMetadata","serviceInfo","getServiceInfo","sortContainers","sort","a","b","comparison","localeCompare","count","bytes","last_modified","Date","getTime","filteredContainers","container","toLowerCase","includes","sortedContainers","handleSearchChange","term","handleSortChange","newSortSettings","resolvedSortBy","toString","resolvedDirection","className","distribution","alignment","direction","variant","size","message","bytesUsed","quotaBytes","remainingBytes","selectedContainerSummaries","c","hasSelection","selectedCount","totalCount","filteredCount","isFiltered","displayedNames","allSelected","every","n","someSelected","some","handleToggleSelectAll","div","gap","onSortByChange","v","onSortDirectionChange","dir","onClick","placeholder","data-testid","onInput","currentTarget","window","setTimeout","onSearch","onClear","checked","indeterminate","onChange","as","disabled","icon","_","plural","span","maxContainerNameLength","max_container_name_length","onCreateSuccess","onCreateError","onEmptySuccess","onEmptyError","onDeleteSuccess","onDeleteError","onPropertiesSuccess","onPropertiesError","onAclSuccess","onAclError","isOpen","onClose","onComplete","useState","trpcReact","Modal","TextInput","Stack","Checkbox","useProjectId","S3_BUCKET_NAME_REGEX","IP_ADDRESS_REGEX","RESERVED_PREFIXES","RESERVED_SUFFIXES","CreateBucketModal","isOpen","onClose","onSuccess","onError","useLingui","projectId","bucketName","setBucketName","nameError","setNameError","enableVersioning","setEnableVersioning","utils","useUtils","createBucketMutation","storage","ceph","containers","create","useMutation","list","invalidate","name","trim","error","message","onSettled","handleClose","reset","validateName","trimmed","t","length","test","includes","prefix","startsWith","suffix","endsWith","handleNameChange","e","value","target","handleSubmit","mutate","project_id","handleKeyDown","key","title","open","onCancel","confirmButtonLabel","onConfirm","cancelButtonLabel","size","disableConfirmButton","isPending","direction","gap","p","className","label","required","onChange","onKeyDown","invalid","errortext","undefined","disabled","autoFocus","placeholder","helptext","checked","useRef","useEffect","useState","useVirtualizer","useNavigate","useParams","Checkbox","DataGrid","DataGridHeadCell","DataGridRow","DataGridCell","PopupMenu","PopupMenuItem","PopupMenuOptions","formatBytesBinary","CreateBucketModal","EmptyBucketModal","DeleteBucketModal","BucketTableView","buckets","createModalOpen","setCreateModalOpen","onCreateSuccess","onCreateError","onEmptySuccess","onEmptyError","onDeleteSuccess","onDeleteError","selectedBuckets","setSelectedBuckets","hasAnyBulkAction","projectId","provider","storageType","strict","useLingui","navigate","parentRef","scrollbarWidth","setScrollbarWidth","emptyModalBucket","setEmptyModalBucket","deleteModalBucket","setDeleteModalBucket","current","width","offsetWidth","clientWidth","length","formatDate","dateString","date","Date","toLocaleString","t","rowVirtualizer","count","getScrollElement","estimateSize","overscan","handleSelectBucket","bucketName","includes","filter","name","columns","className","data-testid","colSpan","div","h3","p","columnCount","gridColumnTemplate","style","paddingRight","marginRight","ref","height","getTotalSize","position","getVirtualItems","map","virtualRow","bucket","index","isSelected","handleRowNavigate","to","params","containerName","data-index","measureElement","top","left","transform","start","display","gridTemplateColumns","alignItems","role","tabIndex","onClick","onKeyDown","e","key","preventDefault","stopPropagation","checked","onChange","span","title","last_modified","creationDate","bytes","label","isOpen","onClose","onSuccess","onError","getBucketCreatedToast","bucketName","message","description","getBucketCreateErrorToast","errorMessage","getBucketEmptiedToast","deletedCount","getBucketEmptyErrorToast","getBucketDeletedToast","getBucketDeleteErrorToast","getBucketsEmptyCompleteToast","emptiedCount","totalDeleted","errors","hasErrors","length","totalBuckets","errorsLength","useState","trpcReact","Modal","Spinner","Stack","TextInput","useProjectId","MAX_VISIBLE","EmptyBucketsModal","isOpen","buckets","onClose","onComplete","useLingui","projectId","progress","setProgress","confirmText","setConfirmText","utils","useUtils","emptyBucketMutation","storage","ceph","objects","deleteAll","useMutation","handleClose","reset","handleConfirm","emptiedCount","totalDeleted","errors","total","length","i","current","bucket","deleted","mutateAsync","project_id","containerName","name","err","message","Error","String","push","containers","list","invalidate","totalCount","visibleBuckets","slice","hiddenCount","isPending","progressCurrent","progressTotal","isConfirmValid","title","open","onCancel","confirmButtonLabel","t","confirmButtonVariant","cancelButtonLabel","onConfirm","disableConfirmButton","disableCancelButton","disableCloseButton","size","direction","distribution","alignment","gap","className","variant","p","div","ul","map","bucketName","bucketCount","count","li","span","label","value","onChange","e","target","placeholder","autoFocus","trpcReact","useProjectId","Button","Stack","toast","CredentialPrompt","onSuccess","projectId","utils","useUtils","createMutation","storage","ceph","ec2Credentials","create","useMutation","list","invalidate","onError","err","errorMessage","message","error","direction","gap","className","h2","p","div","onClick","mutate","project_id","disabled","isPending","useState","useEffect","useRef","startTransition","useNavigate","SortInput","trpcReact","Button","Checkbox","DataGridToolbar","PopupMenu","PopupMenuItem","PopupMenuOptions","PopupMenuToggle","SearchInput","Spinner","Stack","toast","BucketTableView","getBucketCreatedToast","getBucketCreateErrorToast","getBucketEmptiedToast","getBucketEmptyErrorToast","getBucketDeletedToast","getBucketDeleteErrorToast","getBucketsEmptyCompleteToast","EmptyBucketsModal","CredentialPrompt","useProjectId","Route","CreateBucketModal","DeleteBucketModal","DeleteBucketPolicyModal","EmptyBucketModal","DeleteVersionsModal","CephBuckets","i18n","useLingui","projectId","navigate","from","fullPath","sortBy","sortDirection","search","searchParam","useSearch","hasAnyBulkAction","createModalOpen","setCreateModalOpen","emptyAllModalOpen","setEmptyAllModalOpen","selectedBuckets","setSelectedBuckets","localSearchTerm","setLocalSearchTerm","debounceTimer","undefined","clearTimeout","current","handleCreateSuccess","bucketName","message","options","success","handleCreateError","errorMessage","error","handleEmptySuccess","deletedCount","handleEmptyError","handleDeleteSuccess","handleDeleteError","handleEmptyAllComplete","emptiedCount","totalDeleted","errors","length","failedBucketNames","Set","map","e","split","prev","filter","name","has","warning","sortSettings","label","t","value","data","buckets","isLoading","storage","ceph","containers","list","useQuery","project_id","includeMetadata","enabled","retry","sortBuckets","sort","a","b","comparison","localeCompare","count","bytes","last_modified","Date","getTime","filteredBuckets","bucket","toLowerCase","includes","sortedBuckets","handleSearchChange","term","handleSortChange","newSortSettings","resolvedSortBy","toString","resolvedDirection","className","distribution","alignment","direction","variant","size","onSuccess","window","location","reload","isAccessDenied","isAuthError","div","p","selectedBucketSummaries","c","hasSelection","selectedCount","totalCount","filteredCount","displayedNames","allSelected","every","n","someSelected","some","handleToggleSelectAll","gap","selectClassName","onSortByChange","onSortDirectionChange","onClick","placeholder","data-testid","onInput","v","currentTarget","setTimeout","onSearch","onClear","checked","indeterminate","onChange","as","disabled","icon","_","plural","span","trim","onCreateSuccess","onCreateError","onEmptySuccess","onEmptyError","onDeleteSuccess","onDeleteError","isOpen","onClose","onComplete","useParams","ErrorBoundary","SwiftContainers","CephBuckets","Trans","useLingui","ContentHeader","checkServiceAvailability","Route","StorageDashboard","project","provider","from","select","params","projectId","storageType","t","pageTitle","SplitComponent","component"],"sources":["../../src/client/routes/_auth/projects/$projectId/storage/-components/Swift/Containers/CreateContainerModal.tsx","../../src/client/routes/_auth/projects/$projectId/storage/-components/Swift/Containers/EmptyContainerModal.tsx","../../src/client/routes/_auth/projects/$projectId/storage/-components/Swift/Containers/DeleteContainerModal.tsx","../../src/client/routes/_auth/projects/$projectId/storage/-components/Swift/Containers/EditContainerMetadataModal.tsx","../../src/client/routes/_auth/projects/$projectId/storage/-components/Swift/Containers/ManageContainerAccessModal.tsx","../../src/client/routes/_auth/projects/$projectId/storage/-components/Swift/Containers/ContainerTableView.tsx","../../src/client/routes/_auth/projects/$projectId/storage/-components/Swift/Containers/ContainerToastNotifications.tsx","../../src/client/routes/_auth/projects/$projectId/storage/-components/Swift/Containers/ContainerLimitsTooltip.tsx","../../src/client/routes/_auth/projects/$projectId/storage/-components/Swift/Containers/EmptyContainersModal.tsx","../../src/client/routes/_auth/projects/$projectId/storage/-components/Swift/Containers/index.tsx","../../src/client/routes/_auth/projects/$projectId/storage/-components/Ceph/Buckets/CreateBucketModal.tsx","../../src/client/routes/_auth/projects/$projectId/storage/-components/Ceph/Buckets/BucketTableView.tsx","../../src/client/routes/_auth/projects/$projectId/storage/-components/Ceph/Buckets/BucketToastNotifications.tsx","../../src/client/routes/_auth/projects/$projectId/storage/-components/Ceph/Buckets/EmptyBucketsModal.tsx","../../src/client/routes/_auth/projects/$projectId/storage/-components/Ceph/Buckets/CredentialPrompt.tsx","../../src/client/routes/_auth/projects/$projectId/storage/-components/Ceph/Buckets/index.tsx","../../src/client/routes/_auth/projects/$projectId/storage/$provider/$storageType/index.tsx?tsr-split=component"],"sourcesContent":["import { useState } from \"react\"\nimport { Trans, useLingui } from \"@lingui/react/macro\"\nimport { trpcReact } from \"@/client/trpcClient\"\nimport { Modal, TextInput, Stack } from \"@cloudoperators/juno-ui-components\"\nimport { useProjectId } from \"@/client/hooks/useProjectId\"\n\ninterface CreateContainerModalProps {\n isOpen: boolean\n onClose: () => void\n onSuccess?: (containerName: string) => void\n onError?: (containerName: string, errorMessage: string) => void\n maxContainerNameLength?: number\n}\n\nexport const CreateContainerModal = ({\n isOpen,\n onClose,\n onSuccess,\n onError,\n maxContainerNameLength = 256,\n}: CreateContainerModalProps) => {\n const { t } = useLingui()\n const projectId = useProjectId()\n const [containerName, setContainerName] = useState(\"\")\n const [nameError, setNameError] = useState<string | null>(null)\n\n const utils = trpcReact.useUtils()\n\n const createContainerMutation = trpcReact.storage.swift.createContainer.useMutation({\n onSuccess: () => {\n utils.storage.swift.listContainers.invalidate()\n const name = containerName.trim()\n onSuccess?.(name)\n },\n onError: (error) => {\n onError?.(containerName.trim(), error.message)\n },\n onSettled: () => {\n handleClose()\n },\n })\n\n const handleClose = () => {\n setContainerName(\"\")\n setNameError(null)\n createContainerMutation.reset()\n onClose()\n }\n\n const validateName = (name: string): boolean => {\n if (!name.trim()) {\n setNameError(t`Container name is required`)\n return false\n }\n if (name.length > maxContainerNameLength) {\n setNameError(t`Container name must be ${maxContainerNameLength} characters or fewer`)\n return false\n }\n if (name.includes(\"/\")) {\n setNameError(t`Container name cannot contain slashes`)\n return false\n }\n setNameError(null)\n return true\n }\n\n const handleNameChange = (e: React.ChangeEvent<HTMLInputElement>) => {\n const value = e.target.value\n setContainerName(value)\n if (nameError) validateName(value)\n }\n\n const handleSubmit = () => {\n if (!validateName(containerName)) return\n createContainerMutation.mutate({\n project_id: projectId,\n container: containerName.trim(),\n })\n }\n\n const handleKeyDown = (e: React.KeyboardEvent) => {\n if (e.key === \"Enter\") {\n handleSubmit()\n }\n }\n\n if (!isOpen) return null\n\n return (\n <Modal\n title={t`Create Container`}\n open={isOpen}\n onCancel={handleClose}\n confirmButtonLabel={t`Create`}\n onConfirm={handleSubmit}\n cancelButtonLabel={t`Cancel`}\n size=\"small\"\n disableConfirmButton={createContainerMutation.isPending || !containerName.trim()}\n >\n <Stack direction=\"vertical\" gap=\"6\">\n <p className=\"text-theme-default\">\n <Trans>\n Inside a project, objects are stored in containers. Containers are where you define access permissions and\n quotas.\n </Trans>\n </p>\n <TextInput\n label={t`Container name`}\n required\n value={containerName}\n onChange={handleNameChange}\n onKeyDown={handleKeyDown}\n invalid={!!nameError}\n errortext={nameError || undefined}\n disabled={createContainerMutation.isPending}\n autoFocus\n placeholder={t`Enter container name`}\n />\n </Stack>\n </Modal>\n )\n}\n","import { useState, useRef } from \"react\"\nimport { Trans, useLingui } from \"@lingui/react/macro\"\nimport { trpcReact } from \"@/client/trpcClient\"\nimport { useProjectId } from \"@/client/hooks/useProjectId\"\nimport {\n Modal,\n ModalFooter,\n Button,\n ButtonRow,\n TextInput,\n Stack,\n Spinner,\n DataGrid,\n DataGridRow,\n DataGridHeadCell,\n DataGridCell,\n Icon,\n} from \"@cloudoperators/juno-ui-components\"\nimport { ContainerSummary, ObjectSummary } from \"@/server/Storage/types/swift\"\nimport { formatBytesBinary } from \"@/client/utils/formatBytes\"\n\ninterface EmptyContainerModalProps {\n isOpen: boolean\n container: ContainerSummary | null\n onClose: () => void\n onSuccess?: (containerName: string, deletedCount: number) => void\n onError?: (containerName: string, errorMessage: string) => void\n}\n\nexport const EmptyContainerModal = ({ isOpen, container, onClose, onSuccess, onError }: EmptyContainerModalProps) => {\n const { t } = useLingui()\n const projectId = useProjectId()\n const [confirmName, setConfirmName] = useState(\"\")\n const [nameError, setNameError] = useState<string | null>(null)\n const [copied, setCopied] = useState(false)\n const containerNameRef = useRef(\"\")\n\n const handleCopyName = () => {\n if (!container) return\n navigator.clipboard.writeText(container.name).then(() => {\n setCopied(true)\n setTimeout(() => setCopied(false), 2000)\n })\n }\n\n const utils = trpcReact.useUtils()\n\n // Fetch actual objects to get accurate real-time state —\n // container.count can lag due to Swift eventual consistency\n const {\n data: objects,\n isLoading: isLoadingObjects,\n error: objectsError,\n } = trpcReact.storage.swift.listObjects.useQuery(\n { project_id: projectId, container: container?.name ?? \"\", format: \"json\", limit: 100 },\n { enabled: isOpen && container !== null }\n )\n\n const emptyContainerMutation = trpcReact.storage.swift.emptyContainer.useMutation({\n onSuccess: (deletedCount) => {\n utils.storage.swift.listContainers.invalidate()\n utils.storage.swift.listObjects.invalidate({ project_id: projectId, container: containerNameRef.current })\n onSuccess?.(containerNameRef.current, deletedCount)\n },\n onError: (error) => {\n onError?.(containerNameRef.current, error.message)\n },\n onSettled: () => {\n handleClose()\n },\n })\n\n const handleClose = () => {\n setConfirmName(\"\")\n setNameError(null)\n emptyContainerMutation.reset()\n onClose()\n }\n\n const handleConfirmNameChange = (e: React.ChangeEvent<HTMLInputElement>) => {\n const value = e.target.value\n setConfirmName(value)\n if (nameError) setNameError(null)\n }\n\n const handleSubmit = () => {\n if (!container) return\n if (confirmName.trim() !== container.name) {\n setNameError(t`Container name does not match`)\n return\n }\n containerNameRef.current = container.name\n emptyContainerMutation.mutate({ project_id: projectId, container: container.name })\n }\n\n const handleKeyDown = (e: React.KeyboardEvent) => {\n if (e.key === \"Enter\") handleSubmit()\n }\n\n if (!isOpen || !container) return null\n\n const actualObjectCount = objects?.length ?? 0\n\n // ── Case 2: container.count === 0 and listed objects === 0 ────────────────\n // Container is genuinely empty\n const isTrulyEmpty = !isLoadingObjects && container.count === 0 && actualObjectCount === 0\n\n // ── Case 3: container.count > 0 but listed objects === 0 ──────────────────\n // Swift eventual consistency delay — metadata not yet synced after recent delete\n const isConsistencyDelay = !isLoadingObjects && container.count > 0 && actualObjectCount === 0\n\n const showEmptyInfo = isTrulyEmpty || isConsistencyDelay\n\n const modalTitle = (\n <span className=\"flex max-w-[400px] items-center gap-2\">\n <span className=\"shrink-0\">\n <Trans>Empty:</Trans>\n </span>\n <span className=\"truncate\" title={container.name}>\n {container.name}\n </span>\n {!isLoadingObjects && !showEmptyInfo && (\n <button\n type=\"button\"\n onClick={handleCopyName}\n title={copied ? t`Copied!` : t`Copy container name`}\n className=\"text-theme-light hover:text-theme-default inline-flex items-center transition-colors\"\n >\n <Icon icon={copied ? \"checkCircle\" : \"contentCopy\"} size=\"16\" />\n </button>\n )}\n </span>\n )\n\n return (\n <Modal\n title={modalTitle}\n open={isOpen}\n onCancel={handleClose}\n confirmButtonLabel={showEmptyInfo ? undefined : t`Empty`}\n confirmButtonVariant=\"primary-danger\"\n onConfirm={showEmptyInfo ? undefined : handleSubmit}\n cancelButtonLabel={showEmptyInfo ? undefined : t`Cancel`}\n modalFooter={\n showEmptyInfo ? (\n <ModalFooter className=\"flex justify-end\">\n <ButtonRow>\n <Button variant=\"primary\" onClick={handleClose} data-testid=\"empty-info-close-button\">\n <Trans>Close</Trans>\n </Button>\n </ButtonRow>\n </ModalFooter>\n ) : undefined\n }\n size=\"small\"\n disableConfirmButton={\n isLoadingObjects ||\n emptyContainerMutation.isPending ||\n (!showEmptyInfo && !confirmName.trim()) ||\n (!showEmptyInfo && confirmName.trim() !== container.name)\n }\n >\n {objectsError && (\n <p className=\"text-theme-error mb-4\">\n {(() => {\n const errorMessage = objectsError.message\n return <Trans>Failed to load container objects: {errorMessage}</Trans>\n })()}\n </p>\n )}\n {isLoadingObjects ? (\n <Stack direction=\"horizontal\" alignment=\"center\" gap=\"2\" className=\"py-4\">\n <Spinner size=\"small\" />\n <Trans>Loading objects...</Trans>\n </Stack>\n ) : showEmptyInfo && !objectsError ? (\n // ── Case 2 & 3 ──────────────────────────────────────────────────────\n <p className=\"text-theme-default py-2\">\n {isTrulyEmpty ? (\n <Trans>This container is already empty.</Trans>\n ) : (\n <Trans>\n This container appears empty — the object count may not have synced yet due to a recent operation.\n </Trans>\n )}\n </p>\n ) : !objectsError ? (\n // ── Case 1: container has objects ────────────────────────────────────\n <Stack direction=\"vertical\" gap=\"6\">\n <p className=\"text-theme-default\">\n <Trans>\n This action is permanent. All objects in the container will be deleted and this cannot be undone.\n </Trans>\n <br />\n <Trans>\n <strong>Please note:</strong> for <strong>dynamic</strong> and <strong>static large objects</strong> only\n the manifests will be deleted. The related segments will not be deleted.\n </Trans>\n </p>\n\n {/* Object list preview — capped at first 100 */}\n <div className=\"border-theme-background-lvl-3 overflow-hidden rounded border\">\n {container.count > actualObjectCount && (\n <p className=\"text-theme-light px-3 py-2 text-xs\">\n {(() => {\n const total = container.count\n return (\n <Trans>\n Showing first {actualObjectCount} of {total} objects\n </Trans>\n )\n })()}\n </p>\n )}\n <DataGrid columns={3} className=\"text-sm\">\n <DataGridRow>\n <DataGridHeadCell>\n <Trans>Name</Trans>\n </DataGridHeadCell>\n <DataGridHeadCell>\n <Trans>Size</Trans>\n </DataGridHeadCell>\n <DataGridHeadCell>\n <Trans>Last Modified</Trans>\n </DataGridHeadCell>\n </DataGridRow>\n </DataGrid>\n <div className=\"max-h-48 overflow-y-auto\">\n <DataGrid columns={3} className=\"text-sm\">\n {(objects as ObjectSummary[]).map((obj) => (\n <DataGridRow key={obj.name}>\n <DataGridCell className=\"max-w-[200px] truncate\" title={obj.name}>\n {obj.name}\n </DataGridCell>\n <DataGridCell>{formatBytesBinary(obj.bytes)}</DataGridCell>\n <DataGridCell>\n {obj.last_modified ? new Date(obj.last_modified).toLocaleString() : t`N/A`}\n </DataGridCell>\n </DataGridRow>\n ))}\n </DataGrid>\n </div>\n </div>\n\n <TextInput\n label={t`Type container name to confirm`}\n required\n value={confirmName}\n onChange={handleConfirmNameChange}\n onKeyDown={handleKeyDown}\n invalid={!!nameError}\n errortext={nameError || undefined}\n disabled={emptyContainerMutation.isPending}\n autoFocus\n placeholder={container.name}\n />\n </Stack>\n ) : null}\n </Modal>\n )\n}\n","import { useState, useEffect } from \"react\"\nimport { Trans, useLingui } from \"@lingui/react/macro\"\nimport { trpcReact } from \"@/client/trpcClient\"\nimport {\n Modal,\n ModalFooter,\n Button,\n ButtonRow,\n TextInput,\n Stack,\n Spinner,\n Checkbox,\n} from \"@cloudoperators/juno-ui-components\"\nimport { ContainerSummary } from \"@/server/Storage/types/swift\"\nimport { useProjectId } from \"@/client/hooks/useProjectId\"\n\ninterface DeleteContainerModalProps {\n isOpen: boolean\n container: ContainerSummary | null\n onClose: () => void\n onSuccess?: (containerName: string) => void\n onError?: (containerName: string, errorMessage: string) => void\n}\n\nexport const DeleteContainerModal = ({ isOpen, container, onClose, onSuccess, onError }: DeleteContainerModalProps) => {\n const { t } = useLingui()\n const projectId = useProjectId()\n const [confirmName, setConfirmName] = useState(\"\")\n const [nameError, setNameError] = useState<string | null>(null)\n const [versionsConfirmed, setVersionsConfirmed] = useState(false)\n\n const utils = trpcReact.useUtils()\n\n // Fetch actual objects to get accurate real-time state —\n // container.count can lag due to Swift eventual consistency\n const {\n data: objects,\n isLoading: isLoadingObjects,\n error: objectsError,\n } = trpcReact.storage.swift.listObjects.useQuery(\n { project_id: projectId, container: container?.name ?? \"\", format: \"json\", limit: 1 },\n { enabled: isOpen && container !== null }\n )\n\n // Fetch container metadata to check if versioning is enabled\n const { data: containerMetadata, error: metaError } = trpcReact.storage.swift.getContainerMetadata.useQuery(\n { project_id: projectId, container: container?.name ?? \"\" },\n { enabled: isOpen && container !== null }\n )\n\n // Swift versioning v2: x-versions-enabled header; v1: x-versions-location / x-history-location\n const isVersioned = !!(\n containerMetadata?.versionsEnabled ||\n containerMetadata?.versionsLocation ||\n containerMetadata?.historyLocation\n )\n\n const deleteContainerMutation = trpcReact.storage.swift.deleteContainer.useMutation({\n onSuccess: () => {\n utils.storage.swift.listContainers.invalidate()\n onSuccess?.(container!.name)\n },\n onError: (error) => {\n onError?.(container!.name, error.message)\n },\n onSettled: () => {\n handleClose()\n },\n })\n\n useEffect(() => {\n if (!isOpen) {\n setConfirmName(\"\")\n setNameError(null)\n setVersionsConfirmed(false)\n deleteContainerMutation.reset()\n }\n }, [isOpen, container?.name])\n\n const handleClose = () => {\n setConfirmName(\"\")\n setNameError(null)\n setVersionsConfirmed(false)\n deleteContainerMutation.reset()\n onClose()\n }\n\n const handleConfirmNameChange = (e: React.ChangeEvent<HTMLInputElement>) => {\n const value = e.target.value\n setConfirmName(value)\n if (nameError) setNameError(null)\n }\n\n const handleSubmit = () => {\n if (!container) return\n if (objectsError || metaError) return\n if (confirmName.trim() !== \"delete\") {\n setNameError(t`The text must match \"delete\"`)\n return\n }\n if (isVersioned && !versionsConfirmed) return\n deleteContainerMutation.mutate({ project_id: projectId, container: container.name })\n }\n\n const handleKeyDown = (e: React.KeyboardEvent) => {\n if (e.key === \"Enter\") handleSubmit()\n }\n\n if (!isOpen || !container) return null\n\n const actualObjectCount = objects?.length ?? 0\n\n // Container has objects — cannot delete, must empty first.\n // Also covers the Swift consistency delay where count > 0 but listed objects === 0:\n // we trust container.count here to avoid letting the user delete a non-empty container.\n const hasObjects = !isLoadingObjects && (actualObjectCount > 0 || container.count > 0)\n // Swift eventual consistency — count > 0 but listing returned 0 objects,\n // likely because a recent empty/delete hasn't propagated yet.\n const isConsistencyDelay = !isLoadingObjects && container.count > 0 && actualObjectCount === 0\n const hasPreflightError = !!(objectsError || metaError)\n\n const modalTitle = (\n <span className=\"flex max-w-[400px] items-center gap-2\">\n <span className=\"shrink-0\">\n <Trans>Delete container:</Trans>\n </span>\n <span className=\"truncate\" title={container.name}>\n {container.name}\n </span>\n </span>\n )\n\n return (\n <Modal\n title={modalTitle}\n open={isOpen}\n onCancel={handleClose}\n confirmButtonLabel={hasObjects ? undefined : t`Delete`}\n confirmButtonVariant={hasObjects ? undefined : \"primary-danger\"}\n onConfirm={hasObjects ? undefined : handleSubmit}\n cancelButtonLabel={hasObjects ? undefined : t`Cancel`}\n modalFooter={\n hasObjects ? (\n <ModalFooter className=\"flex justify-end\">\n <ButtonRow>\n <Button variant=\"primary\" onClick={handleClose} data-testid=\"delete-has-objects-close-button\">\n <Trans>Close</Trans>\n </Button>\n </ButtonRow>\n </ModalFooter>\n ) : undefined\n }\n size=\"small\"\n disableConfirmButton={\n isLoadingObjects ||\n hasPreflightError ||\n deleteContainerMutation.isPending ||\n (!hasObjects && confirmName.trim() !== \"delete\") ||\n (!hasObjects && isVersioned && !versionsConfirmed)\n }\n >\n {(objectsError || metaError) && (\n <Stack direction=\"vertical\" gap=\"2\" className=\"mb-4\" role=\"alert\" aria-live=\"assertive\">\n {objectsError && (\n <p className=\"text-theme-error\">\n {(() => {\n const errorMessage = objectsError.message\n return <Trans>Failed to load container objects: {errorMessage}</Trans>\n })()}\n </p>\n )}\n {metaError && (\n <p className=\"text-theme-error\">\n {(() => {\n const errorMessage = metaError.message\n return <Trans>Failed to load container properties: {errorMessage}</Trans>\n })()}\n </p>\n )}\n </Stack>\n )}\n {isLoadingObjects ? (\n <Stack direction=\"horizontal\" alignment=\"center\" gap=\"2\" className=\"py-4\">\n <Spinner size=\"small\" />\n <Trans>Loading...</Trans>\n </Stack>\n ) : hasObjects ? (\n // ── Container has objects — block deletion ───────────────────────────\n <Stack direction=\"vertical\" gap=\"3\">\n <p className=\"text-theme-default\">\n <Trans>The container cannot be deleted as it contains objects. Empty the container first.</Trans>\n </p>\n {isConsistencyDelay && (\n <p className=\"text-theme-default\">\n <Trans>\n The container metadata reports objects but none were listed. This may be a temporary synchronization\n delay — please wait a moment and try again.\n </Trans>\n </p>\n )}\n </Stack>\n ) : (\n // ── Container is empty — allow deletion ──────────────────────────────\n <Stack direction=\"vertical\" gap=\"6\">\n <p className=\"text-theme-default\">\n <Trans>The container will be deleted. This action is permanent and cannot be undone.</Trans>\n <br />\n <Trans>\n To confirm type <strong>delete</strong> in the field below.\n </Trans>\n </p>\n {isVersioned && (\n <Checkbox\n label={t`I confirm that all existing versions will also be deleted`}\n checked={versionsConfirmed}\n onChange={(e: React.ChangeEvent<HTMLInputElement>) => setVersionsConfirmed(e.target.checked)}\n invalid={!versionsConfirmed}\n />\n )}\n <TextInput\n label={t`Type \"delete\" to confirm`}\n required\n value={confirmName}\n onChange={handleConfirmNameChange}\n onKeyDown={handleKeyDown}\n invalid={!!nameError}\n errortext={nameError || undefined}\n disabled={deleteContainerMutation.isPending}\n autoFocus\n placeholder={t`delete`}\n />\n </Stack>\n )}\n </Modal>\n )\n}\n","import { useState, useEffect, useRef, useCallback } from \"react\"\nimport { Trans, useLingui } from \"@lingui/react/macro\"\nimport { trpcReact } from \"@/client/trpcClient\"\nimport {\n Modal,\n TextInput,\n Stack,\n Spinner,\n DataGrid,\n DataGridRow,\n DataGridHeadCell,\n DataGridCell,\n Button,\n Checkbox,\n Tooltip,\n TooltipTrigger,\n TooltipContent,\n Icon,\n ComboBox,\n ComboBoxOption,\n} from \"@cloudoperators/juno-ui-components\"\nimport { ContainerSummary } from \"@/server/Storage/types/swift\"\nimport { useProjectId } from \"@/client/hooks/useProjectId\"\n\n// ── Reserved metadata keys that are exposed as dedicated fields ──────────────\nconst RESERVED_META_KEYS = new Set([\n \"quota-bytes\",\n \"quota-count\",\n \"web-index\",\n \"web-listings\",\n \"web-listings-css\",\n \"web-error\",\n])\n\nconst MAX_COMBO_OPTIONS = 50\n\n// RFC 7230 token allowlist — letters, digits, and safe symbols only.\n// Using a positive allowlist avoids the ESLint no-control-regex rule.\nconst VALID_KEY_RE = /^[a-zA-Z0-9!#$%&'*+\\-.^_`|~]+$/\n\ninterface MetadataEntry {\n key: string\n value: string\n isNew?: boolean\n isEditing?: boolean\n originalKey?: string\n originalValue?: string\n}\n\ninterface EditContainerMetadataModalProps {\n isOpen: boolean\n container: ContainerSummary | null\n onClose: () => void\n onSuccess?: (containerName: string) => void\n onError?: (containerName: string, errorMessage: string) => void\n}\n\nexport const EditContainerMetadataModal = ({\n isOpen,\n container,\n onClose,\n onSuccess,\n onError,\n}: EditContainerMetadataModalProps) => {\n const { t } = useLingui()\n const projectId = useProjectId()\n\n // ── Query ─────────────────────────────────────────────────────────────────\n const {\n data: info,\n isLoading,\n isError: isMetaError,\n error: metaError,\n } = trpcReact.storage.swift.getContainerMetadata.useQuery(\n { project_id: projectId, container: container?.name ?? \"\" },\n { enabled: isOpen && container !== null }\n )\n\n const isPublicAccess = info?.read === \".r:*,.rlistings\"\n\n const { data: publicUrl } = trpcReact.storage.swift.getContainerPublicUrl.useQuery(\n { project_id: projectId, container: container?.name ?? \"\" },\n { enabled: isOpen && container !== null && isPublicAccess }\n )\n\n const { data: containers } = trpcReact.storage.swift.listContainers.useQuery(\n { project_id: projectId },\n { enabled: isOpen }\n )\n\n const [containerSearch, setContainerSearch] = useState(\"\")\n const [debouncedSearch, setDebouncedSearch] = useState(\"\")\n const debounceTimer = useRef<ReturnType<typeof setTimeout> | null>(null)\n\n const handleContainerSearch = useCallback((e: React.ChangeEvent<HTMLInputElement>) => {\n const value = e.target.value\n setContainerSearch(value)\n if (debounceTimer.current) clearTimeout(debounceTimer.current)\n debounceTimer.current = setTimeout(() => setDebouncedSearch(value), 300)\n }, [])\n\n const filteredContainers =\n debouncedSearch.trim().length > 0\n ? (containers ?? []).filter(\n (c) => c.name !== container?.name && c.name.toLowerCase().includes(debouncedSearch.toLowerCase())\n )\n : []\n\n const visibleContainers = filteredContainers.slice(0, MAX_COMBO_OPTIONS)\n const hiddenCount = filteredContainers.length - visibleContainers.length\n\n const utils = trpcReact.useUtils()\n\n // ── Form state ────────────────────────────────────────────────────────────\n // Quota fields\n const [quotaBytes, setQuotaBytes] = useState(\"\")\n const [quotaBytesError, setQuotaBytesError] = useState<string | null>(null)\n const [quotaCount, setQuotaCount] = useState(\"\")\n const [quotaCountError, setQuotaCountError] = useState<string | null>(null)\n\n // Static website fields\n const [webIndex, setWebIndex] = useState(\"\")\n const [webListings, setWebListings] = useState(false)\n\n // Versioning\n const [versionsEnabled, setVersionsEnabled] = useState(false)\n const [versionsLocation, setVersionsLocation] = useState(\"\")\n\n // Custom metadata\n const [metadata, setMetadata] = useState<MetadataEntry[]>([])\n const [metaErrors, setMetaErrors] = useState<Record<string, string>>({})\n const [isAddingNew, setIsAddingNew] = useState(false)\n const [newKey, setNewKey] = useState(\"\")\n const [newValue, setNewValue] = useState(\"\")\n const [newKeyError, setNewKeyError] = useState<string | null>(null)\n const [newValueError, setNewValueError] = useState<string | null>(null)\n\n // ── Populate form when data arrives ──────────────────────────────────────\n useEffect(() => {\n if (!info) return\n\n setQuotaBytes(info.quotaBytes != null ? String(info.quotaBytes) : \"\")\n setQuotaCount(info.quotaCount != null ? String(info.quotaCount) : \"\")\n setVersionsEnabled(!!(info.versionsEnabled || info.versionsLocation || info.historyLocation))\n setVersionsLocation(info.versionsLocation || info.historyLocation || \"\")\n\n const rawMetaForWeb = info.metadata ?? {}\n setWebIndex(rawMetaForWeb[\"web-index\"] ?? \"\")\n setWebListings(rawMetaForWeb[\"web-listings\"] === \"1\" || rawMetaForWeb[\"web-listings\"] === \"true\")\n\n // Custom metadata — exclude reserved keys\n const rawMeta = info.metadata ?? {}\n const entries: MetadataEntry[] = Object.entries(rawMeta)\n .filter(([key]) => !RESERVED_META_KEYS.has(key))\n .map(([key, value]) => ({\n key,\n value,\n isNew: false,\n isEditing: false,\n originalKey: key,\n originalValue: value,\n }))\n setMetadata(entries)\n }, [info])\n\n // Reset when closed\n useEffect(() => {\n if (!isOpen) {\n resetForm()\n }\n }, [isOpen])\n\n const resetForm = () => {\n setQuotaBytes(\"\")\n setQuotaBytesError(null)\n setQuotaCount(\"\")\n setQuotaCountError(null)\n setWebIndex(\"\")\n setWebListings(false)\n setVersionsEnabled(false)\n setVersionsLocation(\"\")\n setContainerSearch(\"\")\n setDebouncedSearch(\"\")\n if (debounceTimer.current) clearTimeout(debounceTimer.current)\n setMetadata([])\n setMetaErrors({})\n setIsAddingNew(false)\n setNewKey(\"\")\n setNewValue(\"\")\n setNewKeyError(null)\n setNewValueError(null)\n updateMutation.reset()\n }\n\n // ── Mutation ──────────────────────────────────────────────────────────────\n const updateMutation = trpcReact.storage.swift.updateContainerMetadata.useMutation({\n onSuccess: () => {\n utils.storage.swift.getContainerMetadata.invalidate({ container: container!.name })\n utils.storage.swift.listContainers.invalidate()\n onSuccess?.(container!.name)\n handleClose()\n },\n onError: (error) => {\n onError?.(container!.name, error.message)\n },\n })\n\n // ── Validation ────────────────────────────────────────────────────────────\n const validateQuotas = (): boolean => {\n let valid = true\n if (quotaBytes !== \"\" && (isNaN(Number(quotaBytes)) || Number(quotaBytes) < 0)) {\n setQuotaBytesError(t`Must be a non-negative integer`)\n valid = false\n } else {\n setQuotaBytesError(null)\n }\n if (quotaCount !== \"\" && (isNaN(Number(quotaCount)) || Number(quotaCount) < 0)) {\n setQuotaCountError(t`Must be a non-negative integer`)\n valid = false\n } else {\n setQuotaCountError(null)\n }\n return valid\n }\n\n const validateMetaKey = (key: string, originalKey?: string): string | null => {\n if (!key.trim()) return t`Key is required`\n if (!VALID_KEY_RE.test(key)) return t`Key contains invalid characters`\n if (!/[a-zA-Z0-9]/.test(key)) return t`Key must contain at least one alphanumeric character`\n if (RESERVED_META_KEYS.has(key.toLowerCase())) return t`This key is reserved and managed separately`\n const isDuplicate = metadata.some((e) => e.key.toLowerCase() === key.toLowerCase() && e.originalKey !== originalKey)\n if (isDuplicate) return t`A property with this key already exists`\n return null\n }\n\n // ── Metadata row handlers ─────────────────────────────────────────────────\n const handleAddNew = () => {\n const keyErr = validateMetaKey(newKey)\n if (keyErr) {\n setNewKeyError(keyErr)\n return\n }\n if (!newValue.trim()) {\n setNewValueError(t`Value is required`)\n return\n }\n\n setMetadata([...metadata, { key: newKey.trim(), value: newValue.trim(), isNew: true, isEditing: false }])\n setNewKey(\"\")\n setNewValue(\"\")\n setIsAddingNew(false)\n setNewKeyError(null)\n setNewValueError(null)\n }\n\n const handleCancelAdd = () => {\n setNewKey(\"\")\n setNewValue(\"\")\n setIsAddingNew(false)\n setNewKeyError(null)\n setNewValueError(null)\n }\n\n const handleEdit = (index: number) => {\n setMetadata(metadata.map((e, i) => (i === index ? { ...e, isEditing: true } : { ...e, isEditing: false })))\n setIsAddingNew(false)\n }\n\n const handleSaveEdit = (index: number) => {\n const entry = metadata[index]\n const keyErr = validateMetaKey(entry.key, entry.originalKey)\n if (keyErr) {\n setMetaErrors({ [`edit-${index}`]: keyErr })\n return\n }\n if (!entry.value.trim()) {\n setMetaErrors({ [`edit-${index}`]: t`Value is required` })\n return\n }\n\n setMetadata(\n metadata.map((e, i) => (i === index ? { ...e, isEditing: false, key: e.key.trim(), value: e.value.trim() } : e))\n )\n setMetaErrors({})\n }\n\n const handleCancelEdit = (index: number) => {\n setMetadata(\n metadata.map((e, i) =>\n i === index ? { ...e, isEditing: false, key: e.originalKey ?? e.key, value: e.originalValue ?? e.value } : e\n )\n )\n setMetaErrors({})\n }\n\n const handleDeleteMeta = (index: number) => {\n setMetadata(metadata.filter((_, i) => i !== index))\n setMetaErrors({})\n }\n\n const handleKeyChange = (index: number, value: string) => {\n setMetadata(metadata.map((e, i) => (i === index ? { ...e, key: value } : e)))\n setMetaErrors((prev) => {\n const n = { ...prev }\n delete n[`edit-${index}`]\n return n\n })\n }\n\n const handleValueChange = (index: number, value: string) => {\n setMetadata(metadata.map((e, i) => (i === index ? { ...e, value } : e)))\n setMetaErrors((prev) => {\n const n = { ...prev }\n delete n[`edit-${index}`]\n return n\n })\n }\n\n // ── Submit ────────────────────────────────────────────────────────────────\n const handleSubmit = () => {\n if (!container) return\n if (!validateQuotas()) return\n\n const rawMeta = info?.metadata ?? {}\n\n // Build custom metadata updates/removals\n const metadataToSet: Record<string, string> = {}\n const removeMetadata: string[] = []\n\n // New or changed entries\n metadata.forEach((entry) => {\n if (entry.isNew || entry.value !== entry.originalValue || entry.key !== entry.originalKey) {\n metadataToSet[entry.key] = entry.value\n // Key was renamed — remove the old key explicitly\n if (!entry.isNew && entry.originalKey && entry.key !== entry.originalKey) {\n removeMetadata.push(entry.originalKey)\n }\n }\n })\n\n // Deleted entries — keys that were in original but not in current list at all\n const originalKeys = Object.keys(rawMeta).filter((k) => !RESERVED_META_KEYS.has(k))\n const currentOriginalKeys = metadata.map((e) => e.originalKey).filter(Boolean) as string[]\n originalKeys.forEach((k) => {\n if (!currentOriginalKeys.includes(k) && !removeMetadata.includes(k)) removeMetadata.push(k)\n })\n\n // Web index / listings — only relevant when public access is enabled\n if (isPublicAccess) {\n if (webIndex) {\n metadataToSet[\"web-index\"] = webIndex\n } else if (info?.metadata?.[\"web-index\"]) {\n removeMetadata.push(\"web-index\")\n }\n if (webListings) {\n metadataToSet[\"web-listings\"] = \"1\"\n } else if (info?.metadata?.[\"web-listings\"]) {\n removeMetadata.push(\"web-listings\")\n }\n }\n\n // Determine versioning changes\n const wasVersioned = !!(info?.versionsEnabled || info?.versionsLocation || info?.historyLocation)\n const previousLocation = info?.versionsLocation || info?.historyLocation || \"\"\n\n updateMutation.mutate({\n project_id: projectId,\n container: container.name,\n metadata: metadataToSet,\n removeMetadata: removeMetadata.length ? removeMetadata : undefined,\n quotaBytes: quotaBytes !== \"\" ? Number(quotaBytes) : undefined,\n quotaCount: quotaCount !== \"\" ? Number(quotaCount) : undefined,\n // Enable versioning with selected container, update if location changed, or remove if disabled\n versionsLocation:\n versionsEnabled && (!wasVersioned || versionsLocation !== previousLocation) && versionsLocation\n ? versionsLocation\n : undefined,\n removeVersionsLocation: !versionsEnabled && wasVersioned ? true : undefined,\n })\n }\n\n const handleClose = () => {\n resetForm()\n onClose()\n }\n\n if (!isOpen || !container) return null\n\n const isBusy = isLoading || updateMutation.isPending\n const isMetaFailed = isMetaError && !isLoading\n const hasEditing = metadata.some((e) => e.isEditing)\n\n const initialQuotaBytes = info?.quotaBytes != null ? String(info.quotaBytes) : \"\"\n const initialQuotaCount = info?.quotaCount != null ? String(info.quotaCount) : \"\"\n const initialVersionsEnabled = !!info?.versionsEnabled\n const initialVersionsLocation = info?.versionsLocation || info?.historyLocation || \"\"\n const initialWebIndex = info?.metadata?.[\"web-index\"] ?? \"\"\n const initialWebListings = info?.metadata?.[\"web-listings\"] === \"1\" || info?.metadata?.[\"web-listings\"] === \"true\"\n const initialMetadataKeys = Object.keys(info?.metadata ?? {}).filter((k) => !RESERVED_META_KEYS.has(k))\n\n const metadataUnchanged =\n metadata.length === initialMetadataKeys.length &&\n metadata.every((e) => !e.isNew && e.key === e.originalKey && e.value === e.originalValue)\n\n const isUnchanged =\n quotaBytes === initialQuotaBytes &&\n quotaCount === initialQuotaCount &&\n versionsEnabled === initialVersionsEnabled &&\n versionsLocation === initialVersionsLocation &&\n webIndex === initialWebIndex &&\n webListings === initialWebListings &&\n metadataUnchanged\n\n // ── Render ────────────────────────────────────────────────────────────────\n const displayedQuotaBytes = info?.quotaBytes != null ? `${info.quotaBytes} B` : null\n\n return (\n <Modal\n title={\n <span className=\"flex max-w-[500px] items-center gap-2\">\n <span className=\"shrink-0\">\n <Trans>Container:</Trans>\n </span>\n <span className=\"truncate\" title={container.name}>\n {container.name}\n </span>\n </span>\n }\n open={isOpen}\n onCancel={handleClose}\n confirmButtonLabel={t`Save`}\n onConfirm={handleSubmit}\n cancelButtonLabel={t`Cancel`}\n size=\"large\"\n disableConfirmButton={isBusy || isAddingNew || hasEditing || isUnchanged || isMetaFailed}\n >\n {updateMutation.isError && (\n <p className=\"text-theme-error mb-4\">\n {(() => {\n const errorMessage = updateMutation.error.message\n return <Trans>Failed to update container: {errorMessage}</Trans>\n })()}\n </p>\n )}\n {isLoading ? (\n <Stack direction=\"horizontal\" alignment=\"center\" gap=\"2\" className=\"py-8\">\n <Spinner size=\"small\" />\n <Trans>Loading container properties...</Trans>\n </Stack>\n ) : isMetaFailed ? (\n <p className=\"text-theme-error py-8 text-center\">\n {(() => {\n const errorMessage = metaError?.message ?? \"Unknown error\"\n return <Trans>Failed to load container properties: {errorMessage}</Trans>\n })()}\n </p>\n ) : (\n <div className=\"max-h-[65vh] overflow-y-auto pr-1 pl-1\">\n <Stack direction=\"vertical\" gap=\"6\">\n {/* ── Read-only stats ─────────────────────────────────────────── */}\n <div className=\"grid grid-cols-2 gap-4\">\n <TextInput label={t`Object count`} value={String(container.count)} disabled readOnly />\n <TextInput\n label={t`Total size`}\n value={\n info?.bytesUsed != null\n ? `${info.bytesUsed.toLocaleString()} B`\n : `${container.bytes.toLocaleString()} B`\n }\n disabled\n readOnly\n />\n </div>\n\n {/* ── Quotas ──────────────────────────────────────────────────── */}\n <div className=\"grid grid-cols-2 gap-4\">\n <div>\n <TextInput\n label={t`Object count quota`}\n value={quotaCount}\n onChange={(e: React.ChangeEvent<HTMLInputElement>) => {\n setQuotaCount(e.target.value)\n if (quotaCountError) setQuotaCountError(null)\n }}\n placeholder={t`No limit`}\n invalid={!!quotaCountError}\n errortext={quotaCountError ?? undefined}\n disabled={isBusy}\n />\n </div>\n <div>\n <TextInput\n label={t`Total size quota`}\n value={quotaBytes}\n onChange={(e: React.ChangeEvent<HTMLInputElement>) => {\n setQuotaBytes(e.target.value)\n if (quotaBytesError) setQuotaBytesError(null)\n }}\n placeholder={t`No limit`}\n invalid={!!quotaBytesError}\n errortext={quotaBytesError ?? undefined}\n disabled={isBusy}\n helptext={quotaBytes && displayedQuotaBytes ? displayedQuotaBytes : undefined}\n />\n </div>\n </div>\n\n {/* ── Public URL ──────────────────────────────────────────────── */}\n {isPublicAccess && publicUrl && (\n <div>\n <p className=\"text-theme-default mb-1 text-sm font-semibold\">\n <Trans>URL for public access</Trans>{\" \"}\n <a\n href={publicUrl}\n target=\"_blank\"\n rel=\"noopener noreferrer\"\n className=\"text-theme-info text-xs font-normal underline\"\n >\n <Trans>Open in new tab</Trans>\n </a>\n </p>\n <TextInput value={publicUrl} disabled readOnly />\n </div>\n )}\n\n {/* ── Static website serving ───────────────────────────────────── */}\n <div>\n <p className=\"text-theme-default mb-3 text-sm font-semibold\">\n <Trans>Static website serving</Trans>\n </p>\n {isPublicAccess ? (\n <Stack direction=\"vertical\" gap=\"4\">\n <Stack direction=\"vertical\" gap=\"1\">\n <Checkbox\n label={t`Serve objects as index when file name is:`}\n checked={!!webIndex}\n onChange={(e: React.ChangeEvent<HTMLInputElement>) => {\n if (!e.target.checked) setWebIndex(\"\")\n else if (!webIndex) setWebIndex(\"index.html\")\n }}\n disabled={isBusy}\n />\n <div className=\"pl-6\">\n <TextInput\n value={webIndex}\n onChange={(e: React.ChangeEvent<HTMLInputElement>) => setWebIndex(e.target.value)}\n placeholder=\"index.html\"\n disabled={isBusy || !webIndex}\n className=\"flex-1\"\n />\n </div>\n </Stack>\n <Stack direction=\"horizontal\" alignment=\"start\" gap=\"2\">\n <Checkbox\n label={t`Enable file listing`}\n checked={webListings}\n onChange={(e: React.ChangeEvent<HTMLInputElement>) => setWebListings(e.target.checked)}\n disabled={isBusy}\n />\n <Tooltip triggerEvent=\"hover\">\n <TooltipTrigger>\n <Icon icon=\"help\" size=\"16\" className=\"text-theme-light cursor-help\" />\n </TooltipTrigger>\n <TooltipContent className=\"z-10 max-w-[220px]\">\n <Trans>If there is no index file, the URL displays a list of objects in the container.</Trans>\n </TooltipContent>\n </Tooltip>\n </Stack>\n </Stack>\n ) : (\n <p className=\"text-theme-default text-sm\">\n <Trans>\n Public read access is not enabled. Before configuring static website serving, go to{\" \"}\n <strong>Manage Access</strong> and enable public read access.\n </Trans>\n </p>\n )}\n </div>\n\n {/* ── Object versioning ────────────────────────────────────────── */}\n <div>\n <p className=\"text-theme-default mb-2 text-sm font-semibold\">\n <Trans>Object versioning</Trans>\n </p>\n\n {/* Case 1: server-side versioning active, no user changes yet */}\n {initialVersionsEnabled && !versionsLocation ? (\n <Checkbox\n label={t`Versioning is enabled`}\n checked\n onChange={(e: React.ChangeEvent<HTMLInputElement>) => {\n if (!e.target.checked) {\n setVersionsEnabled(false)\n setVersionsLocation(\"\")\n setContainerSearch(\"\")\n setDebouncedSearch(\"\")\n }\n }}\n disabled={true}\n />\n ) : !versionsEnabled && !versionsLocation ? (\n /* Case 2: nothing enabled, nothing selected */\n <Checkbox\n label={t`Store old object versions`}\n checked={false}\n onChange={(e: React.ChangeEvent<HTMLInputElement>) => setVersionsEnabled(e.target.checked)}\n disabled={isBusy}\n />\n ) : (\n /* Case 3: checkbox checked or a container is selected */\n <Stack direction=\"vertical\" gap=\"1\">\n <Checkbox\n label={t`Store old object versions in container:`}\n checked={versionsEnabled}\n onChange={(e: React.ChangeEvent<HTMLInputElement>) => {\n setVersionsEnabled(e.target.checked)\n if (!e.target.checked) {\n setVersionsLocation(\"\")\n setContainerSearch(\"\")\n setDebouncedSearch(\"\")\n }\n }}\n disabled={isBusy}\n />\n {versionsEnabled && (\n <div className=\"pl-6\">\n <ComboBox\n value={versionsLocation}\n onChange={(value: string) => setVersionsLocation(value)}\n onInputChange={handleContainerSearch}\n placeholder={t`Type to search containers...`}\n helptext={(() => {\n if (containerSearch.trim().length === 0) return t`Start typing to search for a container`\n if (hiddenCount > 0) {\n const maxOptions = MAX_COMBO_OPTIONS\n const totalCount = filteredContainers.length\n return t`Showing first ${maxOptions} of ${totalCount} — refine your search to narrow results`\n }\n return undefined\n })()}\n disabled={isBusy}\n >\n {visibleContainers.map((c) => (\n <ComboBoxOption key={c.name} value={c.name}>\n {c.name}\n </ComboBoxOption>\n ))}\n </ComboBox>\n </div>\n )}\n </Stack>\n )}\n </div>\n\n {/* ── Custom Metadata ──────────────────────────────────────────── */}\n <div>\n <Stack direction=\"horizontal\" alignment=\"center\" distribution=\"between\" className=\"mb-3\">\n <p className=\"text-theme-default text-sm font-semibold\">\n <Trans>Metadata</Trans>\n </p>\n <p className=\"text-theme-light text-xs\">\n <Trans>Reserved keys: web-index, web-listings, quota-count, quota-bytes</Trans>\n </p>\n </Stack>\n\n {/* Add Property button */}\n <Stack direction=\"horizontal\" className=\"jn:bg-theme-background-lvl-1 justify-end p-2\">\n <Button\n label={t`Add Property`}\n onClick={() => setIsAddingNew(true)}\n variant=\"primary\"\n icon=\"addCircle\"\n size=\"small\"\n disabled={isAddingNew || hasEditing || isBusy}\n />\n </Stack>\n\n <DataGrid columns={3}>\n <DataGridRow>\n <DataGridHeadCell>\n <Trans>Key</Trans>\n </DataGridHeadCell>\n <DataGridHeadCell>\n <Trans>Value</Trans>\n </DataGridHeadCell>\n <DataGridHeadCell>\n <Trans>Actions</Trans>\n </DataGridHeadCell>\n </DataGridRow>\n\n {/* New row input */}\n {isAddingNew && (\n <DataGridRow>\n <DataGridCell>\n <TextInput\n value={newKey}\n onChange={(e: React.ChangeEvent<HTMLInputElement>) => {\n setNewKey(e.target.value)\n if (newKeyError) setNewKeyError(null)\n }}\n placeholder={t`property_key`}\n errortext={newKeyError ?? undefined}\n invalid={!!newKeyError}\n autoFocus\n />\n </DataGridCell>\n <DataGridCell>\n <TextInput\n value={newValue}\n onChange={(e: React.ChangeEvent<HTMLInputElement>) => {\n setNewValue(e.target.value)\n if (newValueError) setNewValueError(null)\n }}\n placeholder={t`Value`}\n errortext={newValueError ?? undefined}\n invalid={!!newValueError}\n />\n </DataGridCell>\n <DataGridCell>\n <Stack direction=\"horizontal\" gap=\"2\">\n <Button size=\"small\" variant=\"primary\" onClick={handleAddNew} icon=\"check\" title={t`Save`} />\n <Button\n size=\"small\"\n variant=\"subdued\"\n onClick={handleCancelAdd}\n icon=\"close\"\n title={t`Discard`}\n />\n </Stack>\n </DataGridCell>\n </DataGridRow>\n )}\n\n {/* Existing metadata rows */}\n {metadata.map((entry, index) => (\n <DataGridRow key={index}>\n <DataGridCell>\n {entry.isEditing ? (\n <TextInput\n value={entry.key}\n onChange={(e: React.ChangeEvent<HTMLInputElement>) => handleKeyChange(index, e.target.value)}\n errortext={metaErrors[`edit-${index}`]}\n invalid={!!metaErrors[`edit-${index}`]}\n />\n ) : (\n <span className=\"block max-w-xs truncate text-sm\" title={entry.key}>\n {entry.key}\n </span>\n )}\n </DataGridCell>\n <DataGridCell>\n {entry.isEditing ? (\n <TextInput\n value={entry.value}\n onChange={(e: React.ChangeEvent<HTMLInputElement>) =>\n handleValueChange(index, e.target.value)\n }\n />\n ) : (\n <span className=\"block max-w-md truncate text-sm\" title={entry.value}>\n {entry.value}\n </span>\n )}\n </DataGridCell>\n <DataGridCell>\n {entry.isEditing ? (\n <Stack direction=\"horizontal\" gap=\"2\">\n <Button\n size=\"small\"\n variant=\"primary\"\n onClick={() => handleSaveEdit(index)}\n icon=\"check\"\n title={t`Save`}\n />\n <Button\n size=\"small\"\n variant=\"subdued\"\n onClick={() => handleCancelEdit(index)}\n icon=\"close\"\n title={t`Discard`}\n />\n </Stack>\n ) : (\n <Stack direction=\"horizontal\" gap=\"2\">\n <Button\n size=\"small\"\n variant=\"subdued\"\n onClick={() => handleEdit(index)}\n icon=\"edit\"\n title={t`Edit`}\n disabled={isAddingNew || hasEditing || isBusy}\n />\n <Button\n size=\"small\"\n variant=\"primary-danger\"\n onClick={() => handleDeleteMeta(index)}\n icon=\"deleteForever\"\n title={t`Delete`}\n disabled={isAddingNew || hasEditing || isBusy}\n />\n </Stack>\n )}\n </DataGridCell>\n </DataGridRow>\n ))}\n\n {/* Empty state */}\n {metadata.length === 0 && !isAddingNew && (\n <DataGridRow>\n <DataGridCell colSpan={3} className=\"py-6 text-center\">\n <Stack alignment=\"center\">\n <span className=\"text-theme-light text-sm\">\n <Trans>No custom metadata. Click \"Add Property\" to create one.</Trans>\n </span>\n </Stack>\n </DataGridCell>\n </DataGridRow>\n )}\n </DataGrid>\n </div>\n </Stack>\n </div>\n )}\n </Modal>\n )\n}\n","import { useState, useEffect, useRef, Fragment } from \"react\"\nimport { Trans, useLingui } from \"@lingui/react/macro\"\nimport { t } from \"@lingui/core/macro\"\nimport { trpcReact } from \"@/client/trpcClient\"\nimport { useProjectId } from \"@/client/hooks/useProjectId\"\nimport {\n Modal,\n Textarea,\n Stack,\n Spinner,\n Checkbox,\n Badge,\n Button,\n Icon,\n Tooltip,\n TooltipTrigger,\n TooltipContent,\n Message,\n DescriptionList,\n DescriptionTerm,\n DescriptionDefinition,\n} from \"@cloudoperators/juno-ui-components\"\nimport { ContainerSummary } from \"@/server/Storage/types/swift\"\n\n// ── ACL parsing helpers ──────────────────────────────────────────────────────\n\ntype AclEntryType =\n | \"any-referrer\"\n | \"denied-referrer\"\n | \"specific-referrer\"\n | \"listing-access\"\n | \"all-project-users\"\n | \"specific-user-any-project\"\n | \"specific-user\"\n | \"unknown\"\n\ninterface ParsedAclEntry {\n raw: string\n type: AclEntryType\n host?: string\n projectId?: string\n userId?: string\n description: string\n requiresToken: boolean\n}\n\n/**\n * Parses a single ACL entry string into a human-readable representation.\n * Handles the following Swift ACL formats:\n * .r:* — public read (any referrer)\n * .rlistings — public container listing\n * PROJECT:USER — specific user from a specific project\n * PROJECT:* — all users from a project\n * *:USER — specific user from any project\n */\nfunction parseAclEntry(raw: string): ParsedAclEntry {\n const entry = raw.trim()\n\n if (entry === \".r:*\") {\n return { raw: entry, type: \"any-referrer\", description: \"\", requiresToken: false }\n }\n\n // .r:<referrer> or .r:-<referrer> — specific referrer granted (or denied) access\n if (entry.startsWith(\".r:\")) {\n const referrer = entry.slice(3)\n const isDeny = referrer.startsWith(\"-\")\n const host = isDeny ? referrer.slice(1) : referrer\n return {\n raw: entry,\n type: isDeny ? \"denied-referrer\" : \"specific-referrer\",\n host,\n description: \"\",\n requiresToken: false,\n }\n }\n\n if (entry === \".rlistings\") {\n return { raw: entry, type: \"listing-access\", description: \"\", requiresToken: false }\n }\n\n // PROJECT_ID:* — all users from a project\n if (/^[^:]+:\\*$/.test(entry) && !entry.startsWith(\"*\")) {\n const [projectId] = entry.split(\":\")\n return {\n raw: entry,\n type: \"all-project-users\",\n projectId,\n description: \"\",\n requiresToken: true,\n }\n }\n\n // *:USER_ID — specific user, any project\n if (entry.startsWith(\"*:\")) {\n const userId = entry.slice(2)\n return {\n raw: entry,\n type: \"specific-user-any-project\",\n userId,\n description: \"\",\n requiresToken: true,\n }\n }\n\n // PROJECT_ID:USER_ID\n if (entry.includes(\":\")) {\n const [projectId, userId] = entry.split(\":\")\n return {\n raw: entry,\n type: \"specific-user\",\n projectId,\n userId,\n description: \"\",\n requiresToken: true,\n }\n }\n\n // Fallback — unknown format\n return { raw: entry, type: \"unknown\", description: \"\", requiresToken: true }\n}\n\nfunction parseAclString(aclString: string): ParsedAclEntry[] {\n if (!aclString.trim()) return []\n return aclString\n .split(\",\")\n .map((s) => s.trim())\n .filter(Boolean)\n .map(parseAclEntry)\n}\n\n// ── Public read sentinel values ──────────────────────────────────────────────\n// const PUBLIC_READ_ACL = \".r:*,.rlistings\"\nconst PUBLIC_READ_ENTRIES = [\".r:*\", \".rlistings\"]\n\nfunction isPublicRead(readAcl: string): boolean {\n const entries = readAcl\n .split(\",\")\n .map((s) => s.trim())\n .filter(Boolean)\n return PUBLIC_READ_ENTRIES.every((e) => entries.includes(e))\n}\n\nfunction addPublicReadEntries(current: string): string {\n const existing = current\n .split(\",\")\n .map((s) => s.trim())\n .filter(Boolean)\n const merged = [...new Set([...PUBLIC_READ_ENTRIES, ...existing])]\n return merged.join(\",\")\n}\n\nfunction removePublicReadEntries(current: string): string {\n return current\n .split(\",\")\n .map((s) => s.trim())\n .filter((e) => !PUBLIC_READ_ENTRIES.includes(e))\n .join(\",\")\n}\n\n// ── ACL label rendering helper ──────────────────────────────────────────────\n\nfunction aclEntryLabel(entry: ParsedAclEntry): string {\n switch (entry.type) {\n case \"any-referrer\":\n return t`ANY referrer`\n case \"denied-referrer\": {\n const host = entry.host || \"\"\n return t`Denied referrer: ${host}`\n }\n case \"specific-referrer\": {\n const host = entry.host || \"\"\n return t`Specific referrer: ${host}`\n }\n case \"listing-access\":\n return t`Listing access`\n case \"all-project-users\": {\n const projectId = entry.projectId || \"\"\n return t`All users from project ${projectId}`\n }\n case \"specific-user-any-project\": {\n const userId = entry.userId || \"\"\n return t`User ${userId} (any project)`\n }\n case \"specific-user\": {\n const projectId = entry.projectId || \"\"\n const userId = entry.userId || \"\"\n return t`User ${userId} from project ${projectId}`\n }\n case \"unknown\":\n default:\n return entry.raw\n }\n}\n\n// ── Component ────────────────────────────────────────────────────────────────\n\ninterface ManageContainerAccessModalProps {\n isOpen: boolean\n container: ContainerSummary | null\n onClose: () => void\n onSuccess?: (containerName: string) => void\n onError?: (containerName: string, errorMessage: string) => void\n}\n\nexport const ManageContainerAccessModal = ({\n isOpen,\n container,\n onClose,\n onSuccess,\n onError,\n}: ManageContainerAccessModalProps) => {\n const { t } = useLingui()\n const projectId = useProjectId()\n\n const [readAcl, setReadAcl] = useState(\"\")\n const [writeAcl, setWriteAcl] = useState(\"\")\n const [publicRead, setPublicRead] = useState(false)\n const [showPreview, setShowPreview] = useState(false)\n\n // Auto-collapse preview when both ACL fields are cleared\n useEffect(() => {\n if (!readAcl.trim() && !writeAcl.trim()) setShowPreview(false)\n }, [readAcl, writeAcl])\n\n // ── Query ─────────────────────────────────────────────────────────────────\n const {\n data: info,\n isLoading,\n isError: isMetaError,\n error: metaError,\n } = trpcReact.storage.swift.getContainerMetadata.useQuery(\n { project_id: projectId, container: container?.name ?? \"\" },\n { enabled: isOpen && container !== null }\n )\n\n // ── Populate form when data arrives ──────────────────────────────────────\n useEffect(() => {\n if (!info) return\n const read = info.read ?? \"\"\n const write = info.write ?? \"\"\n setReadAcl(read)\n setWriteAcl(write)\n setPublicRead(isPublicRead(read))\n }, [info])\n\n // ── Mutation ──────────────────────────────────────────────────────────────\n const utils = trpcReact.useUtils()\n\n const updateMutation = trpcReact.storage.swift.updateContainerMetadata.useMutation({\n onSuccess: () => {\n utils.storage.swift.getContainerMetadata.invalidate({ project_id: projectId, container: container!.name })\n utils.storage.swift.listContainers.invalidate()\n onSuccess?.(container!.name)\n handleClose()\n },\n onError: (error) => {\n onError?.(container!.name, error.message)\n },\n })\n\n // Keep a stable ref to reset() so the cleanup effect below doesn't need\n // updateMutation in its dependency array (the mutation object is recreated\n // on every render, which would cause an infinite loop).\n const resetMutationRef = useRef(updateMutation.reset)\n resetMutationRef.current = updateMutation.reset\n\n const handleClose = () => {\n setReadAcl(\"\")\n setWriteAcl(\"\")\n setPublicRead(false)\n setShowPreview(false)\n updateMutation.reset()\n onClose()\n }\n\n // ── Reset when closed ────────────────────────────────────────────────────\n useEffect(() => {\n if (!isOpen) {\n setReadAcl(\"\")\n setWriteAcl(\"\")\n setPublicRead(false)\n resetMutationRef.current()\n }\n }, [isOpen])\n\n // ── Public read checkbox sync ─────────────────────────────────────────────\n const handlePublicReadChange = (e: React.ChangeEvent<HTMLInputElement>) => {\n const checked = e.target.checked\n setPublicRead(checked)\n setReadAcl((prev) => (checked ? addPublicReadEntries(prev) : removePublicReadEntries(prev)))\n }\n\n const handleReadAclChange = (e: React.ChangeEvent<HTMLTextAreaElement>) => {\n const value = e.target.value\n setReadAcl(value)\n setPublicRead(isPublicRead(value))\n }\n\n // ── Submit ────────────────────────────────────────────────────────────────\n const handleSubmit = () => {\n if (!container) return\n updateMutation.mutate({\n project_id: projectId,\n container: container.name,\n read: readAcl.trim(),\n write: writeAcl.trim(),\n })\n }\n\n if (!isOpen || !container) return null\n\n const isBusy = isLoading || updateMutation.isPending\n const hasAnyAcl = readAcl.trim().length > 0 || writeAcl.trim().length > 0\n\n const parsedReadEntries = parseAclString(readAcl)\n const parsedWriteEntries = parseAclString(writeAcl)\n\n const modalTitle = (\n <span className=\"flex items-center gap-2\">\n <Trans>Access Control for Container:</Trans>\n <span className=\"max-w-[250px] truncate\" title={container.name}>\n {container.name}\n </span>\n </span>\n )\n\n return (\n <Modal\n title={modalTitle}\n open={isOpen}\n onCancel={handleClose}\n confirmButtonLabel={t`Save`}\n onConfirm={handleSubmit}\n cancelButtonLabel={t`Cancel`}\n size=\"xl\"\n disableConfirmButton={isBusy || isMetaError}\n >\n {updateMutation.isError && (\n <p className=\"text-theme-error mb-4\">\n {(() => {\n const errorMessage = updateMutation.error.message\n return <Trans>Failed to update ACLs: {errorMessage}</Trans>\n })()}\n </p>\n )}\n <div className=\"max-h-[70vh] overflow-y-auto pr-1 pl-1\">\n {/* ── Info message ─────────────────────────────────────────────────── */}\n <div className=\"mb-4\">\n <Message variant=\"warning\" className=\"mb-4\">\n <Trans>\n Ensure that the Project ID and User ID you enter are correct. The system cannot validate these values —\n incorrect IDs may apply access to wrong projects and users.\n </Trans>\n </Message>\n </div>\n\n {isLoading ? (\n <Stack direction=\"horizontal\" alignment=\"center\" gap=\"2\" className=\"py-6\">\n <Spinner size=\"small\" />\n <Trans>Loading ACLs...</Trans>\n </Stack>\n ) : isMetaError ? (\n <p className=\"text-theme-error py-2\">\n {(() => {\n const errorMessage = metaError?.message ?? \"\"\n return <Trans>Failed to load container ACLs: {errorMessage}</Trans>\n })()}\n </p>\n ) : (\n <>\n <div className=\"flex gap-6\">\n {/* ── Left: editable inputs ──────────────────────────────────── */}\n <div className=\"min-w-0 flex-1\">\n <Stack direction=\"vertical\" gap=\"6\">\n {/* Read ACLs */}\n <div>\n <AclFieldLabel label={t`Read ACLs`} />\n <Textarea\n value={readAcl}\n onChange={handleReadAclChange}\n disabled={isBusy || publicRead}\n placeholder={t`e.g. .r:*,.rlistings`}\n className=\"text-sm\"\n rows={3}\n />\n <Checkbox\n label={t`Public Read Access`}\n checked={publicRead}\n onChange={handlePublicReadChange}\n disabled={isBusy}\n className=\"mt-2\"\n />\n </div>\n\n {/* Write ACLs */}\n <div>\n <AclFieldLabel label={t`Write ACLs`} />\n <Textarea\n value={writeAcl}\n onChange={(e: React.ChangeEvent<HTMLTextAreaElement>) => {\n const value = e.target.value\n setWriteAcl(value)\n }}\n disabled={isBusy}\n placeholder={t`e.g. PROJECT_ID:USER_ID`}\n className=\"text-sm\"\n rows={3}\n />\n </div>\n\n {/* ── Preview toggle button — only shown when at least one ACL is set (only shown when ACL fields have content) ──────────────────────────── */}\n {hasAnyAcl && (\n <Button\n label={showPreview ? t`Hide ACLs Preview` : t`Show ACLs Preview`}\n onClick={() => setShowPreview((v) => !v)}\n variant=\"subdued\"\n disabled={isBusy}\n className=\"self-start\"\n />\n )}\n\n {/* ── Parsed ACL preview — inside left column, below button ── */}\n {showPreview && (parsedReadEntries.length > 0 || parsedWriteEntries.length > 0) && (\n <Stack direction=\"vertical\" gap=\"4\">\n {parsedReadEntries.length > 0 && (\n <div>\n <p className=\"text-theme-default mb-2 text-sm font-semibold\">\n <Trans>Read ACLs — Preview</Trans>\n </p>\n <div className=\"border-theme-background-lvl-3 rounded border p-3\">\n <DescriptionList className=\"grid-cols-2\" alignTerms=\"left\">\n {parsedReadEntries.map((entry, i) => (\n <Fragment key={i}>\n <DescriptionTerm className=\"col-span-1\">\n <span className=\"block truncate text-xs\" title={entry.raw}>\n {entry.raw}\n </span>\n </DescriptionTerm>\n <DescriptionDefinition className=\"col-span-1\">\n <span className=\"block truncate text-sm\" title={aclEntryLabel(entry)}>\n {aclEntryLabel(entry)}\n </span>\n <span className=\"text-theme-light block text-xs\">\n {entry.requiresToken ? (\n <Trans>valid token required: true</Trans>\n ) : (\n <Trans>valid token required: false</Trans>\n )}\n </span>\n </DescriptionDefinition>\n </Fragment>\n ))}\n </DescriptionList>\n </div>\n </div>\n )}\n\n {parsedWriteEntries.length > 0 && (\n <div>\n <p className=\"text-theme-default mb-2 text-sm font-semibold\">\n <Trans>Write ACLs — Preview</Trans>\n </p>\n <div className=\"border-theme-background-lvl-3 rounded border p-3\">\n <DescriptionList className=\"grid-cols-2\" alignTerms=\"left\">\n {parsedWriteEntries.map((entry, i) => (\n <Fragment key={i}>\n <DescriptionTerm className=\"col-span-1\">\n <span className=\"block truncate text-xs\" title={entry.raw}>\n {entry.raw}\n </span>\n </DescriptionTerm>\n <DescriptionDefinition className=\"col-span-1\">\n <span className=\"block truncate text-sm\" title={aclEntryLabel(entry)}>\n {aclEntryLabel(entry)}\n </span>\n <span className=\"text-theme-light block text-xs\">\n {entry.requiresToken ? (\n <Trans>valid token required: true</Trans>\n ) : (\n <Trans>valid token required: false</Trans>\n )}\n </span>\n </DescriptionDefinition>\n </Fragment>\n ))}\n </DescriptionList>\n </div>\n </div>\n )}\n </Stack>\n )}\n </Stack>\n </div>\n\n {/* ── Right: reference panel ─────────────────────────────────── */}\n <div className=\"border-theme-background-lvl-3 w-72 shrink-0 border-l pl-6\">\n <p className=\"text-theme-light mb-3 text-xs\">\n <Trans>Entries in ACLs are comma-separated. Examples:</Trans>\n </p>\n\n <Stack direction=\"vertical\" gap=\"4\">\n <AclExample\n code=\".r:*\"\n description={t`Any user has read access to objects. No token is required in the request.`}\n />\n <AclExample\n code=\".rlistings\"\n description={t`Any user can perform a HEAD or GET operation on the container provided the user also has read access on objects. No token is required.`}\n />\n <AclExample\n code=\"PROJECT_ID:USER_ID\"\n description={t`Grant access to a user from a different project.`}\n />\n <AclExample code=\"PROJECT_ID:*\" description={t`Grant access to all users from that project.`} />\n <AclExample\n code=\"*:USER_ID\"\n description={t`The specified user has access. A token for the user (scoped to any project) must be included in the request.`}\n />\n </Stack>\n\n <p className=\"text-theme-light mt-4 text-xs\">\n <Trans>\n For more details, have a look at the{\" \"}\n <a\n href=\"https://docs.openstack.org/swift/latest/overview_acl.html\"\n target=\"_blank\"\n rel=\"noopener noreferrer\"\n className=\"text-theme-link underline\"\n >\n documentation\n </a>\n .\n </Trans>\n </p>\n </div>\n </div>\n </>\n )}\n\n {/* Note shown at the bottom of the modal body, just above the Save button */}\n {!isLoading && !isMetaError && (\n <p className=\"text-theme-light mt-4 text-xs\">\n <Trans>Changes take effect immediately after saving.</Trans>\n </p>\n )}\n </div>\n </Modal>\n )\n}\n\n// ── AclExample sub-component ─────────────────────────────────────────────────\n\ninterface AclExampleProps {\n code: string\n description: string\n}\n\nfunction AclExample({ code, description }: AclExampleProps) {\n return (\n <div>\n <Badge variant=\"info\" className=\"mb-1 text-xs\">\n {code}\n </Badge>\n <p className=\"text-theme-light text-xs leading-relaxed\">{description}</p>\n </div>\n )\n}\n\n// ── AclFieldLabel sub-component ──────────────────────────────────────────────\n\ninterface AclFieldLabelProps {\n label: string\n}\n\nfunction AclFieldLabel({ label }: AclFieldLabelProps) {\n return (\n <div className=\"mb-1 flex items-center gap-1\">\n <label className=\"text-theme-default text-sm font-semibold\">{label}</label>\n <Tooltip triggerEvent=\"hover\">\n <TooltipTrigger>\n <Icon icon=\"info\" size=\"14\" className=\"text-theme-light cursor-help\" />\n </TooltipTrigger>\n <TooltipContent className=\"z-10 max-w-[350px]\">\n <Trans>\n Ensure ACL entries are valid — correct project IDs, user IDs, and formats are your responsibility. Invalid\n entries may silently grant or deny unintended access.\n </Trans>\n </TooltipContent>\n </Tooltip>\n </div>\n )\n}\n","import { useRef, useEffect, useState } from \"react\"\nimport { useVirtualizer } from \"@tanstack/react-virtual\"\nimport { useNavigate, useParams } from \"@tanstack/react-router\"\nimport {\n Checkbox,\n DataGrid,\n DataGridHeadCell,\n DataGridRow,\n DataGridCell,\n PopupMenu,\n PopupMenuItem,\n PopupMenuOptions,\n} from \"@cloudoperators/juno-ui-components\"\nimport { Trans, useLingui } from \"@lingui/react/macro\"\nimport { ContainerSummary } from \"@/server/Storage/types/swift\"\nimport { formatBytesBinary } from \"@/client/utils/formatBytes\"\nimport { CreateContainerModal } from \"./CreateContainerModal\"\nimport { EmptyContainerModal } from \"./EmptyContainerModal\"\nimport { DeleteContainerModal } from \"./DeleteContainerModal\"\nimport { EditContainerMetadataModal } from \"./EditContainerMetadataModal\"\nimport { ManageContainerAccessModal } from \"./ManageContainerAccessModal\"\n\ninterface ContainerTableViewProps {\n containers: ContainerSummary[]\n createModalOpen: boolean\n setCreateModalOpen: (open: boolean) => void\n maxContainerNameLength?: number\n onCreateSuccess: (containerName: string) => void\n onCreateError: (containerName: string, errorMessage: string) => void\n onEmptySuccess: (containerName: string, deletedCount: number) => void\n onEmptyError: (containerName: string, errorMessage: string) => void\n onDeleteSuccess: (containerName: string) => void\n onDeleteError: (containerName: string, errorMessage: string) => void\n onPropertiesSuccess: (containerName: string) => void\n onPropertiesError: (containerName: string, errorMessage: string) => void\n onAclSuccess: (containerName: string) => void\n onAclError: (containerName: string, errorMessage: string) => void\n selectedContainers: string[]\n setSelectedContainers: (containers: string[]) => void\n // When false, the row-selection column (header checkbox + per-row checkboxes)\n // is dropped entirely and the grid renders one fewer column. Defaults to true\n // so existing callers that don't pass it keep the selectable layout.\n hasAnyBulkAction?: boolean\n}\n\nexport const ContainerTableView = ({\n containers,\n createModalOpen,\n setCreateModalOpen,\n maxContainerNameLength,\n onCreateSuccess,\n onCreateError,\n onEmptySuccess,\n onEmptyError,\n onDeleteSuccess,\n onDeleteError,\n onPropertiesSuccess,\n onPropertiesError,\n onAclSuccess,\n onAclError,\n selectedContainers,\n setSelectedContainers,\n hasAnyBulkAction = true,\n}: ContainerTableViewProps) => {\n const { projectId, provider, storageType } = useParams({\n from: \"/_auth/projects/$projectId/storage/$provider/$storageType/\",\n })\n\n const { t } = useLingui()\n const navigate = useNavigate()\n\n const parentRef = useRef<HTMLDivElement>(null)\n const [scrollbarWidth, setScrollbarWidth] = useState(0)\n const [emptyModalContainer, setEmptyModalContainer] = useState<ContainerSummary | null>(null)\n const [deleteModalContainer, setDeleteModalContainer] = useState<ContainerSummary | null>(null)\n const [propertiesModalContainer, setPropertiesModalContainer] = useState<ContainerSummary | null>(null)\n const [accessControlModalContainer, setAccessControlModalContainer] = useState<ContainerSummary | null>(null)\n\n // Calculate scrollbar width\n useEffect(() => {\n if (parentRef.current) {\n const width = parentRef.current.offsetWidth - parentRef.current.clientWidth\n setScrollbarWidth(width)\n }\n }, [containers.length])\n\n // Format date to localized string\n const formatDate = (dateString: string): string => {\n try {\n const date = new Date(dateString)\n return date.toLocaleString()\n } catch {\n return t`N/A`\n }\n }\n\n const rowVirtualizer = useVirtualizer({\n count: containers.length,\n getScrollElement: () => parentRef.current,\n estimateSize: () => 48, // Estimated row height\n overscan: 10,\n })\n\n const handleSelectContainer = (containerName: string) => {\n if (selectedContainers.includes(containerName)) {\n setSelectedContainers(selectedContainers.filter((name) => name !== containerName))\n } else {\n setSelectedContainers([...selectedContainers, containerName])\n }\n }\n\n if (!containers || containers.length === 0) {\n return (\n <>\n <DataGrid columns={4} className=\"containers\" data-testid=\"no-containers\">\n <DataGridRow>\n <DataGridCell colSpan={4}>\n <div className=\"py-8 text-center\">\n <h3 className=\"text-lg font-semibold\">\n <Trans>No containers found</Trans>\n </h3>\n <p className=\"text-theme-light mt-2\">\n <Trans>\n There are no containers available with the current search criteria. Try adjusting your search term.\n </Trans>\n </p>\n </div>\n </DataGridCell>\n </DataGridRow>\n </DataGrid>\n\n <CreateContainerModal\n isOpen={createModalOpen}\n onClose={() => setCreateModalOpen(false)}\n onSuccess={onCreateSuccess}\n onError={onCreateError}\n maxContainerNameLength={maxContainerNameLength}\n />\n </>\n )\n }\n\n // Column count and template depend on whether the selection column is shown.\n // With selection: checkbox, name, count, last modified, size, actions menu (6).\n // Without selection: the leading 40px checkbox column is dropped (5).\n const columnCount = hasAnyBulkAction ? 6 : 5\n const gridColumnTemplate = hasAnyBulkAction\n ? \"40px minmax(200px, 2fr) minmax(100px, 1fr) minmax(180px, 2fr) minmax(100px, 1fr) 60px\"\n : \"minmax(200px, 2fr) minmax(100px, 1fr) minmax(180px, 2fr) minmax(100px, 1fr) 60px\"\n\n return (\n <>\n <div className=\"relative\">\n {/* Table Header with scrollbar padding */}\n <div style={{ paddingRight: `${scrollbarWidth}px` }}>\n <DataGrid\n columns={columnCount}\n gridColumnTemplate={gridColumnTemplate}\n className=\"containers\"\n data-testid=\"containers-table-header\"\n >\n <DataGridRow>\n {hasAnyBulkAction && <DataGridHeadCell />}\n <DataGridHeadCell>\n <Trans>Container Name</Trans>\n </DataGridHeadCell>\n <DataGridHeadCell>\n <Trans>Object Count</Trans>\n </DataGridHeadCell>\n <DataGridHeadCell>\n <Trans>Last Modified</Trans>\n </DataGridHeadCell>\n <DataGridHeadCell>\n <Trans>Total Size</Trans>\n </DataGridHeadCell>\n <DataGridHeadCell style={{ marginRight: `-${scrollbarWidth}px` }} />\n </DataGridRow>\n </DataGrid>\n </div>\n\n {/* Virtualized Table Body with dynamic height */}\n <div\n ref={parentRef}\n className=\"overflow-auto\"\n style={{\n height: \"calc(100vh - 490px)\", // Dynamic height based on viewport\n // minHeight: \"400px\", // Minimum height for usability\n // maxHeight: \"800px\", // Maximum height to prevent overflow\n }}\n data-testid=\"containers-table-body\"\n >\n <div\n style={{\n height: `${rowVirtualizer.getTotalSize()}px`,\n width: \"100%\",\n position: \"relative\",\n }}\n >\n {rowVirtualizer.getVirtualItems().map((virtualRow) => {\n const container = containers[virtualRow.index]\n const isSelected = selectedContainers.includes(container.name)\n\n const handleRowNavigate = () =>\n navigate({\n to: \"/projects/$projectId/storage/$provider/$storageType/$containerName/objects\",\n params: { projectId, provider, storageType, containerName: container.name },\n })\n\n return (\n <div\n key={container.name}\n data-index={virtualRow.index}\n ref={rowVirtualizer.measureElement}\n className=\"juno-datagrid group hover:bg-theme-background-lvl-1 cursor-pointer\"\n style={{\n position: \"absolute\",\n top: 0,\n left: 0,\n width: \"100%\",\n transform: `translateY(${virtualRow.start}px)`,\n display: \"grid\",\n gridTemplateColumns: gridColumnTemplate,\n alignItems: \"stretch\",\n }}\n data-testid={`container-row-${container.name}`}\n role=\"link\"\n tabIndex={0}\n onClick={handleRowNavigate}\n onKeyDown={(e) => {\n if (e.key === \"Enter\" || e.key === \" \") {\n e.preventDefault()\n handleRowNavigate()\n }\n }}\n >\n {hasAnyBulkAction && (\n <DataGridCell\n onClick={(e) => e.stopPropagation()}\n onKeyDown={(e) => {\n if (e.key === \"Enter\" || e.key === \" \") {\n e.stopPropagation()\n }\n }}\n >\n <Checkbox\n checked={isSelected}\n onChange={() => handleSelectContainer(container.name)}\n data-testid={`select-container-${container.name}`}\n />\n </DataGridCell>\n )}\n <DataGridCell className=\"min-w-0 overflow-hidden\">\n <span className=\"block truncate\" title={container.name}>\n {container.name}\n </span>\n </DataGridCell>\n <DataGridCell>{container.count.toLocaleString()}</DataGridCell>\n <DataGridCell>{container.last_modified ? formatDate(container.last_modified) : t`N/A`}</DataGridCell>\n <DataGridCell>{formatBytesBinary(container.bytes)}</DataGridCell>\n <DataGridCell onClick={(e) => e.stopPropagation()}>\n <PopupMenu>\n <PopupMenuOptions>\n <PopupMenuItem\n label={t`Manage Access`}\n onClick={() => setAccessControlModalContainer(container)}\n data-testid={`access-control-action-${container.name}`}\n />\n <PopupMenuItem\n label={t`Preview and Edit metadata`}\n onClick={() => setPropertiesModalContainer(container)}\n data-testid={`properties-action-${container.name}`}\n />\n <PopupMenuItem\n label={t`Empty`}\n onClick={() => setEmptyModalContainer(container)}\n data-testid={`empty-action-${container.name}`}\n />\n <PopupMenuItem\n label={t`Delete`}\n onClick={() => setDeleteModalContainer(container)}\n data-testid={`delete-action-${container.name}`}\n />\n </PopupMenuOptions>\n </PopupMenu>\n </DataGridCell>\n </div>\n )\n })}\n </div>\n </div>\n </div>\n\n <CreateContainerModal\n isOpen={createModalOpen}\n onClose={() => setCreateModalOpen(false)}\n onSuccess={onCreateSuccess}\n onError={onCreateError}\n maxContainerNameLength={maxContainerNameLength}\n />\n\n <EmptyContainerModal\n isOpen={emptyModalContainer !== null}\n container={emptyModalContainer}\n onClose={() => setEmptyModalContainer(null)}\n onSuccess={onEmptySuccess}\n onError={onEmptyError}\n />\n\n <DeleteContainerModal\n isOpen={deleteModalContainer !== null}\n container={deleteModalContainer}\n onClose={() => setDeleteModalContainer(null)}\n onSuccess={onDeleteSuccess}\n onError={onDeleteError}\n />\n\n <EditContainerMetadataModal\n isOpen={propertiesModalContainer !== null}\n container={propertiesModalContainer}\n onClose={() => setPropertiesModalContainer(null)}\n onSuccess={onPropertiesSuccess}\n onError={onPropertiesError}\n />\n\n <ManageContainerAccessModal\n isOpen={accessControlModalContainer !== null}\n container={accessControlModalContainer}\n onClose={() => setAccessControlModalContainer(null)}\n onSuccess={onAclSuccess}\n onError={onAclError}\n />\n </>\n )\n}\n","import { ReactNode } from \"react\"\nimport { ToastProps } from \"@cloudoperators/juno-ui-components\"\nimport { Trans, Plural } from \"@lingui/react/macro\"\nimport { Stack } from \"@cloudoperators/juno-ui-components/index\"\n\ninterface NotificationTextProps {\n title: ReactNode\n description: ReactNode\n}\n\nexport function NotificationText({ title, description }: NotificationTextProps) {\n return (\n <Stack direction=\"vertical\" gap=\"1.5\">\n <span>{title}</span>\n <span className=\"text-theme-light\">{description}</span>\n </Stack>\n )\n}\n\ninterface ToastConfig {\n onDismiss: () => void\n}\n\nexport const getContainerCreatedToast = (containerName: string, config: ToastConfig): ToastProps => ({\n variant: \"success\",\n children: (\n <NotificationText\n title={<Trans>Container Created</Trans>}\n description={<Trans>Container \"{containerName}\" was successfully created.</Trans>}\n />\n ),\n onDismiss: config.onDismiss,\n})\n\nexport const getContainerCreateErrorToast = (\n containerName: string,\n errorMessage: string,\n config: ToastConfig\n): ToastProps => ({\n variant: \"error\",\n children: (\n <NotificationText\n title={<Trans>Failed to Create Container</Trans>}\n description={\n <Trans>\n Could not create container \"{containerName}\": {errorMessage}\n </Trans>\n }\n />\n ),\n onDismiss: config.onDismiss,\n})\n\nexport const getContainerEmptiedToast = (\n containerName: string,\n deletedCount: number,\n config: ToastConfig\n): ToastProps => ({\n variant: \"success\",\n children: (\n <NotificationText\n title={<Trans>Container Emptied</Trans>}\n description={\n deletedCount === 0 ? (\n <Trans>Container \"{containerName}\" was already empty.</Trans>\n ) : deletedCount === 1 ? (\n <Trans>\n Container \"{containerName}\" was successfully emptied. {deletedCount} object deleted.\n </Trans>\n ) : (\n <Trans>\n Container \"{containerName}\" was successfully emptied. {deletedCount} objects deleted.\n </Trans>\n )\n }\n />\n ),\n onDismiss: config.onDismiss,\n})\n\nexport const getContainerEmptyErrorToast = (\n containerName: string,\n errorMessage: string,\n config: ToastConfig\n): ToastProps => ({\n variant: \"error\",\n children: (\n <NotificationText\n title={<Trans>Failed to Empty Container</Trans>}\n description={\n <Trans>\n Could not empty container \"{containerName}\": {errorMessage}\n </Trans>\n }\n />\n ),\n onDismiss: config.onDismiss,\n})\n\nexport const getContainerDeletedToast = (containerName: string, config: ToastConfig): ToastProps => ({\n variant: \"success\",\n children: (\n <NotificationText\n title={<Trans>Container Deleted</Trans>}\n description={<Trans>Container \"{containerName}\" was successfully deleted.</Trans>}\n />\n ),\n onDismiss: config.onDismiss,\n})\n\nexport const getContainerDeleteErrorToast = (\n containerName: string,\n errorMessage: string,\n config: ToastConfig\n): ToastProps => ({\n variant: \"error\",\n children: (\n <NotificationText\n title={<Trans>Failed to Delete Container</Trans>}\n description={\n <Trans>\n Could not delete container \"{containerName}\": {errorMessage}\n </Trans>\n }\n />\n ),\n onDismiss: config.onDismiss,\n})\n\nexport const getContainerUpdatedToast = (containerName: string, config: ToastConfig): ToastProps => ({\n variant: \"success\",\n children: (\n <NotificationText\n title={<Trans>Container Updated</Trans>}\n description={<Trans>Container \"{containerName}\" properties were successfully updated.</Trans>}\n />\n ),\n onDismiss: config.onDismiss,\n})\n\nexport const getContainerUpdateErrorToast = (\n containerName: string,\n errorMessage: string,\n config: ToastConfig\n): ToastProps => ({\n variant: \"error\",\n children: (\n <NotificationText\n title={<Trans>Failed to Update Container</Trans>}\n description={\n <Trans>\n Could not update container \"{containerName}\": {errorMessage}\n </Trans>\n }\n />\n ),\n onDismiss: config.onDismiss,\n})\n\nexport const getContainerAclUpdatedToast = (containerName: string, config: ToastConfig): ToastProps => ({\n variant: \"success\",\n children: (\n <NotificationText\n title={<Trans>Access Control Updated</Trans>}\n description={<Trans>ACLs for container \"{containerName}\" were successfully updated.</Trans>}\n />\n ),\n onDismiss: config.onDismiss,\n})\n\nexport const getContainerAclUpdateErrorToast = (\n containerName: string,\n errorMessage: string,\n config: ToastConfig\n): ToastProps => ({\n variant: \"error\",\n children: (\n <NotificationText\n title={<Trans>Failed to Update Access Control</Trans>}\n description={\n <Trans>\n Could not update ACLs for container \"{containerName}\": {errorMessage}\n </Trans>\n }\n />\n ),\n onDismiss: config.onDismiss,\n})\n\nexport const getContainersEmptiedToast = (\n emptiedCount: number,\n totalDeleted: number,\n config: ToastConfig\n): ToastProps => ({\n variant: \"success\",\n children: (\n <NotificationText\n title={<Trans>Containers Emptied</Trans>}\n description={\n totalDeleted === 0 ? (\n <Plural value={emptiedCount} one=\"# container was already empty.\" other=\"# containers were already empty.\" />\n ) : (\n <Trans>\n <Plural value={emptiedCount} one=\"# container\" other=\"# containers\" /> successfully emptied.{\" \"}\n <Plural value={totalDeleted} one=\"# object\" other=\"# objects\" /> deleted in total.\n </Trans>\n )\n }\n />\n ),\n onDismiss: config.onDismiss,\n})\n\nexport const getContainersEmptyErrorToast = (errorMessage: string, config: ToastConfig): ToastProps => ({\n variant: \"error\",\n children: (\n <NotificationText\n title={<Trans>Failed to Empty Containers</Trans>}\n description={\n <span className=\"whitespace-pre-line\">\n <Trans>One or more containers could not be emptied: {errorMessage}</Trans>\n </span>\n }\n />\n ),\n onDismiss: config.onDismiss,\n})\nexport const getContainersEmptyCompleteToast = (\n emptiedCount: number,\n totalDeleted: number,\n errors: string[],\n config: ToastConfig\n): ToastProps => {\n const hasErrors = errors.length > 0\n const hasSuccess = emptiedCount > 0\n const isPartial = hasErrors && hasSuccess\n\n return {\n variant: isPartial ? \"warning\" : hasErrors ? \"error\" : \"success\",\n children: (\n <NotificationText\n title={\n isPartial ? (\n <Trans>Containers Partially Emptied</Trans>\n ) : hasErrors ? (\n <Trans>Failed to Empty Containers</Trans>\n ) : (\n <Trans>Containers Emptied</Trans>\n )\n }\n description={\n <Stack direction=\"vertical\" gap=\"1\">\n {hasSuccess && (\n <span>\n <Trans>\n <Plural value={emptiedCount} one=\"# container\" other=\"# containers\" /> successfully emptied.{\" \"}\n <Plural value={totalDeleted} one=\"# object\" other=\"# objects\" /> deleted in total.\n </Trans>\n </span>\n )}\n {hasErrors && (\n <span className=\"whitespace-pre-line\">\n {(() => {\n const errorDetails = errors.join(\"\\n\")\n return <Trans>Failed: {errorDetails}</Trans>\n })()}\n </span>\n )}\n </Stack>\n }\n />\n ),\n onDismiss: config.onDismiss,\n }\n}\n","import { Trans, useLingui } from \"@lingui/react/macro\"\nimport { Tooltip, TooltipTrigger, TooltipContent, Icon } from \"@cloudoperators/juno-ui-components\"\nimport { ServiceInfo, AccountInfo } from \"@/server/Storage/types/swift\"\nimport { formatBytesBinary } from \"@/client/utils/formatBytes\"\n\ninterface ContainerLimitsTooltipProps {\n serviceInfo?: ServiceInfo\n accountInfo?: AccountInfo\n open?: boolean\n}\n\ninterface LimitItemProps {\n label: string\n value?: string | number\n}\n\nconst LimitItem = ({ label, value }: LimitItemProps) => {\n if (value === undefined || value === null) return null\n return (\n <span className=\"flex items-start gap-1.5\">\n <Icon icon=\"check\" size=\"16px\" className=\"text-theme-success mt-0.5 shrink-0\" />\n <span>\n <span className=\"font-medium\">{label}:</span> {value}\n </span>\n </span>\n )\n}\n\nconst CapabilityItem = ({ label }: { label: string }) => (\n <span className=\"flex items-start gap-1.5\">\n <Icon icon=\"check\" size=\"16px\" className=\"text-theme-success mt-0.5 shrink-0\" />\n <span>{label}</span>\n </span>\n)\n\nconst Section = ({ title, children }: { title: React.ReactNode; children: React.ReactNode }) => (\n <span className=\"flex flex-col gap-1.5\">\n <span className=\"text-theme-default block font-semibold\">{title}</span>\n {children}\n </span>\n)\n\nexport const ContainerLimitsTooltip = ({ serviceInfo, accountInfo, open }: ContainerLimitsTooltipProps) => {\n const { t } = useLingui()\n\n const swift = serviceInfo?.swift\n\n const capabilityMap = {\n account_quotas: t`Account quotas`,\n container_quotas: t`Container quotas`,\n bulk_delete: t`Efficient bulk deletion`,\n bulk_upload: t`Bulk upload of archive files`,\n slo: t`Static large object support`,\n container_sync: t`Container syncing`,\n tempurl: t`Temporary URLs`,\n symlink: t`Symlinks`,\n versioned_writes: t`Versioned writes`,\n } as const\n\n const capabilities = Object.entries(capabilityMap)\n .filter(([key]) => swift?.[key as keyof typeof swift])\n .map(([, label]) => label)\n\n return (\n <Tooltip triggerEvent=\"hover\" placement=\"bottom-end\" open={open}>\n <TooltipTrigger asChild>\n <Icon icon=\"info\" size=\"20px\" className=\"text-theme-light hover:text-theme-default cursor-pointer\" />\n </TooltipTrigger>\n <TooltipContent className=\"z-10 w-72 text-sm\">\n <span className=\"flex flex-col gap-3 p-1\">\n {/* Account stats */}\n {accountInfo && (\n <Section title={<Trans>Account</Trans>}>\n <LimitItem label={t`Containers`} value={accountInfo.containerCount.toLocaleString()} />\n <LimitItem label={t`Objects`} value={accountInfo.objectCount.toLocaleString()} />\n <LimitItem label={t`Used`} value={formatBytesBinary(accountInfo.bytesUsed)} />\n {accountInfo.quotaBytes !== undefined && (\n <LimitItem label={t`Quota`} value={formatBytesBinary(accountInfo.quotaBytes)} />\n )}\n </Section>\n )}\n\n {/* Limits */}\n {swift && (\n <Section title={<Trans>Limits</Trans>}>\n <LimitItem\n label={t`Max file size`}\n value={swift.max_file_size !== undefined ? formatBytesBinary(swift.max_file_size) : undefined}\n />\n <LimitItem label={t`Max container name length`} value={swift.max_container_name_length} />\n <LimitItem label={t`Max object name length`} value={swift.max_object_name_length} />\n <LimitItem label={t`Container listing limit`} value={swift.container_listing_limit?.toLocaleString()} />\n <LimitItem label={t`Account listing limit`} value={swift.account_listing_limit?.toLocaleString()} />\n <LimitItem label={t`Max header size`} value={swift.max_header_size} />\n <LimitItem label={t`Max meta count`} value={swift.max_meta_count} />\n <LimitItem label={t`Max meta name length`} value={swift.max_meta_name_length} />\n <LimitItem label={t`Max meta value length`} value={swift.max_meta_value_length} />\n <LimitItem label={t`Max meta overall size`} value={swift.max_meta_overall_size} />\n {swift.bulk_delete && (\n <LimitItem\n label={t`Max deletes per request`}\n value={swift.bulk_delete.max_deletes_per_request.toLocaleString()}\n />\n )}\n {swift.bulk_upload && (\n <LimitItem\n label={t`Max containers per extraction`}\n value={swift.bulk_upload.max_containers_per_extraction.toLocaleString()}\n />\n )}\n {swift.slo && (\n <LimitItem label={t`Max SLO segments`} value={swift.slo.max_manifest_segments.toLocaleString()} />\n )}\n </Section>\n )}\n\n {/* Capabilities */}\n {capabilities.length > 0 && (\n <Section title={<Trans>Capabilities</Trans>}>\n {capabilities.map((cap) => (\n <CapabilityItem key={cap} label={cap} />\n ))}\n </Section>\n )}\n </span>\n </TooltipContent>\n </Tooltip>\n )\n}\n","import { useState, Fragment } from \"react\"\nimport React from \"react\"\nimport { Plural, Trans, useLingui } from \"@lingui/react/macro\"\nimport { plural } from \"@lingui/core/macro\"\nimport { trpcReact } from \"@/client/trpcClient\"\nimport {\n Modal,\n Spinner,\n Stack,\n Message,\n TextInput,\n DescriptionList,\n DescriptionTerm,\n DescriptionDefinition,\n} from \"@cloudoperators/juno-ui-components\"\nimport { ContainerSummary } from \"@/server/Storage/types/swift\"\nimport { useProjectId } from \"@/client/hooks/useProjectId\"\n\n// Max number of container names shown in the list before truncating\nconst MAX_VISIBLE = 20\n\n// The literal word the user must type to confirm this destructive action.\n// The gating logic (isConfirmed) compares against this constant, NOT the\n// translated label — so a mistranslated label can never weaken or break the\n// confirmation gate. The English label below should name the same word for clarity.\nconst CONFIRM_WORD = \"empty\"\n\ninterface EmptyContainersResult {\n emptiedCount: number\n totalDeleted: number\n errors: string[]\n}\n\ninterface EmptyContainersModalProps {\n isOpen: boolean\n containers: ContainerSummary[]\n onClose: () => void\n onComplete?: (result: EmptyContainersResult) => void\n}\n\nexport const EmptyContainersModal = ({ isOpen, containers, onClose, onComplete }: EmptyContainersModalProps) => {\n const { t, i18n } = useLingui()\n const projectId = useProjectId()\n\n const [progress, setProgress] = useState<{ current: number; total: number } | null>(null)\n const [confirmValue, setConfirmValue] = useState(\"\")\n const isConfirmed = confirmValue.trim() === CONFIRM_WORD\n\n const utils = trpcReact.useUtils()\n\n const emptyContainerMutation = trpcReact.storage.swift.emptyContainer.useMutation()\n\n const handleClose = () => {\n emptyContainerMutation.reset()\n setProgress(null)\n setConfirmValue(\"\")\n onClose()\n }\n\n const handleConfirm = async () => {\n let emptiedCount = 0\n let totalDeleted = 0\n const errors: string[] = []\n const total = containers.length\n\n for (let i = 0; i < containers.length; i++) {\n setProgress({ current: i + 1, total })\n const container = containers[i]\n\n try {\n const deleted = await emptyContainerMutation.mutateAsync({ project_id: projectId, container: container.name })\n totalDeleted += deleted\n emptiedCount++\n } catch (err) {\n const message = err instanceof Error ? err.message : String(err)\n errors.push(`${container.name}: ${message}`)\n }\n }\n\n if (emptiedCount > 0) {\n await utils.storage.swift.listContainers.invalidate()\n }\n\n onComplete?.({ emptiedCount, totalDeleted, errors })\n\n handleClose()\n }\n\n if (!isOpen || containers.length === 0) return null\n\n const totalCount = containers.length\n const visibleContainers = containers.slice(0, MAX_VISIBLE)\n const hiddenCount = totalCount - visibleContainers.length\n const isPending = emptyContainerMutation.isPending || progress !== null\n const progressCurrent = progress?.current\n const progressTotal = progress?.total\n\n return (\n <Modal\n title={<Plural value={totalCount} one=\"Empty Container\" other=\"Empty # Containers\" />}\n open={isOpen}\n onCancel={handleClose}\n confirmButtonLabel={isPending ? t`Emptying...` : t`Empty`}\n confirmButtonVariant=\"primary-danger\"\n cancelButtonLabel={t`Cancel`}\n onConfirm={handleConfirm}\n disableConfirmButton={isPending || !isConfirmed}\n disableCancelButton={isPending}\n disableCloseButton={isPending}\n size=\"small\"\n >\n {isPending ? (\n <Stack direction=\"vertical\" distribution=\"center\" alignment=\"center\" gap=\"2\" className=\"py-4\">\n <Spinner variant=\"primary\" />\n {progress && (\n <p className=\"text-theme-light text-sm\">\n <Trans>\n Emptying container {progressCurrent} of {progressTotal}, please wait...\n </Trans>\n </p>\n )}\n </Stack>\n ) : (\n <div className=\"my-6\">\n <Message variant=\"danger\" className=\"mb-6\">\n <Trans>All objects in the selected containers will be permanently deleted. This cannot be undone.</Trans>\n </Message>\n\n <p className=\"text-theme-default mb-6 text-sm\">\n <Trans>\n For <strong>dynamic</strong> and <strong>static large objects</strong> only the manifests are deleted —\n the related segments are not deleted.\n </Trans>\n </p>\n\n <div className=\"mb-6\">\n <h3 className=\"jn:text-theme-high mb-3 font-semibold\">\n <Trans>Containers to be emptied ({totalCount})</Trans>\n </h3>\n <div className=\"jn:bg-theme-background-lvl-1 max-h-48 overflow-y-auto rounded p-4\">\n <DescriptionList className=\"grid-cols-2\" alignTerms=\"left\">\n {visibleContainers.map((container) => {\n const count = container.count\n return (\n <Fragment key={container.name}>\n <DescriptionTerm className=\"col-span-1\">\n <span className=\"block truncate\" title={container.name}>\n {container.name}\n </span>\n </DescriptionTerm>\n <DescriptionDefinition className=\"col-span-1\">\n <span className=\"whitespace-nowrap\">\n {count != null ? i18n._(plural(count, { one: \"# object\", other: \"# objects\" })) : \"\"}\n </span>\n </DescriptionDefinition>\n </Fragment>\n )\n })}\n </DescriptionList>\n {hiddenCount > 0 && (\n <p className=\"text-theme-light mt-2 text-xs\">\n <Trans>... and {hiddenCount} more</Trans>\n </p>\n )}\n </div>\n </div>\n\n <TextInput\n label={t`Type \"empty\" to confirm`}\n placeholder={CONFIRM_WORD}\n value={confirmValue}\n onChange={(e: React.ChangeEvent<HTMLInputElement>) => setConfirmValue(e.target.value)}\n />\n </div>\n )}\n </Modal>\n )\n}\n","import { useState, useEffect, useRef, startTransition } from \"react\"\nimport { Plural, Trans, useLingui } from \"@lingui/react/macro\"\nimport { plural } from \"@lingui/core/macro\"\nimport { SortInput } from \"@/client/components/ListToolbar/SortInput\"\nimport { SortSettings } from \"@/client/components/ListToolbar/types\"\nimport { ContainerSummary } from \"@/server/Storage/types/swift\"\nimport { trpcReact } from \"@/client/trpcClient\"\nimport {\n Button,\n Checkbox,\n DataGridToolbar,\n PopupMenu,\n PopupMenuItem,\n PopupMenuOptions,\n PopupMenuToggle,\n SearchInput,\n Spinner,\n Stack,\n Toast,\n ToastProps,\n} from \"@cloudoperators/juno-ui-components\"\nimport { formatBytesBinary } from \"@/client/utils/formatBytes\"\nimport { ContainerTableView } from \"./ContainerTableView\"\nimport {\n getContainerCreatedToast,\n getContainerCreateErrorToast,\n getContainerEmptiedToast,\n getContainerEmptyErrorToast,\n getContainerDeletedToast,\n getContainerDeleteErrorToast,\n getContainerUpdatedToast,\n getContainerUpdateErrorToast,\n getContainerAclUpdatedToast,\n getContainerAclUpdateErrorToast,\n getContainersEmptyCompleteToast,\n} from \"./ContainerToastNotifications\"\nimport { ContainerLimitsTooltip } from \"./ContainerLimitsTooltip\"\nimport { EmptyContainersModal } from \"./EmptyContainersModal\"\nimport { useNavigate } from \"@tanstack/react-router\"\nimport { Route } from \"../../../$provider/$storageType/\"\nimport { useProjectId } from \"@/client/hooks/useProjectId\"\n\nexport const SwiftContainers = () => {\n const { t, i18n } = useLingui()\n const projectId = useProjectId()\n const navigate = useNavigate({ from: Route.fullPath })\n\n // Sort and search state are persisted in the URL so they survive navigation,\n // browser back/forward, and deep links.\n const { sortBy, sortDirection, search: searchParam = \"\" } = Route.useSearch()\n\n // Whether the list exposes any bulk action — drives the selection column in\n // ContainerTableView and the Zone 3 bulk-action controls. Hardcoded to true\n // for now; the only bulk action today is the destructive Empty.\n //\n // TODO(perms): wire this to the real Swift container permission source\n // (e.g. a usePermissions hook or a tRPC permissions query) instead of\n // hardcoding it.\n const hasAnyBulkAction = true\n\n const [createModalOpen, setCreateModalOpen] = useState(false)\n const [emptyAllModalOpen, setEmptyAllModalOpen] = useState(false)\n const [selectedContainers, setSelectedContainers] = useState<string[]>([])\n const [toastData, setToastData] = useState<ToastProps | null>(null)\n\n // Local mirror of the committed search term so typing stays responsive while\n // the URL commit is debounced (see Zone 2 SearchInput below).\n const [localSearchTerm, setLocalSearchTerm] = useState(searchParam)\n const debounceTimer = useRef<number | undefined>(undefined)\n useEffect(() => () => clearTimeout(debounceTimer.current), [])\n\n // Keep the input in sync when the committed search term changes from outside\n // the input — browser back/forward, deep links, or programmatic navigation —\n // so the field never drifts from the URL-backed filter state. When the change\n // originated from our own debounced commit, searchParam already equals\n // localSearchTerm, so this is a no-op and won't disturb the caret.\n useEffect(() => {\n setLocalSearchTerm(searchParam)\n }, [searchParam])\n\n const handleToastDismiss = () => setToastData(null)\n\n const handleCreateSuccess = (containerName: string) => {\n setToastData(getContainerCreatedToast(containerName, { onDismiss: handleToastDismiss }))\n }\n\n const handleCreateError = (containerName: string, errorMessage: string) => {\n setToastData(getContainerCreateErrorToast(containerName, errorMessage, { onDismiss: handleToastDismiss }))\n }\n\n const handleEmptySuccess = (containerName: string, deletedCount: number) => {\n setToastData(getContainerEmptiedToast(containerName, deletedCount, { onDismiss: handleToastDismiss }))\n }\n\n const handleEmptyError = (containerName: string, errorMessage: string) => {\n setToastData(getContainerEmptyErrorToast(containerName, errorMessage, { onDismiss: handleToastDismiss }))\n }\n\n const handleDeleteSuccess = (containerName: string) => {\n setToastData(getContainerDeletedToast(containerName, { onDismiss: handleToastDismiss }))\n }\n\n const handleDeleteError = (containerName: string, errorMessage: string) => {\n setToastData(getContainerDeleteErrorToast(containerName, errorMessage, { onDismiss: handleToastDismiss }))\n }\n\n const handlePropertiesSuccess = (containerName: string) => {\n setToastData(getContainerUpdatedToast(containerName, { onDismiss: handleToastDismiss }))\n }\n\n const handlePropertiesError = (containerName: string, errorMessage: string) => {\n setToastData(getContainerUpdateErrorToast(containerName, errorMessage, { onDismiss: handleToastDismiss }))\n }\n\n const handleAclSuccess = (containerName: string) => {\n setToastData(getContainerAclUpdatedToast(containerName, { onDismiss: handleToastDismiss }))\n }\n\n const handleAclError = (containerName: string, errorMessage: string) => {\n setToastData(getContainerAclUpdateErrorToast(containerName, errorMessage, { onDismiss: handleToastDismiss }))\n }\n\n const handleEmptyAllComplete = ({\n emptiedCount,\n totalDeleted,\n errors,\n }: {\n emptiedCount: number\n totalDeleted: number\n errors: string[]\n }) => {\n if (errors.length === 0) {\n setSelectedContainers([])\n } else {\n // Extract the container name from each error string formatted as \"<containerName>: <message>\".\n // Using exact name extraction avoids the false-positive substring match that\n // errorMessage.includes(containerName) would produce (e.g. \"foo\" matched inside \"foobar\" error).\n const failedContainerNames = new Set(errors.map((e) => e.split(\": \")[0]))\n setSelectedContainers((prev) => prev.filter((name) => failedContainerNames.has(name)))\n }\n setToastData(getContainersEmptyCompleteToast(emptiedCount, totalDeleted, errors, { onDismiss: handleToastDismiss }))\n }\n\n const sortSettings: SortSettings = {\n options: [\n { label: t`Name`, value: \"name\" },\n { label: t`Object Count`, value: \"count\" },\n { label: t`Total Size`, value: \"bytes\" },\n { label: t`Last Modified`, value: \"last_modified\" },\n ],\n sortBy: sortBy ?? \"name\",\n sortDirection: sortDirection ?? \"asc\",\n }\n\n // Fetch containers from tRPC\n const {\n data: containers,\n isLoading,\n error,\n } = trpcReact.storage.swift.listContainers.useQuery({\n project_id: projectId,\n format: \"json\",\n })\n\n // Fetch account metadata for quota information\n const { data: accountInfo } = trpcReact.storage.swift.getAccountMetadata.useQuery({\n project_id: projectId,\n })\n\n // Fetch Swift service info\n const { data: serviceInfo } = trpcReact.storage.swift.getServiceInfo.useQuery()\n\n // Sort containers based on sort settings\n const sortContainers = (containers: ContainerSummary[]): ContainerSummary[] => {\n return [...containers].sort((a, b) => {\n let comparison: number\n\n switch (sortBy ?? \"name\") {\n case \"name\":\n comparison = a.name.localeCompare(b.name)\n break\n case \"count\":\n comparison = a.count - b.count\n break\n case \"bytes\":\n comparison = a.bytes - b.bytes\n break\n case \"last_modified\":\n if (!a.last_modified || !b.last_modified) {\n return a.last_modified ? -1 : 1\n }\n comparison = new Date(a.last_modified).getTime() - new Date(b.last_modified).getTime()\n break\n default:\n comparison = a.name.localeCompare(b.name)\n }\n\n return (sortDirection ?? \"asc\") === \"desc\" ? -comparison : comparison\n })\n }\n\n // Filter containers based on search term\n const filteredContainers = (containers || []).filter((container) =>\n container.name.toLowerCase().includes(searchParam.toLowerCase())\n )\n\n // Apply sorting to filtered containers\n const sortedContainers = sortContainers(filteredContainers)\n\n const handleSearchChange = (term: string | number | string[] | undefined) => {\n const value = typeof term === \"string\" ? term : \"\"\n startTransition(() => {\n navigate({\n search: (prev) => ({ ...prev, search: value || undefined }),\n })\n })\n }\n\n const handleSortChange = (newSortSettings: SortSettings) => {\n const resolvedSortBy = (newSortSettings.sortBy?.toString() || \"name\") as\n | \"name\"\n | \"count\"\n | \"bytes\"\n | \"last_modified\"\n const resolvedDirection = (newSortSettings.sortDirection || \"asc\") as \"asc\" | \"desc\"\n startTransition(() => {\n navigate({\n search: (prev) => ({\n ...prev,\n sortBy: resolvedSortBy,\n sortDirection: resolvedDirection,\n }),\n })\n })\n }\n\n // Handle loading state\n if (isLoading) {\n return (\n <Stack className=\"absolute inset-0\" distribution=\"center\" alignment=\"center\" direction=\"vertical\">\n <Spinner variant=\"primary\" size=\"large\" className=\"mb-2\" />\n <Trans>Loading Containers...</Trans>\n </Stack>\n )\n }\n\n // Handle error state\n if (error) {\n const errorMessage = error.message\n\n return (\n <Stack className=\"absolute inset-0\" distribution=\"center\" alignment=\"center\" direction=\"vertical\">\n <Trans>Error Loading Containers: {errorMessage}</Trans>\n </Stack>\n )\n }\n\n // Calculate quota information\n const bytesUsed = accountInfo?.bytesUsed || 0\n const quotaBytes = accountInfo?.quotaBytes || 0\n const remainingBytes = quotaBytes > 0 ? quotaBytes - bytesUsed : 0\n\n // Resolve selected ContainerSummary objects from the full unfiltered list so\n // the modal always operates on what was actually selected — not the filtered\n // subset currently visible in the table.\n const selectedContainerSummaries = (containers || []).filter((c) => selectedContainers.includes(c.name))\n const hasSelection = selectedContainerSummaries.length > 0\n const selectedCount = selectedContainerSummaries.length\n\n const totalCount = (containers || []).length\n const filteredCount = filteredContainers.length\n const isFiltered = filteredCount !== totalCount\n\n // Select-all operates on the currently displayed (filtered + sorted) rows.\n const displayedNames = sortedContainers.map((c) => c.name)\n const allSelected = displayedNames.length > 0 && displayedNames.every((n) => selectedContainers.includes(n))\n const someSelected = displayedNames.some((n) => selectedContainers.includes(n))\n\n const handleToggleSelectAll = () => {\n if (allSelected) {\n setSelectedContainers((prev) => prev.filter((n) => !displayedNames.includes(n)))\n } else {\n setSelectedContainers((prev) => [...new Set([...prev, ...displayedNames])])\n }\n }\n\n return (\n <div className=\"relative\">\n <Stack direction=\"vertical\">\n {/* Zone 1 — sort controls and the create action (plain Stack, no background) */}\n <Stack distribution=\"end\" alignment=\"center\" gap=\"2\" className=\"pb-2\">\n <Stack gap=\"0.5\" alignment=\"center\">\n <SortInput\n options={sortSettings.options}\n sortBy={sortSettings.sortBy}\n sortDirection={sortSettings.sortDirection ?? \"asc\"}\n onSortByChange={(v) =>\n handleSortChange({ ...sortSettings, sortBy: v, sortDirection: sortSettings.sortDirection })\n }\n onSortDirectionChange={(dir) => handleSortChange({ ...sortSettings, sortDirection: dir })}\n />\n </Stack>\n <Button variant=\"primary\" className=\"whitespace-nowrap\" onClick={() => setCreateModalOpen(true)}>\n <Trans>Create Container</Trans>\n </Button>\n </Stack>\n\n {/* Zone 2 — search (+ filter pills). DataGridToolbar provides the background.\n Swift containers expose no filterable dimensions yet, so there is no\n FiltersInput / SelectedFilters here. When filter dimensions are added,\n add FiltersInput alongside the search (switch the inner Stack to\n distribution=\"between\") and render SelectedFilters below, using\n applyFilterSelection from urlHelpers for merge logic. */}\n <DataGridToolbar>\n <Stack direction=\"vertical\" gap=\"2\">\n <Stack distribution=\"end\" alignment=\"center\">\n <SearchInput\n placeholder={t`Search containers...`}\n data-testid=\"searchbar\"\n value={localSearchTerm}\n onInput={(e: React.FormEvent<HTMLInputElement>) => {\n const v = e.currentTarget.value\n setLocalSearchTerm(v)\n clearTimeout(debounceTimer.current)\n debounceTimer.current = window.setTimeout(() => handleSearchChange(v), 500)\n }}\n onSearch={(v) => {\n clearTimeout(debounceTimer.current)\n handleSearchChange(typeof v === \"string\" ? v : \"\")\n }}\n onClear={() => {\n clearTimeout(debounceTimer.current)\n setLocalSearchTerm(\"\")\n handleSearchChange(\"\")\n }}\n />\n </Stack>\n </Stack>\n </DataGridToolbar>\n\n {/* Zone 3 — bulk actions (gated) plus the container/quota info.\n Unlike the Images reference (where Zone 3 carries only bulk actions and is\n omitted entirely without permissions), this bar also hosts the Swift-specific\n count + remaining-quota + limits info, which must always be visible. So the\n bar always renders; only the bulk controls are gated. */}\n <DataGridToolbar>\n <Stack distribution=\"start\" gap=\"2\" alignment=\"center\" className=\"text-sm\">\n {hasAnyBulkAction ? (\n <Stack gap=\"2\" alignment=\"center\">\n <Checkbox\n checked={allSelected}\n indeterminate={someSelected && !allSelected}\n onChange={handleToggleSelectAll}\n />\n <PopupMenu className=\"flex items-center\">\n <PopupMenuToggle as=\"div\">\n <Button disabled={!hasSelection} size=\"small\" icon=\"moreVert\" label={t`Actions`} />\n </PopupMenuToggle>\n {hasSelection && (\n <PopupMenuOptions>\n <PopupMenuItem\n disabled={!hasSelection}\n label={i18n._(\n plural(selectedCount, {\n one: \"Empty Container\",\n other: \"Empty # Containers\",\n })\n )}\n onClick={() => setEmptyAllModalOpen(true)}\n />\n </PopupMenuOptions>\n )}\n </PopupMenu>\n </Stack>\n ) : (\n <span />\n )}\n\n <div className=\"text-theme-light flex items-center gap-1\" data-testid=\"containers-info-block\">\n {isFiltered ? (\n <Plural\n value={filteredCount}\n one={`${filteredCount} of ${totalCount} container`}\n other={`${filteredCount} of ${totalCount} containers`}\n />\n ) : (\n <Plural value={totalCount} one={`${totalCount} container`} other={`${totalCount} containers`} />\n )}\n {quotaBytes > 0 && (\n <>\n <span>,</span>\n <span>\n <Trans>Remaining Quota:</Trans>{\" \"}\n <span className=\"text-theme-default font-semibold\">{formatBytesBinary(remainingBytes)}</span>\n </span>\n </>\n )}\n <ContainerLimitsTooltip serviceInfo={serviceInfo} accountInfo={accountInfo} />\n </div>\n </Stack>\n </DataGridToolbar>\n </Stack>\n\n <ContainerTableView\n containers={sortedContainers}\n createModalOpen={createModalOpen}\n setCreateModalOpen={setCreateModalOpen}\n maxContainerNameLength={serviceInfo?.swift?.max_container_name_length}\n onCreateSuccess={handleCreateSuccess}\n onCreateError={handleCreateError}\n onEmptySuccess={handleEmptySuccess}\n onEmptyError={handleEmptyError}\n onDeleteSuccess={handleDeleteSuccess}\n onDeleteError={handleDeleteError}\n onPropertiesSuccess={handlePropertiesSuccess}\n onPropertiesError={handlePropertiesError}\n onAclSuccess={handleAclSuccess}\n onAclError={handleAclError}\n selectedContainers={selectedContainers}\n setSelectedContainers={setSelectedContainers}\n hasAnyBulkAction={hasAnyBulkAction}\n />\n\n <EmptyContainersModal\n isOpen={emptyAllModalOpen}\n containers={selectedContainerSummaries}\n onClose={() => setEmptyAllModalOpen(false)}\n onComplete={handleEmptyAllComplete}\n />\n\n {toastData && (\n <Toast {...toastData} className=\"border-theme-light fixed top-5 right-5 z-50 rounded-lg border shadow-lg\" />\n )}\n </div>\n )\n}\n","import { useState } from \"react\"\nimport { Trans, useLingui } from \"@lingui/react/macro\"\nimport { trpcReact } from \"@/client/trpcClient\"\nimport { Modal, TextInput, Stack, Checkbox } from \"@cloudoperators/juno-ui-components\"\nimport { useProjectId } from \"@/client/hooks/useProjectId\"\n\ninterface CreateBucketModalProps {\n isOpen: boolean\n onClose: () => void\n onSuccess?: (bucketName: string) => void\n onError?: (bucketName: string, errorMessage: string) => void\n}\n\n// S3 bucket naming validation patterns\nconst S3_BUCKET_NAME_REGEX = /^[a-z0-9][a-z0-9.-]*[a-z0-9]$/\nconst IP_ADDRESS_REGEX = /^(\\d{1,3}\\.){3}\\d{1,3}$/\nconst RESERVED_PREFIXES = [\"xn--\", \"sthree-\", \"amzn-s3-demo-\"]\nconst RESERVED_SUFFIXES = [\"-s3alias\", \"--ol-s3\", \".mrap\", \"--x-s3\", \"--table-s3\"]\n\nexport const CreateBucketModal = ({ isOpen, onClose, onSuccess, onError }: CreateBucketModalProps) => {\n const { t } = useLingui()\n const projectId = useProjectId()\n const [bucketName, setBucketName] = useState(\"\")\n const [nameError, setNameError] = useState<string | null>(null)\n const [enableVersioning, setEnableVersioning] = useState(false)\n\n const utils = trpcReact.useUtils()\n\n const createBucketMutation = trpcReact.storage.ceph.containers.create.useMutation({\n onSuccess: () => {\n utils.storage.ceph.containers.list.invalidate()\n const name = bucketName.trim()\n onSuccess?.(name)\n },\n onError: (error) => {\n onError?.(bucketName.trim(), error.message)\n },\n onSettled: () => {\n handleClose()\n },\n })\n\n const handleClose = () => {\n setBucketName(\"\")\n setNameError(null)\n setEnableVersioning(false)\n createBucketMutation.reset()\n onClose()\n }\n\n const validateName = (name: string): boolean => {\n const trimmed = name.trim()\n\n // Length validation\n if (!trimmed) {\n setNameError(t`Bucket name is required`)\n return false\n }\n if (trimmed.length < 3) {\n setNameError(t`Bucket name must be at least 3 characters`)\n return false\n }\n if (trimmed.length > 63) {\n setNameError(t`Bucket name must be 63 characters or fewer`)\n return false\n }\n\n // Character set validation (lowercase letters, numbers, periods, hyphens)\n if (!S3_BUCKET_NAME_REGEX.test(trimmed)) {\n setNameError(t`Bucket name must contain only lowercase letters, numbers, periods, and hyphens`)\n return false\n }\n\n // Must start and end with letter or number (already covered by regex, but explicit message)\n if (!/^[a-z0-9]/.test(trimmed) || !/[a-z0-9]$/.test(trimmed)) {\n setNameError(t`Bucket name must start and end with a letter or number`)\n return false\n }\n\n // No consecutive periods\n if (trimmed.includes(\"..\")) {\n setNameError(t`Bucket name must not contain consecutive periods`)\n return false\n }\n\n // Not formatted as IP address\n if (IP_ADDRESS_REGEX.test(trimmed)) {\n setNameError(t`Bucket name must not be formatted as an IP address`)\n return false\n }\n\n // Check reserved prefixes\n for (const prefix of RESERVED_PREFIXES) {\n if (trimmed.startsWith(prefix)) {\n setNameError(t`Bucket name must not start with reserved prefix \"${prefix}\"`)\n return false\n }\n }\n\n // Check reserved suffixes\n for (const suffix of RESERVED_SUFFIXES) {\n if (trimmed.endsWith(suffix)) {\n setNameError(t`Bucket name must not end with reserved suffix \"${suffix}\"`)\n return false\n }\n }\n\n setNameError(null)\n return true\n }\n\n const handleNameChange = (e: React.ChangeEvent<HTMLInputElement>) => {\n const value = e.target.value\n setBucketName(value)\n if (nameError) validateName(value)\n }\n\n const handleSubmit = () => {\n if (!validateName(bucketName)) return\n createBucketMutation.mutate({\n project_id: projectId,\n bucketName: bucketName.trim(),\n enableVersioning,\n })\n }\n\n const handleKeyDown = (e: React.KeyboardEvent) => {\n if (e.key === \"Enter\") {\n handleSubmit()\n }\n }\n\n if (!isOpen) return null\n\n return (\n <Modal\n title={t`Create Bucket`}\n open={isOpen}\n onCancel={handleClose}\n confirmButtonLabel={t`Create`}\n onConfirm={handleSubmit}\n cancelButtonLabel={t`Cancel`}\n size=\"small\"\n disableConfirmButton={createBucketMutation.isPending || !bucketName.trim()}\n >\n <Stack direction=\"vertical\" gap=\"6\">\n <p className=\"text-theme-default\">\n <Trans>\n S3 bucket names must be 3-63 characters long and contain only lowercase letters, numbers, periods, and\n hyphens. They must start and end with a letter or number, and be globally unique within the cluster.\n </Trans>\n </p>\n <TextInput\n label={t`Bucket name`}\n required\n value={bucketName}\n onChange={handleNameChange}\n onKeyDown={handleKeyDown}\n invalid={!!nameError}\n errortext={nameError || undefined}\n disabled={createBucketMutation.isPending}\n autoFocus\n placeholder={t`my-bucket-name`}\n />\n <Checkbox\n label={t`Enable versioning`}\n helptext={t`Keep multiple versions of objects. Cannot be fully disabled once enabled, only suspended.`}\n checked={enableVersioning}\n onChange={(e: React.ChangeEvent<HTMLInputElement>) => setEnableVersioning(e.target.checked)}\n disabled={createBucketMutation.isPending}\n />\n </Stack>\n </Modal>\n )\n}\n","import { useRef, useEffect, useState } from \"react\"\nimport { useVirtualizer } from \"@tanstack/react-virtual\"\nimport { useNavigate, useParams } from \"@tanstack/react-router\"\nimport {\n Checkbox,\n DataGrid,\n DataGridHeadCell,\n DataGridRow,\n DataGridCell,\n PopupMenu,\n PopupMenuItem,\n PopupMenuOptions,\n} from \"@cloudoperators/juno-ui-components\"\nimport { Trans, useLingui } from \"@lingui/react/macro\"\nimport { Bucket } from \"@/server/Storage/types/ceph\"\nimport { formatBytesBinary } from \"@/client/utils/formatBytes\"\nimport { CreateBucketModal } from \"./CreateBucketModal\"\nimport { EmptyBucketModal } from \"./EmptyBucketModal\"\nimport { DeleteBucketModal } from \"./DeleteBucketModal\"\n\ninterface BucketTableViewProps {\n buckets: Bucket[]\n createModalOpen: boolean\n setCreateModalOpen: (open: boolean) => void\n onCreateSuccess: (bucketName: string) => void\n onCreateError: (bucketName: string, errorMessage: string) => void\n onEmptySuccess: (bucketName: string, deletedCount: number) => void\n onEmptyError: (bucketName: string, errorMessage: string) => void\n onDeleteSuccess: (bucketName: string) => void\n onDeleteError: (bucketName: string, errorMessage: string) => void\n selectedBuckets: string[]\n setSelectedBuckets: (buckets: string[]) => void\n // When false, the selection column (header select-all + per-row checkboxes) is dropped.\n hasAnyBulkAction?: boolean\n}\n\nexport const BucketTableView = ({\n buckets,\n createModalOpen,\n setCreateModalOpen,\n onCreateSuccess,\n onCreateError,\n onEmptySuccess,\n onEmptyError,\n onDeleteSuccess,\n onDeleteError,\n selectedBuckets,\n setSelectedBuckets,\n hasAnyBulkAction = true,\n}: BucketTableViewProps) => {\n const { projectId, provider, storageType } = useParams({ strict: false })\n const { t } = useLingui()\n const navigate = useNavigate()\n\n const parentRef = useRef<HTMLDivElement>(null)\n const [scrollbarWidth, setScrollbarWidth] = useState(0)\n const [emptyModalBucket, setEmptyModalBucket] = useState<Bucket | null>(null)\n const [deleteModalBucket, setDeleteModalBucket] = useState<Bucket | null>(null)\n\n // Calculate scrollbar width\n useEffect(() => {\n if (parentRef.current) {\n const width = parentRef.current.offsetWidth - parentRef.current.clientWidth\n setScrollbarWidth(width)\n }\n }, [buckets.length])\n\n // Format date to localized string\n const formatDate = (dateString: string): string => {\n try {\n const date = new Date(dateString)\n return date.toLocaleString()\n } catch {\n return t`N/A`\n }\n }\n\n const rowVirtualizer = useVirtualizer({\n count: buckets.length,\n getScrollElement: () => parentRef.current,\n estimateSize: () => 48, // Estimated row height\n overscan: 10,\n })\n\n const handleSelectBucket = (bucketName: string) => {\n if (selectedBuckets.includes(bucketName)) {\n setSelectedBuckets(selectedBuckets.filter((name) => name !== bucketName))\n } else {\n setSelectedBuckets([...selectedBuckets, bucketName])\n }\n }\n\n if (!buckets || buckets.length === 0) {\n return (\n <DataGrid columns={4} className=\"buckets\" data-testid=\"no-buckets\">\n <DataGridRow>\n <DataGridCell colSpan={4}>\n <div className=\"py-8 text-center\">\n <h3 className=\"text-lg font-semibold\">\n <Trans>No buckets found</Trans>\n </h3>\n <p className=\"text-theme-light mt-2\">\n <Trans>\n There are no buckets available with the current search criteria. Try adjusting your search term.\n </Trans>\n </p>\n </div>\n </DataGridCell>\n </DataGridRow>\n </DataGrid>\n )\n }\n\n // Column template — drops the leading 40px selection track when bulk actions are unavailable.\n // The header and the absolutely-positioned virtual rows must share an identical track string.\n const columnCount = hasAnyBulkAction ? 6 : 5\n const gridColumnTemplate = hasAnyBulkAction\n ? \"40px minmax(200px, 2fr) minmax(100px, 1fr) minmax(180px, 2fr) minmax(100px, 1fr) 60px\"\n : \"minmax(200px, 2fr) minmax(100px, 1fr) minmax(180px, 2fr) minmax(100px, 1fr) 60px\"\n\n return (\n <>\n <div className=\"relative\">\n {/* Table Header with scrollbar padding */}\n <div style={{ paddingRight: `${scrollbarWidth}px` }}>\n <DataGrid\n columns={columnCount}\n gridColumnTemplate={gridColumnTemplate}\n className=\"buckets\"\n data-testid=\"buckets-table-header\"\n >\n <DataGridRow>\n {hasAnyBulkAction && <DataGridHeadCell />}\n <DataGridHeadCell>\n <Trans>Bucket Name</Trans>\n </DataGridHeadCell>\n <DataGridHeadCell>\n <Trans>Object Count</Trans>\n </DataGridHeadCell>\n <DataGridHeadCell>\n <Trans>Last Modified</Trans>\n </DataGridHeadCell>\n <DataGridHeadCell>\n <Trans>Total Size</Trans>\n </DataGridHeadCell>\n <DataGridHeadCell style={{ marginRight: `-${scrollbarWidth}px` }} />\n </DataGridRow>\n </DataGrid>\n </div>\n\n {/* Virtualized Table Body with dynamic height */}\n <div\n ref={parentRef}\n className=\"overflow-auto\"\n style={{\n height: \"calc(100vh - 490px)\", // Dynamic height based on viewport\n }}\n data-testid=\"buckets-table-body\"\n >\n <div\n style={{\n height: `${rowVirtualizer.getTotalSize()}px`,\n width: \"100%\",\n position: \"relative\",\n }}\n >\n {rowVirtualizer.getVirtualItems().map((virtualRow) => {\n const bucket = buckets[virtualRow.index]\n const isSelected = selectedBuckets.includes(bucket.name)\n\n const handleRowNavigate = () =>\n navigate({\n to: \"/projects/$projectId/storage/$provider/$storageType/$containerName/objects\",\n params: {\n projectId: projectId ?? \"\",\n provider: (provider as string) ?? \"ceph\",\n storageType: (storageType as string) ?? \"buckets\",\n containerName: bucket.name,\n },\n })\n\n return (\n <div\n key={bucket.name}\n data-index={virtualRow.index}\n ref={rowVirtualizer.measureElement}\n className=\"juno-datagrid group hover:bg-theme-background-lvl-1 cursor-pointer\"\n style={{\n position: \"absolute\",\n top: 0,\n left: 0,\n width: \"100%\",\n transform: `translateY(${virtualRow.start}px)`,\n display: \"grid\",\n gridTemplateColumns: gridColumnTemplate,\n alignItems: \"stretch\",\n }}\n data-testid={`bucket-row-${bucket.name}`}\n role=\"link\"\n tabIndex={0}\n onClick={handleRowNavigate}\n onKeyDown={(e) => {\n if (e.key === \"Enter\" || e.key === \" \") {\n e.preventDefault()\n handleRowNavigate()\n }\n }}\n >\n {hasAnyBulkAction && (\n <DataGridCell\n onClick={(e) => e.stopPropagation()}\n onKeyDown={(e) => {\n if (e.key === \"Enter\" || e.key === \" \") {\n e.stopPropagation()\n }\n }}\n >\n <Checkbox\n checked={isSelected}\n onChange={() => handleSelectBucket(bucket.name)}\n data-testid={`select-bucket-${bucket.name}`}\n />\n </DataGridCell>\n )}\n <DataGridCell className=\"min-w-0 overflow-hidden\">\n <span className=\"block truncate\" title={bucket.name}>\n {bucket.name}\n </span>\n </DataGridCell>\n <DataGridCell>{bucket.count.toLocaleString()}</DataGridCell>\n <DataGridCell>{formatDate(bucket.last_modified || bucket.creationDate || \"\")}</DataGridCell>\n <DataGridCell>{formatBytesBinary(bucket.bytes)}</DataGridCell>\n <DataGridCell onClick={(e) => e.stopPropagation()}>\n <PopupMenu>\n <PopupMenuOptions>\n <PopupMenuItem\n label={t`Show Details`}\n onClick={handleRowNavigate}\n data-testid={`show-details-action-${bucket.name}`}\n />\n <PopupMenuItem\n label={t`Empty`}\n onClick={() => setEmptyModalBucket(bucket)}\n data-testid={`empty-action-${bucket.name}`}\n />\n <PopupMenuItem\n label={t`Delete`}\n onClick={() => setDeleteModalBucket(bucket)}\n data-testid={`delete-action-${bucket.name}`}\n />\n </PopupMenuOptions>\n </PopupMenu>\n </DataGridCell>\n </div>\n )\n })}\n </div>\n </div>\n </div>\n\n <CreateBucketModal\n isOpen={createModalOpen}\n onClose={() => setCreateModalOpen(false)}\n onSuccess={onCreateSuccess}\n onError={onCreateError}\n />\n\n <EmptyBucketModal\n isOpen={emptyModalBucket !== null}\n bucket={emptyModalBucket}\n onClose={() => setEmptyModalBucket(null)}\n onSuccess={onEmptySuccess}\n onError={onEmptyError}\n />\n\n <DeleteBucketModal\n isOpen={deleteModalBucket !== null}\n bucket={deleteModalBucket}\n onClose={() => setDeleteModalBucket(null)}\n onSuccess={onDeleteSuccess}\n onError={onDeleteError}\n />\n </>\n )\n}\n","import { ReactNode } from \"react\"\nimport { NotificationOptions } from \"@cloudoperators/juno-ui-components\"\nimport { Trans, Plural } from \"@lingui/react/macro\"\n\nexport const getBucketCreatedToast = (bucketName: string): { message: ReactNode } & NotificationOptions => ({\n message: <Trans>Bucket Created</Trans>,\n description: <Trans>Bucket \"{bucketName}\" was successfully created.</Trans>,\n})\n\nexport const getBucketCreateErrorToast = (\n bucketName: string,\n errorMessage: string\n): { message: ReactNode } & NotificationOptions => ({\n message: <Trans>Failed to Create Bucket</Trans>,\n description: (\n <Trans>\n Could not create bucket \"{bucketName}\": {errorMessage}\n </Trans>\n ),\n})\n\nexport const getBucketEmptiedToast = (\n bucketName: string,\n deletedCount: number\n): { message: ReactNode } & NotificationOptions => ({\n message: <Trans>Bucket Emptied</Trans>,\n description:\n deletedCount === 0 ? (\n <Trans>Bucket \"{bucketName}\" was already empty.</Trans>\n ) : deletedCount === 1 ? (\n <Trans>\n Bucket \"{bucketName}\" was successfully emptied. {deletedCount} object deleted.\n </Trans>\n ) : (\n <Trans>\n Bucket \"{bucketName}\" was successfully emptied. {deletedCount} objects deleted.\n </Trans>\n ),\n})\n\nexport const getBucketEmptyErrorToast = (\n bucketName: string,\n errorMessage: string\n): { message: ReactNode } & NotificationOptions => ({\n message: <Trans>Failed to Empty Bucket</Trans>,\n description: (\n <Trans>\n Could not empty bucket \"{bucketName}\": {errorMessage}\n </Trans>\n ),\n})\n\nexport const getBucketDeletedToast = (bucketName: string): { message: ReactNode } & NotificationOptions => ({\n message: <Trans>Bucket Deleted</Trans>,\n description: <Trans>Bucket \"{bucketName}\" was successfully deleted.</Trans>,\n})\n\nexport const getBucketDeleteErrorToast = (\n bucketName: string,\n errorMessage: string\n): { message: ReactNode } & NotificationOptions => ({\n message: <Trans>Failed to Delete Bucket</Trans>,\n description: (\n <Trans>\n Could not delete bucket \"{bucketName}\": {errorMessage}\n </Trans>\n ),\n})\n\nexport const getBucketsEmptyCompleteToast = (\n emptiedCount: number,\n totalDeleted: number,\n errors: string[]\n): { message: ReactNode } & NotificationOptions => {\n const hasErrors = errors.length > 0\n const totalBuckets = emptiedCount + errors.length\n const errorsLength = errors.length\n\n return {\n message: hasErrors ? <Trans>Empty All Completed with Errors</Trans> : <Trans>All Buckets Emptied</Trans>,\n description: hasErrors ? (\n <Trans>\n Successfully emptied {emptiedCount} of {totalBuckets}{\" \"}\n <Plural value={totalBuckets} one=\"bucket\" other=\"buckets\" />, deleting {totalDeleted}{\" \"}\n <Plural value={totalDeleted} one=\"object\" other=\"objects\" />. {errorsLength}{\" \"}\n <Plural value={errorsLength} one=\"bucket\" other=\"buckets\" /> failed.\n </Trans>\n ) : (\n <Trans>\n Successfully emptied {emptiedCount} <Plural value={emptiedCount} one=\"bucket\" other=\"buckets\" />, deleting{\" \"}\n {totalDeleted} <Plural value={totalDeleted} one=\"object\" other=\"objects\" />.\n </Trans>\n ),\n }\n}\n","import { useState } from \"react\"\nimport { Trans, useLingui, Plural } from \"@lingui/react/macro\"\nimport { trpcReact } from \"@/client/trpcClient\"\nimport { Modal, Spinner, Stack, TextInput } from \"@cloudoperators/juno-ui-components\"\nimport { Bucket } from \"@/server/Storage/types/ceph\"\nimport { useProjectId } from \"@/client/hooks/useProjectId\"\n\nconst MAX_VISIBLE = 20\n\ninterface EmptyBucketsResult {\n emptiedCount: number\n totalDeleted: number\n errors: string[]\n}\n\ninterface EmptyBucketsModalProps {\n isOpen: boolean\n buckets: Bucket[]\n onClose: () => void\n onComplete?: (result: EmptyBucketsResult) => void\n}\n\nexport const EmptyBucketsModal = ({ isOpen, buckets, onClose, onComplete }: EmptyBucketsModalProps) => {\n const { t } = useLingui()\n const projectId = useProjectId()\n const [progress, setProgress] = useState<{ current: number; total: number } | null>(null)\n const [confirmText, setConfirmText] = useState(\"\")\n\n const utils = trpcReact.useUtils()\n const emptyBucketMutation = trpcReact.storage.ceph.objects.deleteAll.useMutation()\n\n const handleClose = () => {\n emptyBucketMutation.reset()\n setProgress(null)\n setConfirmText(\"\")\n onClose()\n }\n\n const handleConfirm = async () => {\n let emptiedCount = 0\n let totalDeleted = 0\n const errors: string[] = []\n const total = buckets.length\n\n for (let i = 0; i < buckets.length; i++) {\n setProgress({ current: i + 1, total })\n const bucket = buckets[i]\n\n try {\n const deleted = await emptyBucketMutation.mutateAsync({\n project_id: projectId,\n containerName: bucket.name,\n })\n totalDeleted += deleted\n emptiedCount++\n } catch (err) {\n const message = err instanceof Error ? err.message : String(err)\n errors.push(`${bucket.name}: ${message}`)\n }\n }\n\n if (emptiedCount > 0) {\n await utils.storage.ceph.containers.list.invalidate()\n }\n\n onComplete?.({ emptiedCount, totalDeleted, errors })\n handleClose()\n }\n\n if (!isOpen || buckets.length === 0) return null\n\n const totalCount = buckets.length\n const visibleBuckets = buckets.slice(0, MAX_VISIBLE)\n const hiddenCount = totalCount - visibleBuckets.length\n const isPending = emptyBucketMutation.isPending || progress !== null\n const progressCurrent = progress?.current\n const progressTotal = progress?.total\n const isConfirmValid = confirmText === \"empty\"\n\n return (\n <Modal\n title={<Plural value={totalCount} one=\"Empty Bucket\" other=\"Empty Buckets\" />}\n open={isOpen}\n onCancel={handleClose}\n confirmButtonLabel={isPending ? t`Emptying...` : t`Empty`}\n confirmButtonVariant=\"primary-danger\"\n cancelButtonLabel={t`Cancel`}\n onConfirm={handleConfirm}\n disableConfirmButton={isPending || !isConfirmValid}\n disableCancelButton={isPending}\n disableCloseButton={isPending}\n size=\"small\"\n >\n {isPending ? (\n <Stack direction=\"vertical\" distribution=\"center\" alignment=\"center\" gap=\"2\" className=\"py-4\">\n <Spinner variant=\"primary\" />\n {progress && (\n <p className=\"text-theme-light text-sm\">\n <Trans>\n Emptying bucket {progressCurrent} of {progressTotal}, please wait...\n </Trans>\n </p>\n )}\n </Stack>\n ) : (\n <Stack direction=\"vertical\" gap=\"4\">\n <Trans>\n This will permanently delete all objects from {totalCount} selected{\" \"}\n <Plural value={totalCount} one=\"bucket\" other=\"buckets\" />. This action cannot be undone.\n </Trans>\n\n <div>\n <p className=\"text-theme-light mb-2 text-sm\">\n <Trans>Buckets to empty:</Trans>\n </p>\n <ul className=\"list-inside list-disc space-y-1 text-sm\">\n {visibleBuckets.map((bucket) => {\n const bucketName = bucket.name\n const bucketCount = bucket.count\n return (\n <li key={bucketName}>\n {bucketName}\n {bucketCount > 0 && (\n <span className=\"text-theme-light ml-2\">\n ({bucketCount} <Plural value={bucketCount} one=\"object\" other=\"objects\" />)\n </span>\n )}\n </li>\n )\n })}\n {hiddenCount > 0 && (\n <li className=\"text-theme-light\">\n <Trans>... and {hiddenCount} more</Trans>\n </li>\n )}\n </ul>\n </div>\n\n <TextInput\n label={t`Type \"empty\" to confirm`}\n value={confirmText}\n onChange={(e) => setConfirmText(e.target.value)}\n placeholder=\"empty\"\n autoFocus\n />\n </Stack>\n )}\n </Modal>\n )\n}\n","import { Trans } from \"@lingui/react/macro\"\nimport { trpcReact } from \"@/client/trpcClient\"\nimport { useProjectId } from \"@/client/hooks/useProjectId\"\nimport { Button, Stack, toast } from \"@cloudoperators/juno-ui-components\"\n\ninterface CredentialPromptProps {\n onSuccess: () => void\n}\n\nexport function CredentialPrompt({ onSuccess }: CredentialPromptProps) {\n const projectId = useProjectId()\n const utils = trpcReact.useUtils()\n\n const createMutation = trpcReact.storage.ceph.ec2Credentials.create.useMutation({\n onSuccess: () => {\n utils.storage.ceph.ec2Credentials.list.invalidate()\n onSuccess()\n },\n onError: (err) => {\n const errorMessage = err.message\n toast.error(<Trans>Failed to create credential: {errorMessage}</Trans>)\n },\n })\n\n return (\n <Stack direction=\"vertical\" gap=\"4\" className=\"mt-8 max-w-lg\">\n <h2 className=\"text-lg font-semibold\">\n <Trans>S3 Object Storage — Setup Required</Trans>\n </h2>\n <p className=\"text-theme-default\">\n <Trans>\n To access S3 Object Storage, you need EC2 credentials (access key + secret key). These credentials\n authenticate your requests to the Ceph storage backend.\n </Trans>\n </p>\n <p className=\"text-theme-default text-sm\">\n <Trans>\n Click the button below to automatically generate credentials for this project. You only need to do this once.\n </Trans>\n </p>\n <div>\n <Button\n onClick={() => projectId && createMutation.mutate({ project_id: projectId })}\n disabled={createMutation.isPending || !projectId}\n >\n {createMutation.isPending ? <Trans>Creating Credentials...</Trans> : <Trans>Create S3 Credentials</Trans>}\n </Button>\n </div>\n </Stack>\n )\n}\n","import { useState, useEffect, useRef, startTransition } from \"react\"\nimport { Plural, Trans, useLingui } from \"@lingui/react/macro\"\nimport { plural } from \"@lingui/core/macro\"\nimport { useNavigate } from \"@tanstack/react-router\"\nimport { SortInput } from \"@/client/components/ListToolbar/SortInput\"\nimport { SortSettings } from \"@/client/components/ListToolbar/types\"\nimport { Bucket } from \"@/server/Storage/types/ceph\"\nimport { trpcReact } from \"@/client/trpcClient\"\nimport {\n Button,\n Checkbox,\n DataGridToolbar,\n PopupMenu,\n PopupMenuItem,\n PopupMenuOptions,\n PopupMenuToggle,\n SearchInput,\n Spinner,\n Stack,\n toast,\n} from \"@cloudoperators/juno-ui-components\"\nimport { BucketTableView } from \"./BucketTableView\"\nimport {\n getBucketCreatedToast,\n getBucketCreateErrorToast,\n getBucketEmptiedToast,\n getBucketEmptyErrorToast,\n getBucketDeletedToast,\n getBucketDeleteErrorToast,\n getBucketsEmptyCompleteToast,\n} from \"./BucketToastNotifications\"\nimport { EmptyBucketsModal } from \"./EmptyBucketsModal\"\nimport { CredentialPrompt } from \"./CredentialPrompt\"\nimport { useProjectId } from \"@/client/hooks/useProjectId\"\nimport { Route } from \"@/client/routes/_auth/projects/$projectId/storage/$provider/$storageType\"\n\nexport { CredentialPrompt } from \"./CredentialPrompt\"\nexport { CreateBucketModal } from \"./CreateBucketModal\"\nexport { DeleteBucketModal } from \"./DeleteBucketModal\"\nexport { DeleteBucketPolicyModal } from \"./DeleteBucketPolicyModal\"\nexport { EmptyBucketModal } from \"./EmptyBucketModal\"\nexport { EmptyBucketsModal } from \"./EmptyBucketsModal\"\nexport { DeleteVersionsModal } from \"./DeleteVersionsModal\"\nexport * from \"./BucketToastNotifications\"\n\nexport const CephBuckets = () => {\n const { t, i18n } = useLingui()\n const projectId = useProjectId()\n const navigate = useNavigate({ from: Route.fullPath })\n\n // Sort and search state are persisted in the URL so they survive navigation,\n // browser back/forward, and deep links.\n const { sortBy, sortDirection, search: searchParam = \"\" } = Route.useSearch()\n\n // TODO(perms): wire to a real permission source once Ceph Buckets exposes one.\n // Hardcoded true preserves the current always-on bulk behavior while putting the\n // selection-column gating structure in place.\n const hasAnyBulkAction = true\n\n const [createModalOpen, setCreateModalOpen] = useState(false)\n const [emptyAllModalOpen, setEmptyAllModalOpen] = useState(false)\n const [selectedBuckets, setSelectedBuckets] = useState<string[]>([])\n\n // Local mirror of the committed search term so typing stays responsive while\n // the URL commit is debounced (see Zone 2 SearchInput below).\n const [localSearchTerm, setLocalSearchTerm] = useState(searchParam)\n const debounceTimer = useRef<number | undefined>(undefined)\n useEffect(() => () => clearTimeout(debounceTimer.current), [])\n\n // Keep the input in sync when the committed search term changes from outside\n // the input — browser back/forward, deep links, or programmatic navigation —\n // so the field never drifts from the URL-backed filter state. When the change\n // originated from our own debounced commit, searchParam already equals\n // localSearchTerm, so this is a no-op and won't disturb the caret.\n useEffect(() => {\n setLocalSearchTerm(searchParam)\n }, [searchParam])\n\n const handleCreateSuccess = (bucketName: string) => {\n const { message, ...options } = getBucketCreatedToast(bucketName)\n\n toast.success(message, options)\n }\n\n const handleCreateError = (bucketName: string, errorMessage: string) => {\n const { message, ...options } = getBucketCreateErrorToast(bucketName, errorMessage)\n\n toast.error(message, options)\n }\n\n const handleEmptySuccess = (bucketName: string, deletedCount: number) => {\n const { message, ...options } = getBucketEmptiedToast(bucketName, deletedCount)\n\n toast.success(message, options)\n }\n\n const handleEmptyError = (bucketName: string, errorMessage: string) => {\n const { message, ...options } = getBucketEmptyErrorToast(bucketName, errorMessage)\n\n toast.error(message, options)\n }\n\n const handleDeleteSuccess = (bucketName: string) => {\n const { message, ...options } = getBucketDeletedToast(bucketName)\n\n toast.success(message, options)\n }\n\n const handleDeleteError = (bucketName: string, errorMessage: string) => {\n const { message, ...options } = getBucketDeleteErrorToast(bucketName, errorMessage)\n\n toast.error(message, options)\n }\n\n const handleEmptyAllComplete = ({\n emptiedCount,\n totalDeleted,\n errors,\n }: {\n emptiedCount: number\n totalDeleted: number\n errors: string[]\n }) => {\n if (errors.length === 0) {\n setSelectedBuckets([])\n } else {\n // Extract the bucket name from each error string formatted as \"<bucketName>: <message>\".\n // Using exact name extraction avoids the false-positive substring match that\n // errorMessage.includes(bucketName) would produce (e.g. \"foo\" matched inside \"foobar\" error).\n const failedBucketNames = new Set(errors.map((e) => e.split(\": \")[0]))\n setSelectedBuckets((prev) => prev.filter((name) => failedBucketNames.has(name)))\n }\n\n const { message, ...options } = getBucketsEmptyCompleteToast(emptiedCount, totalDeleted, errors)\n\n if (errors.length > 0) {\n toast.warning(message, options)\n } else {\n toast.success(message, options)\n }\n }\n\n const sortSettings: SortSettings = {\n options: [\n { label: t`Name`, value: \"name\" },\n { label: t`Object Count`, value: \"count\" },\n { label: t`Total Size`, value: \"bytes\" },\n { label: t`Last Modified`, value: \"last_modified\" },\n ],\n sortBy: sortBy ?? \"name\",\n sortDirection: sortDirection ?? \"asc\",\n }\n\n // Fetch buckets from tRPC\n const {\n data: buckets,\n isLoading,\n error,\n } = trpcReact.storage.ceph.containers.list.useQuery(\n {\n project_id: projectId,\n includeMetadata: true, // Fetch full metadata for table view with sorting\n },\n {\n enabled: !!projectId,\n retry: false, // Don't retry on NO_CEPH_CREDENTIALS error\n }\n )\n\n // Sort buckets based on sort settings\n const sortBuckets = (buckets: Bucket[]): Bucket[] => {\n return [...buckets].sort((a, b) => {\n let comparison: number\n\n switch (sortBy ?? \"name\") {\n case \"name\":\n comparison = a.name.localeCompare(b.name)\n break\n case \"count\":\n comparison = a.count - b.count\n break\n case \"bytes\":\n comparison = a.bytes - b.bytes\n break\n case \"last_modified\":\n if (!a.last_modified && !b.last_modified) {\n return 0\n }\n if (!a.last_modified) {\n return 1\n }\n if (!b.last_modified) {\n return -1\n }\n comparison = new Date(a.last_modified).getTime() - new Date(b.last_modified).getTime()\n break\n default:\n comparison = a.name.localeCompare(b.name)\n }\n\n return (sortDirection ?? \"asc\") === \"desc\" ? -comparison : comparison\n })\n }\n\n // Filter buckets based on search term\n const filteredBuckets = (buckets || []).filter((bucket) =>\n bucket.name.toLowerCase().includes(searchParam.toLowerCase())\n )\n\n // Apply sorting to filtered buckets\n const sortedBuckets = sortBuckets(filteredBuckets)\n\n const handleSearchChange = (term: string | number | string[] | undefined) => {\n const value = typeof term === \"string\" ? term : \"\"\n startTransition(() => {\n navigate({\n search: (prev) => ({ ...prev, search: value || undefined }),\n })\n })\n }\n\n const handleSortChange = (newSortSettings: SortSettings) => {\n const resolvedSortBy = (newSortSettings.sortBy?.toString() || \"name\") as\n | \"name\"\n | \"count\"\n | \"bytes\"\n | \"last_modified\"\n const resolvedDirection = (newSortSettings.sortDirection || \"asc\") as \"asc\" | \"desc\"\n startTransition(() => {\n navigate({\n search: (prev) => ({\n ...prev,\n sortBy: resolvedSortBy,\n sortDirection: resolvedDirection,\n }),\n })\n })\n }\n\n // Handle loading state\n if (isLoading) {\n return (\n <Stack className=\"absolute inset-0\" distribution=\"center\" alignment=\"center\" direction=\"vertical\">\n <Spinner variant=\"primary\" size=\"large\" className=\"mb-2\" />\n <Trans>Loading Buckets...</Trans>\n </Stack>\n )\n }\n\n // Handle error state\n if (error) {\n const errorMessage = error.message\n\n // Check if this is a NO_CEPH_CREDENTIALS error\n if (errorMessage === \"NO_CEPH_CREDENTIALS\") {\n return <CredentialPrompt onSuccess={() => window.location.reload()} />\n }\n\n // Render error message based on error type\n const isAccessDenied = errorMessage.includes(\"Access denied\") || errorMessage.includes(\"AccessDenied\")\n const isAuthError = errorMessage.includes(\"Invalid access key\") || errorMessage.includes(\"InvalidAccessKeyId\")\n\n return (\n <div className=\"p-8\">\n <p className=\"text-theme-default text-sm\">\n {isAccessDenied ? (\n <Trans>\n Your credentials are valid but you don't have permission to perform this operation. Please contact your\n administrator to grant you the necessary permissions.\n </Trans>\n ) : isAuthError ? (\n <Trans>\n Your S3 credentials are invalid or expired. Please try creating new credentials or contact your\n administrator.\n </Trans>\n ) : (\n <Trans>Failed to load buckets: {errorMessage}</Trans>\n )}\n </p>\n </div>\n )\n }\n\n // Resolve selected Bucket objects from the full unfiltered list so\n // the modal always operates on what was actually selected — not the filtered\n // subset currently visible in the table.\n const selectedBucketSummaries = (buckets || []).filter((c) => selectedBuckets.includes(c.name))\n const hasSelection = selectedBucketSummaries.length > 0\n const selectedCount = selectedBucketSummaries.length\n const totalCount = (buckets || []).length\n const filteredCount = filteredBuckets.length\n\n // Select-all operates on the currently displayed (filtered + sorted) rows.\n const displayedNames = sortedBuckets.map((c) => c.name)\n const allSelected = displayedNames.length > 0 && displayedNames.every((n) => selectedBuckets.includes(n))\n const someSelected = displayedNames.some((n) => selectedBuckets.includes(n))\n const handleToggleSelectAll = () => {\n if (allSelected) {\n setSelectedBuckets((prev) => prev.filter((n) => !displayedNames.includes(n)))\n } else {\n setSelectedBuckets((prev) => [...new Set([...prev, ...displayedNames])])\n }\n }\n\n return (\n <div className=\"relative\">\n <Stack direction=\"vertical\">\n {/* Zone 1 — sort controls and the create action (plain Stack, no background) */}\n <Stack distribution=\"end\" alignment=\"center\" gap=\"2\" className=\"pb-2\">\n <Stack gap=\"0.5\" alignment=\"center\">\n <SortInput\n options={sortSettings.options}\n sortBy={sortSettings.sortBy}\n sortDirection={sortSettings.sortDirection ?? \"asc\"}\n selectClassName=\"w-40\"\n onSortByChange={(value) =>\n handleSortChange({ ...sortSettings, sortBy: value, sortDirection: sortSettings.sortDirection })\n }\n onSortDirectionChange={(direction) => handleSortChange({ ...sortSettings, sortDirection: direction })}\n />\n </Stack>\n <Button variant=\"primary\" className=\"whitespace-nowrap\" onClick={() => setCreateModalOpen(true)}>\n <Trans>Create Bucket</Trans>\n </Button>\n </Stack>\n\n {/* Zone 2 — debounced search. DataGridToolbar provides the background.\n Ceph buckets expose no filterable dimensions yet, so there is no\n FiltersInput / SelectedFilters here. When filter dimensions are added,\n add FiltersInput alongside the search (switch the inner Stack to\n distribution=\"between\") and render SelectedFilters below. */}\n <DataGridToolbar>\n <Stack direction=\"vertical\" gap=\"2\">\n <Stack distribution=\"end\" alignment=\"center\">\n <SearchInput\n placeholder={t`Search buckets...`}\n data-testid=\"searchbar\"\n value={localSearchTerm}\n onInput={(e: React.FormEvent<HTMLInputElement>) => {\n const v = e.currentTarget.value\n setLocalSearchTerm(v)\n clearTimeout(debounceTimer.current)\n debounceTimer.current = window.setTimeout(() => handleSearchChange(v), 500)\n }}\n onSearch={(v) => {\n clearTimeout(debounceTimer.current)\n handleSearchChange(typeof v === \"string\" ? v : \"\")\n }}\n onClear={() => {\n clearTimeout(debounceTimer.current)\n setLocalSearchTerm(\"\")\n handleSearchChange(\"\")\n }}\n />\n </Stack>\n </Stack>\n </DataGridToolbar>\n\n {/* Zone 3 — bulk actions (gated) plus the bucket count. The bar also hosts the\n count info, which must always be visible, so it always renders; only the\n bulk controls are gated. */}\n <DataGridToolbar>\n <Stack distribution=\"start\" gap=\"2\" alignment=\"center\" className=\"text-sm\">\n {hasAnyBulkAction ? (\n <Stack gap=\"2\" alignment=\"center\">\n <Checkbox\n checked={allSelected}\n indeterminate={someSelected && !allSelected}\n onChange={handleToggleSelectAll}\n />\n <PopupMenu className=\"flex items-center\">\n <PopupMenuToggle as=\"div\">\n <Button disabled={!hasSelection} size=\"small\" icon=\"moreVert\" label={t`Actions`} />\n </PopupMenuToggle>\n {hasSelection && (\n <PopupMenuOptions>\n <PopupMenuItem\n disabled={!hasSelection}\n label={i18n._(\n plural(selectedCount, {\n one: \"Empty Bucket\",\n other: \"Empty Buckets\",\n })\n )}\n onClick={() => setEmptyAllModalOpen(true)}\n />\n </PopupMenuOptions>\n )}\n </PopupMenu>\n </Stack>\n ) : (\n <span />\n )}\n\n <div className=\"text-theme-light flex items-center gap-1\" data-testid=\"buckets-info-block\">\n {searchParam.trim() ? (\n <Plural\n value={totalCount}\n one={`${filteredCount} of ${totalCount} bucket`}\n other={`${filteredCount} of ${totalCount} buckets`}\n />\n ) : (\n <Plural value={totalCount} one={`${totalCount} bucket`} other={`${totalCount} buckets`} />\n )}\n </div>\n </Stack>\n </DataGridToolbar>\n </Stack>\n\n <BucketTableView\n buckets={sortedBuckets}\n createModalOpen={createModalOpen}\n setCreateModalOpen={setCreateModalOpen}\n onCreateSuccess={handleCreateSuccess}\n onCreateError={handleCreateError}\n onEmptySuccess={handleEmptySuccess}\n onEmptyError={handleEmptyError}\n onDeleteSuccess={handleDeleteSuccess}\n onDeleteError={handleDeleteError}\n selectedBuckets={selectedBuckets}\n setSelectedBuckets={setSelectedBuckets}\n hasAnyBulkAction={hasAnyBulkAction}\n />\n\n <EmptyBucketsModal\n isOpen={emptyAllModalOpen}\n buckets={selectedBucketSummaries}\n onClose={() => setEmptyAllModalOpen(false)}\n onComplete={handleEmptyAllComplete}\n />\n </div>\n )\n}\n","import { createFileRoute, redirect, useParams } from \"@tanstack/react-router\"\nimport { z } from \"zod\"\nimport { getServiceIndex } from \"@/server/Authentication/helpers\"\nimport { ErrorBoundary } from \"react-error-boundary\"\nimport { SwiftContainers } from \"../../-components/Swift/Containers\"\nimport { CephBuckets } from \"../../-components/Ceph/Buckets\"\nimport { Trans, useLingui } from \"@lingui/react/macro\"\nimport type { RouteInfo } from \"@/client/routes/routeInfo\"\nimport { ContentHeader } from \"@/client/components/ContentHeader/ContentHeader\"\n\n/**\n * Validates that the requested storage provider is available for the given project,\n * and redirects to an appropriate fallback route when it is not.\n *\n * Redirect rules (in priority order):\n * 1. No `object-store` service at all → redirect to the project overview.\n * 2. Unknown provider (neither \"swift\" nor \"ceph\") → redirect to the first\n * available provider, or to the project overview if none exist.\n * 3. Requested provider unavailable → redirect to the other provider,\n * or to the project overview if no alternative exists.\n *\n * Ceph has a temporary fallback flag (`cephFallbackEnabled`) that treats it as\n * available even when absent from the OpenStack service catalog.\n *\n * @throws {redirect} - Always throws a TanStack Router redirect; never returns normally\n * when the requested provider/project combination is unavailable.\n */\nexport const checkServiceAvailability = (\n availableServices: {\n type: string\n name: string\n }[],\n params: {\n projectId: string\n provider: string\n }\n) => {\n const { provider, projectId } = params\n\n const serviceIndex = getServiceIndex(availableServices)\n\n // Redirect to the \"Projects Overview\" page if no storage services available\n if (!serviceIndex[\"object-store\"]) {\n throw redirect({\n to: \"/projects/$projectId\",\n params: { projectId },\n })\n }\n\n // Check provider availability\n const hasSwift = Boolean(serviceIndex[\"object-store\"][\"swift\"])\n const hasCeph = Boolean(serviceIndex[\"object-store\"][\"ceph\"])\n\n // TEMPORARY: Allow Ceph access even if not in catalog (relies on env config)\n // TODO: Properly register Ceph in OpenStack service catalog\n const cephFallbackEnabled = true // Set to false once Ceph is in catalog\n\n // Effective availability includes fallback flag for Ceph\n const hasEffectiveCeph = hasCeph || cephFallbackEnabled\n const fallbackProvider = hasSwift ? \"swift\" : hasEffectiveCeph ? \"ceph\" : null\n const fallbackStorageType = hasSwift ? \"containers\" : hasEffectiveCeph ? \"buckets\" : null\n\n if (provider !== \"swift\" && provider !== \"ceph\") {\n if (!fallbackProvider || !fallbackStorageType) {\n throw redirect({\n to: \"/projects/$projectId\",\n params: { projectId },\n })\n }\n throw redirect({\n to: \"/projects/$projectId/storage/$provider/$storageType\",\n params: { ...params, provider: fallbackProvider, storageType: fallbackStorageType },\n })\n }\n\n if (provider === \"swift\" && !hasSwift) {\n if (!hasEffectiveCeph) {\n throw redirect({\n to: \"/projects/$projectId\",\n params: { projectId },\n })\n }\n\n throw redirect({\n to: \"/projects/$projectId/storage/$provider/$storageType\",\n params: { ...params, provider: \"ceph\", storageType: \"buckets\" },\n })\n }\n\n if (provider === \"ceph\" && !hasEffectiveCeph) {\n if (!hasSwift) {\n throw redirect({\n to: \"/projects/$projectId\",\n params: { projectId },\n })\n }\n\n throw redirect({\n to: \"/projects/$projectId/storage/$provider/$storageType\",\n params: { ...params, provider: \"swift\", storageType: \"containers\" },\n })\n }\n}\n\n// Search params schema\n// - sortBy: active sort column — persisted for deep links and back navigation\n// - sortDirection: \"asc\" | \"desc\" — persisted alongside sortBy\n// - search: active filter string — persisted so deep links preserve the current search\nconst containersSearchSchema = z.object({\n sortBy: z.enum([\"name\", \"count\", \"bytes\", \"last_modified\"]).optional(),\n sortDirection: z.enum([\"asc\", \"desc\"]).optional(),\n search: z.string().optional(),\n})\n\nexport const Route = createFileRoute(\"/_auth/projects/$projectId/storage/$provider/$storageType/\")({\n staticData: {\n section: \"storage\",\n service: \"containers\",\n sectionCrumb: { labelKey: \"Storage\" },\n crumb: { useParamAsLabel: \"provider\" },\n } satisfies RouteInfo,\n validateSearch: containersSearchSchema,\n head: ({ match }) => ({\n meta: [\n {\n title:\n match.params.provider === \"swift\"\n ? \"Object Storage (Swift)\"\n : match.params.provider === \"ceph\"\n ? \"Object Storage (Ceph)\"\n : \"Storage Overview\",\n },\n ],\n }),\n component: () => {\n return <StorageDashboard />\n },\n notFoundComponent: () => {\n return <p>Storage service not found</p>\n },\n loader: async ({ context }) => {\n const { trpcClient } = context\n const availableServices = await trpcClient?.auth.getAvailableServices.query()\n\n return {\n client: trpcClient,\n availableServices,\n }\n },\n beforeLoad: async ({ context, params }) => {\n const { trpcClient } = context\n const availableServices = await trpcClient?.auth.getAvailableServices.query()\n checkServiceAvailability(availableServices!, params)\n },\n})\n\nfunction StorageDashboard() {\n const { project, provider } = useParams({\n from: \"/_auth/projects/$projectId/storage/$provider/$storageType/\",\n select: (params) => {\n return { project: params.projectId, provider: params.provider, storageType: params.storageType }\n },\n })\n\n const { t } = useLingui()\n\n let pageTitle: string\n switch (provider) {\n case \"swift\":\n pageTitle = t`Object Storage (Swift)`\n break\n case \"ceph\":\n pageTitle = t`Object Storage (Ceph)`\n break\n default:\n pageTitle = t`Storage Overview`\n }\n\n return (\n <div>\n <ContentHeader title={pageTitle} projectId={project} />\n {project ? (\n <ErrorBoundary\n resetKeys={[project, provider]}\n fallback={\n <div className=\"p-4 text-center\">\n <Trans>Error loading component</Trans>\n </div>\n }\n >\n {(() => {\n switch (provider) {\n case \"swift\":\n return <SwiftContainers />\n case \"ceph\":\n return <CephBuckets />\n default:\n return <div>Storage Overview Page</div> // replace when available\n }\n })()}\n </ErrorBoundary>\n ) : (\n <div className=\"p-4 text-center\">\n <Trans>No project selected</Trans>\n </div>\n )}\n </div>\n )\n}\n"],"mappings":";;;;;;;;;;;;;;;;AAcA,IAAaM,MAAwB,EACnCC,WACAC,YACAC,cACAC,YACAC,4BAAyB,UACC;CAC1B,IAAM,EAAA,MAAA,GAAA,GAAA,MAAQC,EAAAA,GACRC,IAAYR,EAAAA,GACZ,CAACS,GAAeC,KAAoBf,EAAS,EAAA,GAC7C,CAACgB,GAAWC,KAAgBjB,EAAwB,IAAA,GAEpDkB,IAAQjB,EAAUkB,SAAQ,GAE1BC,IAA0BnB,EAAUoB,QAAQC,MAAMC,gBAAgBC,YAAY;EAClFf,iBAAW;GACTS,EAAMG,QAAQC,MAAMG,eAAeC,WAAU;GAC7C,IAAMC,IAAOb,EAAcc,KAAI;GAC/BnB,IAAYkB,CAAAA;EACd;EACAjB,UAAUmB,MAAAA;GACRnB,IAAUI,EAAcc,KAAI,GAAIC,EAAMC,OAAO;EAC/C;EACAC,iBAAW;GACTC,EAAAA;EACF;CACF,CAAA,GAEMA,UAAc;EAIlBxB,AAHAO,EAAiB,EAAA,GACjBE,EAAa,IAAA,GACbG,EAAwBa,MAAK,GAC7BzB,EAAAA;CACF,GAEM0B,KAAgBP,MACfA,EAAKC,KAAI,IAIVD,EAAKS,SAASzB,KAChBM,EAAakB,EAAAA,EAAC;;YAA0BxB,0BAAAA;CAA2C,CAAA,CAAA,GAC5E,MAELgB,EAAKU,SAAS,GAAA,KAChBpB,EAAakB,EAAAA,EAAC,EAAA,IAAA,SAAsC,CAAA,CAAA,GAC7C,OAETlB,EAAa,IAAA,GACN,OAZLA,EAAakB,EAAAA,EAAC,EAAA,IAAA,SAA2B,CAAA,CAAA,GAClC,KAcLG,KAAoBC,MAAAA;EACxB,IAAMC,IAAQD,EAAEE,OAAOD;EAEvB,AADAzB,EAAiByB,CAAAA,GACbxB,KAAWkB,EAAaM,CAAAA;CAC9B,GAEME,UAAe;EACdR,EAAapB,CAAAA,KAClBM,EAAwBuB,OAAO;GAC7BC,YAAY/B;GACZgC,WAAW/B,EAAcc,KAAI;EAC/B,CAAA;CACF;CAUA,OAFKrB,IAGH,gBAACL,GAAAA;EACC8C,OAAOb,EAAAA,EAAC,EAAA,IAAA,SAAiB,CAAA;EACzBc,MAAM1C;EACN2C,UAAUlB;EACVmB,oBAAoBhB,EAAAA,EAAC,EAAA,IAAA,SAAO,CAAA;EAC5BiB,WAAWV;EACXW,mBAAmBlB,EAAAA,EAAC,EAAA,IAAA,SAAO,CAAA;EAC3BmB,MAAK;EACLC,sBAAsBnC,EAAwBoC,aAAa,CAAC1C,EAAcc,KAAI;YAE9E,gBAACxB,GAAAA;GAAMqD,WAAU;GAAWC,KAAI;cAC9B,gBAACC,KAAAA;IAAEC,WAAU;cACX,gBAAA,GAAA,EAAA,IAAA,SAAA,CAAA;OAKF,gBAACzD,GAAAA;IACC0D,OAAO1B,EAAAA,EAAC,EAAA,IAAA,SAAe,CAAA;IACvB2B,UAAQ;IACRtB,OAAO1B;IACPiD,UAAUzB;IACV0B,YA/BezB,MAAAA;KACrB,AAAIA,EAAEQ,QAAQ,WACZL,EAAAA;IAEJ;IA4BQuB,SAAS,CAAC,CAACjD;IACXkD,WAAWlD,KAAamD,KAAAA;IACxBC,UAAUhD,EAAwBoC;IAClCa,WAAS;IACTC,aAAanC,EAAAA,EAAC,EAAA,IAAA,SAAqB,CAAA;;;MA9BvB;AAmCtB,GC5FaqD,KAAuB,EAAEC,WAAQC,cAAWC,YAASC,cAAWC,iBAAmC;CAC9G,IAAM,EAAA,MAAA,GAAA,GAAA,MAAQC,EAAAA,GACRC,IAAYrB,EAAAA,GACZ,CAACsB,GAAaC,KAAkB1B,EAAS,EAAA,GACzC,CAAC2B,GAAWC,KAAgB5B,EAAwB,IAAA,GACpD,CAAC6B,GAAQC,KAAa9B,EAAS,EAAA,GAC/B+B,IAAmB9B,GAAO,EAAA,GAE1B+B,UAAiB;EAChBb,KACLc,UAAUC,UAAUC,UAAUhB,EAAUiB,IAAI,EAAEC,WAAK;GAEjDC,AADAR,EAAU,EAAA,GACVQ,iBAAiBR,EAAU,EAAA,GAAQ,GAAA;EACrC,CAAA;CACF,GAEMS,IAAQrC,EAAUsC,SAAQ,GAI1B,EACJC,MAAMC,GACNC,WAAWC,GACXC,OAAOC,MACL5C,EAAU6C,QAAQC,MAAMC,YAAYC,SACtC;EAAEC,YAAY3B;EAAWL,WAAWA,GAAWiB,QAAQ;EAAIgB,QAAQ;EAAQC,OAAO;CAAI,GACtF,EAAEC,SAASpC,KAAUC,MAAc,KAAK,CAAA,GAGpCoC,IAAyBrD,EAAU6C,QAAQC,MAAMQ,eAAeC,YAAY;EAChFpC,YAAYqC,MAAAA;GAGVrC,AAFAkB,EAAMQ,QAAQC,MAAMW,eAAeC,WAAU,GAC7CrB,EAAMQ,QAAQC,MAAMC,YAAYW,WAAW;IAAET,YAAY3B;IAAWL,WAAWY,EAAiB8B;GAAQ,CAAA,GACxGxC,IAAYU,EAAiB8B,SAASH,CAAAA;EACxC;EACApC,UAAUuB,MAAAA;GACRvB,IAAUS,EAAiB8B,SAAShB,EAAMiB,OAAO;EACnD;EACAC,iBAAW;GACTC,EAAAA;EACF;CACF,CAAA,GAEMA,UAAc;EAIlB5C,AAHAM,EAAe,EAAA,GACfE,EAAa,IAAA,GACb2B,EAAuBU,MAAK,GAC5B7C,EAAAA;CACF,GAEM8C,MAA2BC,MAAAA;EAC/B,IAAMC,IAAQD,EAAEE,OAAOD;EAEvB,AADA1C,EAAe0C,CAAAA,GACXzC,KAAWC,EAAa,IAAA;CAC9B,GAEM0C,WAAe;EACdnD,OACL;OAAIM,EAAY8C,KAAI,MAAOpD,EAAUiB,MAAM;IACzCR,EAAa4C,EAAAA,EAAC,EAAA,IAAA,SAA8B,CAAA,CAAA;IAC5C;GACF;GAEAjB,AADAxB,EAAiB8B,UAAU1C,EAAUiB,MACrCmB,EAAuBkB,OAAO;IAAEtB,YAAY3B;IAAWL,WAAWA,EAAUiB;GAAK,CAAA;EAFjF;CAGF,GAEMsC,KAAiBP,MAAAA;EACrB,AAAIA,EAAEQ,QAAQ,WAASL,GAAAA;CACzB;CAEA,IAAI,CAACpD,KAAU,CAACC,GAAW,OAAO;CAElC,IAAMyD,IAAoBlC,GAASmC,UAAU,GAIvCC,KAAe,CAAClC,KAAoBzB,EAAU4D,UAAU,KAAKH,MAAsB,GAInFI,KAAqB,CAACpC,KAAoBzB,EAAU4D,QAAQ,KAAKH,MAAsB,GAEvFK,IAAgBH,MAAgBE;CAuBtC,OACE,gBAAC5E,GAAAA;EACCiF,OAtBF,kBAACF,QAAAA;GAAKC,WAAU;;IACd,gBAACD,QAAAA;KAAKC,WAAU;eACd,gBAAA,GAAA,EAAA,IAAA,SAAA,CAAA;;IAEF,gBAACD,QAAAA;KAAKC,WAAU;KAAWC,OAAOlE,EAAUiB;eACzCjB,EAAUiB;;IAEZ,CAACQ,KAAoB,CAACqC,KACrB,gBAACK,UAAAA;KACCC,MAAK;KACLC,SAASxD;KACTqD,OAAOxD,IAAS2C,EAAAA,EAAC,EAAA,IAAA,SAAQ,CAAA,IAAIA,EAAAA,EAAC,EAAA,IAAA,SAAoB,CAAA;KAClDY,WAAU;eAEV,gBAACrE,GAAAA;MAAK0E,MAAM5D,IAAS,gBAAgB;MAAe6D,MAAK;;;;GAQtDR;EACPS,MAAMzE;EACN0E,UAAU5B;EACV6B,oBAAoBZ,IAAgBa,KAAAA,IAAYtB,EAAAA,EAAC,EAAA,IAAA,SAAM,CAAA;EACvDuB,sBAAqB;EACrBC,WAAWf,IAAgBa,KAAAA,IAAYxB;EACvC2B,mBAAmBhB,IAAgBa,KAAAA,IAAYtB,EAAAA,EAAC,EAAA,IAAA,SAAO,CAAA;EACvD0B,aACEjB,IACE,gBAAC5E,GAAAA;GAAY+E,WAAU;aACrB,gBAAC7E,GAAAA,EAAAA,UACC,gBAACD,GAAAA;IAAO6F,SAAQ;IAAUX,SAASxB;IAAaoC,eAAY;cAC1D,gBAAA,GAAA,EAAA,IAAA,SAAA,CAAA;;OAIJN,KAAAA;EAENJ,MAAK;EACLW,sBACEzD,KACAW,EAAuB+C,aACtB,CAACrB,KAAiB,CAACxD,EAAY8C,KAAI,KACnC,CAACU,KAAiBxD,EAAY8C,KAAI,MAAOpD,EAAUiB;aAGrDU,KACC,gBAACyD,KAAAA;GAAEnB,WAAU;oBACT;IACA,IAAMoB,IAAe1D,EAAagB;IAClC,OAAO,gBAAA,GAAA;;eAA0C0C,gBAAAA;;GACnD,GAAA;MAGH5D,IACC,gBAACnC,GAAAA;GAAMgG,WAAU;GAAaC,WAAU;GAASC,KAAI;GAAIvB,WAAU;cACjE,gBAAC1E,GAAAA,EAAQgF,MAAK,QAAA,CAAA,GACd,gBAAA,GAAA,EAAA,IAAA,SAAA,CAAA,CAAA;OAEAT,KAAiB,CAACnC,IAEpB,gBAACyD,KAAAA;GAAEnB,WAAU;aACVN,KACC,gBAAA,GAAA,EAAA,IAAA,SAAA,CAAA,IAEA,gBAAA,GAAA,EAAA,IAAA,SAAA,CAAA;OAKDhC,IAuED,OArEF,gBAACrC,GAAAA;GAAMgG,WAAU;GAAWE,KAAI;;IAC9B,gBAACJ,KAAAA;KAAEnB,WAAU;;MACX,gBAAA,GAAA,EAAA,IAAA,SAAA,CAAA;MAGA,gBAACwB,MAAAA,CAAAA,CAAAA;MACD,gBAAA,GAAA;;;2BACGC,UAAAA,CAAAA,CAAAA;2BAAkCA,UAAAA,CAAAA,CAAAA;2BAA6BA,UAAAA,CAAAA,CAAAA;;;;;IAMpE,gBAACC,OAAAA;KAAI1B,WAAU;;MACZjE,EAAU4D,QAAQH,KACjB,gBAAC2B,KAAAA;OAAEnB,WAAU;wBACT;QACA,IAAM2B,IAAQ5F,EAAU4D;QACxB,OACE,gBAAA,GAAA;;;UACiBH;UAAuBmC;;;OAG5C,GAAA;;MAGJ,gBAACpG,GAAAA;OAASqG,SAAS;OAAG5B,WAAU;iBAC9B,gBAACxE,GAAAA,EAAAA,UAAAA;QACC,gBAACC,GAAAA,EAAAA,UACC,gBAAA,GAAA,EAAA,IAAA,SAAA,CAAA,EAAA,CAAA;QAEF,gBAACA,GAAAA,EAAAA,UACC,gBAAA,GAAA,EAAA,IAAA,SAAA,CAAA,EAAA,CAAA;QAEF,gBAACA,GAAAA,EAAAA,UACC,gBAAA,GAAA,EAAA,IAAA,SAAA,CAAA,EAAA,CAAA;;;MAIN,gBAACiG,OAAAA;OAAI1B,WAAU;iBACb,gBAACzE,GAAAA;QAASqG,SAAS;QAAG5B,WAAU;kBAC7B,EAA6B6B,KAAKC,MACjC,gBAACtG,GAAAA,EAAAA,UAAAA;SACC,gBAACE,GAAAA;UAAasE,WAAU;UAAyBC,OAAO6B,EAAI9E;oBACzD8E,EAAI9E;;SAEP,gBAACtB,GAAAA,EAAAA,UAAcE,EAAkBkG,EAAIC,KAAK,EAAA,CAAA;SAC1C,gBAACrG,GAAAA,EAAAA,UACEoG,EAAIE,gBAAgB,IAAIC,KAAKH,EAAIE,aAAa,EAAEE,eAAc,IAAK9C,EAAAA,EAAC,EAAA,IAAA,SAAI,CAAA,EAAA,CAAA;aAN3D0C,EAAI9E,IAAI,CAAA;;;;;IAclC,gBAAC5B,GAAAA;KACC+G,OAAO/C,EAAAA,EAAC,EAAA,IAAA,SAA+B,CAAA;KACvCgD,UAAQ;KACRpD,OAAO3C;KACPgG,UAAUvD;KACVwD,WAAWhD;KACXiD,SAAS,CAAC,CAAChG;KACXiG,WAAWjG,KAAamE,KAAAA;KACxB+B,UAAUtE,EAAuB+C;KACjCwB,WAAS;KACTC,aAAa5G,EAAUiB;;;IAGzB;;AAGV,GC5OawG,MAAwB,EAAEC,WAAQC,cAAWC,YAASC,cAAWC,iBAAoC;CAChH,IAAM,EAAA,MAAA,GAAA,GAAA,MAAQC,EAAAA,GACRC,IAAYR,EAAAA,GACZ,CAACS,GAAaC,KAAkBrB,EAAS,EAAA,GACzC,CAACsB,GAAWC,KAAgBvB,EAAwB,IAAA,GACpD,CAACwB,GAAmBC,KAAwBzB,EAAS,EAAA,GAErD0B,IAAQxB,EAAUyB,SAAQ,GAI1B,EACJC,MAAMC,GACNC,WAAWC,GACXC,OAAOC,MACL/B,EAAUgC,QAAQC,MAAMC,YAAYC,SACtC;EAAEC,YAAYnB;EAAWL,WAAWA,GAAWyB,QAAQ;EAAIC,QAAQ;EAAQC,OAAO;CAAE,GACpF,EAAEC,SAAS7B,KAAUC,MAAc,KAAK,CAAA,GAIpC,EAAEc,MAAMe,GAAmBX,OAAOY,MAAc1C,EAAUgC,QAAQC,MAAMU,qBAAqBR,SACjG;EAAEC,YAAYnB;EAAWL,WAAWA,GAAWyB,QAAQ;CAAG,GAC1D,EAAEG,SAAS7B,KAAUC,MAAc,KAAK,CAAA,GAIpCgC,IAAc,CAAC,EACnBH,GAAmBI,mBACnBJ,GAAmBK,oBACnBL,GAAmBM,kBAGfC,IAA0BhD,EAAUgC,QAAQC,MAAMgB,gBAAgBC,YAAY;EAClFpC,iBAAW;GAETA,AADAU,EAAMQ,QAAQC,MAAMkB,eAAeC,WAAU,GAC7CtC,IAAYF,EAAWyB,IAAI;EAC7B;EACAtB,UAAUe,MAAAA;GACRf,IAAUH,EAAWyB,MAAMP,EAAMuB,OAAO;EAC1C;EACAC,iBAAW;GACTC,EAAAA;EACF;CACF,CAAA;CAEAxD,SAAU;EACR,AAAKY,MACHQ,EAAe,EAAA,GACfE,EAAa,IAAA,GACbE,EAAqB,EAAA,GACrByB,EAAwBQ,MAAK;CAEjC,GAAG,CAAC7C,GAAQC,GAAWyB,IAAAA,CAAK;CAE5B,IAAMkB,UAAc;EAKlB1C,AAJAM,EAAe,EAAA,GACfE,EAAa,IAAA,GACbE,EAAqB,EAAA,GACrByB,EAAwBQ,MAAK,GAC7B3C,EAAAA;CACF,GAEM4C,KAA2BC,MAAAA;EAC/B,IAAMC,IAAQD,EAAEE,OAAOD;EAEvB,AADAxC,EAAewC,CAAAA,GACXvC,KAAWC,EAAa,IAAA;CAC9B,GAEMwC,UAAe;EACdjD,SACDmB,OAAgBW,IACpB;OAAIxB,EAAY4C,KAAI,MAAO,UAAU;IACnCzC,EAAa0C,EAAAA,EAAC,EAAA,IAAA,SAA6B,CAAA,CAAA;IAC3C;GACF;GACInB,KAAe,CAACtB,KACpB0B,EAAwBgB,OAAO;IAAE5B,YAAYnB;IAAWL,WAAWA,EAAUyB;GAAK,CAAA;EAFlF;CAGF,GAEM4B,KAAiBP,MAAAA;EACrB,AAAIA,EAAEQ,QAAQ,WAASL,EAAAA;CACzB;CAEA,IAAI,CAAClD,KAAU,CAACC,GAAW,OAAO;CAElC,IAAMuD,KAAoBxC,GAASyC,UAAU,GAKvCC,IAAa,CAACxC,MAAqBsC,KAAoB,KAAKvD,EAAU0D,QAAQ,IAG9EC,KAAqB,CAAC1C,KAAoBjB,EAAU0D,QAAQ,KAAKH,OAAsB,GACvFK,IAAoB,CAAC,EAAEzC,KAAgBW;CAa7C,OACE,gBAACzC,GAAAA;EACC2E,OAZF,kBAACF,QAAAA;GAAKC,WAAU;cACd,gBAACD,QAAAA;IAAKC,WAAU;cACd,gBAAA,GAAA,EAAA,IAAA,SAAA,CAAA;OAEF,gBAACD,QAAAA;IAAKC,WAAU;IAAWC,OAAOhE,EAAUyB;cACzCzB,EAAUyB;;GAONoC;EACPI,MAAMlE;EACNmE,UAAUvB;EACVwB,oBAAoBV,IAAaW,KAAAA,IAAYjB,EAAAA,EAAC,EAAA,IAAA,SAAO,CAAA;EACrDkB,sBAAsBZ,IAAaW,KAAAA,IAAY;EAC/CE,WAAWb,IAAaW,KAAAA,IAAYnB;EACpCsB,mBAAmBd,IAAaW,KAAAA,IAAYjB,EAAAA,EAAC,EAAA,IAAA,SAAO,CAAA;EACpDqB,aACEf,IACE,gBAACnE,GAAAA;GAAYyE,WAAU;aACrB,gBAACvE,GAAAA,EAAAA,UACC,gBAACD,GAAAA;IAAOkF,SAAQ;IAAUC,SAAS/B;IAAagC,eAAY;cAC1D,gBAAA,GAAA,EAAA,IAAA,SAAA,CAAA;;OAIJP,KAAAA;EAENQ,MAAK;EACLC,sBACE5D,KACA2C,KACAxB,EAAwB0C,aACvB,CAACrB,KAAcnD,EAAY4C,KAAI,MAAO,YACtC,CAACO,KAAczB,KAAe,CAACtB;cAGhCS,KAAgBW,MAChB,gBAACpC,GAAAA;GAAMqF,WAAU;GAAWC,KAAI;GAAIjB,WAAU;GAAOkB,MAAK;GAAQC,aAAU;cACzE/D,KACC,gBAACgE,KAAAA;IAAEpB,WAAU;qBACT;KACA,IAAMqB,IAAejE,EAAasB;KAClC,OAAO,gBAAA,GAAA;;gBAA0C2C,gBAAAA;;IACnD,GAAA;OAGHtD,KACC,gBAACqD,KAAAA;IAAEpB,WAAU;qBACT;KACA,IAAMqB,IAAetD,EAAUW;KAC/B,OAAO,gBAAA,GAAA;;gBAA6C2C,gBAAAA;;IACtD,GAAA;;MAKPnE,IACC,gBAACvB,GAAAA;GAAMqF,WAAU;GAAaM,WAAU;GAASL,KAAI;GAAIjB,WAAU;cACjE,gBAACpE,GAAAA,EAAQiF,MAAK,QAAA,CAAA,GACd,gBAAA,GAAA,EAAA,IAAA,SAAA,CAAA,CAAA;OAEAnB,IAEF,gBAAC/D,GAAAA;GAAMqF,WAAU;GAAWC,KAAI;cAC9B,gBAACG,KAAAA;IAAEpB,WAAU;cACX,gBAAA,GAAA,EAAA,IAAA,SAAA,CAAA;OAEDJ,MACC,gBAACwB,KAAAA;IAAEpB,WAAU;cACX,gBAAA,GAAA,EAAA,IAAA,SAAA,CAAA;;OASN,gBAACrE,GAAAA;GAAMqF,WAAU;GAAWC,KAAI;;IAC9B,gBAACG,KAAAA;KAAEpB,WAAU;;MACX,gBAAA,GAAA,EAAA,IAAA,SAAA,CAAA;MACA,gBAACuB,MAAAA,CAAAA,CAAAA;MACD,gBAAA,GAAA;;wCACmBC,UAAAA,CAAAA,CAAAA,EAAAA;;;;IAGpBvD,KACC,gBAACpC,GAAAA;KACC4F,OAAOrC,EAAAA,EAAC,EAAA,IAAA,SAA0D,CAAA;KAClEsC,SAAS/E;KACTgF,WAAW5C,MAA2CnC,EAAqBmC,EAAEE,OAAOyC,OAAO;KAC3FE,SAAS,CAACjF;;IAGd,gBAACjB,GAAAA;KACC+F,OAAOrC,EAAAA,EAAC,EAAA,IAAA,SAAyB,CAAA;KACjCyC,UAAQ;KACR7C,OAAOzC;KACPoF,UAAU7C;KACVgD,WAAWxC;KACXsC,SAAS,CAAC,CAACnF;KACXsF,WAAWtF,KAAa4D,KAAAA;KACxB2B,UAAU3D,EAAwB0C;KAClCkB,WAAS;KACTC,aAAa9C,EAAAA,EAAC,EAAA,IAAA,SAAO,CAAA;;;;;AAMjC,GClNMqE,KAAqB,IAAIC,IAAI;CACjC;CACA;CACA;CACA;CACA;CACA;CACD,GAEKC,KAAoB,IAIpBC,KAAe,kCAmBRC,KAA8B,EACzCC,WACAC,cACAC,YACAC,cACAC,iBACgC;CAChC,IAAM,EAAA,MAAA,GAAA,GAAA,MAAQC,EAAAA,GACRC,IAAYZ,EAAAA,GAGZ,EACJa,MAAMC,GACNC,cACAC,SAASC,GACTC,OAAOC,MACLpC,EAAUqC,QAAQC,MAAMC,qBAAqBC,SAC/C;EAAEC,YAAYZ;EAAWL,WAAWA,GAAWkB,QAAQ;CAAG,GAC1D,EAAEC,SAASpB,KAAUC,MAAc,KAAK,CAAA,GAGpCoB,IAAiBb,GAAMc,SAAS,mBAEhC,EAAEf,MAAMgB,MAAc9C,EAAUqC,QAAQC,MAAMS,sBAAsBP,SACxE;EAAEC,YAAYZ;EAAWL,WAAWA,GAAWkB,QAAQ;CAAG,GAC1D,EAAEC,SAASpB,KAAUC,MAAc,QAAQoB,EAAe,CAAA,GAGtD,EAAEd,MAAMkB,MAAehD,EAAUqC,QAAQC,MAAMW,eAAeT,SAClE,EAAEC,YAAYZ,EAAU,GACxB,EAAEc,SAASpB,EAAO,CAAA,GAGd,CAAC2B,GAAiBC,KAAsBvD,EAAS,EAAA,GACjD,CAACwD,GAAiBC,MAAsBzD,EAAS,EAAA,GACjD0D,IAAgBxD,GAA6C,IAAA,GAE7DyD,KAAwBxD,GAAayD,MAAAA;EACzC,IAAMC,IAAQD,EAAEE,OAAOD;EAGvBH,AAFAH,EAAmBM,CAAAA,GACfH,EAAcK,WAASC,aAAaN,EAAcK,OAAO,GAC7DL,EAAcK,UAAUE,iBAAiBR,GAAmBI,CAAAA,GAAQ,GAAA;CACtE,GAAG,CAAA,CAAE,GAECK,IACJV,EAAgBW,KAAI,EAAGC,SAAS,KAC3BhB,KAAc,CAAA,GAAIiB,QAChBC,MAAMA,EAAExB,SAASlB,GAAWkB,QAAQwB,EAAExB,KAAKyB,YAAW,EAAGC,SAAShB,EAAgBe,YAAW,CAAA,CAAA,IAEhG,CAAA,GAEAE,IAAoBP,EAAmBQ,MAAM,GAAGlD,EAAAA,GAChDmD,KAAcT,EAAmBE,SAASK,EAAkBL,QAE5DQ,KAAQxE,EAAUyE,SAAQ,GAI1B,CAACC,GAAYC,MAAiB/E,EAAS,EAAA,GACvC,CAACgF,GAAiBC,MAAsBjF,EAAwB,IAAA,GAChE,CAACkF,GAAYC,MAAiBnF,EAAS,EAAA,GACvC,CAACoF,GAAiBC,MAAsBrF,EAAwB,IAAA,GAGhE,CAACsF,GAAUC,MAAevF,EAAS,EAAA,GACnC,CAACwF,IAAaC,MAAkBzF,EAAS,EAAA,GAGzC,CAAC0F,IAAiBC,MAAsB3F,EAAS,EAAA,GACjD,CAAC4F,IAAkBC,MAAuB7F,EAAS,EAAA,GAGnD,CAAC8F,GAAUC,KAAe/F,EAA0B,CAAA,CAAE,GACtD,CAACgG,IAAYC,MAAiBjG,EAAiC,CAAC,CAAA,GAChE,CAACkG,GAAaC,MAAkBnG,EAAS,EAAA,GACzC,CAACoG,IAAQC,MAAarG,EAAS,EAAA,GAC/B,CAACsG,IAAUC,MAAevG,EAAS,EAAA,GACnC,CAACwG,IAAaC,MAAkBzG,EAAwB,IAAA,GACxD,CAAC0G,IAAeC,MAAoB3G,EAAwB,IAAA;CA+BlEC,AA5BAA,SAAU;EACR,IAAI,CAACkC,GAAM;EAKX0D,AAHAd,GAAc5C,EAAK2C,cAAc,OAAiC,KAA1B8B,OAAOzE,EAAK2C,UAAU,CAAI,GAClEK,GAAchD,EAAK+C,cAAc,OAAiC,KAA1B0B,OAAOzE,EAAK+C,UAAU,CAAI,GAClES,GAAmB,CAAC,EAAExD,EAAKuD,mBAAmBvD,EAAKyD,oBAAoBzD,EAAK0E,gBAAc,GAC1FhB,GAAoB1D,EAAKyD,oBAAoBzD,EAAK0E,mBAAmB,EAAA;EAErE,IAAMC,IAAgB3E,EAAK2D,YAAY,CAAC;EAExCL,AADAF,GAAYuB,EAAc,gBAAgB,EAAA,GAC1CrB,GAAeqB,EAAc,oBAAoB,OAAOA,EAAc,oBAAoB,MAAA;EAG1F,IAAMC,IAAU5E,EAAK2D,YAAY,CAAC;EAWlCC,EAViCkB,OAAOD,QAAQD,CAAAA,EAC7C1C,QAAQ,CAAC6C,OAAS,CAAC5F,GAAmB6F,IAAID,CAAAA,CAAAA,EAC1CE,KAAK,CAACF,GAAKrD,QAAY;GACtBqD;GACArD;GACAwD,OAAO;GACPC,WAAW;GACXC,aAAaL;GACbM,eAAe3D;EACjB,EACUmD,CAAAA;CACd,GAAG,CAAC7E,CAAAA,CAAK,GAGTlC,SAAU;EACR,AAAK0B,KACH8F,GAAAA;CAEJ,GAAG,CAAC9F,CAAAA,CAAO;CAEX,IAAM8F,WAAY;EAmBhBC,AAlBA3C,GAAc,EAAA,GACdE,GAAmB,IAAA,GACnBE,GAAc,EAAA,GACdE,GAAmB,IAAA,GACnBE,GAAY,EAAA,GACZE,GAAe,EAAA,GACfE,GAAmB,EAAA,GACnBE,GAAoB,EAAA,GACpBtC,EAAmB,EAAA,GACnBE,GAAmB,EAAA,GACfC,EAAcK,WAASC,aAAaN,EAAcK,OAAO,GAC7DgC,EAAY,CAAA,CAAE,GACdE,GAAc,CAAC,CAAA,GACfE,GAAe,EAAA,GACfE,GAAU,EAAA,GACVE,GAAY,EAAA,GACZE,GAAe,IAAA,GACfE,GAAiB,IAAA,GACjBe,GAAeC,MAAK;CACtB,GAGMD,KAAiBtH,EAAUqC,QAAQC,MAAMkF,wBAAwBC,YAAY;EACjF/F,iBAAW;GAITiG,AAHAnD,GAAMnC,QAAQC,MAAMC,qBAAqBmF,WAAW,EAAElG,WAAWA,EAAWkB,KAAK,CAAA,GACjF8B,GAAMnC,QAAQC,MAAMW,eAAeyE,WAAU,GAC7ChG,IAAYF,EAAWkB,IAAI,GAC3BiF,GAAAA;EACF;EACAhG,UAAUQ,MAAAA;GACRR,IAAUH,EAAWkB,MAAMP,EAAMyF,OAAO;EAC1C;CACF,CAAA,GAGMC,UAAiB;EACrB,IAAIC,IAAQ;EAaZ,OAZIpD,MAAe,OAAOqD,MAAMC,OAAOtD,CAAAA,CAAAA,KAAgBsD,OAAOtD,CAAAA,IAAc,MAC1EG,GAAmBoD,EAAAA,EAAC,EAAA,IAAA,SAA+B,CAAA,CAAA,GACnDH,IAAQ,MAERjD,GAAmB,IAAA,GAEjBC,MAAe,OAAOiD,MAAMC,OAAOlD,CAAAA,CAAAA,KAAgBkD,OAAOlD,CAAAA,IAAc,MAC1EG,GAAmBgD,EAAAA,EAAC,EAAA,IAAA,SAA+B,CAAA,CAAA,GACnDH,IAAQ,MAER7C,GAAmB,IAAA,GAEd6C;CACT,GAEMI,MAAmBpB,GAAaK,MAC/BL,EAAI/C,KAAI,IACR1C,GAAa8G,KAAKrB,CAAAA,IAClB,cAAcqB,KAAKrB,CAAAA,IACpB5F,GAAmB6F,IAAID,EAAI3C,YAAW,CAAA,IAAY8D,EAAAA,EAAC,EAAA,IAAA,SAA4C,CAAA,IAC/EvC,EAAS2C,MAAM7E,MAAMA,EAAEsD,IAAI3C,YAAW,MAAO2C,EAAI3C,YAAW,KAAMX,EAAE2D,gBAAgBA,CACpGiB,IAAoBH,EAAAA,EAAC,EAAA,IAAA,SAAwC,CAAA,IAC1D,OAJ8BA,EAAAA,EAAC,EAAA,IAAA,SAAqD,CAAA,IADvDA,EAAAA,EAAC,EAAA,IAAA,SAAgC,CAAA,IAD7CA,EAAAA,EAAC,EAAA,IAAA,SAAgB,CAAA,GAUrCK,WAAe;EACnB,IAAMC,IAASL,GAAgBlC,EAAAA;EAC/B,IAAIuC,GAAQ;GACVlC,GAAekC,CAAAA;GACf;EACF;EACA,IAAI,CAACrC,GAASnC,KAAI,GAAI;GACpBwC,GAAiB0B,EAAAA,EAAC,EAAA,IAAA,SAAkB,CAAA,CAAA;GACpC;EACF;EAOA1B,AALAZ,EAAY,CAAA,GAAID,GAAU;GAAEoB,KAAKd,GAAOjC,KAAI;GAAIN,OAAOyC,GAASnC,KAAI;GAAIkD,OAAO;GAAMC,WAAW;EAAM,CAAA,CAAE,GACxGjB,GAAU,EAAA,GACVE,GAAY,EAAA,GACZJ,GAAe,EAAA,GACfM,GAAe,IAAA,GACfE,GAAiB,IAAA;CACnB,GAEMiC,WAAkB;EAKtBjC,AAJAN,GAAU,EAAA,GACVE,GAAY,EAAA,GACZJ,GAAe,EAAA,GACfM,GAAe,IAAA,GACfE,GAAiB,IAAA;CACnB,GAEMkC,MAAcC,MAAAA;EAElB3C,AADAJ,EAAYD,EAASsB,KAAKxD,GAAGmF,MAAOA,MAAMD,IAAQ;GAAE,GAAGlF;GAAG0D,WAAW;EAAK,IAAI;GAAE,GAAG1D;GAAG0D,WAAW;EAAM,CAAA,CAAA,GACvGnB,GAAe,EAAA;CACjB,GAEM6C,MAAkBF,MAAAA;EACtB,IAAMG,IAAQnD,EAASgD,IACjBH,IAASL,GAAgBW,EAAM/B,KAAK+B,EAAM1B,WAAW;EAC3D,IAAIoB,GAAQ;GACV1C,GAAc,GAAG,QAAQ6C,MAAUH,EAAO,CAAA;GAC1C;EACF;EACA,IAAI,CAACM,EAAMpF,MAAMM,KAAI,GAAI;GACvB8B,GAAc,GAAG,QAAQ6C,MAAUT,EAAAA,EAAC,EAAA,IAAA,SAAkB,CAAA,EAAE,CAAA;GACxD;EACF;EAKApC,AAHAF,EACED,EAASsB,KAAKxD,GAAGmF,MAAOA,MAAMD,IAAQ;GAAE,GAAGlF;GAAG0D,WAAW;GAAOJ,KAAKtD,EAAEsD,IAAI/C,KAAI;GAAIN,OAAOD,EAAEC,MAAMM,KAAI;EAAG,IAAIP,CAAAA,CAAAA,GAE/GqC,GAAc,CAAC,CAAA;CACjB,GAEMiD,MAAoBJ,MAAAA;EAMxB7C,AALAF,EACED,EAASsB,KAAKxD,GAAGmF,MACfA,MAAMD,IAAQ;GAAE,GAAGlF;GAAG0D,WAAW;GAAOJ,KAAKtD,EAAE2D,eAAe3D,EAAEsD;GAAKrD,OAAOD,EAAE4D,iBAAiB5D,EAAEC;EAAM,IAAID,CAAAA,CAAAA,GAG/GqC,GAAc,CAAC,CAAA;CACjB,GAEMkD,MAAoBL,MAAAA;EAExB7C,AADAF,EAAYD,EAASzB,QAAQ+E,GAAGL,MAAMA,MAAMD,CAAAA,CAAAA,GAC5C7C,GAAc,CAAC,CAAA;CACjB,GAEMoD,MAAmBP,GAAejF,MAAAA;EAEtCoC,AADAF,EAAYD,EAASsB,KAAKxD,GAAGmF,MAAOA,MAAMD,IAAQ;GAAE,GAAGlF;GAAGsD,KAAKrD;EAAM,IAAID,CAAAA,CAAAA,GACzEqC,IAAeqD,MAAAA;GACb,IAAMC,IAAI,EAAE,GAAGD,EAAK;GAEpB,OADA,OAAOC,EAAE,QAAQT,MACVS;EACT,CAAA;CACF,GAEMC,MAAqBV,GAAejF,MAAAA;EAExCoC,AADAF,EAAYD,EAASsB,KAAKxD,GAAGmF,MAAOA,MAAMD,IAAQ;GAAE,GAAGlF;GAAGC;EAAM,IAAID,CAAAA,CAAAA,GACpEqC,IAAeqD,MAAAA;GACb,IAAMC,IAAI,EAAE,GAAGD,EAAK;GAEpB,OADA,OAAOC,EAAE,QAAQT,MACVS;EACT,CAAA;CACF,GAGME,WAAe;EAEnB,IADI,CAAC7H,KACD,CAACqG,EAAAA,GAAkB;EAEvB,IAAMlB,IAAU5E,GAAM2D,YAAY,CAAC,GAG7B4D,IAAwC,CAAC,GACzCC,IAA2B,CAAA;EAGjC7D,EAAS8D,SAASX,MAAAA;GAChB,CAAIA,EAAM5B,SAAS4B,EAAMpF,UAAUoF,EAAMzB,iBAAiByB,EAAM/B,QAAQ+B,EAAM1B,iBAC5EmC,EAAcT,EAAM/B,OAAO+B,EAAMpF,OAE7B,CAACoF,EAAM5B,SAAS4B,EAAM1B,eAAe0B,EAAM/B,QAAQ+B,EAAM1B,eAC3DoC,EAAeE,KAAKZ,EAAM1B,WAAW;EAG3C,CAAA;EAGA,IAAMuC,IAAe7C,OAAO8C,KAAKhD,CAAAA,EAAS1C,QAAQ2F,MAAM,CAAC1I,GAAmB6F,IAAI6C,CAAAA,CAAAA,GAC1EC,IAAsBnE,EAASsB,KAAKxD,MAAMA,EAAE2D,WAAW,EAAElD,OAAO6F,OAAAA;EAMtE,AALAJ,EAAaF,SAASI,MAAAA;GACpB,AAAI,CAACC,EAAoBzF,SAASwF,CAAAA,KAAM,CAACL,EAAenF,SAASwF,CAAAA,KAAIL,EAAeE,KAAKG,CAAAA;EAC3F,CAAA,GAGIhH,MACEsC,IACFoE,EAAc,eAAepE,IACpBnD,GAAM2D,WAAW,gBAC1B6D,EAAeE,KAAK,WAAA,GAElBrE,KACFkE,EAAc,kBAAkB,MACvBvH,GAAM2D,WAAW,mBAC1B6D,EAAeE,KAAK,cAAA;EAKxB,IAAMM,IAAe,CAAC,EAAEhI,GAAMuD,mBAAmBvD,GAAMyD,oBAAoBzD,GAAM0E,kBAC3EuD,IAAmBjI,GAAMyD,oBAAoBzD,GAAM0E,mBAAmB;EAE5Ea,GAAe2C,OAAO;GACpBxH,YAAYZ;GACZL,WAAWA,EAAUkB;GACrBgD,UAAU4D;GACVC,gBAAgBA,EAAevF,SAASuF,IAAiBW,KAAAA;GACzDxF,YAAYA,MAAe,KAA0BwF,KAAAA,IAArBlC,OAAOtD,CAAAA;GACvCI,YAAYA,MAAe,KAA0BoF,KAAAA,IAArBlC,OAAOlD,CAAAA;GAEvCU,kBACEF,OAAoB,CAACyE,KAAgBvE,OAAqBwE,MAAqBxE,KAC3EA,KACA0E,KAAAA;GACNC,wBAAwB,CAAC7E,MAAmByE,IAAe,KAAOG,KAAAA;EACpE,CAAA;CACF,GAEMvC,WAAc;EAElBlG,AADA4F,GAAAA,GACA5F,EAAAA;CACF;CAEA,IAAI,CAACF,KAAU,CAACC,GAAW,OAAO;CAElC,IAAM4I,KAASpI,KAAasF,GAAe+C,WACrCC,KAAepI,KAAe,CAACF,GAC/BuI,KAAa7E,EAAS2C,MAAM7E,MAAMA,EAAE0D,SAAS,GAE7CsD,KAAoBzI,GAAM2C,cAAc,OAAiC,KAA1B8B,OAAOzE,EAAK2C,UAAU,GACrE+F,KAAoB1I,GAAM+C,cAAc,OAAiC,KAA1B0B,OAAOzE,EAAK+C,UAAU,GACrE4F,KAAyB,CAAC,CAAC3I,GAAMuD,iBACjCqF,KAA0B5I,GAAMyD,oBAAoBzD,GAAM0E,mBAAmB,IAC7EmE,KAAkB7I,GAAM2D,WAAW,gBAAgB,IACnDmF,KAAqB9I,GAAM2D,WAAW,oBAAoB,OAAO3D,GAAM2D,WAAW,oBAAoB,QACtGoF,KAAsBjE,OAAO8C,KAAK5H,GAAM2D,YAAY,CAAC,CAAA,EAAGzB,QAAQ2F,MAAM,CAAC1I,GAAmB6F,IAAI6C,CAAAA,CAAAA,GAE9FmB,KACJrF,EAAS1B,WAAW8G,GAAoB9G,UACxC0B,EAASsF,OAAOxH,MAAM,CAACA,EAAEyD,SAASzD,EAAEsD,QAAQtD,EAAE2D,eAAe3D,EAAEC,UAAUD,EAAE4D,aAAa,GAEpF6D,KACJvG,MAAe8F,MACf1F,MAAe2F,MACfnF,OAAoBoF,MACpBlF,OAAqBmF,MACrBzF,MAAa0F,MACbxF,OAAgByF,MAChBE,IAGIG,KAAsBnJ,GAAM2C,cAAc,OAAgC,OAAzB,GAAG3C,EAAK2C,WAAW;CAE1E,OACE,gBAACzE,GAAAA;EACCkL,OACE,gBAACC,QAAAA;GAAKC,WAAU;cACd,gBAACD,QAAAA;IAAKC,WAAU;cACd,gBAAA,GAAA,EAAA,IAAA,SAAA,CAAA;OAEF,gBAACD,QAAAA;IAAKC,WAAU;IAAWF,OAAO3J,EAAUkB;cACzClB,EAAUkB;;;EAIjB4I,MAAM/J;EACNgK,UAAU5D;EACV6D,oBAAoBvD,EAAAA,EAAC,EAAA,IAAA,SAAK,CAAA;EAC1BwD,WAAWpC;EACXqC,mBAAmBzD,EAAAA,EAAC,EAAA,IAAA,SAAO,CAAA;EAC3B0D,MAAK;EACLC,sBAAsBxB,MAAUtE,KAAeyE,MAAcU,MAAeX;aAE3EhD,GAAerF,WACd,gBAAC4J,KAAAA;GAAER,WAAU;oBACT;IACA,IAAMS,IAAexE,GAAenF,MAAMyF;IAC1C,OAAO,gBAAA,GAAA;;eAAoCkE,gBAAAA;;GAC7C,GAAA;MAGH9J,IACC,gBAAC7B,GAAAA;GAAM4L,WAAU;GAAaC,WAAU;GAASC,KAAI;GAAIZ,WAAU;cACjE,gBAACjL,GAAAA,EAAQuL,MAAK,QAAA,CAAA,GACd,gBAAA,GAAA,EAAA,IAAA,SAAA,CAAA,CAAA;OAEArB,KACF,gBAACuB,KAAAA;GAAER,WAAU;aAGF,gBAAA,GAAA;;cAA6CS,cAD/B1J,GAAWwF,WAAW,gBAAA;;OAK/C,gBAACsE,OAAAA;GAAIb,WAAU;aACb,gBAAClL,GAAAA;IAAM4L,WAAU;IAAWE,KAAI;;KAE9B,gBAACC,OAAAA;MAAIb,WAAU;iBACb,gBAACnL,GAAAA;OAAUiM,OAAOlE,EAAAA,EAAC,EAAA,IAAA,SAAa,CAAA;OAAGxE,OAAO+C,OAAOhF,EAAU4K,KAAK;OAAGC,UAAQ;OAACC,UAAQ;UACpF,gBAACpM,GAAAA;OACCiM,OAAOlE,EAAAA,EAAC,EAAA,IAAA,SAAW,CAAA;OACnBxE,OACE1B,GAAMwK,aAAa,OAEf,GAAG/K,EAAUiL,MAAMD,eAAc,EAAG,MADpC,GAAGzK,EAAKwK,UAAUC,eAAc,EAAG;OAGzCH,UAAQ;OACRC,UAAQ;;;KAKZ,gBAACJ,OAAAA;MAAIb,WAAU;iBACb,gBAACa,OAAAA,EAAAA,UACC,gBAAChM,GAAAA;OACCiM,OAAOlE,EAAAA,EAAC,EAAA,IAAA,SAAmB,CAAA;OAC3BxE,OAAOqB;OACP4H,WAAWlJ,MAAAA;QAET,AADAuB,GAAcvB,EAAEE,OAAOD,KAAK,GACxBuB,KAAiBC,GAAmB,IAAA;OAC1C;OACA0H,aAAa1E,EAAAA,EAAC,EAAA,IAAA,SAAS,CAAA;OACvB2E,SAAS,CAAC,CAAC5H;OACX6H,WAAW7H,KAAmBkF,KAAAA;OAC9BmC,UAAUjC;aAGd,gBAAC8B,OAAAA,EAAAA,UACC,gBAAChM,GAAAA;OACCiM,OAAOlE,EAAAA,EAAC,EAAA,IAAA,SAAiB,CAAA;OACzBxE,OAAOiB;OACPgI,WAAWlJ,MAAAA;QAET,AADAmB,GAAcnB,EAAEE,OAAOD,KAAK,GACxBmB,KAAiBC,GAAmB,IAAA;OAC1C;OACA8H,aAAa1E,EAAAA,EAAC,EAAA,IAAA,SAAS,CAAA;OACvB2E,SAAS,CAAC,CAAChI;OACXiI,WAAWjI,KAAmBsF,KAAAA;OAC9BmC,UAAUjC;OACV0C,UAAUpI,KAAcwG,KAAsBA,KAAsBhB,KAAAA;;;KAMzEtH,KAAkBE,KACjB,gBAACoJ,OAAAA,EAAAA,UAAAA,CACC,gBAACL,KAAAA;MAAER,WAAU;;OACX,gBAAA,GAAA,EAAA,IAAA,SAAA,CAAA;OAAqC;OACrC,gBAAC0B,KAAAA;QACCC,MAAMlK;QACNY,QAAO;QACPuJ,KAAI;QACJ5B,WAAU;kBAEV,gBAAA,GAAA,EAAA,IAAA,SAAA,CAAA;;;SAGJ,gBAACnL,GAAAA;MAAUuD,OAAOX;MAAWuJ,UAAQ;MAACC,UAAQ;;KAKlD,gBAACJ,OAAAA,EAAAA,UAAAA,CACC,gBAACL,KAAAA;MAAER,WAAU;gBACX,gBAAA,GAAA,EAAA,IAAA,SAAA,CAAA;SAEDzI,IACC,gBAACzC,GAAAA;MAAM4L,WAAU;MAAWE,KAAI;iBAC9B,gBAAC9L,GAAAA;OAAM4L,WAAU;OAAWE,KAAI;kBAC9B,gBAACvL,GAAAA;QACCyL,OAAOlE,EAAAA,EAAC,EAAA,IAAA,SAA0C,CAAA;QAClDiF,SAAS,CAAC,CAAChI;QACXwH,WAAWlJ,MAAAA;SACT,AAAKA,EAAEE,OAAOwJ,UACJhI,KAAUC,GAAY,YAAA,IADTA,GAAY,EAAA;QAErC;QACAkH,UAAUjC;WAEZ,gBAAC8B,OAAAA;QAAIb,WAAU;kBACb,gBAACnL,GAAAA;SACCuD,OAAOyB;SACPwH,WAAWlJ,MAA2C2B,GAAY3B,EAAEE,OAAOD,KAAK;SAChFkJ,aAAY;SACZN,UAAUjC,MAAU,CAAClF;SACrBmG,WAAU;;;UAIhB,gBAAClL,GAAAA;OAAM4L,WAAU;OAAaC,WAAU;OAAQC,KAAI;kBAClD,gBAACvL,GAAAA;QACCyL,OAAOlE,EAAAA,EAAC,EAAA,IAAA,SAAoB,CAAA;QAC5BiF,SAAS9H;QACTsH,WAAWlJ,MAA2C6B,GAAe7B,EAAEE,OAAOwJ,OAAO;QACrFb,UAAUjC;WAEZ,gBAACzJ,GAAAA;QAAQwM,cAAa;mBACpB,gBAACvM,GAAAA,EAAAA,UACC,gBAACE,GAAAA;SAAKsM,MAAK;SAAOzB,MAAK;SAAKN,WAAU;eAExC,gBAACxK,GAAAA;SAAewK,WAAU;mBACxB,gBAAA,GAAA,EAAA,IAAA,SAAA,CAAA;;;;UAMR,gBAACQ,KAAAA;MAAER,WAAU;gBACX,gBAAA,GAAA;;wCAEGgC,UAAAA,CAAAA,CAAAA,EAAAA;;;KAOT,gBAACnB,OAAAA,EAAAA,UAAAA,CACC,gBAACL,KAAAA;MAAER,WAAU;gBACX,gBAAA,GAAA,EAAA,IAAA,SAAA,CAAA;SAIDX,MAA0B,CAAClF,KAC1B,gBAAC9E,GAAAA;MACCyL,OAAOlE,EAAAA,EAAC,EAAA,IAAA,SAAsB,CAAA;MAC9BiF,SAAO;MACPR,WAAWlJ,MAAAA;OACT,AAAKA,EAAEE,OAAOwJ,YACZ3H,GAAmB,EAAA,GACnBE,GAAoB,EAAA,GACpBtC,EAAmB,EAAA,GACnBE,GAAmB,EAAA;MAEvB;MACAgJ,UAAU;UAEV,CAAC/G,MAAmB,CAACE,KAEvB,gBAAC9E,GAAAA;MACCyL,OAAOlE,EAAAA,EAAC,EAAA,IAAA,SAA0B,CAAA;MAClCiF,SAAS;MACTR,WAAWlJ,MAA2C+B,GAAmB/B,EAAEE,OAAOwJ,OAAO;MACzFb,UAAUjC;UAIZ,gBAACjK,GAAAA;MAAM4L,WAAU;MAAWE,KAAI;iBAC9B,gBAACvL,GAAAA;OACCyL,OAAOlE,EAAAA,EAAC,EAAA,IAAA,SAAwC,CAAA;OAChDiF,SAAS5H;OACToH,WAAWlJ,MAAAA;QAET,AADA+B,GAAmB/B,EAAEE,OAAOwJ,OAAO,GAC9B1J,EAAEE,OAAOwJ,YACZzH,GAAoB,EAAA,GACpBtC,EAAmB,EAAA,GACnBE,GAAmB,EAAA;OAEvB;OACAgJ,UAAUjC;UAEX9E,MACC,gBAAC4G,OAAAA;OAAIb,WAAU;iBACb,gBAACtK,GAAAA;QACC0C,OAAO+B;QACPkH,WAAWjJ,MAAkBgC,GAAoBhC,CAAAA;QACjD6J,eAAe/J;QACfoJ,aAAa1E,EAAAA,EAAC,EAAA,IAAA,SAA6B,CAAA;QAC3C6E,iBAAW;SACT,IAAI5J,EAAgBa,KAAI,EAAGC,WAAW,GAAG,OAAOiE,EAAAA,EAAC,EAAA,IAAA,SAAuC,CAAA;SACxF,IAAI1D,KAAc,GAAG;UACnB,IAAMgJ,IAAanM,IACboM,IAAa1J,EAAmBE;UACtC,OAAOiE,EAAAA,EAAC;;;YAAiBsF;YAAiBC;;UAAkD,CAAA;SAC9F;QAEF,GAAA;QACAnB,UAAUjC;kBAET/F,EAAkB2C,KAAK9C,MACtB,gBAAClD,GAAAA;SAA4ByC,OAAOS,EAAExB;mBACnCwB,EAAExB;WADgBwB,EAAExB,IAAI,CAAA;;;;KAYzC,gBAACwJ,OAAAA,EAAAA,UAAAA;MACC,gBAAC/L,GAAAA;OAAM4L,WAAU;OAAaC,WAAU;OAASyB,cAAa;OAAUpC,WAAU;kBAChF,gBAACQ,KAAAA;QAAER,WAAU;kBACX,gBAAA,GAAA,EAAA,IAAA,SAAA,CAAA;WAEF,gBAACQ,KAAAA;QAAER,WAAU;kBACX,gBAAA,GAAA,EAAA,IAAA,SAAA,CAAA;;;MAKJ,gBAAClL,GAAAA;OAAM4L,WAAU;OAAaV,WAAU;iBACtC,gBAAC5K,GAAAA;QACC0L,OAAOlE,EAAAA,EAAC,EAAA,IAAA,SAAa,CAAA;QACrByF,eAAe3H,GAAe,EAAA;QAC9B4H,SAAQ;QACRP,MAAK;QACLzB,MAAK;QACLU,UAAUvG,KAAeyE,MAAcH;;;MAI3C,gBAAC/J,GAAAA;OAASuN,SAAS;;QACjB,gBAACtN,GAAAA,EAAAA,UAAAA;SACC,gBAACC,GAAAA,EAAAA,UACC,gBAAA,GAAA,EAAA,IAAA,SAAA,CAAA,EAAA,CAAA;SAEF,gBAACA,GAAAA,EAAAA,UACC,gBAAA,GAAA,EAAA,IAAA,SAAA,CAAA,EAAA,CAAA;SAEF,gBAACA,GAAAA,EAAAA,UACC,gBAAA,GAAA,EAAA,IAAA,SAAA,CAAA,EAAA,CAAA;;QAKHuF,KACC,gBAACxF,GAAAA,EAAAA,UAAAA;SACC,gBAACE,GAAAA,EAAAA,UACC,gBAACN,GAAAA;UACCuD,OAAOuC;UACP0G,WAAWlJ,MAAAA;WAET,AADAyC,GAAUzC,EAAEE,OAAOD,KAAK,GACpB2C,MAAaC,GAAe,IAAA;UAClC;UACAsG,aAAa1E,EAAAA,EAAC,EAAA,IAAA,SAAa,CAAA;UAC3B4E,WAAWzG,MAAe8D,KAAAA;UAC1B0C,SAAS,CAAC,CAACxG;UACXyH,WAAS;;SAGb,gBAACrN,GAAAA,EAAAA,UACC,gBAACN,GAAAA;UACCuD,OAAOyC;UACPwG,WAAWlJ,MAAAA;WAET,AADA2C,GAAY3C,EAAEE,OAAOD,KAAK,GACtB6C,MAAeC,GAAiB,IAAA;UACtC;UACAoG,aAAa1E,EAAAA,EAAC,EAAA,IAAA,SAAM,CAAA;UACpB4E,WAAWvG,MAAiB4D,KAAAA;UAC5B0C,SAAS,CAAC,CAACtG;;SAGf,gBAAC9F,GAAAA,EAAAA,UACC,gBAACL,GAAAA;UAAM4L,WAAU;UAAaE,KAAI;qBAChC,gBAACxL,GAAAA;WAAOkL,MAAK;WAAQgC,SAAQ;WAAUD,SAASpF;WAAc8E,MAAK;WAAQjC,OAAOlD,EAAAA,EAAC,EAAA,IAAA,SAAK,CAAA;cACxF,gBAACxH,GAAAA;WACCkL,MAAK;WACLgC,SAAQ;WACRD,SAASlF;WACT4E,MAAK;WACLjC,OAAOlD,EAAAA,EAAC,EAAA,IAAA,SAAQ,CAAA;;;;QAQzBvC,EAASsB,KAAK6B,GAAOH,MACpB,gBAACpI,GAAAA,EAAAA,UAAAA;SACC,gBAACE,GAAAA,EAAAA,UACEqI,EAAM3B,YACL,gBAAChH,GAAAA;UACCuD,OAAOoF,EAAM/B;UACb4F,WAAWlJ,MAA2CyF,GAAgBP,GAAOlF,EAAEE,OAAOD,KAAK;UAC3FoJ,WAAWjH,GAAW,QAAQ8C;UAC9BkE,SAAS,CAAC,CAAChH,GAAW,QAAQ8C;cAGhC,gBAAC0C,QAAAA;UAAKC,WAAU;UAAkCF,OAAOtC,EAAM/B;oBAC5D+B,EAAM/B;;SAIb,gBAACtG,GAAAA,EAAAA,UACEqI,EAAM3B,YACL,gBAAChH,GAAAA;UACCuD,OAAOoF,EAAMpF;UACbiJ,WAAWlJ,MACT4F,GAAkBV,GAAOlF,EAAEE,OAAOD,KAAK;cAI3C,gBAAC2H,QAAAA;UAAKC,WAAU;UAAkCF,OAAOtC,EAAMpF;oBAC5DoF,EAAMpF;;SAIb,gBAACjD,GAAAA,EAAAA,UACEqI,EAAM3B,YACL,gBAAC/G,GAAAA;UAAM4L,WAAU;UAAaE,KAAI;qBAChC,gBAACxL,GAAAA;WACCkL,MAAK;WACLgC,SAAQ;WACRD,eAAe9E,GAAeF,CAAAA;WAC9B0E,MAAK;WACLjC,OAAOlD,EAAAA,EAAC,EAAA,IAAA,SAAK,CAAA;cAEf,gBAACxH,GAAAA;WACCkL,MAAK;WACLgC,SAAQ;WACRD,eAAe5E,GAAiBJ,CAAAA;WAChC0E,MAAK;WACLjC,OAAOlD,EAAAA,EAAC,EAAA,IAAA,SAAQ,CAAA;;cAIpB,gBAAC9H,GAAAA;UAAM4L,WAAU;UAAaE,KAAI;qBAChC,gBAACxL,GAAAA;WACCkL,MAAK;WACLgC,SAAQ;WACRD,eAAejF,GAAWC,CAAAA;WAC1B0E,MAAK;WACLjC,OAAOlD,EAAAA,EAAC,EAAA,IAAA,SAAK,CAAA;WACboE,UAAUvG,KAAeyE,MAAcH;cAEzC,gBAAC3J,GAAAA;WACCkL,MAAK;WACLgC,SAAQ;WACRD,eAAe3E,GAAiBL,CAAAA;WAChC0E,MAAK;WACLjC,OAAOlD,EAAAA,EAAC,EAAA,IAAA,SAAO,CAAA;WACfoE,UAAUvG,KAAeyE,MAAcH;;;aA/D/B1B,CAAAA,CAAAA;QAwEnBhD,EAAS1B,WAAW,KAAK,CAAC8B,KACzB,gBAACxF,GAAAA,EAAAA,UACC,gBAACE,GAAAA;SAAasN,SAAS;SAAGzC,WAAU;mBAClC,gBAAClL,GAAAA;UAAM6L,WAAU;oBACf,gBAACZ,QAAAA;WAAKC,WAAU;qBACd,gBAAA,GAAA,EAAA,IAAA,SAAA,CAAA;;;;;;;;;;;AAa1B;;;AClwBA,SAAS+D,GAAcC,GAAW;CAChC,IAAMC,IAAQD,EAAIE,KAAI;CAEtB,IAAID,MAAU,QACZ,OAAO;EAAED,KAAKC;EAAOE,MAAM;EAAgBC,aAAa;EAAIC,eAAe;CAAM;CAInF,IAAIJ,EAAMK,WAAW,KAAA,GAAQ;EAC3B,IAAMC,IAAWN,EAAMO,MAAM,CAAA,GACvBC,IAASF,EAASD,WAAW,GAAA,GAC7BI,IAAOD,IAASF,EAASC,MAAM,CAAA,IAAKD;EAC1C,OAAO;GACLP,KAAKC;GACLE,MAAMM,IAAS,oBAAoB;GACnCC;GACAN,aAAa;GACbC,eAAe;EACjB;CACF;CAEA,IAAIJ,MAAU,cACZ,OAAO;EAAED,KAAKC;EAAOE,MAAM;EAAkBC,aAAa;EAAIC,eAAe;CAAM;CAIrF,IAAI,aAAaM,KAAKV,CAAAA,KAAU,CAACA,EAAMK,WAAW,GAAA,GAAM;EACtD,IAAM,CAACM,KAAaX,EAAMY,MAAM,GAAA;EAChC,OAAO;GACLb,KAAKC;GACLE,MAAM;GACNS;GACAR,aAAa;GACbC,eAAe;EACjB;CACF;CAGA,IAAIJ,EAAMK,WAAW,IAAA,GAEnB,OAAO;EACLN,KAAKC;EACLE,MAAM;EACNW,QAJab,EAAMO,MAAM,CAIzBM;EACAV,aAAa;EACbC,eAAe;CACjB;CAIF,IAAIJ,EAAMc,SAAS,GAAA,GAAM;EACvB,IAAM,CAACH,GAAWE,KAAUb,EAAMY,MAAM,GAAA;EACxC,OAAO;GACLb,KAAKC;GACLE,MAAM;GACNS;GACAE;GACAV,aAAa;GACbC,eAAe;EACjB;CACF;CAGA,OAAO;EAAEL,KAAKC;EAAOE,MAAM;EAAWC,aAAa;EAAIC,eAAe;CAAK;AAC7E;AAEA,SAASW,GAAeC,GAAiB;CAEvC,OADKA,EAAUf,KAAI,IACZe,EACJJ,MAAM,GAAA,EACNK,KAAKC,MAAMA,EAAEjB,KAAI,CAAA,EACjBkB,OAAOC,OAAAA,EACPH,IAAInB,EAAAA,IALuB,CAAA;AAMhC;AAIA,IAAMuB,KAAsB,CAAC,QAAQ,YAAA;AAErC,SAASC,GAAaC,GAAe;CACnC,IAAMC,IAAUD,EACbX,MAAM,GAAA,EACNK,KAAKC,MAAMA,EAAEjB,KAAI,CAAA,EACjBkB,OAAOC,OAAAA;CACV,OAAOC,GAAoBI,OAAOC,MAAMF,EAAQV,SAASY,CAAAA,CAAAA;AAC3D;AAEA,SAASC,GAAqBC,GAAe;CAC3C,IAAMC,IAAWD,EACdhB,MAAM,GAAA,EACNK,KAAKC,MAAMA,EAAEjB,KAAI,CAAA,EACjBkB,OAAOC,OAAAA;CAEV,OAAOU,CAAAA,GADY,IAAIC,IAAI,CAAA,GAAIV,IAAAA,GAAwBQ,CAAAA,CAAS,CACzDC,EAAOE,KAAK,GAAA;AACrB;AAEA,SAASC,GAAwBL,GAAe;CAC9C,OAAOA,EACJhB,MAAM,GAAA,EACNK,KAAKC,MAAMA,EAAEjB,KAAI,CAAA,EACjBkB,QAAQO,MAAM,CAACL,GAAoBP,SAASY,CAAAA,CAAAA,EAC5CM,KAAK,GAAA;AACV;AAIA,SAASE,GAAclC,GAAqB;CAC1C,QAAQA,EAAME,MAAd;EACE,KAAK,gBACH,OAAOiC,EAAAA,EAAC,EAAA,IAAA,SAAa,CAAA;EACvB,KAAK,mBAAmB;GACtB,IAAM1B,IAAOT,EAAMS,QAAQ;GAC3B,OAAO0B,EAAAA,EAAC;;cAAoB1B,QAAAA;GAAK,CAAA;EACnC;EACA,KAAK,qBAAqB;GACxB,IAAMA,IAAOT,EAAMS,QAAQ;GAC3B,OAAO0B,EAAAA,EAAC;;cAAsB1B,QAAAA;GAAK,CAAA;EACrC;EACA,KAAK,kBACH,OAAO0B,EAAAA,EAAC,EAAA,IAAA,SAAe,CAAA;EACzB,KAAK,qBAAqB;GACxB,IAAMxB,IAAYX,EAAMW,aAAa;GACrC,OAAOwB,EAAAA,EAAC;;cAA0BxB,aAAAA;GAAU,CAAA;EAC9C;EACA,KAAK,6BAA6B;GAChC,IAAME,IAASb,EAAMa,UAAU;GAC/B,OAAOsB,EAAAA,EAAC;;cAAQtB,UAAAA;GAAqB,CAAA;EACvC;EACA,KAAK,iBAAiB;GACpB,IAAMF,IAAYX,EAAMW,aAAa,IAC/BE,IAASb,EAAMa,UAAU;GAC/B,OAAOsB,EAAAA,EAAC;;;KAAQtB;KAAuBF;;GAAU,CAAA;EACnD;EAEA,SACE,OAAOX,EAAMD;CACjB;AACF;AAYA,IAAaqC,KAA8B,EACzCC,WACAC,cACAC,YACAC,cACAC,iBACgC;CAChC,IAAM,EAAA,MAAA,GAAA,GAAA,MAAQC,EAAAA,GACR/B,IAAY7B,EAAAA,GAEZ,CAACyC,GAASoB,KAAclE,EAAS,EAAA,GACjC,CAACmE,GAAUC,KAAepE,EAAS,EAAA,GACnC,CAACqE,GAAYC,KAAiBtE,EAAS,EAAA,GACvC,CAACuE,GAAaC,KAAkBxE,EAAS,EAAA;CAG/CC,SAAU;EACR,AAAI,CAAC6C,EAAQtB,KAAI,KAAM,CAAC2C,EAAS3C,KAAI,KAAIgD,EAAe,EAAA;CAC1D,GAAG,CAAC1B,GAASqB,CAAAA,CAAS;CAGtB,IAAM,EACJM,MAAMC,GACNC,cACAC,SAASC,GACTC,OAAOC,MACL3E,EAAU4E,QAAQC,MAAMC,qBAAqBC,SAC/C;EAAEC,YAAYlD;EAAW2B,WAAWA,GAAWwB,QAAQ;CAAG,GAC1D,EAAEC,SAAS1B,KAAUC,MAAc,KAAK,CAAA;CAI1C5D,SAAU;EACR,IAAI,CAACyE,GAAM;EACX,IAAMa,IAAOb,EAAKa,QAAQ,IACpBC,IAAQd,EAAKc,SAAS;EAG5BlB,AAFAJ,EAAWqB,CAAAA,GACXnB,EAAYoB,CAAAA,GACZlB,EAAczB,GAAa0C,CAAAA,CAAAA;CAC7B,GAAG,CAACb,CAAAA,CAAK;CAGT,IAAMe,IAAQrF,EAAUsF,SAAQ,GAE1BC,IAAiBvF,EAAU4E,QAAQC,MAAMW,wBAAwBC,YAAY;EACjF9B,iBAAW;GAITiC,AAHAP,EAAMT,QAAQC,MAAMC,qBAAqBY,WAAW;IAAEV,YAAYlD;IAAW2B,WAAWA,EAAWwB;GAAK,CAAA,GACxGI,EAAMT,QAAQC,MAAMc,eAAeD,WAAU,GAC7C/B,IAAYF,EAAWwB,IAAI,GAC3BW,EAAAA;EACF;EACAhC,UAAUc,MAAAA;GACRd,IAAUH,EAAWwB,MAAMP,EAAMmB,OAAO;EAC1C;CACF,CAAA,GAKMC,IAAmBhG,GAAOyF,EAAeQ,KAAK;CACpDD,EAAiB/C,UAAUwC,EAAeQ;CAE1C,IAAMH,UAAc;EAMlBlC,AALAI,EAAW,EAAA,GACXE,EAAY,EAAA,GACZE,EAAc,EAAA,GACdE,EAAe,EAAA,GACfmB,EAAeQ,MAAK,GACpBrC,EAAAA;CACF;CAGA7D,SAAU;EACR,AAAK2D,MACHM,EAAW,EAAA,GACXE,EAAY,EAAA,GACZE,EAAc,EAAA,GACd4B,EAAiB/C,QAAO;CAE5B,GAAG,CAACS,CAAAA,CAAO;CAGX,IAAMwC,MAA0BnD,MAAAA;EAC9B,IAAMoD,IAAUpD,EAAEqD,OAAOD;EAEzBnC,AADAI,EAAc+B,CAAAA,GACdnC,GAAYqC,MAAUF,IAAUnD,GAAqBqD,CAAAA,IAAQ/C,GAAwB+C,CAAAA,CAAAA;CACvF,GAEMC,KAAuBvD,MAAAA;EAC3B,IAAMwD,IAAQxD,EAAEqD,OAAOG;EAEvBnC,AADAJ,EAAWuC,CAAAA,GACXnC,EAAczB,GAAa4D,CAAAA,CAAAA;CAC7B,GAGMC,WAAe;EACd7C,KACL8B,EAAegB,OAAO;GACpBvB,YAAYlD;GACZ2B,WAAWA,EAAUwB;GACrBE,MAAMzC,EAAQtB,KAAI;GAClBgE,OAAOrB,EAAS3C,KAAI;EACtB,CAAA;CACF;CAEA,IAAI,CAACoC,KAAU,CAACC,GAAW,OAAO;CAElC,IAAM+C,IAASjC,KAAagB,EAAekB,WACrCC,KAAYhE,EAAQtB,KAAI,EAAGuF,SAAS,KAAK5C,EAAS3C,KAAI,EAAGuF,SAAS,GAElEC,IAAoB1E,GAAeQ,CAAAA,GACnCmE,IAAqB3E,GAAe6B,CAAAA;CAW1C,OACE,gBAAC7D,GAAAA;EACC+G,OAVF,kBAACF,QAAAA;GAAKC,WAAU;cACd,gBAAA,GAAA,EAAA,IAAA,SAAA,CAAA,GACA,gBAACD,QAAAA;IAAKC,WAAU;IAAyBC,OAAOxD,EAAUwB;cACvDxB,EAAUwB;;GAON6B;EACPI,MAAM1D;EACN2D,UAAUvB;EACVwB,oBAAoB9D,EAAAA,EAAC,EAAA,IAAA,SAAK,CAAA;EAC1B+D,WAAWf;EACXgB,mBAAmBhE,EAAAA,EAAC,EAAA,IAAA,SAAO,CAAA;EAC3BiE,MAAK;EACLC,sBAAsBhB,KAAU/B;aAE/Bc,EAAef,WACd,gBAACiD,KAAAA;GAAET,WAAU;oBACT;IACA,IAAMU,IAAenC,EAAeb,MAAMmB;IAC1C,OAAO,gBAAA,GAAA;;eAA+B6B,gBAAAA;;GACxC,GAAA;MAGJ,gBAACC,OAAAA;GAAIX,WAAU;;IAEb,gBAACW,OAAAA;KAAIX,WAAU;eACb,gBAACnG,GAAAA;MAAQ+G,SAAQ;MAAUZ,WAAU;gBACnC,gBAAA,GAAA,EAAA,IAAA,SAAA,CAAA;;;IAOHzC,IACC,gBAACnE,GAAAA;KAAMyH,WAAU;KAAaC,WAAU;KAASC,KAAI;KAAIf,WAAU;gBACjE,gBAAC3G,GAAAA,EAAQkH,MAAK,QAAA,CAAA,GACd,gBAAA,GAAA,EAAA,IAAA,SAAA,CAAA,CAAA;SAEA9C,IACF,gBAACgD,KAAAA;KAAET,WAAU;eAGF,gBAAA,GAAA;;gBAAuCU,cADzB/C,GAAWkB,WAAW,GAAA;;SAK/C,gBAAA,GAAA,EAAA,UACE,gBAAC8B,OAAAA;KAAIX,WAAU;gBAEb,gBAACW,OAAAA;MAAIX,WAAU;gBACb,gBAAC5G,GAAAA;OAAMyH,WAAU;OAAWE,KAAI;;QAE9B,gBAACJ,OAAAA,EAAAA,UAAAA;SACC,gBAACK,IAAAA,EAAcC,OAAO3E,EAAAA,EAAC,EAAA,IAAA,SAAU,CAAA,EAAA,CAAA;SACjC,gBAACnD,GAAAA;UACCkG,OAAO3D;UACPwF,UAAU9B;UACV+B,UAAU3B,KAAUvC;UACpBmE,aAAa9E,EAAAA,EAAC,EAAA,IAAA,SAAqB,CAAA;UACnC0D,WAAU;UACVqB,MAAM;;SAER,gBAAC/H,GAAAA;UACC2H,OAAO3E,EAAAA,EAAC,EAAA,IAAA,SAAmB,CAAA;UAC3B2C,SAAShC;UACTiE,UAAUlC;UACVmC,UAAU3B;UACVQ,WAAU;;;QAKd,gBAACW,OAAAA,EAAAA,UAAAA,CACC,gBAACK,IAAAA,EAAcC,OAAO3E,EAAAA,EAAC,EAAA,IAAA,SAAW,CAAA,EAAA,CAAA,GAClC,gBAACnD,GAAAA;SACCkG,OAAOtC;SACPmE,WAAWrF,MAAAA;UACT,IAAMwD,IAAQxD,EAAEqD,OAAOG;UACvBrC,EAAYqC,CAAAA;SACd;SACA8B,UAAU3B;SACV4B,aAAa9E,EAAAA,EAAC,EAAA,IAAA,SAAwB,CAAA;SACtC0D,WAAU;SACVqB,MAAM;;QAKT3B,MACC,gBAAClG,GAAAA;SACCyH,OAAO9D,IAAcb,EAAAA,EAAC,EAAA,IAAA,SAAkB,CAAA,IAAIA,EAAAA,EAAC,EAAA,IAAA,SAAkB,CAAA;SAC/DgF,eAAelE,GAAgBmE,MAAM,CAACA,CAAAA;SACtCX,SAAQ;SACRO,UAAU3B;SACVQ,WAAU;;QAKb7C,MAAgByC,EAAkBD,SAAS,KAAKE,EAAmBF,SAAS,MAC3E,gBAACvG,GAAAA;SAAMyH,WAAU;SAAWE,KAAI;oBAC7BnB,EAAkBD,SAAS,KAC1B,gBAACgB,OAAAA,EAAAA,UAAAA,CACC,gBAACF,KAAAA;UAAET,WAAU;oBACX,gBAAA,GAAA,EAAA,IAAA,SAAA,CAAA;aAEF,gBAACW,OAAAA;UAAIX,WAAU;oBACb,gBAAClG,GAAAA;WAAgBkG,WAAU;WAAcwB,YAAW;qBACjD5B,EAAkBxE,KAAKjB,GAAOsH,MAC7B,gBAAC1I,IAAAA,EAAAA,UAAAA,CACC,gBAACgB,GAAAA;YAAgBiG,WAAU;sBACzB,gBAACD,QAAAA;aAAKC,WAAU;aAAyBC,OAAO9F,EAAMD;uBACnDC,EAAMD;;eAGX,gBAACF,GAAAA;YAAsBgG,WAAU;uBAC/B,gBAACD,QAAAA;aAAKC,WAAU;aAAyBC,OAAO5D,GAAclC,CAAAA;uBAC3DkC,GAAclC,CAAAA;gBAEjB,gBAAC4F,QAAAA;aAAKC,WAAU;uBACb7F,EAAMI,gBACL,gBAAA,GAAA,EAAA,IAAA,SAAA,CAAA,IAEA,gBAAA,GAAA,EAAA,IAAA,SAAA,CAAA;;kBAdOkH,CAAAA,CAAAA;;iBAyBxB5B,EAAmBF,SAAS,KAC3B,gBAACgB,OAAAA,EAAAA,UAAAA,CACC,gBAACF,KAAAA;UAAET,WAAU;oBACX,gBAAA,GAAA,EAAA,IAAA,SAAA,CAAA;aAEF,gBAACW,OAAAA;UAAIX,WAAU;oBACb,gBAAClG,GAAAA;WAAgBkG,WAAU;WAAcwB,YAAW;qBACjD3B,EAAmBzE,KAAKjB,GAAOsH,MAC9B,gBAAC1I,IAAAA,EAAAA,UAAAA,CACC,gBAACgB,GAAAA;YAAgBiG,WAAU;sBACzB,gBAACD,QAAAA;aAAKC,WAAU;aAAyBC,OAAO9F,EAAMD;uBACnDC,EAAMD;;eAGX,gBAACF,GAAAA;YAAsBgG,WAAU;uBAC/B,gBAACD,QAAAA;aAAKC,WAAU;aAAyBC,OAAO5D,GAAclC,CAAAA;uBAC3DkC,GAAclC,CAAAA;gBAEjB,gBAAC4F,QAAAA;aAAKC,WAAU;uBACb7F,EAAMI,gBACL,gBAAA,GAAA,EAAA,IAAA,SAAA,CAAA,IAEA,gBAAA,GAAA,EAAA,IAAA,SAAA,CAAA;;kBAdOkH,CAAAA,CAAAA;;;;;;SA8BjC,gBAACd,OAAAA;MAAIX,WAAU;;OACb,gBAACS,KAAAA;QAAET,WAAU;kBACX,gBAAA,GAAA,EAAA,IAAA,SAAA,CAAA;;OAGF,gBAAC5G,GAAAA;QAAMyH,WAAU;QAAWE,KAAI;;SAC9B,gBAACW,GAAAA;UACCC,MAAK;UACLrH,aAAagC,EAAAA,EAAC,EAAA,IAAA,SAA0E,CAAA;;SAE1F,gBAACoF,GAAAA;UACCC,MAAK;UACLrH,aAAagC,EAAAA,EAAC,EAAA,IAAA,SAAuI,CAAA;;SAEvJ,gBAACoF,GAAAA;UACCC,MAAK;UACLrH,aAAagC,EAAAA,EAAC,EAAA,IAAA,SAAiD,CAAA;;SAEjE,gBAACoF,GAAAA;UAAWC,MAAK;UAAerH,aAAagC,EAAAA,EAAC,EAAA,IAAA,SAA6C,CAAA;;SAC3F,gBAACoF,GAAAA;UACCC,MAAK;UACLrH,aAAagC,EAAAA,EAAC,EAAA,IAAA,SAA6G,CAAA;;;;OAI/H,gBAACmE,KAAAA;QAAET,WAAU;kBACX,gBAAA,GAAA;;0CAEG4B,KAAAA;UACCC,MAAK;UACL3C,QAAO;UACP4C,KAAI;UACJ9B,WAAU;;;;;;;IAavB,CAACzC,KAAa,CAACE,KACd,gBAACgD,KAAAA;KAAET,WAAU;eACX,gBAAA,GAAA,EAAA,IAAA,SAAA,CAAA;;;;;AAMZ;AASA,SAAS0B,EAAW,EAAEC,SAAMrH,kBAA8B;CACxD,OACE,gBAACqG,OAAAA,EAAAA,UAAAA,CACC,gBAACpH,GAAAA;EAAMqH,SAAQ;EAAOZ,WAAU;YAC7B2B;KAEH,gBAAClB,KAAAA;EAAET,WAAU;YAA4C1F;;AAG/D;AAQA,SAAS0G,GAAc,EAAEC,YAA2B;CAClD,OACE,gBAACN,OAAAA;EAAIX,WAAU;aACb,gBAACiB,SAAAA;GAAMjB,WAAU;aAA4CiB;MAC7D,gBAACvH,GAAAA;GAAQqI,cAAa;cACpB,gBAACpI,GAAAA,EAAAA,UACC,gBAACF,GAAAA;IAAKuI,MAAK;IAAOzB,MAAK;IAAKP,WAAU;UAExC,gBAACpG,GAAAA;IAAeoG,WAAU;cACxB,gBAAA,GAAA,EAAA,IAAA,SAAA,CAAA;;;;AAQV;;;ACliBA,IAAaqD,MAAsB,EACjCC,eACAC,oBACAC,uBACAC,2BACAC,oBACAC,kBACAC,mBACAC,iBACAC,oBACAC,kBACAC,wBACAC,sBACAC,iBACAC,eACAC,uBACAC,0BACAC,sBAAmB,SACK;CACxB,IAAM,EAAEC,cAAWC,aAAUC,mBAAgBnC,GAAU,EACrDoC,MAAM,6DACR,CAAA,GAEM,EAAA,MAAA,GAAA,GAAA,MAAQC,EAAAA,GACRC,IAAWvC,EAAAA,GAEXwC,IAAY5C,GAAuB,IAAA,GACnC,CAAC6C,GAAgBC,KAAqB5C,EAAS,CAAA,GAC/C,CAAC6C,GAAqBC,MAA0B9C,EAAkC,IAAA,GAClF,CAAC+C,GAAsBC,MAA2BhD,EAAkC,IAAA,GACpF,CAACiD,GAA0BC,MAA+BlD,EAAkC,IAAA,GAC5F,CAACmD,IAA6BC,KAAkCpD,EAAkC,IAAA;CAGxGD,SAAU;EACR,AAAI2C,EAAUW,WAEZT,EADcF,EAAUW,QAAQE,cAAcb,EAAUW,QAAQG,WAC9CF;CAEtB,GAAG,CAACnC,EAAWsC,MAAAA,CAAO;CAGtB,IAAMC,KAAcC,MAAAA;EAClB,IAAI;GAEF,OAAOC,IADUC,KAAKF,CACfC,EAAKE,eAAc;EAC5B,QAAQ;GACN,OAAOC,EAAAA,EAAC,EAAA,IAAA,SAAI,CAAA;EACd;CACF,GAEMC,KAAiB/D,EAAe;EACpCgE,OAAO9C,EAAWsC;EAClBS,wBAAwBxB,EAAUW;EAClCc,oBAAoB;EACpBC,UAAU;CACZ,CAAA,GAEMC,MAAyBC,MAAAA;EAC7B,AAAIrC,EAAmBsC,SAASD,CAAAA,IAC9BpC,EAAsBD,EAAmBuC,QAAQC,MAASA,MAASH,CAAAA,CAAAA,IAEnEpC,EAAsB,CAAA,GAAID,GAAoBqC,CAAAA,CAAc;CAEhE;CAEA,IAAI,CAACnD,KAAcA,EAAWsC,WAAW,GACvC,OACE,gBAAA,GAAA,EAAA,UAAA,CACE,gBAACpD,GAAAA;EAASqE,SAAS;EAAGC,WAAU;EAAaC,eAAY;YACvD,gBAACrE,GAAAA,EAAAA,UACC,gBAACC,GAAAA;GAAaqE,SAAS;aACrB,gBAACC,OAAAA;IAAIH,WAAU;eACb,gBAACI,MAAAA;KAAGJ,WAAU;eACZ,gBAAA,GAAA,EAAA,IAAA,SAAA,CAAA;QAEF,gBAACK,KAAAA;KAAEL,WAAU;eACX,gBAAA,GAAA,EAAA,IAAA,SAAA,CAAA;;;;KASV,gBAAC9D,IAAAA;EACCoE,QAAQ7D;EACR8D,eAAe7D,EAAmB,EAAA;EAClC8D,WAAW5D;EACX6D,SAAS5D;EACeF;;CAShC,IAAM+D,KAAclD,IAAmB,IAAI,GACrCmD,KAAqBnD,IACvB,0FACA;CAEJ,OACE,gBAAA,GAAA,EAAA,UAAA;EACE,gBAAC2C,OAAAA;GAAIH,WAAU;cAEb,gBAACG,OAAAA;IAAIS,OAAO,EAAEC,cAAc,GAAG7C,EAAe,IAAI;cAChD,gBAACtC,GAAAA;KACCqE,SAASW;KACWC;KACpBX,WAAU;KACVC,eAAY;eAEZ,gBAACrE,GAAAA,EAAAA,UAAAA;MACE4B,KAAoB,gBAAC7B,GAAAA,CAAAA,CAAAA;MACtB,gBAACA,GAAAA,EAAAA,UACC,gBAAA,GAAA,EAAA,IAAA,SAAA,CAAA,EAAA,CAAA;MAEF,gBAACA,GAAAA,EAAAA,UACC,gBAAA,GAAA,EAAA,IAAA,SAAA,CAAA,EAAA,CAAA;MAEF,gBAACA,GAAAA,EAAAA,UACC,gBAAA,GAAA,EAAA,IAAA,SAAA,CAAA,EAAA,CAAA;MAEF,gBAACA,GAAAA,EAAAA,UACC,gBAAA,GAAA,EAAA,IAAA,SAAA,CAAA,EAAA,CAAA;MAEF,gBAACA,GAAAA,EAAiBiF,OAAO,EAAEE,aAAa,IAAI9C,EAAe,IAAI,EAAA,CAAA;;;OAMrE,gBAACmC,OAAAA;IACCY,KAAKhD;IACLiC,WAAU;IACVY,OAAO,EACLI,QAAQ,sBAGV;IACAf,eAAY;cAEZ,gBAACE,OAAAA;KACCS,OAAO;MACLI,QAAQ,GAAG3B,GAAe4B,aAAY,EAAG;MACzCtC,OAAO;MACPuC,UAAU;KACZ;eAEC7B,GAAe8B,gBAAe,EAAGC,KAAKC,MAAAA;MACrC,IAAMC,IAAY9E,EAAW6E,EAAWE,QAClCC,IAAalE,EAAmBsC,SAAS0B,EAAUxB,IAAI,GAEvD2B,UACJ3D,EAAS;OACP4D,IAAI;OACJC,QAAQ;QAAElE;QAAWC;QAAUC;QAAagC,eAAe2B,EAAUxB;OAAK;MAC5E,CAAA;MAEF,OACE,gBAACK,OAAAA;OAECyB,cAAYP,EAAWE;OACvBR,KAAK1B,GAAewC;OACpB7B,WAAU;OACVY,OAAO;QACLM,UAAU;QACVY,KAAK;QACLC,MAAM;QACNpD,OAAO;QACPqD,WAAW,cAAcX,EAAWY,MAAM;QAC1CC,SAAS;QACTC,qBAAqBxB;QACrByB,YAAY;OACd;OACAnC,eAAa,iBAAiBqB,EAAUxB;OACxCuC,MAAK;OACLC,UAAU;OACVC,SAASd;OACTe,YAAYC,MAAAA;QACV,CAAIA,EAAEC,QAAQ,WAAWD,EAAEC,QAAQ,SACjCD,EAAEE,eAAc,GAChBlB,EAAAA;OAEJ;;QAECjE,KACC,gBAAC3B,GAAAA;SACC0G,UAAUE,MAAMA,EAAEG,gBAAe;SACjCJ,YAAYC,MAAAA;UACV,CAAIA,EAAEC,QAAQ,WAAWD,EAAEC,QAAQ,QACjCD,EAAEG,gBAAe;SAErB;mBAEA,gBAACnH,GAAAA;UACCoH,SAASrB;UACTsB,gBAAgBpD,GAAsB4B,EAAUxB,IAAI;UACpDG,eAAa,oBAAoBqB,EAAUxB;;;QAIjD,gBAACjE,GAAAA;SAAamE,WAAU;mBACtB,gBAAC+C,QAAAA;UAAK/C,WAAU;UAAiBgD,OAAO1B,EAAUxB;oBAC/CwB,EAAUxB;;;QAGf,gBAACjE,GAAAA,EAAAA,UAAcyF,EAAUhC,MAAMH,eAAc,EAAA,CAAA;QAC7C,gBAACtD,GAAAA,EAAAA,UAAcyF,EAAU2B,gBAAgBlE,EAAWuC,EAAU2B,aAAa,IAAI7D,EAAAA,EAAC,EAAA,IAAA,SAAI,CAAA,EAAA,CAAA;QACpF,gBAACvD,GAAAA,EAAAA,UAAcI,EAAkBqF,EAAU4B,KAAK,EAAA,CAAA;QAChD,gBAACrH,GAAAA;SAAa0G,UAAUE,MAAMA,EAAEG,gBAAe;mBAC7C,gBAAC9G,GAAAA,EAAAA,UACC,gBAACE,GAAAA,EAAAA,UAAAA;UACC,gBAACD,GAAAA;WACCoH,OAAO/D,EAAAA,EAAC,EAAA,IAAA,SAAc,CAAA;WACtBmD,eAAe9D,EAA+B6C,CAAAA;WAC9CrB,eAAa,yBAAyBqB,EAAUxB;;UAElD,gBAAC/D,GAAAA;WACCoH,OAAO/D,EAAAA,EAAC,EAAA,IAAA,SAA0B,CAAA;WAClCmD,eAAehE,GAA4B+C,CAAAA;WAC3CrB,eAAa,qBAAqBqB,EAAUxB;;UAE9C,gBAAC/D,GAAAA;WACCoH,OAAO/D,EAAAA,EAAC,EAAA,IAAA,SAAM,CAAA;WACdmD,eAAepE,GAAuBmD,CAAAA;WACtCrB,eAAa,gBAAgBqB,EAAUxB;;UAEzC,gBAAC/D,GAAAA;WACCoH,OAAO/D,EAAAA,EAAC,EAAA,IAAA,SAAO,CAAA;WACfmD,eAAelE,GAAwBiD,CAAAA;WACvCrB,eAAa,iBAAiBqB,EAAUxB;;;;;SAtE3CwB,EAAUxB,IAAI;KA6EzB,CAAA;;;;EAKN,gBAAC5D,IAAAA;GACCoE,QAAQ7D;GACR8D,eAAe7D,EAAmB,EAAA;GAClC8D,WAAW5D;GACX6D,SAAS5D;GACeF;;EAG1B,gBAACR,GAAAA;GACCmE,QAAQpC,MAAwB;GAChCoD,WAAWpD;GACXqC,eAAepC,GAAuB,IAAA;GACtCqC,WAAW1D;GACX2D,SAAS1D;;EAGX,gBAACX,IAAAA;GACCkE,QAAQlC,MAAyB;GACjCkD,WAAWlD;GACXmC,eAAelC,GAAwB,IAAA;GACvCmC,WAAWxD;GACXyD,SAASxD;;EAGX,gBAACZ,GAAAA;GACCiE,QAAQhC,MAA6B;GACrCgD,WAAWhD;GACXiC,eAAehC,GAA4B,IAAA;GAC3CiC,WAAWtD;GACXuD,SAAStD;;EAGX,gBAACb,GAAAA;GACCgE,QAAQ9B,OAAgC;GACxC8C,WAAW9C;GACX+B,eAAe9B,EAA+B,IAAA;GAC9C+B,WAAWpD;GACXqD,SAASpD;;;AAIjB;;;ACnUA,SAAgBgG,EAAiB,EAAEC,UAAOC,kBAAoC;CAC5E,OACE,gBAACH,GAAAA;EAAMI,WAAU;EAAWC,KAAI;aAC9B,gBAACC,QAAAA,EAAAA,UAAMJ,EAAAA,CAAAA,GACP,gBAACI,QAAAA;GAAKC,WAAU;aAAoBJ;;;AAG1C;AAMA,IAAaK,MAA4BC,GAAuBC,OAAqC;CACnGC,SAAS;CACTC,UACE,gBAACX,GAAAA;EACCC,OAAO,gBAAA,GAAA,EAAA,IAAA,SAAA,CAAA;EACPC,aAAa,gBAAA,GAAA;;aAAmBM,iBAAAA;;;CAGpCI,WAAWH,EAAOG;AACpB,IAEaC,MACXL,GACAM,GACAL,OACgB;CAChBC,SAAS;CACTC,UACE,gBAACX,GAAAA;EACCC,OAAO,gBAAA,GAAA,EAAA,IAAA,SAAA,CAAA;EACPC,aACE,gBAAA,GAAA;;;IAC+BM;IAAkBM;;;;CAKvDF,WAAWH,EAAOG;AACpB,IAEaG,MACXP,GACAQ,GACAP,OACgB;CAChBC,SAAS;CACTC,UACE,gBAACX,GAAAA;EACCC,OAAO,gBAAA,GAAA,EAAA,IAAA,SAAA,CAAA;EACPC,aACEc,MAAiB,IACf,gBAAA,GAAA;;aAAmBR,iBAAAA;OACjBQ,MAAiB,IACnB,gBAAA,GAAA;;;IACcR;IAA2CQ;;OAGzD,gBAAA,GAAA;;;IACcR;IAA2CQ;;;;CAMjEJ,WAAWH,EAAOG;AACpB,IAEaK,MACXT,GACAM,GACAL,OACgB;CAChBC,SAAS;CACTC,UACE,gBAACX,GAAAA;EACCC,OAAO,gBAAA,GAAA,EAAA,IAAA,SAAA,CAAA;EACPC,aACE,gBAAA,GAAA;;;IAC8BM;IAAkBM;;;;CAKtDF,WAAWH,EAAOG;AACpB,IAEaM,MAA4BV,GAAuBC,OAAqC;CACnGC,SAAS;CACTC,UACE,gBAACX,GAAAA;EACCC,OAAO,gBAAA,GAAA,EAAA,IAAA,SAAA,CAAA;EACPC,aAAa,gBAAA,GAAA;;aAAmBM,iBAAAA;;;CAGpCI,WAAWH,EAAOG;AACpB,IAEaO,MACXX,GACAM,GACAL,OACgB;CAChBC,SAAS;CACTC,UACE,gBAACX,GAAAA;EACCC,OAAO,gBAAA,GAAA,EAAA,IAAA,SAAA,CAAA;EACPC,aACE,gBAAA,GAAA;;;IAC+BM;IAAkBM;;;;CAKvDF,WAAWH,EAAOG;AACpB,IAEaQ,MAA4BZ,GAAuBC,OAAqC;CACnGC,SAAS;CACTC,UACE,gBAACX,GAAAA;EACCC,OAAO,gBAAA,GAAA,EAAA,IAAA,SAAA,CAAA;EACPC,aAAa,gBAAA,GAAA;;aAAmBM,iBAAAA;;;CAGpCI,WAAWH,EAAOG;AACpB,IAEaS,MACXb,GACAM,GACAL,OACgB;CAChBC,SAAS;CACTC,UACE,gBAACX,GAAAA;EACCC,OAAO,gBAAA,GAAA,EAAA,IAAA,SAAA,CAAA;EACPC,aACE,gBAAA,GAAA;;;IAC+BM;IAAkBM;;;;CAKvDF,WAAWH,EAAOG;AACpB,IAEaU,MAA+Bd,GAAuBC,OAAqC;CACtGC,SAAS;CACTC,UACE,gBAACX,GAAAA;EACCC,OAAO,gBAAA,GAAA,EAAA,IAAA,SAAA,CAAA;EACPC,aAAa,gBAAA,GAAA;;aAA4BM,iBAAAA;;;CAG7CI,WAAWH,EAAOG;AACpB,IAEaW,MACXf,GACAM,GACAL,OACgB;CAChBC,SAAS;CACTC,UACE,gBAACX,GAAAA;EACCC,OAAO,gBAAA,GAAA,EAAA,IAAA,SAAA,CAAA;EACPC,aACE,gBAAA,GAAA;;;IACwCM;IAAkBM;;;;CAKhEF,WAAWH,EAAOG;AACpB,IAwCagB,MACXH,GACAC,GACAG,GACApB,MAAAA;CAEA,IAAMqB,IAAYD,EAAOE,SAAS,GAC5BC,IAAaP,IAAe,GAC5BQ,IAAYH,KAAaE;CAE/B,OAAO;EACLtB,SAASuB,IAAY,YAAYH,IAAY,UAAU;EACvDnB,UACE,gBAACX,GAAAA;GACCC,OACEgC,IACE,gBAAA,GAAA,EAAA,IAAA,SAAA,CAAA,IACEH,IACF,gBAAA,GAAA,EAAA,IAAA,SAAA,CAAA,IAEA,gBAAA,GAAA,EAAA,IAAA,SAAA,CAAA;GAGJ5B,aACE,gBAACH,GAAAA;IAAMI,WAAU;IAAWC,KAAI;eAC7B4B,KACC,gBAAC3B,QAAAA,EAAAA,UACC,gBAAA,GAAA;;;MACiBoB;MACAC;;WAIpBI,KACC,gBAACzB,QAAAA;KAAKC,WAAU;eAGL,gBAAA,GAAA;;gBAAgB4B,cADFL,EAAOM,KAAK,IACVD,EAAAA;;;;;EAQrCtB,WAAWH,EAAOG;CACpB;AACF,GClQM6B,KAAa,EAAEC,UAAOC,eACtBA,KAAiC,OAAa,OAEhD,gBAACE,QAAAA;CAAKC,WAAU;YACd,gBAACP,GAAAA;EAAKQ,MAAK;EAAQC,MAAK;EAAOF,WAAU;KACzC,gBAACD,QAAAA,EAAAA,UAAAA;EACC,gBAACA,QAAAA;GAAKC,WAAU;cAAeJ,GAAM,GAAA;;EAAQ;EAAEC;;IAMjDM,MAAkB,EAAEP,eACxB,gBAACG,QAAAA;CAAKC,WAAU;YACd,gBAACP,GAAAA;EAAKQ,MAAK;EAAQC,MAAK;EAAOF,WAAU;KACzC,gBAACD,QAAAA,EAAAA,UAAMH,EAAAA,CAAAA,CAAAA;IAILQ,MAAW,EAAEC,UAAOC,kBACxB,gBAACP,QAAAA;CAAKC,WAAU;YACd,gBAACD,QAAAA;EAAKC,WAAU;YAA0CK;KACzDC,CAAAA;IAIQC,MAA0B,EAAEC,gBAAaC,gBAAaC,cAAmC;CACpG,IAAM,EAAA,MAAA,GAAA,GAAA,MAAQC,EAAAA,GAERC,IAAQJ,GAAaI,OAErBC,IAAgB;EACpBC,gBAAgBC,EAAAA,EAAC,EAAA,IAAA,SAAe,CAAA;EAChCC,kBAAkBD,EAAAA,EAAC,EAAA,IAAA,SAAiB,CAAA;EACpCE,aAAaF,EAAAA,EAAC,EAAA,IAAA,SAAwB,CAAA;EACtCG,aAAaH,EAAAA,EAAC,EAAA,IAAA,SAA6B,CAAA;EAC3CI,KAAKJ,EAAAA,EAAC,EAAA,IAAA,SAA4B,CAAA;EAClCK,gBAAgBL,EAAAA,EAAC,EAAA,IAAA,SAAkB,CAAA;EACnCM,SAASN,EAAAA,EAAC,EAAA,IAAA,SAAe,CAAA;EACzBO,SAASP,EAAAA,EAAC,EAAA,IAAA,SAAS,CAAA;EACnBQ,kBAAkBR,EAAAA,EAAC,EAAA,IAAA,SAAiB,CAAA;CACtC,GAEMS,IAAeC,OAAOC,QAAQb,CAAAA,EACjCc,QAAQ,CAACC,OAAShB,IAAQgB,EAA0B,EACpDC,KAAK,GAAGjC,OAAWA,CAAAA;CAEtB,OACE,gBAACN,GAAAA;EAAQwC,cAAa;EAAQC,WAAU;EAAmBrB;aACzD,gBAACnB,GAAAA;GAAeyC,SAAO;aACrB,gBAACvC,GAAAA;IAAKQ,MAAK;IAAOC,MAAK;IAAOF,WAAU;;MAE1C,gBAACR,GAAAA;GAAeQ,WAAU;aACxB,gBAACD,QAAAA;IAAKC,WAAU;;KAEbS,KACC,gBAACL,IAAAA;MAAQC,OAAO,gBAAA,GAAA,EAAA,IAAA,SAAA,CAAA;;OACd,gBAACV,GAAAA;QAAUC,OAAOmB,EAAAA,EAAC,EAAA,IAAA,SAAW,CAAA;QAAGlB,OAAOY,EAAYwB,eAAeC,eAAc;;OACjF,gBAACvC,GAAAA;QAAUC,OAAOmB,EAAAA,EAAC,EAAA,IAAA,SAAQ,CAAA;QAAGlB,OAAOY,EAAY0B,YAAYD,eAAc;;OAC3E,gBAACvC,GAAAA;QAAUC,OAAOmB,EAAAA,EAAC,EAAA,IAAA,SAAK,CAAA;QAAGlB,OAAOH,EAAkBe,EAAY2B,SAAS;;OACxE3B,EAAY4B,eAAevC,KAAAA,KAC1B,gBAACH,GAAAA;QAAUC,OAAOmB,EAAAA,EAAC,EAAA,IAAA,SAAM,CAAA;QAAGlB,OAAOH,EAAkBe,EAAY4B,UAAU;;;;KAMhFzB,KACC,gBAACR,IAAAA;MAAQC,OAAO,gBAAA,GAAA,EAAA,IAAA,SAAA,CAAA;;OACd,gBAACV,GAAAA;QACCC,OAAOmB,EAAAA,EAAC,EAAA,IAAA,SAAc,CAAA;QACtBlB,OAAOe,EAAM0B,kBAAkBxC,KAAAA,IAAqDA,KAAAA,IAAzCJ,EAAkBkB,EAAM0B,aAAa;;OAElF,gBAAC3C,GAAAA;QAAUC,OAAOmB,EAAAA,EAAC,EAAA,IAAA,SAA0B,CAAA;QAAGlB,OAAOe,EAAM2B;;OAC7D,gBAAC5C,GAAAA;QAAUC,OAAOmB,EAAAA,EAAC,EAAA,IAAA,SAAuB,CAAA;QAAGlB,OAAOe,EAAM4B;;OAC1D,gBAAC7C,GAAAA;QAAUC,OAAOmB,EAAAA,EAAC,EAAA,IAAA,SAAwB,CAAA;QAAGlB,OAAOe,EAAM6B,yBAAyBP,eAAAA;;OACpF,gBAACvC,GAAAA;QAAUC,OAAOmB,EAAAA,EAAC,EAAA,IAAA,SAAsB,CAAA;QAAGlB,OAAOe,EAAM8B,uBAAuBR,eAAAA;;OAChF,gBAACvC,GAAAA;QAAUC,OAAOmB,EAAAA,EAAC,EAAA,IAAA,SAAgB,CAAA;QAAGlB,OAAOe,EAAM+B;;OACnD,gBAAChD,GAAAA;QAAUC,OAAOmB,EAAAA,EAAC,EAAA,IAAA,SAAe,CAAA;QAAGlB,OAAOe,EAAMgC;;OAClD,gBAACjD,GAAAA;QAAUC,OAAOmB,EAAAA,EAAC,EAAA,IAAA,SAAqB,CAAA;QAAGlB,OAAOe,EAAMiC;;OACxD,gBAAClD,GAAAA;QAAUC,OAAOmB,EAAAA,EAAC,EAAA,IAAA,SAAsB,CAAA;QAAGlB,OAAOe,EAAMkC;;OACzD,gBAACnD,GAAAA;QAAUC,OAAOmB,EAAAA,EAAC,EAAA,IAAA,SAAsB,CAAA;QAAGlB,OAAOe,EAAMmC;;OACxDnC,EAAMK,eACL,gBAACtB,GAAAA;QACCC,OAAOmB,EAAAA,EAAC,EAAA,IAAA,SAAwB,CAAA;QAChClB,OAAOe,EAAMK,YAAY+B,wBAAwBd,eAAc;;OAGlEtB,EAAMM,eACL,gBAACvB,GAAAA;QACCC,OAAOmB,EAAAA,EAAC,EAAA,IAAA,SAA8B,CAAA;QACtClB,OAAOe,EAAMM,YAAY+B,8BAA8Bf,eAAc;;OAGxEtB,EAAMO,OACL,gBAACxB,GAAAA;QAAUC,OAAOmB,EAAAA,EAAC,EAAA,IAAA,SAAiB,CAAA;QAAGlB,OAAOe,EAAMO,IAAI+B,sBAAsBhB,eAAc;;;;KAMjGV,EAAa2B,SAAS,KACrB,gBAAC/C,IAAAA;MAAQC,OAAO,gBAAA,GAAA,EAAA,IAAA,SAAA,CAAA;gBACbmB,EAAaK,KAAKuB,MACjB,gBAACjD,IAAAA,EAAyBP,OAAOwD,EAAAA,GAAZA,CAAAA,CAAAA;;;;;;AAQrC,GC7GMc,KAAc,IAMdC,KAAe,SAeRC,MAAwB,EAAEC,WAAQC,eAAYC,YAASC,oBAAuC;CACzG,IAAM,EAAA,MAAA,GAAKC,SAAI,GAAA,MAAKC,EAAAA,GACdC,IAAYV,EAAAA,GAEZ,CAACW,GAAUC,KAAexB,EAAoD,IAAA,GAC9E,CAACyB,GAAcC,KAAmB1B,EAAS,EAAA,GAC3C2B,IAAcF,EAAaG,KAAI,MAAOd,IAEtCe,IAAQ1B,EAAU2B,SAAQ,GAE1BC,IAAyB5B,EAAU6B,QAAQC,MAAMC,eAAeC,YAAW,GAE3EC,UAAc;EAIlBlB,AAHAa,EAAuBM,MAAK,GAC5Bb,EAAY,IAAA,GACZE,EAAgB,EAAA,GAChBR,EAAAA;CACF,GAEMoB,IAAgB,YAAA;EACpB,IAAIC,IAAe,GACfC,IAAe,GACbC,IAAmB,CAAA,GACnBC,IAAQzB,EAAW0B;EAEzB,KAAK,IAAIC,IAAI,GAAGA,IAAI3B,EAAW0B,QAAQC,KAAK;GAC1CpB,EAAY;IAAEqB,SAASD,IAAI;IAAGF;GAAM,CAAA;GACpC,IAAMI,IAAY7B,EAAW2B;GAE7B,IAAI;IACF,IAAMG,IAAU,MAAMhB,EAAuBiB,YAAY;KAAEC,YAAY3B;KAAWwB,WAAWA,EAAUI;IAAK,CAAA;IAE5GX,AADAC,KAAgBO,GAChBR;GACF,SAASY,GAAK;IACZ,IAAMC,IAAUD,aAAeE,QAAQF,EAAIC,UAAUE,OAAOH,CAAAA;IAC5DV,EAAOc,KAAK,GAAGT,EAAUI,KAAK,IAAIE,GAAS;GAC7C;EACF;EAQAhB,AANIG,IAAe,KACjB,MAAMV,EAAMG,QAAQC,MAAMuB,eAAeC,WAAU,GAGrDtC,IAAa;GAAEoB;GAAcC;GAAcC;EAAO,CAAA,GAElDL,EAAAA;CACF;CAEA,IAAI,CAACpB,KAAUC,EAAW0B,WAAW,GAAG,OAAO;CAE/C,IAAMe,IAAazC,EAAW0B,QACxBgB,IAAoB1C,EAAW2C,MAAM,GAAG/C,EAAAA,GACxCgD,IAAcH,IAAaC,EAAkBhB,QAC7CmB,IAAY/B,EAAuB+B,aAAavC,MAAa,MAC7DwC,IAAkBxC,GAAUsB,SAC5BmB,IAAgBzC,GAAUmB;CAEhC,OACE,gBAACtC,GAAAA;EACC6D,OAAO,gBAAA,GAAA;;aAAeP,cAAAA;;EACtBQ,MAAMlD;EACNmD,UAAU/B;EACVgC,oBAAoBN,IAAYO,EAAAA,EAAC,EAAA,IAAA,SAAY,CAAA,IAAIA,EAAAA,EAAC,EAAA,IAAA,SAAM,CAAA;EACxDC,sBAAqB;EACrBC,mBAAmBF,EAAAA,EAAC,EAAA,IAAA,SAAO,CAAA;EAC3BG,WAAWlC;EACXmC,sBAAsBX,KAAa,CAACnC;EACpC+C,qBAAqBZ;EACrBa,oBAAoBb;EACpBc,MAAK;YAEJd,IACC,gBAACxD,GAAAA;GAAMuE,WAAU;GAAWC,cAAa;GAASC,WAAU;GAASC,KAAI;GAAIC,WAAU;cACrF,gBAAC5E,GAAAA,EAAQ6E,SAAQ,UAAA,CAAA,GAChB3D,KACC,gBAAC4D,KAAAA;IAAEF,WAAU;cACX,gBAAA,GAAA;;;MACsBlB;MAAqBC;;;;OAMjD,gBAACoB,OAAAA;GAAIH,WAAU;;IACb,gBAAC1E,GAAAA;KAAQ2E,SAAQ;KAASD,WAAU;eAClC,gBAAA,GAAA,EAAA,IAAA,SAAA,CAAA;;IAGF,gBAACE,KAAAA;KAAEF,WAAU;eACX,gBAAA,GAAA;;;0BACOI,UAAAA,CAAAA,CAAAA;0BAA6BA,UAAAA,CAAAA,CAAAA;;;;IAKtC,gBAACD,OAAAA;KAAIH,WAAU;gBACb,gBAACK,MAAAA;MAAGL,WAAU;gBACZ,gBAAA,GAAA;;iBAAkCvB,cAAAA;;SAEpC,gBAAC0B,OAAAA;MAAIH,WAAU;iBACb,gBAACxE,GAAAA;OAAgBwE,WAAU;OAAcM,YAAW;iBACjD5B,EAAkB6B,KAAK1C,MAAAA;QACtB,IAAM2C,IAAQ3C,EAAU2C;QACxB,OACE,gBAACxF,IAAAA,EAAAA,UAAAA,CACC,gBAACS,GAAAA;SAAgBuE,WAAU;mBACzB,gBAACS,QAAAA;UAAKT,WAAU;UAAiBhB,OAAOnB,EAAUI;oBAC/CJ,EAAUI;;YAGf,gBAACvC,GAAAA;SAAsBsE,WAAU;mBAC/B,gBAACS,QAAAA;UAAKT,WAAU;oBACbQ,KAAS,OAAwE,KAAjErE,EAAKuE,EAAEC,EAAAA,EAAOH;;qBAAAA,SAAAA;UAAI,CAAA,CAAA;;eAR1B3C,EAAUI,IAAI;OAajC,CAAA;UAEDW,IAAc,KACb,gBAACsB,KAAAA;OAAEF,WAAU;iBACX,gBAAA,GAAA;;kBAAgBpB,eAAAA;;;;;IAMxB,gBAACrD,GAAAA;KACCqF,OAAOxB,EAAAA,EAAC,EAAA,IAAA,SAAwB,CAAA;KAChCyB,aAAahF;KACbiF,OAAOtE;KACPuE,WAAWC,MAA2CvE,EAAgBuE,EAAEC,OAAOH,KAAK;;;;;AAMhG,GCvIauC,WAAkB;CAC7B,IAAM,EAAA,MAAA,GAAKC,SAAI,GAAA,MAAKC,EAAAA,GACdC,IAAYJ,EAAAA,GACZK,IAAWP,EAAY,EAAEQ,MAAMP,EAAMQ,SAAS,CAAA,GAI9C,EAAEC,WAAQC,kBAAeC,QAAQC,IAAc,OAAOZ,EAAMa,UAAS,GAWrE,CAACE,GAAiBC,KAAsBjD,EAAS,EAAA,GACjD,CAACkD,GAAmBC,KAAwBnD,EAAS,EAAA,GACrD,CAACoD,GAAoBC,KAAyBrD,EAAmB,CAAA,CAAE,GACnE,CAACsD,GAAWC,KAAgBvD,EAA4B,IAAA,GAIxD,CAACwD,GAAiBC,KAAsBzD,EAAS6C,CAAAA,GACjDa,IAAgBxD,GAA2ByD,KAAAA,CAAAA;CAQjD1D,AAPAA,eAAsB2D,aAAaF,EAAcG,OAAO,GAAG,CAAA,CAAE,GAO7D5D,SAAU;EACRwD,EAAmBZ,CAAAA;CACrB,GAAG,CAACA,CAAAA,CAAY;CAEhB,IAAMiB,UAA2BP,EAAa,IAAA,GAExCQ,KAAuBC,MAAAA;EAC3BT,EAAapC,GAAyB6C,GAAe,EAAEC,WAAWH,EAAmB,CAAA,CAAA;CACvF,GAEMI,KAAqBF,GAAuBG,MAAAA;EAChDZ,EAAanC,GAA6B4C,GAAeG,GAAc,EAAEF,WAAWH,EAAmB,CAAA,CAAA;CACzG,GAEMM,MAAsBJ,GAAuBK,MAAAA;EACjDd,EAAalC,GAAyB2C,GAAeK,GAAc,EAAEJ,WAAWH,EAAmB,CAAA,CAAA;CACrG,GAEMQ,KAAoBN,GAAuBG,MAAAA;EAC/CZ,EAAajC,GAA4B0C,GAAeG,GAAc,EAAEF,WAAWH,EAAmB,CAAA,CAAA;CACxG,GAEMS,MAAuBP,MAAAA;EAC3BT,EAAahC,GAAyByC,GAAe,EAAEC,WAAWH,EAAmB,CAAA,CAAA;CACvF,GAEMU,KAAqBR,GAAuBG,MAAAA;EAChDZ,EAAa/B,GAA6BwC,GAAeG,GAAc,EAAEF,WAAWH,EAAmB,CAAA,CAAA;CACzG,GAEMW,MAA2BT,MAAAA;EAC/BT,EAAa9B,GAAyBuC,GAAe,EAAEC,WAAWH,EAAmB,CAAA,CAAA;CACvF,GAEMY,KAAyBV,GAAuBG,MAAAA;EACpDZ,EAAa7B,GAA6BsC,GAAeG,GAAc,EAAEF,WAAWH,EAAmB,CAAA,CAAA;CACzG,GAEMa,MAAoBX,MAAAA;EACxBT,EAAa5B,GAA4BqC,GAAe,EAAEC,WAAWH,EAAmB,CAAA,CAAA;CAC1F,GAEMc,KAAkBZ,GAAuBG,MAAAA;EAC7CZ,EAAa3B,GAAgCoC,GAAeG,GAAc,EAAEF,WAAWH,EAAmB,CAAA,CAAA;CAC5G,GAEMe,MAA0B,EAC9BC,iBACAC,iBACAC,gBAKD;EACC,IAAIA,EAAOC,WAAW,GACpB5B,EAAsB,CAAA,CAAE;OACnB;GAIL,IAAM6B,IAAuB,IAAIC,IAAIH,EAAOI,KAAKC,MAAMA,EAAEC,MAAM,IAAA,EAAM,EAAE,CAAA;GACvEjC,GAAuBkC,MAASA,EAAKC,QAAQC,MAASP,EAAqBQ,IAAID,CAAAA,CAAAA,CAAAA;EACjF;EACAlC,EAAa1B,GAAgCiD,GAAcC,GAAcC,GAAQ,EAAEf,WAAWH,EAAmB,CAAA,CAAA;CACnH,GAEM6B,IAA6B;EACjCC,SAAS;GACP;IAAEC,OAAOC,EAAAA,EAAC,EAAA,IAAA,SAAK,CAAA;IAAGC,OAAO;GAAO;GAChC;IAAEF,OAAOC,EAAAA,EAAC,EAAA,IAAA,SAAa,CAAA;IAAGC,OAAO;GAAQ;GACzC;IAAEF,OAAOC,EAAAA,EAAC,EAAA,IAAA,SAAW,CAAA;IAAGC,OAAO;GAAQ;GACvC;IAAEF,OAAOC,EAAAA,EAAC,EAAA,IAAA,SAAc,CAAA;IAAGC,OAAO;GAAgB;;EAEpDrD,QAAQA,KAAU;EAClBC,eAAeA,KAAiB;CAClC,GAGM,EACJqD,MAAMC,IACNC,eACAC,cACE9F,EAAU+F,QAAQC,MAAMC,eAAeC,SAAS;EAClDC,YAAYlE;EACZmE,QAAQ;CACV,CAAA,GAGM,EAAET,MAAMU,OAAgBrG,EAAU+F,QAAQC,MAAMM,mBAAmBJ,SAAS,EAChFC,YAAYlE,EACd,CAAA,GAGM,EAAE0D,MAAMY,MAAgBvG,EAAU+F,QAAQC,MAAMQ,eAAeN,SAAQ,GAGvEO,MAAkBb,MACf,CAAA,GAAIA,CAAAA,EAAYc,MAAMC,GAAGC,MAAAA;EAC9B,IAAIC;EAEJ,QAAQxE,KAAU,QAAlB;GACE,KAAK;IACHwE,IAAaF,EAAEvB,KAAK0B,cAAcF,EAAExB,IAAI;IACxC;GACF,KAAK;IACHyB,IAAaF,EAAEI,QAAQH,EAAEG;IACzB;GACF,KAAK;IACHF,IAAaF,EAAEK,QAAQJ,EAAEI;IACzB;GACF,KAAK;IACH,IAAI,CAACL,EAAEM,iBAAiB,CAACL,EAAEK,eACzB,OAAON,EAAEM,gBAAgB,KAAK;IAEhCJ,IAAa,IAAIK,KAAKP,EAAEM,aAAa,EAAEE,QAAO,IAAK,IAAID,KAAKN,EAAEK,aAAa,EAAEE,QAAO;IACpF;GACF,SACEN,IAAaF,EAAEvB,KAAK0B,cAAcF,EAAExB,IAAI;EAC5C;EAEA,QAAQ9C,KAAiB,WAAW,SAAS,CAACuE,IAAaA;CAC7D,CAAA,GAIIO,MAAsBxB,MAAc,CAAA,GAAIT,QAAQkC,MACpDA,EAAUjC,KAAKkC,YAAW,EAAGC,SAAS/E,EAAY8E,YAAW,CAAA,CAAA,GAIzDE,KAAmBf,GAAeW,EAAAA,GAElCK,MAAsBC,MAAAA;EAC1B,IAAMhC,IAAQ,OAAOgC,KAAS,WAAWA,IAAO;EAChD5H,SAAgB;GACdoC,EAAS,EACPK,SAAS2C,OAAU;IAAE,GAAGA;IAAM3C,QAAQmD,KAASpC,KAAAA;GAAU,GAC3D,CAAA;EACF,CAAA;CACF,GAEMqE,MAAoBC,MAAAA;EACxB,IAAMC,IAAkBD,EAAgBvF,QAAQyF,SAAAA,KAAc,QAKxDC,IAAqBH,EAAgBtF,iBAAiB;EAC5DxC,SAAgB;GACdoC,EAAS,EACPK,SAAS2C,OAAU;IACjB,GAAGA;IACH7C,QAAQwF;IACRvF,eAAeyF;GACjB,GACF,CAAA;EACF,CAAA;CACF;CAGA,IAAIlC,IACF,OACE,gBAACnF,GAAAA;EAAMsH,WAAU;EAAmBC,cAAa;EAASC,WAAU;EAASC,WAAU;aACrF,gBAAC1H,GAAAA;GAAQ2H,SAAQ;GAAUC,MAAK;GAAQL,WAAU;MAClD,gBAAA,GAAA,EAAA,IAAA,SAAA,CAAA,CAAA;;CAMN,IAAIlC,IAAO;EACT,IAAMhC,IAAegC,GAAMwC;EAE3B,OACE,gBAAC5H,GAAAA;GAAMsH,WAAU;GAAmBC,cAAa;GAASC,WAAU;GAASC,WAAU;aACrF,gBAAA,GAAA;;cAAkCrE,gBAAAA;;;CAGxC;CAGA,IAAMyE,KAAYlC,IAAakC,aAAa,GACtCC,KAAanC,IAAamC,cAAc,GACxCC,IAAiBD,KAAa,IAAIA,KAAaD,KAAY,GAK3DG,KAA8B9C,MAAc,CAAA,GAAIT,QAAQwD,MAAM5F,EAAmBwE,SAASoB,EAAEvD,IAAI,CAAA,GAChGwD,KAAeF,EAA2B9D,SAAS,GACnDiE,IAAgBH,EAA2B9D,QAE3CkE,KAAclD,MAAc,CAAA,GAAIhB,QAChCmE,KAAgB3B,GAAmBxC,QACnCoE,KAAaD,OAAkBD,GAG/BG,KAAiBzB,GAAiBzC,KAAK4D,MAAMA,EAAEvD,IAAI,GACnD8D,KAAcD,GAAerE,SAAS,KAAKqE,GAAeE,OAAOC,MAAMrG,EAAmBwE,SAAS6B,CAAAA,CAAAA,GACnGC,KAAeJ,GAAeK,MAAMF,MAAMrG,EAAmBwE,SAAS6B,CAAAA,CAAAA;CAU5E,OACE,gBAACI,OAAAA;EAAIxB,WAAU;;GACb,gBAACtH,GAAAA;IAAMyH,WAAU;;KAEf,gBAACzH,GAAAA;MAAMuH,cAAa;MAAMC,WAAU;MAASuB,KAAI;MAAIzB,WAAU;iBAC7D,gBAACtH,GAAAA;OAAM+I,KAAI;OAAMvB,WAAU;iBACzB,gBAACnI,IAAAA;QACCwF,SAASD,EAAaC;QACtBlD,QAAQiD,EAAajD;QACrBC,eAAegD,EAAahD,iBAAiB;QAC7CoH,iBAAiBC,MACfhC,GAAiB;SAAE,GAAGrC;SAAcjD,QAAQsH;SAAGrH,eAAegD,EAAahD;QAAc,CAAA;QAE3FsH,wBAAwBC,MAAQlC,GAAiB;SAAE,GAAGrC;SAAchD,eAAeuH;QAAI,CAAA;;UAG3F,gBAAC5J,GAAAA;OAAOmI,SAAQ;OAAUJ,WAAU;OAAoB8B,eAAelH,EAAmB,EAAA;iBACxF,gBAAA,GAAA,EAAA,IAAA,SAAA,CAAA;;;KAUJ,gBAACzC,GAAAA,EAAAA,UACC,gBAACO,GAAAA;MAAMyH,WAAU;MAAWsB,KAAI;gBAC9B,gBAAC/I,GAAAA;OAAMuH,cAAa;OAAMC,WAAU;iBAClC,gBAAC1H,GAAAA;QACCuJ,aAAatE,EAAAA,EAAC,EAAA,IAAA,SAAqB,CAAA;QACnCuE,eAAY;QACZtE,OAAOvC;QACP8G,UAAUjF,MAAAA;SACR,IAAM2E,IAAI3E,EAAEkF,cAAcxE;SAG1BrC,AAFAD,EAAmBuG,CAAAA,GACnBpG,aAAaF,EAAcG,OAAO,GAClCH,EAAcG,UAAU2G,OAAOC,iBAAiB3C,GAAmBkC,CAAAA,GAAI,GAAA;QACzE;QACAU,WAAWV,MAAAA;SAETlC,AADAlE,aAAaF,EAAcG,OAAO,GAClCiE,GAAmB,OAAOkC,KAAM,WAAWA,IAAI,EAAA;QACjD;QACAW,eAAS;SAGP7C,AAFAlE,aAAaF,EAAcG,OAAO,GAClCJ,EAAmB,EAAA,GACnBqE,GAAmB,EAAA;QACrB;;;;KAWR,gBAACtH,GAAAA,EAAAA,UACC,gBAACO,GAAAA;MAAMuH,cAAa;MAAQwB,KAAI;MAAIvB,WAAU;MAASF,WAAU;iBAE7D,gBAACtH,GAAAA;OAAM+I,KAAI;OAAIvB,WAAU;kBACvB,gBAAChI,GAAAA;QACCqK,SAASrB;QACTsB,eAAenB,MAAgB,CAACH;QAChCuB,gBA1Ec;SAC5B,AACEzH,EADEkG,MACqBhE,MAASA,EAAKC,QAAQiE,MAAM,CAACH,GAAe1B,SAAS6B,CAAAA,CAAAA,KAErDlE,MAAS,CAAA,GAAI,IAAIJ,IAAI,CAAA,GAAII,GAAAA,GAAS+D,EAAAA,CAAe,CAAA,CAAE;QAE9E;WAsEc,gBAAC7I,GAAAA;QAAU4H,WAAU;mBACnB,gBAACzH,GAAAA;SAAgBmK,IAAG;mBAClB,gBAACzK,GAAAA;UAAO0K,UAAU,CAAC/B;UAAcP,MAAK;UAAQuC,MAAK;UAAWpF,OAAOC,EAAAA,EAAC,EAAA,IAAA,SAAQ,CAAA;;YAE/EmD,MACC,gBAACtI,GAAAA,EAAAA,UACC,gBAACD,GAAAA;SACCsK,UAAU,CAAC/B;SACXpD,OAAOzD,EAAK8I,EACVC,EAAAA,EAAOjC;;oBAAAA,iBAAAA;SAAY,CAAA,CAAA;SAKrBiB,eAAehH,EAAqB,EAAA;;;UAUhD,gBAAC0G,OAAAA;OAAIxB,WAAU;OAA2CgC,eAAY;;QACnEhB,KACC,gBAAA,GAAA;;;UACSD;UACqBD;;aAI9B,gBAAA,GAAA;;mBAAeA,cAAAA;;QAEhBN,KAAa,KACZ,gBAAA,GAAA,EAAA,UAAA,CACE,gBAACuC,QAAAA,EAAAA,UAAK,IAAA,CAAA,GACN,gBAACA,QAAAA,EAAAA,UAAAA;SACC,gBAAA,GAAA,EAAA,IAAA,SAAA,CAAA;SAAgC;SAChC,gBAACA,QAAAA;UAAK/C,WAAU;oBAAoCpH,EAAkB6H,CAAAA;;;QAI5E,gBAAChH,IAAAA;SAAoC8E;SAA0BF;;;;;;;GAMvE,gBAACxF,IAAAA;IACC+E,YAAY4B;IACK7E;IACGC;IACpBoI,wBAAwBzE,GAAaP,OAAOiF;IAC5CC,iBAAiBxH;IACjByH,eAAetH;IACfuH,gBAAgBrH;IAChBsH,cAAcpH;IACdqH,iBAAiBpH;IACjBqH,eAAepH;IACfqH,qBAAqBpH;IACrBqH,mBAAmBpH;IACnBqH,cAAcpH;IACdqH,YAAYpH;IACQxB;IACGC;IACLN;;GAGpB,gBAAChB,IAAAA;IACCkK,QAAQ/I;IACR+C,YAAY8C;IACZmD,eAAe/I,EAAqB,EAAA;IACpCgJ,YAAYtH;;GAGbvB,KACC,gBAACtC,GAAAA;IAAO,GAAGsC;IAAW+E,WAAU;;;;AAIxC,GCraMsE,KAAuB,iCACvBC,KAAmB,2BACnBC,KAAoB;CAAC;CAAQ;CAAW;GACxCC,KAAoB;CAAC;CAAY;CAAW;CAAS;CAAU;GAExDC,MAAqB,EAAEC,WAAQC,YAASC,cAAWC,iBAAiC;CAC/F,IAAM,EAAA,MAAA,GAAA,GAAA,MAAQC,EAAAA,GACRC,IAAYX,EAAAA,GACZ,CAACY,GAAYC,KAAiBnB,EAAS,EAAA,GACvC,CAACoB,GAAWC,KAAgBrB,EAAwB,IAAA,GACpD,CAACsB,GAAkBC,KAAuBvB,EAAS,EAAA,GAEnDwB,IAAQvB,EAAUwB,SAAQ,GAE1BC,IAAuBzB,EAAU0B,QAAQC,KAAKC,WAAWC,OAAOC,YAAY;EAChFjB,iBAAW;GACTU,EAAMG,QAAQC,KAAKC,WAAWG,KAAKC,WAAU;GAC7C,IAAMC,IAAOhB,EAAWiB,KAAI;GAC5BrB,IAAYoB,CAAAA;EACd;EACAnB,UAAUqB,MAAAA;GACRrB,IAAUG,EAAWiB,KAAI,GAAIC,EAAMC,OAAO;EAC5C;EACAC,iBAAW;GACTC,EAAAA;EACF;CACF,CAAA,GAEMA,UAAc;EAKlB1B,AAJAM,EAAc,EAAA,GACdE,EAAa,IAAA,GACbE,EAAoB,EAAA,GACpBG,EAAqBc,MAAK,GAC1B3B,EAAAA;CACF,GAEM4B,KAAgBP,MAAAA;EACpB,IAAMQ,IAAUR,EAAKC,KAAI;EAGzB,IAAI,CAACO,GAEH,OADArB,EAAasB,EAAAA,EAAC,EAAA,IAAA,SAAwB,CAAA,CAAA,GAC/B;EAET,IAAID,EAAQE,SAAS,GAEnB,OADAvB,EAAasB,EAAAA,EAAC,EAAA,IAAA,SAA0C,CAAA,CAAA,GACjD;EAET,IAAID,EAAQE,SAAS,IAEnB,OADAvB,EAAasB,EAAAA,EAAC,EAAA,IAAA,SAA2C,CAAA,CAAA,GAClD;EAIT,IAAI,CAACpC,GAAqBsC,KAAKH,CAAAA,GAE7B,OADArB,EAAasB,EAAAA,EAAC,EAAA,IAAA,SAA+E,CAAA,CAAA,GACtF;EAIT,IAAI,CAAC,YAAYE,KAAKH,CAAAA,KAAY,CAAC,YAAYG,KAAKH,CAAAA,GAElD,OADArB,EAAasB,EAAAA,EAAC,EAAA,IAAA,SAAuD,CAAA,CAAA,GAC9D;EAIT,IAAID,EAAQI,SAAS,IAAA,GAEnB,OADAzB,EAAasB,EAAAA,EAAC,EAAA,IAAA,SAAiD,CAAA,CAAA,GACxD;EAIT,IAAInC,GAAiBqC,KAAKH,CAAAA,GAExB,OADArB,EAAasB,EAAAA,EAAC,EAAA,IAAA,SAAmD,CAAA,CAAA,GAC1D;EAIT,KAAK,IAAMI,KAAUtC,IACnB,IAAIiC,EAAQM,WAAWD,CAAAA,GAErB,OADA1B,EAAasB,EAAAA,EAAC;;aAAoDI,UAAAA;EAAQ,CAAA,CAAA,GACnE;EAKX,KAAK,IAAME,KAAUvC,IACnB,IAAIgC,EAAQQ,SAASD,CAAAA,GAEnB,OADA5B,EAAasB,EAAAA,EAAC;;aAAkDM,UAAAA;EAAQ,CAAA,CAAA,GACjE;EAKX,OADA5B,EAAa,IAAA,GACN;CACT,GAEM8B,KAAoBC,MAAAA;EACxB,IAAMC,IAAQD,EAAEE,OAAOD;EAEvB,AADAlC,EAAckC,CAAAA,GACVjC,KAAWqB,EAAaY,CAAAA;CAC9B,GAEME,UAAe;EACdd,EAAavB,CAAAA,KAClBQ,EAAqB8B,OAAO;GAC1BC,YAAYxC;GACZC,YAAYA,EAAWiB,KAAI;GAC3Bb;EACF,CAAA;CACF;CAUA,OAFKV,IAGH,gBAACV,GAAAA;EACC0D,OAAOjB,EAAAA,EAAC,EAAA,IAAA,SAAc,CAAA;EACtBkB,MAAMjD;EACNkD,UAAUvB;EACVwB,oBAAoBpB,EAAAA,EAAC,EAAA,IAAA,SAAO,CAAA;EAC5BqB,WAAWT;EACXU,mBAAmBtB,EAAAA,EAAC,EAAA,IAAA,SAAO,CAAA;EAC3BuB,MAAK;EACLC,sBAAsBzC,EAAqB0C,aAAa,CAAClD,EAAWiB,KAAI;YAExE,gBAAC/B,GAAAA;GAAMiE,WAAU;GAAWC,KAAI;;IAC9B,gBAACC,KAAAA;KAAEC,WAAU;eACX,gBAAA,GAAA,EAAA,IAAA,SAAA,CAAA;;IAKF,gBAACrE,GAAAA;KACCsE,OAAO9B,EAAAA,EAAC,EAAA,IAAA,SAAY,CAAA;KACpB+B,UAAQ;KACRrB,OAAOnC;KACPyD,UAAUxB;KACVyB,YA/BexB,MAAAA;MACrB,AAAIA,EAAEO,QAAQ,WACZJ,EAAAA;KAEJ;KA4BQsB,SAAS,CAAC,CAACzD;KACX0D,WAAW1D,KAAa2D,KAAAA;KACxBC,UAAUtD,EAAqB0C;KAC/Ba,WAAS;KACTC,aAAavC,EAAAA,EAAC,EAAA,IAAA,SAAe,CAAA;;IAE/B,gBAACtC,GAAAA;KACCoE,OAAO9B,EAAAA,EAAC,EAAA,IAAA,SAAkB,CAAA;KAC1BwC,UAAUxC,EAAAA,EAAC,EAAA,IAAA,SAA0F,CAAA;KACrGyC,SAAS9D;KACTqD,WAAWvB,MAA2C7B,EAAoB6B,EAAEE,OAAO8B,OAAO;KAC1FJ,UAAUtD,EAAqB0C;;;;MArCnB;AA0CtB,GC1IamC,MAAmB,EAC9BC,YACAC,oBACAC,uBACAC,oBACAC,kBACAC,mBACAC,iBACAC,oBACAC,kBACAC,oBACAC,uBACAC,sBAAmB,SACE;CACrB,IAAM,EAAEC,cAAWC,aAAUC,mBAAgB5B,GAAU,EAAE6B,QAAQ,GAAM,CAAA,GACjE,EAAA,MAAA,GAAA,GAAA,MAAQC,EAAAA,GACRC,IAAWhC,EAAAA,GAEXiC,IAAYrC,GAAuB,IAAA,GACnC,CAACsC,GAAgBC,KAAqBrC,EAAS,CAAA,GAC/C,CAACsC,GAAkBC,KAAuBvC,EAAwB,IAAA,GAClE,CAACwC,GAAmBC,KAAwBzC,EAAwB,IAAA;CAG1ED,SAAU;EACR,AAAIoC,EAAUO,WAEZL,EADcF,EAAUO,QAAQE,cAAcT,EAAUO,QAAQG,WAC9CF;CAEtB,GAAG,CAAC1B,EAAQ6B,MAAAA,CAAO;CAGnB,IAAMC,KAAcC,MAAAA;EAClB,IAAI;GAEF,OAAOC,IADUC,KAAKF,CACfC,EAAKE,eAAc;EAC5B,QAAQ;GACN,OAAOC,EAAAA,EAAC,EAAA,IAAA,SAAI,CAAA;EACd;CACF,GAEMC,IAAiBpD,EAAe;EACpCqD,OAAOrC,EAAQ6B;EACfS,wBAAwBpB,EAAUO;EAClCc,oBAAoB;EACpBC,UAAU;CACZ,CAAA,GAEMC,MAAsBC,MAAAA;EAC1B,AAAIjC,EAAgBkC,SAASD,CAAAA,IAC3BhC,EAAmBD,EAAgBmC,QAAQC,MAASA,MAASH,CAAAA,CAAAA,IAE7DhC,EAAmB,CAAA,GAAID,GAAiBiC,CAAAA,CAAW;CAEvD;CAEA,IAAI,CAAC1C,KAAWA,EAAQ6B,WAAW,GACjC,OACE,gBAACzC,GAAAA;EAAS0D,SAAS;EAAGC,WAAU;EAAUC,eAAY;YACpD,gBAAC1D,GAAAA,EAAAA,UACC,gBAACC,GAAAA;GAAa0D,SAAS;aACrB,gBAACC,OAAAA;IAAIH,WAAU;eACb,gBAACI,MAAAA;KAAGJ,WAAU;eACZ,gBAAA,GAAA,EAAA,IAAA,SAAA,CAAA;QAEF,gBAACK,KAAAA;KAAEL,WAAU;eACX,gBAAA,GAAA,EAAA,IAAA,SAAA,CAAA;;;;;CAad,IAAMM,IAAc1C,IAAmB,IAAI,GACrC2C,KAAqB3C,IACvB,0FACA;CAEJ,OACE,gBAAA,GAAA,EAAA,UAAA;EACE,gBAACuC,OAAAA;GAAIH,WAAU;cAEb,gBAACG,OAAAA;IAAIK,OAAO,EAAEC,cAAc,GAAGrC,EAAe,IAAI;cAChD,gBAAC/B,GAAAA;KACC0D,SAASO;KACWC;KACpBP,WAAU;KACVC,eAAY;eAEZ,gBAAC1D,GAAAA,EAAAA,UAAAA;MACEqB,KAAoB,gBAACtB,GAAAA,CAAAA,CAAAA;MACtB,gBAACA,GAAAA,EAAAA,UACC,gBAAA,GAAA,EAAA,IAAA,SAAA,CAAA,EAAA,CAAA;MAEF,gBAACA,GAAAA,EAAAA,UACC,gBAAA,GAAA,EAAA,IAAA,SAAA,CAAA,EAAA,CAAA;MAEF,gBAACA,GAAAA,EAAAA,UACC,gBAAA,GAAA,EAAA,IAAA,SAAA,CAAA,EAAA,CAAA;MAEF,gBAACA,GAAAA,EAAAA,UACC,gBAAA,GAAA,EAAA,IAAA,SAAA,CAAA,EAAA,CAAA;MAEF,gBAACA,GAAAA,EAAiBkE,OAAO,EAAEE,aAAa,IAAItC,EAAe,IAAI,EAAA,CAAA;;;OAMrE,gBAAC+B,OAAAA;IACCQ,KAAKxC;IACL6B,WAAU;IACVQ,OAAO,EACLI,QAAQ,sBACV;IACAX,eAAY;cAEZ,gBAACE,OAAAA;KACCK,OAAO;MACLI,QAAQ,GAAGvB,EAAewB,aAAY,EAAG;MACzClC,OAAO;MACPmC,UAAU;KACZ;eAECzB,EAAe0B,gBAAe,EAAGC,KAAKC,MAAAA;MACrC,IAAMC,IAASjE,EAAQgE,EAAWE,QAC5BC,IAAa1D,EAAgBkC,SAASsB,EAAOpB,IAAI,GAEjDuB,UACJnD,EAAS;OACPoD,IAAI;OACJC,QAAQ;QACN1D,WAAWA,KAAa;QACxBC,UAAU,KAAwB;QAClCC,aAAa,KAA2B;QACxCyD,eAAeN,EAAOpB;OACxB;MACF,CAAA;MAEF,OACE,gBAACK,OAAAA;OAECsB,cAAYR,EAAWE;OACvBR,KAAKtB,EAAeqC;OACpB1B,WAAU;OACVQ,OAAO;QACLM,UAAU;QACVa,KAAK;QACLC,MAAM;QACNjD,OAAO;QACPkD,WAAW,cAAcZ,EAAWa,MAAM;QAC1CC,SAAS;QACTC,qBAAqBzB;QACrB0B,YAAY;OACd;OACAhC,eAAa,cAAciB,EAAOpB;OAClCoC,MAAK;OACLC,UAAU;OACVC,SAASf;OACTgB,YAAYC,MAAAA;QACV,CAAIA,EAAEC,QAAQ,WAAWD,EAAEC,QAAQ,SACjCD,EAAEE,eAAc,GAChBnB,EAAAA;OAEJ;;QAECzD,KACC,gBAACpB,GAAAA;SACC4F,UAAUE,MAAMA,EAAEG,gBAAe;SACjCJ,YAAYC,MAAAA;UACV,CAAIA,EAAEC,QAAQ,WAAWD,EAAEC,QAAQ,QACjCD,EAAEG,gBAAe;SAErB;mBAEA,gBAACrG,GAAAA;UACCsG,SAAStB;UACTuB,gBAAgBjD,GAAmBwB,EAAOpB,IAAI;UAC9CG,eAAa,iBAAiBiB,EAAOpB;;;QAI3C,gBAACtD,GAAAA;SAAawD,WAAU;mBACtB,gBAAC4C,QAAAA;UAAK5C,WAAU;UAAiB6C,OAAO3B,EAAOpB;oBAC5CoB,EAAOpB;;;QAGZ,gBAACtD,GAAAA,EAAAA,UAAc0E,EAAO5B,MAAMH,eAAc,EAAA,CAAA;QAC1C,gBAAC3C,GAAAA,EAAAA,UAAcuC,EAAWmC,EAAO4B,iBAAiB5B,EAAO6B,gBAAgB,EAAA,EAAA,CAAA;QACzE,gBAACvG,GAAAA,EAAAA,UAAcI,EAAkBsE,EAAO8B,KAAK,EAAA,CAAA;QAC7C,gBAACxG,GAAAA;SAAa4F,UAAUE,MAAMA,EAAEG,gBAAe;mBAC7C,gBAAChG,GAAAA,EAAAA,UACC,gBAACE,GAAAA,EAAAA,UAAAA;UACC,gBAACD,GAAAA;WACCuG,OAAO7D,EAAAA,EAAC,EAAA,IAAA,SAAa,CAAA;WACrBgD,SAASf;WACTpB,eAAa,uBAAuBiB,EAAOpB;;UAE7C,gBAACpD,GAAAA;WACCuG,OAAO7D,EAAAA,EAAC,EAAA,IAAA,SAAM,CAAA;WACdgD,eAAe7D,EAAoB2C,CAAAA;WACnCjB,eAAa,gBAAgBiB,EAAOpB;;UAEtC,gBAACpD,GAAAA;WACCuG,OAAO7D,EAAAA,EAAC,EAAA,IAAA,SAAO,CAAA;WACfgD,eAAe3D,EAAqByC,CAAAA;WACpCjB,eAAa,iBAAiBiB,EAAOpB;;;;;SAjExCoB,EAAOpB,IAAI;KAwEtB,CAAA;;;;EAKN,gBAACjD,IAAAA;GACCqG,QAAQhG;GACRiG,eAAehG,EAAmB,EAAA;GAClCiG,WAAWhG;GACXiG,SAAShG;;EAGX,gBAACP,GAAAA;GACCoG,QAAQ5E,MAAqB;GAC7B4C,QAAQ5C;GACR6E,eAAe5E,EAAoB,IAAA;GACnC6E,WAAW9F;GACX+F,SAAS9F;;EAGX,gBAACR,IAAAA;GACCmG,QAAQ1E,MAAsB;GAC9B0C,QAAQ1C;GACR2E,eAAe1E,EAAqB,IAAA;GACpC2E,WAAW5F;GACX6F,SAAS5F;;;AAIjB,GCxRa6F,MAAyBC,OAAsE;CAC1GC,SAAS,gBAAA,GAAA,EAAA,IAAA,SAAA,CAAA;CACTC,aAAa,gBAAA,GAAA;;YAAgBF,cAAAA;;AAC/B,IAEaG,MACXH,GACAI,OACkD;CAClDH,SAAS,gBAAA,GAAA,EAAA,IAAA,SAAA,CAAA;CACTC,aACE,gBAAA,GAAA;;;GAC4BF;GAAeI;;;AAG/C,IAEaC,MACXL,GACAM,OACkD;CAClDL,SAAS,gBAAA,GAAA,EAAA,IAAA,SAAA,CAAA;CACTC,aACEI,MAAiB,IACf,gBAAA,GAAA;;YAAgBN,cAAAA;MACdM,MAAiB,IACnB,gBAAA,GAAA;;;GACWN;GAAwCM;;MAGnD,gBAAA,GAAA;;;GACWN;GAAwCM;;;AAGzD,IAEaC,MACXP,GACAI,OACkD;CAClDH,SAAS,gBAAA,GAAA,EAAA,IAAA,SAAA,CAAA;CACTC,aACE,gBAAA,GAAA;;;GAC2BF;GAAeI;;;AAG9C,IAEaI,MAAyBR,OAAsE;CAC1GC,SAAS,gBAAA,GAAA,EAAA,IAAA,SAAA,CAAA;CACTC,aAAa,gBAAA,GAAA;;YAAgBF,cAAAA;;AAC/B,IAEaS,MACXT,GACAI,OACkD;CAClDH,SAAS,gBAAA,GAAA,EAAA,IAAA,SAAA,CAAA;CACTC,aACE,gBAAA,GAAA;;;GAC4BF;GAAeI;;;AAG/C,IAEaM,MACXC,GACAC,GACAC,MAAAA;CAEA,IAAMC,IAAYD,EAAOE,SAAS,GAC5BC,IAAeL,IAAeE,EAAOE,QACrCE,IAAeJ,EAAOE;CAE5B,OAAO;EACLd,SAASa,IAAY,gBAAA,GAAA,EAAA,IAAA,SAAA,CAAA,IAAiD,gBAAA,GAAA,EAAA,IAAA,SAAA,CAAA;EACtEZ,aAAaY,IACX,gBAAA,GAAA;;;IACwBH;IAAkBK;IACgCJ;IACTK;;OAIjE,gBAAA,GAAA;;;IACwBN;IACrBC;;;CAGP;AACF,GCvFMa,KAAc,IAePC,MAAqB,EAAEC,WAAQC,YAASC,YAASC,oBAAoC;CAChG,IAAM,EAAA,MAAA,GAAA,GAAA,MAAQC,EAAAA,GACRC,IAAYR,EAAAA,GACZ,CAACS,GAAUC,KAAehB,EAAoD,IAAA,GAC9E,CAACiB,GAAaC,KAAkBlB,EAAS,EAAA,GAEzCmB,IAAQlB,EAAUmB,SAAQ,GAC1BC,IAAsBpB,EAAUqB,QAAQC,KAAKC,QAAQC,UAAUC,YAAW,GAE1EC,UAAc;EAIlBhB,AAHAU,EAAoBO,MAAK,GACzBZ,EAAY,IAAA,GACZE,EAAe,EAAA,GACfP,EAAAA;CACF,GAEMkB,IAAgB,YAAA;EACpB,IAAIC,IAAe,GACfC,IAAe,GACbC,IAAmB,CAAA,GACnBC,IAAQvB,EAAQwB;EAEtB,KAAK,IAAIC,IAAI,GAAGA,IAAIzB,EAAQwB,QAAQC,KAAK;GACvCnB,EAAY;IAAEoB,SAASD,IAAI;IAAGF;GAAM,CAAA;GACpC,IAAMI,IAAS3B,EAAQyB;GAEvB,IAAI;IACF,IAAMG,IAAU,MAAMjB,EAAoBkB,YAAY;KACpDC,YAAY1B;KACZ2B,eAAeJ,EAAOK;IACxB,CAAA;IAEAZ,AADAC,KAAgBO,GAChBR;GACF,SAASa,GAAK;IACZ,IAAMC,IAAUD,aAAeE,QAAQF,EAAIC,UAAUE,OAAOH,CAAAA;IAC5DX,EAAOe,KAAK,GAAGV,EAAOK,KAAK,IAAIE,GAAS;GAC1C;EACF;EAOAjB,AALIG,IAAe,KACjB,MAAMX,EAAMG,QAAQC,KAAKyB,WAAWC,KAAKC,WAAU,GAGrDtC,IAAa;GAAEkB;GAAcC;GAAcC;EAAO,CAAA,GAClDL,EAAAA;CACF;CAEA,IAAI,CAAClB,KAAUC,EAAQwB,WAAW,GAAG,OAAO;CAE5C,IAAMiB,IAAazC,EAAQwB,QACrBkB,IAAiB1C,EAAQ2C,MAAM,GAAG9C,EAAAA,GAClC+C,IAAcH,IAAaC,EAAelB,QAC1CqB,IAAYlC,EAAoBkC,aAAaxC,MAAa,MAC1DyC,IAAkBzC,GAAUqB,SAC5BqB,IAAgB1C,GAAUkB,OAC1ByB,IAAiBzC,MAAgB;CAEvC,OACE,gBAACf,GAAAA;EACCyD,OAAO,gBAAA,GAAA;;aAAeR,cAAAA;;EACtBS,MAAMnD;EACNoD,UAAUlC;EACVmC,oBAAoBP,IAAYQ,EAAAA,EAAC,EAAA,IAAA,SAAY,CAAA,IAAIA,EAAAA,EAAC,EAAA,IAAA,SAAM,CAAA;EACxDC,sBAAqB;EACrBC,mBAAmBF,EAAAA,EAAC,EAAA,IAAA,SAAO,CAAA;EAC3BG,WAAWrC;EACXsC,sBAAsBZ,KAAa,CAACG;EACpCU,qBAAqBb;EACrBc,oBAAoBd;EACpBe,MAAK;YAEJf,IACC,gBAACnD,GAAAA;GAAMmE,WAAU;GAAWC,cAAa;GAASC,WAAU;GAASC,KAAI;GAAIC,WAAU;cACrF,gBAACxE,GAAAA,EAAQyE,SAAQ,UAAA,CAAA,GAChB7D,KACC,gBAAC8D,KAAAA;IAAEF,WAAU;cACX,gBAAA,GAAA;;;MACmBnB;MAAqBC;;;;OAM9C,gBAACrD,GAAAA;GAAMmE,WAAU;GAAWG,KAAI;;IAC9B,gBAAA,GAAA;;eACiDvB,cAAAA;;IAIjD,gBAAC2B,OAAAA,EAAAA,UAAAA,CACC,gBAACD,KAAAA;KAAEF,WAAU;eACX,gBAAA,GAAA,EAAA,IAAA,SAAA,CAAA;QAEF,gBAACI,MAAAA;KAAGJ,WAAU;gBACXvB,EAAe4B,KAAK3C,MAAAA;MACnB,IAAM4C,IAAa5C,EAAOK,MACpBwC,IAAc7C,EAAO8C;MAC3B,OACE,gBAACC,MAAAA,EAAAA,UAAAA,CACEH,GACAC,IAAc,KACb,gBAACG,QAAAA;OAAKV,WAAU;;QAAwB;QACpCO;QAAY;QAAC,gBAAA,GAAA;;mBAAeA,eAAAA;;QAA4C;;aAJvED,CAAAA;KASb,CAAA,GACC3B,IAAc,KACb,gBAAC8B,MAAAA;MAAGT,WAAU;gBACZ,gBAAA,GAAA;;iBAAgBrB,eAAAA;;;;IAMxB,gBAACjD,GAAAA;KACCiF,OAAOvB,EAAAA,EAAC,EAAA,IAAA,SAAwB,CAAA;KAChCwB,OAAOtE;KACPuE,WAAWC,MAAMvE,EAAeuE,EAAEC,OAAOH,KAAK;KAC9CI,aAAY;KACZC,WAAS;;;;;AAMrB;;;AC5IA,SAAgBM,GAAiB,EAAEC,gBAAkC;CACnE,IAAMC,IAAYN,EAAAA,GACZO,IAAQR,EAAUS,SAAQ,GAE1BC,IAAiBV,EAAUW,QAAQC,KAAKC,eAAeC,OAAOC,YAAY;EAC9ET,iBAAW;GAETA,AADAE,EAAMG,QAAQC,KAAKC,eAAeG,KAAKC,WAAU,GACjDX,EAAAA;EACF;EACAY,UAAUC,MAAAA;GACR,IAAMC,IAAeD,EAAIE;GACzBjB,EAAMkB,MAAM,gBAAA,GAAA;;cAAqCF,gBAAAA;;EACnD;CACF,CAAA;CAEA,OACE,gBAACjB,GAAAA;EAAMoB,WAAU;EAAWC,KAAI;EAAIC,WAAU;;GAC5C,gBAACC,MAAAA;IAAGD,WAAU;cACZ,gBAAA,GAAA,EAAA,IAAA,SAAA,CAAA;;GAEF,gBAACE,KAAAA;IAAEF,WAAU;cACX,gBAAA,GAAA,EAAA,IAAA,SAAA,CAAA;;GAKF,gBAACE,KAAAA;IAAEF,WAAU;cACX,gBAAA,GAAA,EAAA,IAAA,SAAA,CAAA;;GAIF,gBAACG,OAAAA,EAAAA,UACC,gBAAC1B,GAAAA;IACC2B,eAAetB,KAAaG,EAAeoB,OAAO,EAAEC,YAAYxB,EAAU,CAAA;IAC1EyB,UAAUtB,EAAeuB,aAAa,CAAC1B;cAEtCG,EAAeuB,YAAY,gBAAA,GAAA,EAAA,IAAA,SAAA,CAAA,IAAyC,gBAAA,GAAA,EAAA,IAAA,SAAA,CAAA;;;;AAK/E;;;ACLA,IAAaoC,WAAc;CACzB,IAAM,EAAA,MAAA,GAAKC,SAAI,GAAA,MAAKC,EAAAA,GACdC,IAAYV,EAAAA,GACZW,IAAWnC,EAAY,EAAEoC,MAAMX,EAAMY,SAAS,CAAA,GAI9C,EAAEC,WAAQC,kBAAeC,QAAQC,IAAc,OAAOhB,EAAMiB,UAAS,GAOrE,CAACE,GAAiBC,KAAsBjD,EAAS,EAAA,GACjD,CAACkD,GAAmBC,KAAwBnD,EAAS,EAAA,GACrD,CAACoD,GAAiBC,KAAsBrD,EAAmB,CAAA,CAAE,GAI7D,CAACsD,GAAiBC,KAAsBvD,EAAS6C,CAAAA,GACjDW,IAAgBtD,GAA2BuD,KAAAA,CAAAA;CAQjDxD,AAPAA,eAAsByD,aAAaF,EAAcG,OAAO,GAAG,CAAA,CAAE,GAO7D1D,SAAU;EACRsD,EAAmBV,CAAAA;CACrB,GAAG,CAACA,CAAAA,CAAY;CAEhB,IAAMe,KAAuBC,MAAAA;EAC3B,IAAM,EAAEC,YAAS,GAAGC,MAAY5C,GAAsB0C,CAAAA;EAEtD5C,EAAM+C,QAAQF,GAASC,CAAAA;CACzB,GAEME,KAAqBJ,GAAoBK,MAAAA;EAC7C,IAAM,EAAEJ,YAAS,GAAGC,MAAY3C,GAA0ByC,GAAYK,CAAAA;EAEtEjD,EAAMkD,MAAML,GAASC,CAAAA;CACvB,GAEMK,KAAsBP,GAAoBQ,MAAAA;EAC9C,IAAM,EAAEP,YAAS,GAAGC,MAAY1C,GAAsBwC,GAAYQ,CAAAA;EAElEpD,EAAM+C,QAAQF,GAASC,CAAAA;CACzB,GAEMO,KAAoBT,GAAoBK,MAAAA;EAC5C,IAAM,EAAEJ,YAAS,GAAGC,MAAYzC,GAAyBuC,GAAYK,CAAAA;EAErEjD,EAAMkD,MAAML,GAASC,CAAAA;CACvB,GAEMQ,KAAuBV,MAAAA;EAC3B,IAAM,EAAEC,YAAS,GAAGC,MAAYxC,GAAsBsC,CAAAA;EAEtD5C,EAAM+C,QAAQF,GAASC,CAAAA;CACzB,GAEMS,KAAqBX,GAAoBK,MAAAA;EAC7C,IAAM,EAAEJ,YAAS,GAAGC,MAAYvC,GAA0BqC,GAAYK,CAAAA;EAEtEjD,EAAMkD,MAAML,GAASC,CAAAA;CACvB,GAEMU,MAA0B,EAC9BC,iBACAC,iBACAC,gBAKD;EACC,IAAIA,EAAOC,WAAW,GACpBxB,EAAmB,CAAA,CAAE;OAChB;GAIL,IAAMyB,IAAoB,IAAIC,IAAIH,EAAOI,KAAKC,MAAMA,EAAEC,MAAM,IAAA,EAAM,EAAE,CAAA;GACpE7B,GAAoB8B,MAASA,EAAKC,QAAQC,MAASP,EAAkBQ,IAAID,CAAAA,CAAAA,CAAAA;EAC3E;EAEA,IAAM,EAAEvB,YAAS,GAAGC,MAAYtC,GAA6BiD,GAAcC,GAAcC,CAAAA;EAEzF,AAAIA,EAAOC,SAAS,IAClB5D,EAAMsE,QAAQzB,GAASC,CAAAA,IAEvB9C,EAAM+C,QAAQF,GAASC,CAAAA;CAE3B,GAEMyB,IAA6B;EACjCzB,SAAS;GACP;IAAE0B,OAAOC,EAAAA,EAAC,EAAA,IAAA,SAAK,CAAA;IAAGC,OAAO;GAAO;GAChC;IAAEF,OAAOC,EAAAA,EAAC,EAAA,IAAA,SAAa,CAAA;IAAGC,OAAO;GAAQ;GACzC;IAAEF,OAAOC,EAAAA,EAAC,EAAA,IAAA,SAAW,CAAA;IAAGC,OAAO;GAAQ;GACvC;IAAEF,OAAOC,EAAAA,EAAC,EAAA,IAAA,SAAc,CAAA;IAAGC,OAAO;GAAgB;;EAEpDjD,QAAQA,KAAU;EAClBC,eAAeA,KAAiB;CAClC,GAGM,EACJiD,MAAMC,GACNC,eACA3B,aACE7D,EAAUyF,QAAQC,KAAKC,WAAWC,KAAKC,SACzC;EACEC,YAAY9D;EACZ+D,iBAAiB;CACnB,GACA;EACEC,SAAS,CAAC,CAAChE;EACXiE,OAAO;CACT,CAAA,GAIIC,MAAeX,MACZ,CAAA,GAAIA,CAAAA,EAASY,MAAMC,GAAGC,MAAAA;EAC3B,IAAIC;EAEJ,QAAQlE,KAAU,QAAlB;GACE,KAAK;IACHkE,IAAaF,EAAErB,KAAKwB,cAAcF,EAAEtB,IAAI;IACxC;GACF,KAAK;IACHuB,IAAaF,EAAEI,QAAQH,EAAEG;IACzB;GACF,KAAK;IACHF,IAAaF,EAAEK,QAAQJ,EAAEI;IACzB;GACF,KAAK;IACH,IAAI,CAACL,EAAEM,iBAAiB,CAACL,EAAEK,eACzB,OAAO;IAET,IAAI,CAACN,EAAEM,eACL,OAAO;IAET,IAAI,CAACL,EAAEK,eACL,OAAO;IAETJ,IAAa,IAAIK,KAAKP,EAAEM,aAAa,EAAEE,QAAO,IAAK,IAAID,KAAKN,EAAEK,aAAa,EAAEE,QAAO;IACpF;GACF,SACEN,IAAaF,EAAErB,KAAKwB,cAAcF,EAAEtB,IAAI;EAC5C;EAEA,QAAQ1C,KAAiB,WAAW,SAAS,CAACiE,IAAaA;CAC7D,CAAA,GAIIO,KAAmBtB,KAAW,CAAA,GAAIT,QAAQgC,MAC9CA,EAAO/B,KAAKgC,YAAW,EAAGC,SAASzE,EAAYwE,YAAW,CAAA,CAAA,GAItDE,KAAgBf,GAAYW,CAAAA,GAE5BK,KAAsBC,MAAAA;EAC1B,IAAM9B,IAAQ,OAAO8B,KAAS,WAAWA,IAAO;EAChDtH,SAAgB;GACdoC,EAAS,EACPK,SAASuC,OAAU;IAAE,GAAGA;IAAMvC,QAAQ+C,KAASlC,KAAAA;GAAU,GAC3D,CAAA;EACF,CAAA;CACF,GAEMiE,MAAoBC,MAAAA;EACxB,IAAMC,IAAkBD,EAAgBjF,QAAQmF,SAAAA,KAAc,QAKxDC,IAAqBH,EAAgBhF,iBAAiB;EAC5DxC,SAAgB;GACdoC,EAAS,EACPK,SAASuC,OAAU;IACjB,GAAGA;IACHzC,QAAQkF;IACRjF,eAAemF;GACjB,GACF,CAAA;EACF,CAAA;CACF;CAGA,IAAIhC,IACF,OACE,gBAAC9E,GAAAA;EAAM+G,WAAU;EAAmBC,cAAa;EAASC,WAAU;EAASC,WAAU;aACrF,gBAACnH,GAAAA;GAAQoH,SAAQ;GAAUC,MAAK;GAAQL,WAAU;MAClD,gBAAA,GAAA,EAAA,IAAA,SAAA,CAAA,CAAA;;CAMN,IAAI5D,GAAO;EACT,IAAMD,IAAeC,EAAML;EAG3B,IAAII,MAAiB,uBACnB,OAAO,gBAACvC,IAAAA,EAAiB0G,iBAAiBC,OAAOC,SAASC,OAAM,EAAA,CAAA;EAIlE,IAAMC,IAAiBvE,EAAaoD,SAAS,eAAA,KAAoBpD,EAAaoD,SAAS,cAAA,GACjFoB,IAAcxE,EAAaoD,SAAS,oBAAA,KAAyBpD,EAAaoD,SAAS,oBAAA;EAEzF,OACE,gBAACqB,OAAAA;GAAIZ,WAAU;aACb,gBAACa,KAAAA;IAAEb,WAAU;cACVU,IACC,gBAAA,GAAA,EAAA,IAAA,SAAA,CAAA,IAIEC,IACF,gBAAA,GAAA,EAAA,IAAA,SAAA,CAAA,IAKA,gBAAA,GAAA;;eAAgCxE,gBAAAA;;;;CAK1C;CAKA,IAAM2E,KAA2BhD,KAAW,CAAA,GAAIT,QAAQ0D,MAAM1F,EAAgBkE,SAASwB,EAAEzD,IAAI,CAAA,GACvF0D,KAAeF,EAAwBhE,SAAS,GAChDmE,KAAgBH,EAAwBhE,QACxCoE,MAAcpD,KAAW,CAAA,GAAIhB,QAC7BqE,KAAgB/B,EAAgBtC,QAGhCsE,IAAiB5B,GAAcvC,KAAK8D,MAAMA,EAAEzD,IAAI,GAChD+D,KAAcD,EAAetE,SAAS,KAAKsE,EAAeE,OAAOC,MAAMlG,EAAgBkE,SAASgC,CAAAA,CAAAA,GAChGC,KAAeJ,EAAeK,MAAMF,MAAMlG,EAAgBkE,SAASgC,CAAAA,CAAAA;CASzE,OACE,gBAACX,OAAAA;EAAIZ,WAAU;;GACb,gBAAC/G,GAAAA;IAAMkH,WAAU;;KAEf,gBAAClH,GAAAA;MAAMgH,cAAa;MAAMC,WAAU;MAASyB,KAAI;MAAI3B,WAAU;iBAC7D,gBAAC/G,GAAAA;OAAM0I,KAAI;OAAMzB,WAAU;iBACzB,gBAAC5H,IAAAA;QACC0D,SAASyB,EAAazB;QACtBrB,QAAQ8C,EAAa9C;QACrBC,eAAe6C,EAAa7C,iBAAiB;QAC7CgH,iBAAgB;QAChBC,iBAAiBjE,MACf+B,GAAiB;SAAE,GAAGlC;SAAc9C,QAAQiD;SAAOhD,eAAe6C,EAAa7C;QAAc,CAAA;QAE/FkH,wBAAwB3B,MAAcR,GAAiB;SAAE,GAAGlC;SAAc7C,eAAeuF;QAAU,CAAA;;UAGvG,gBAAC3H,GAAAA;OAAO4H,SAAQ;OAAUJ,WAAU;OAAoB+B,eAAe7G,EAAmB,EAAA;iBACxF,gBAAA,GAAA,EAAA,IAAA,SAAA,CAAA;;;KASJ,gBAACxC,GAAAA,EAAAA,UACC,gBAACO,GAAAA;MAAMkH,WAAU;MAAWwB,KAAI;gBAC9B,gBAAC1I,GAAAA;OAAMgH,cAAa;OAAMC,WAAU;iBAClC,gBAACnH,GAAAA;QACCiJ,aAAarE,EAAAA,EAAC,EAAA,IAAA,SAAkB,CAAA;QAChCsE,eAAY;QACZrE,OAAOrC;QACP2G,UAAUhF,MAAAA;SACR,IAAMiF,IAAIjF,EAAEkF,cAAcxE;SAG1BnC,AAFAD,EAAmB2G,CAAAA,GACnBxG,aAAaF,EAAcG,OAAO,GAClCH,EAAcG,UAAU2E,OAAO8B,iBAAiB5C,EAAmB0C,CAAAA,GAAI,GAAA;QACzE;QACAG,WAAWH,MAAAA;SAET1C,AADA9D,aAAaF,EAAcG,OAAO,GAClC6D,EAAmB,OAAO0C,KAAM,WAAWA,IAAI,EAAA;QACjD;QACAI,eAAS;SAGP9C,AAFA9D,aAAaF,EAAcG,OAAO,GAClCJ,EAAmB,EAAA,GACnBiE,EAAmB,EAAA;QACrB;;;;KASR,gBAAC/G,GAAAA,EAAAA,UACC,gBAACO,GAAAA;MAAMgH,cAAa;MAAQ0B,KAAI;MAAIzB,WAAU;MAASF,WAAU;iBAE7D,gBAAC/G,GAAAA;OAAM0I,KAAI;OAAIzB,WAAU;kBACvB,gBAACzH,GAAAA;QACC+J,SAASnB;QACToB,eAAejB,MAAgB,CAACH;QAChCqB,gBAxEc;SAC5B,AACEpH,EADE+F,MACkBjE,MAASA,EAAKC,QAAQkE,MAAM,CAACH,EAAe7B,SAASgC,CAAAA,CAAAA,KAErDnE,MAAS,CAAA,GAAI,IAAIJ,IAAI,CAAA,GAAII,GAAAA,GAASgE,CAAAA,CAAe,CAAA,CAAE;QAE3E;WAoEc,gBAACzI,GAAAA;QAAUqH,WAAU;mBACnB,gBAAClH,GAAAA;SAAgB6J,IAAG;mBAClB,gBAACnK,GAAAA;UAAOoK,UAAU,CAAC5B;UAAcX,MAAK;UAAQwC,MAAK;UAAWnF,OAAOC,EAAAA,EAAC,EAAA,IAAA,SAAQ,CAAA;;YAE/EqD,MACC,gBAACnI,GAAAA,EAAAA,UACC,gBAACD,GAAAA;SACCgK,UAAU,CAAC5B;SACXtD,OAAOrD,EAAKyI,EACVC,EAAAA,EAAO9B;;oBAAAA,kBAAAA;SAAY,CAAA,CAAA;SAKrBc,eAAe3G,EAAqB,EAAA;;;UAUhD,gBAACwF,OAAAA;OAAIZ,WAAU;OAA2CiC,eAAY;iBACnEnH,EAAYmI,KAAI,IACf,gBAAA,GAAA;;;SACS/B;SACCC;;YAIV,gBAAA,GAAA;;kBAAeD,eAAAA;;;;;;GAOzB,gBAAC/H,IAAAA;IACC2E,SAAS0B;IACQvE;IACGC;IACpBgI,iBAAiBrH;IACjBsH,eAAejH;IACfkH,gBAAgB/G;IAChBgH,cAAc9G;IACd+G,iBAAiB9G;IACjB+G,eAAe9G;IACEpB;IACGC;IACFN;;GAGpB,gBAACrB,IAAAA;IACC6J,QAAQrI;IACR2C,SAASgD;IACT2C,eAAerI,EAAqB,EAAA;IACpCsI,YAAYhH;;;;AAIpB;;;ACpRA,SAAS0H,KAAAA;CACP,IAAM,EAAEC,YAASC,gBAAaX,GAAU;EACtCY,MAAM;EACNC,SAASC,OACA;GAAEJ,SAASI,EAAOC;GAAWJ,UAAUG,EAAOH;GAAUK,aAAaF,EAAOE;EAAY;CAEnG,CAAA,GAEM,EAAA,MAAA,GAAA,GAAA,MAAQX,EAAAA,GAEVa;CACJ,QAAQP,GAAR;EACE,KAAK;GACHO,IAAYD,EAAAA,EAAC,EAAA,IAAA,SAAA,CAAA;GACb;EACF,KAAK;GACHC,IAAYD,EAAAA,EAAC,EAAA,IAAA,SAAA,CAAA;GACb;EACF,SACEC,IAAYD,EAAAA,EAAC,EAAA,IAAA,SAAA,CAAA;CACjB;CAEA,OACE,gBAAC,OAAA,EAAA,UAAA,CACC,gBAAC,GAAA;EAAc,OAAOC;EAAW,WAAWR;KAC3CA,IACC,gBAAC,IAAA;EACC,WAAW,CAACA,GAASC,CAAAA;EACrB,UACE,gBAAC,OAAA;GAAI,WAAU;aACb,gBAAA,GAAA,EAAA,IAAA,SAAA,CAAA;;mBAIF;GACA,QAAQA,GAAR;IACE,KAAK,SACH,OAAO,gBAAC,IAAA,CAAA,CAAA;IACV,KAAK,QACH,OAAO,gBAAC,IAAA,CAAA,CAAA;IACV,SACE,OAAO,gBAAC,OAAA,EAAA,UAAI,wBAAA,CAAA;GAChB;EACF,GAAA;MAGF,gBAAC,OAAA;EAAI,WAAU;YACb,gBAAA,GAAA,EAAA,IAAA,SAAA,CAAA;;AAKV;AAAC,IAAAQ,WAzEU,gBAAC,IAAA,CAAA,CAAA"}
|