@cobaltcore-dev/aurora 2.1.0 → 2.1.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/client/DeleteFlavorModal-C4nAi7gY.mjs +724 -0
- package/dist/client/DeleteFlavorModal-C4nAi7gY.mjs.map +1 -0
- package/dist/client/_flavorId-BPvssEzn.mjs +277 -0
- package/dist/client/_flavorId-BPvssEzn.mjs.map +1 -0
- package/dist/client/{_flavorId-CgueqKTs.mjs → _flavorId-CFUBcU-l.mjs} +3 -3
- package/dist/client/{_flavorId-CgueqKTs.mjs.map → _flavorId-CFUBcU-l.mjs.map} +1 -1
- package/dist/client/{_flavorId-B7fp6Nk8.mjs → _flavorId-CZcIp0Ih.mjs} +2 -2
- package/dist/client/{_flavorId-B7fp6Nk8.mjs.map → _flavorId-CZcIp0Ih.mjs.map} +1 -1
- package/dist/client/_imageId-BAezmV0Y.mjs +526 -0
- package/dist/client/_imageId-BAezmV0Y.mjs.map +1 -0
- package/dist/client/{_imageId-Ccv8PedW.mjs → _imageId-D-jqz3e3.mjs} +3 -3
- package/dist/client/_imageId-D-jqz3e3.mjs.map +1 -0
- package/dist/client/{_imageId-D9LR-02T.mjs → _imageId-gMdrdnVt.mjs} +2 -2
- package/dist/client/_imageId-gMdrdnVt.mjs.map +1 -0
- package/dist/client/{_projectId-BDARsteX.mjs → _projectId-BYccdAtX.mjs} +3 -3
- package/dist/client/{_projectId-BDARsteX.mjs.map → _projectId-BYccdAtX.mjs.map} +1 -1
- package/dist/client/{_projectId-ZBk6vka0.mjs → _projectId-CBjZC1tv.mjs} +5 -5
- package/dist/client/{_projectId-ZBk6vka0.mjs.map → _projectId-CBjZC1tv.mjs.map} +1 -1
- package/dist/client/{_projectId-CtyAHqhH.mjs → _projectId-CLEa1zgw.mjs} +2 -2
- package/dist/client/{_projectId-CtyAHqhH.mjs.map → _projectId-CLEa1zgw.mjs.map} +1 -1
- package/dist/client/{flavors-Ce3J-cFa.mjs → flavors-CJVSNz6R.mjs} +2 -2
- package/dist/client/{flavors-Ce3J-cFa.mjs.map → flavors-CJVSNz6R.mjs.map} +1 -1
- package/dist/client/{flavors-D5ThLaXO.mjs → flavors-CflJDIEH.mjs} +25 -24
- package/dist/client/{flavors-D5ThLaXO.mjs.map → flavors-CflJDIEH.mjs.map} +1 -1
- package/dist/client/imageHelpers-DBhL2ebL.mjs +1272 -0
- package/dist/client/imageHelpers-DBhL2ebL.mjs.map +1 -0
- package/dist/client/{images-C8M3ysWR.mjs → images-BsylWUiH.mjs} +836 -848
- package/dist/client/images-BsylWUiH.mjs.map +1 -0
- package/dist/client/{images-Cf5R28NR.mjs → images-zQq1nSVv.mjs} +2 -2
- package/dist/client/{images-Cf5R28NR.mjs.map → images-zQq1nSVv.mjs.map} +1 -1
- package/dist/client/index.js +10 -9
- package/dist/client/index.js.map +1 -1
- package/dist/client/{securitygroups-DXrfyuVF.mjs → securitygroups-CSmsBzUb.mjs} +104 -103
- package/dist/client/securitygroups-CSmsBzUb.mjs.map +1 -0
- package/dist/client/{securitygroups-67fFxiwt.mjs → securitygroups-T7kaNFEp.mjs} +2 -2
- package/dist/client/{securitygroups-67fFxiwt.mjs.map → securitygroups-T7kaNFEp.mjs.map} +1 -1
- package/dist/client/trpcClient.d.ts +0 -1
- package/dist/client/useErrorTranslation-Dc0eE8Zt.mjs +83 -0
- package/dist/client/useErrorTranslation-Dc0eE8Zt.mjs.map +1 -0
- package/dist/server/index.d.ts +0 -1
- package/dist/server/index.js +786 -534
- package/package.json +2 -2
- package/dist/client/DeleteFlavorModal-Be2GFiB_.mjs +0 -802
- package/dist/client/DeleteFlavorModal-Be2GFiB_.mjs.map +0 -1
- package/dist/client/ImageToastNotifications-BWfzOUMc.mjs +0 -1135
- package/dist/client/ImageToastNotifications-BWfzOUMc.mjs.map +0 -1
- package/dist/client/_flavorId-0PioWpEp.mjs +0 -276
- package/dist/client/_flavorId-0PioWpEp.mjs.map +0 -1
- package/dist/client/_imageId-Ccv8PedW.mjs.map +0 -1
- package/dist/client/_imageId-CiqEQB_J.mjs +0 -558
- package/dist/client/_imageId-CiqEQB_J.mjs.map +0 -1
- package/dist/client/_imageId-D9LR-02T.mjs.map +0 -1
- package/dist/client/images-C8M3ysWR.mjs.map +0 -1
- package/dist/client/securitygroups-DXrfyuVF.mjs.map +0 -1
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"DeleteFlavorModal-C4nAi7gY.mjs","names":["React","useState","useEffect","useMemo","useErrorTranslation","Modal","Button","Status","Stack","DescriptionList","DescriptionTerm","DescriptionDefinition","TextInput","Message","toast","buildInitialSpecs","extraSpecs","Object","entries","map","key","value","isEditing","createExtraSpecsPromise","client","project","flavorId","compute","getExtraSpecs","query","project_id","EditSpecModalInner","flavor","isLoading","onClose","initialSpecs","useLingui","translateError","specs","setSpecs","errors","setErrors","isAddingNew","setIsAddingNew","newKey","setNewKey","newValue","setNewValue","operationInProgress","setOperationInProgress","validationMessage","setValidationMessage","isModalDisabled","some","e","validateKey","rowIndex","normalized","trim","t","isDuplicate","entry","idx","handleAddNew","keyError","length","createExtraSpecs","mutate","id","extra_specs","success","description","error","errorMsg","Error","message","handleCancelAdd","handleEdit","index","i","editingValue","handleSaveEdit","spec","trimmedValue","handleCancelEdit","handleDelete","deleteExtraSpec","filter","_","handleValueChange","prev","next","handleClose","open","onCancel","size","title","cancelButtonLabel","disableCancelButton","status","className","div","variant","text","direction","label","onClick","disabled","body","alignTerms","onChange","target","placeholder","invalid","autoFocus","gap","icon","aria-label","Fragment","span","data-testid","EditSpecModal","isOpen","extraSpecsData","setExtraSpecsData","isLoadingSpecs","setIsLoadingSpecs","loadError","setLoadError","cancelled","loadData","getFlavorCreatedToast","name","message","description","getFlavorDeletedToast","getFlavorAccessAddedToast","projectId","flavorName","getFlavorAccessRemovedToast","getFlavorAccessAddErrorToast","errorMessage","getFlavorAccessRemoveErrorToast","React","useState","useEffect","useMemo","useErrorTranslation","Modal","Message","DescriptionList","DescriptionTerm","DescriptionDefinition","Stack","Status","Button","TextInput","toast","getFlavorAccessAddedToast","getFlavorAccessRemovedToast","getFlavorAccessRemoveErrorToast","buildInitialAccess","flavorAccess","map","access","projectId","tenant_id","createPermissionsPromise","client","project","compute","canUser","query","project_id","permission","then","canAdd","canRemove","createFlavorAccessPromise","flavorId","getFlavorAccess","ManageAccessModalInner","flavor","isLoading","onClose","initialAccess","useLingui","translateError","setAccess","errors","setErrors","isAddingNew","setIsAddingNew","newProjectId","setNewProjectId","deletingProjectIds","setDeletingProjectIds","Set","addingProjectId","setAddingProjectId","isPublicFlavor","validateProjectId","normalized","trim","t","isDuplicate","some","entry","handleAddNew","error","trimmedProjectId","addTenantAccess","mutate","id","targetProjectId","prev","message","options","name","success","errorMessage","Error","handleCancelAdd","handleDelete","add","removeTenantAccess","filter","a","next","delete","handleClose","flavorName","open","onCancel","size","title","p","className","isAnyOperationInProgress","status","div","variant","text","direction","label","onClick","disabled","length","span","value","onChange","e","target","placeholder","invalid","autoFocus","wrapperClassName","icon","progress","isDeleting","has","Fragment","gap","alignment","data-testid","ManageAccessModal","isOpen","flavorAccessData","setFlavorAccessData","permissionsData","setPermissionsData","isLoadingData","setIsLoadingData","loadError","setLoadError","cancelled","loadData","accessData","permissions","Promise","all","deduped","idx","arr","findIndex","body","z","useForm","useStore","React","useState","Modal","Stack","Form","FormSection","TextInput","DescriptionList","DescriptionTerm","DescriptionDefinition","Message","useErrorTranslation","useModalTracking","DeleteFlavorModal","client","isOpen","onClose","project","flavor","onSuccess","useLingui","translateError","isLoading","setIsLoading","formError","setFormError","trackClose","markSubmitted","resetTracking","actionPrefix","formSchema","object","confirm","string","refine","value","message","t","form","defaultValues","validators","onSubmit","id","compute","deleteFlavor","mutate","project_id","flavorId","handleClose","error","errorMessage","canDelete","store","state","isSubmitting","values","reset","confirmLabel","flavorName","name","open","onCancel","title","size","confirmButtonLabel","confirmButtonVariant","onConfirm","handleSubmit","cancelButtonLabel","disableConfirmButton","disableCancelButton","disableCloseButton","direction","gap","variant","p","className","vcpus","ram","disk","swap","Number","e","preventDefault","Field","children","field","label","onChange","handleChange","target","placeholder","autoFocus","disabled","required"],"sources":["../../src/client/routes/_auth/projects/$projectId/compute/flavors/-components/EditSpecModal.tsx","../../src/client/routes/_auth/projects/$projectId/compute/flavors/-components/FlavorToastNotifications.tsx","../../src/client/routes/_auth/projects/$projectId/compute/flavors/-components/ManageAccessModal.tsx","../../src/client/routes/_auth/projects/$projectId/compute/flavors/-components/DeleteFlavorModal.tsx"],"sourcesContent":["import React, { useState, useEffect, useMemo } from \"react\"\nimport { useLingui } from \"@lingui/react/macro\"\nimport { TrpcClient } from \"@/client/trpcClient\"\nimport { useErrorTranslation } from \"@/client/utils/useErrorTranslation\"\nimport {\n Modal,\n Button,\n Status,\n Stack,\n DescriptionList,\n DescriptionTerm,\n DescriptionDefinition,\n TextInput,\n Message,\n toast,\n} from \"@cloudoperators/juno-ui-components\"\nimport { Flavor } from \"@/server/Compute/types/flavor\"\n\ninterface EditSpecModalProps {\n client: TrpcClient\n isOpen: boolean\n onClose: () => void\n project: string\n flavor: Flavor | null\n}\n\ninterface SpecEntry {\n key: string\n value: string\n isEditing?: boolean\n editingValue?: string\n}\n\nfunction buildInitialSpecs(extraSpecs: Record<string, string>): SpecEntry[] {\n return Object.entries(extraSpecs).map(([key, value]) => ({\n key,\n value,\n isEditing: false,\n }))\n}\n\nconst createExtraSpecsPromise = (client: TrpcClient, project: string, flavorId: string) => {\n return client.compute.getExtraSpecs.query({\n project_id: project,\n flavorId: flavorId,\n })\n}\n\nfunction EditSpecModalInner({\n client,\n project,\n flavor,\n isLoading,\n onClose,\n initialSpecs,\n}: {\n client: TrpcClient\n project: string\n flavor: Flavor\n isLoading: boolean\n onClose: () => void\n initialSpecs: SpecEntry[]\n}) {\n const { t } = useLingui()\n const { translateError } = useErrorTranslation()\n\n const [specs, setSpecs] = useState<SpecEntry[]>(initialSpecs)\n const [errors, setErrors] = useState<{ [key: string]: string }>({})\n const [isAddingNew, setIsAddingNew] = useState(false)\n const [newKey, setNewKey] = useState(\"\")\n const [newValue, setNewValue] = useState(\"\")\n const [operationInProgress, setOperationInProgress] = useState(false)\n const [validationMessage, setValidationMessage] = useState<string | null>(null)\n\n const isModalDisabled = operationInProgress || isAddingNew || specs.some((e) => e.isEditing)\n\n const validateKey = (key: string, rowIndex?: number): string | null => {\n const normalized = key?.trim()\n if (!normalized) {\n return t`Key is required`\n }\n const isDuplicate = specs.some((entry, idx) => entry.key.trim() === normalized && idx !== rowIndex)\n if (isDuplicate) {\n return t`A property with this key already exists`\n }\n return null\n }\n\n const handleAddNew = async () => {\n const keyError = validateKey(newKey, specs.length)\n if (keyError) {\n setErrors({ newKey: \"error\" })\n setValidationMessage(keyError)\n return\n }\n if (!newValue.trim()) {\n setErrors({ newValue: \"error\" })\n setValidationMessage(t`Value is required`)\n return\n }\n\n setOperationInProgress(true)\n try {\n await client.compute.createExtraSpecs.mutate({\n project_id: project,\n flavorId: flavor.id,\n extra_specs: { [newKey.trim()]: newValue.trim() },\n })\n\n setSpecs([...specs, { key: newKey.trim(), value: newValue.trim(), isEditing: false }])\n setNewKey(\"\")\n setNewValue(\"\")\n setIsAddingNew(false)\n setErrors({})\n setValidationMessage(null)\n\n toast.success(t`Property Created`, {\n description: t`Property was successfully created.`,\n })\n } catch (error) {\n const errorMsg = translateError(error instanceof Error ? error.message : \"Failed to create property\")\n setValidationMessage(errorMsg)\n } finally {\n setOperationInProgress(false)\n }\n }\n\n const handleCancelAdd = () => {\n setNewKey(\"\")\n setNewValue(\"\")\n setIsAddingNew(false)\n setErrors({})\n setValidationMessage(null)\n }\n\n const handleEdit = (index: number) => {\n setSpecs(\n specs.map((e, i) => (i === index ? { ...e, isEditing: true, editingValue: e.value } : { ...e, isEditing: false }))\n )\n setIsAddingNew(false)\n }\n\n const handleSaveEdit = async (index: number) => {\n const spec = specs[index]\n\n if (!spec.value.trim()) {\n setErrors({ [`edit-value-${index}`]: \"error\" })\n setValidationMessage(t`Value is required`)\n return\n }\n\n setOperationInProgress(true)\n try {\n const trimmedValue = spec.value.trim()\n\n // Create/update the spec (OpenStack API handles upsert)\n await client.compute.createExtraSpecs.mutate({\n project_id: project,\n flavorId: flavor.id,\n extra_specs: { [spec.key]: trimmedValue },\n })\n\n setSpecs(specs.map((e, i) => (i === index ? { key: spec.key, value: trimmedValue, isEditing: false } : e)))\n setErrors({})\n setValidationMessage(null)\n\n toast.success(t`Property Updated`, {\n description: t`Property was successfully updated.`,\n })\n } catch (error) {\n const errorMsg = translateError(error instanceof Error ? error.message : \"Failed to update property\")\n setValidationMessage(errorMsg)\n } finally {\n setOperationInProgress(false)\n }\n }\n\n const handleCancelEdit = (index: number) => {\n setSpecs(\n specs.map((e, i) => (i === index ? { key: e.key, value: e.editingValue ?? e.value, isEditing: false } : e))\n )\n setErrors({})\n setValidationMessage(null)\n }\n\n const handleDelete = async (index: number) => {\n const spec = specs[index]\n setOperationInProgress(true)\n\n try {\n await client.compute.deleteExtraSpec.mutate({\n project_id: project,\n flavorId: flavor.id,\n key: spec.key,\n })\n\n setSpecs(specs.filter((_, i) => i !== index))\n setErrors({})\n setValidationMessage(null)\n\n toast.success(t`Property Deleted`, {\n description: t`Property was successfully deleted.`,\n })\n } catch (error) {\n const errorMsg = translateError(error instanceof Error ? error.message : \"Failed to delete property\")\n setValidationMessage(errorMsg)\n } finally {\n setOperationInProgress(false)\n }\n }\n\n const handleValueChange = (index: number, value: string) => {\n setSpecs(specs.map((entry, i) => (i === index ? { ...entry, value } : entry)))\n if (errors[`edit-value-${index}`]) {\n setErrors((prev) => {\n const next = { ...prev }\n delete next[`edit-value-${index}`]\n return next\n })\n setValidationMessage(null)\n }\n }\n\n const handleClose = () => {\n if (!operationInProgress) {\n setIsAddingNew(false)\n setNewKey(\"\")\n setNewValue(\"\")\n setErrors({})\n setValidationMessage(null)\n onClose()\n }\n }\n\n return (\n <Modal\n open\n onCancel={handleClose}\n size=\"xl\"\n title={t`Edit Metadata`}\n cancelButtonLabel={t`Close`}\n disableCancelButton={operationInProgress}\n >\n {isLoading ? (\n <Status status=\"progress\" title={t`Loading Metadata...`} className=\"mt-0\" />\n ) : (\n <div>\n {validationMessage && <Message variant=\"error\" text={validationMessage} className=\"mb-4\" />}\n\n <Stack direction=\"horizontal\" className=\"mb-4 justify-end\">\n <Button label={t`Add Property`} onClick={() => setIsAddingNew(true)} disabled={isModalDisabled} />\n </Stack>\n\n {specs.length === 0 && !isAddingNew ? (\n <Status\n status=\"empty\"\n title={t`No Metadata Properties Found`}\n body={t`Click \"Add Property\" to create one.`}\n className=\"m-0\"\n />\n ) : (\n <DescriptionList className=\"mb-6 grid-cols-2\" alignTerms=\"left\">\n <>\n {isAddingNew && (\n <>\n <DescriptionTerm className=\"col-span-1\">\n <TextInput\n value={newKey}\n onChange={(e) => {\n setNewKey(e.target.value)\n if (errors.newKey) {\n setErrors((prev) => {\n const next = { ...prev }\n delete next.newKey\n return next\n })\n setValidationMessage(null)\n }\n }}\n placeholder={t`property_key`}\n invalid={!!errors.newKey}\n autoFocus\n disabled={operationInProgress}\n />\n </DescriptionTerm>\n <DescriptionDefinition className=\"col-span-1 flex items-center gap-2\">\n <div className=\"flex-1\">\n <TextInput\n value={newValue}\n onChange={(e) => {\n setNewValue(e.target.value)\n if (errors.newValue) {\n setErrors((prev) => {\n const next = { ...prev }\n delete next.newValue\n return next\n })\n setValidationMessage(null)\n }\n }}\n placeholder={t`Value`}\n invalid={!!errors.newValue}\n disabled={operationInProgress}\n />\n </div>\n <Stack direction=\"horizontal\" gap=\"2\" className=\"shrink-0\">\n <Button\n size=\"small\"\n variant=\"primary\"\n onClick={handleAddNew}\n icon=\"check\"\n title={t`Save`}\n aria-label={t`Save`}\n disabled={operationInProgress}\n />\n <Button\n size=\"small\"\n variant=\"subdued\"\n onClick={handleCancelAdd}\n icon=\"close\"\n title={t`Discard`}\n aria-label={t`Discard`}\n disabled={operationInProgress}\n />\n </Stack>\n </DescriptionDefinition>\n </>\n )}\n </>\n\n <>\n {specs.map((entry, index) => (\n <React.Fragment key={index}>\n <DescriptionTerm className=\"col-span-1\">\n {entry.isEditing ? (\n <span className=\"jn:text-theme-high block break-all\" title={entry.key}>\n {entry.key}\n </span>\n ) : (\n <span className=\"jn:text-theme-high block break-all\" title={entry.key}>\n {entry.key}\n </span>\n )}\n </DescriptionTerm>\n <DescriptionDefinition className=\"col-span-1 flex items-center gap-2\">\n {entry.isEditing ? (\n <>\n <div className=\"flex-1\">\n <TextInput\n value={entry.value}\n onChange={(e) => handleValueChange(index, e.target.value)}\n invalid={!!errors[`edit-value-${index}`]}\n disabled={operationInProgress}\n />\n </div>\n <Stack direction=\"horizontal\" gap=\"2\" className=\"shrink-0\">\n <Button\n size=\"small\"\n variant=\"primary\"\n onClick={() => handleSaveEdit(index)}\n icon=\"check\"\n title={t`Save`}\n aria-label={t`Save`}\n disabled={operationInProgress}\n />\n <Button\n size=\"small\"\n variant=\"subdued\"\n onClick={() => handleCancelEdit(index)}\n icon=\"close\"\n title={t`Discard`}\n aria-label={t`Discard`}\n disabled={operationInProgress}\n />\n </Stack>\n </>\n ) : (\n <>\n <span className=\"jn:text-theme-default flex-1 break-all\" title={entry.value}>\n {entry.value}\n </span>\n <Stack direction=\"horizontal\" gap=\"2\" className=\"shrink-0\">\n <Button\n size=\"small\"\n variant=\"subdued\"\n onClick={() => handleEdit(index)}\n icon=\"edit\"\n data-testid={`edit-${entry.key}`}\n title={t`Edit`}\n disabled={isModalDisabled}\n />\n <Button\n size=\"small\"\n onClick={() => handleDelete(index)}\n icon=\"deleteForever\"\n data-testid={`delete-${entry.key}`}\n title={t`Delete`}\n aria-label={t`Delete`}\n disabled={isModalDisabled}\n />\n </Stack>\n </>\n )}\n </DescriptionDefinition>\n </React.Fragment>\n ))}\n </>\n </DescriptionList>\n )}\n </div>\n )}\n </Modal>\n )\n}\n\nexport const EditSpecModal: React.FC<EditSpecModalProps> = ({ client, isOpen, onClose, project, flavor }) => {\n const { t } = useLingui()\n const { translateError } = useErrorTranslation()\n\n const [extraSpecsData, setExtraSpecsData] = useState<Record<string, string> | null>(null)\n const [isLoadingSpecs, setIsLoadingSpecs] = useState(false)\n const [loadError, setLoadError] = useState<string | null>(null)\n\n useEffect(() => {\n if (!isOpen || !flavor?.id) {\n setExtraSpecsData(null)\n setLoadError(null)\n return\n }\n\n let cancelled = false\n setIsLoadingSpecs(true)\n setLoadError(null)\n\n const loadData = async () => {\n try {\n const specs = await createExtraSpecsPromise(client, project, flavor.id)\n if (cancelled) return\n setExtraSpecsData(specs)\n } catch (error) {\n if (cancelled) return\n setLoadError(error instanceof Error ? error.message : \"Failed to Load Metadata\")\n } finally {\n if (!cancelled) setIsLoadingSpecs(false)\n }\n }\n\n loadData()\n return () => {\n cancelled = true\n }\n }, [isOpen, flavor?.id, client, project])\n\n const initialSpecs = useMemo(() => (extraSpecsData ? buildInitialSpecs(extraSpecsData) : []), [extraSpecsData])\n\n if (!isOpen || !flavor) {\n return null\n }\n\n if (isLoadingSpecs) {\n return (\n <Modal open onCancel={onClose} size=\"xl\" title={t`Edit Metadata`}>\n <Status status=\"progress\" title={t`Loading Metadata...`} className=\"mt-0\" />\n </Modal>\n )\n }\n\n if (loadError) {\n return (\n <Modal open onCancel={onClose} size=\"xl\" title={t`Edit Metadata`}>\n <Status status=\"error\" title={t`Failed to Load Metadata`} body={translateError(loadError)} className=\"mt-0\" />\n </Modal>\n )\n }\n\n return (\n <EditSpecModalInner\n key={flavor.id}\n client={client}\n project={project}\n flavor={flavor}\n isLoading={false}\n onClose={onClose}\n initialSpecs={initialSpecs}\n />\n )\n}\n","import { ReactNode } from \"react\"\nimport { NotificationOptions } from \"@cloudoperators/juno-ui-components\"\nimport { Trans } from \"@lingui/react/macro\"\n\ntype ToastReturnType = { message: ReactNode } & NotificationOptions\n\nexport const getFlavorCreatedToast = (name: string): ToastReturnType => ({\n message: <Trans>Flavor Created</Trans>,\n description: <Trans>Flavor \"{name}\" was successfully created.</Trans>,\n})\n\nexport const getFlavorDeletedToast = (name: string): ToastReturnType => ({\n message: <Trans>Flavor Deleted</Trans>,\n description: <Trans>Flavor \"{name}\" was successfully deleted.</Trans>,\n})\n\nexport const getFlavorAccessAddedToast = (projectId: string, flavorName: string): ToastReturnType => ({\n message: <Trans>Access Added</Trans>,\n description: (\n <Trans>\n Project \"{projectId}\" now has access to flavor \"{flavorName}\".\n </Trans>\n ),\n})\n\nexport const getFlavorAccessRemovedToast = (projectId: string, flavorName: string): ToastReturnType => ({\n message: <Trans>Access Removed</Trans>,\n description: (\n <Trans>\n Access for project \"{projectId}\" to flavor \"{flavorName}\" was successfully revoked.\n </Trans>\n ),\n})\n\nexport const getFlavorAccessAddErrorToast = (projectId: string, errorMessage: string): ToastReturnType => ({\n message: <Trans>Failed to Add Access</Trans>,\n description: (\n <Trans>\n Could not add access for project \"{projectId}\": {errorMessage}\n </Trans>\n ),\n})\n\nexport const getFlavorAccessRemoveErrorToast = (projectId: string, errorMessage: string): ToastReturnType => ({\n message: <Trans>Failed to Remove Access</Trans>,\n description: (\n <Trans>\n Could not remove access for project \"{projectId}\": {errorMessage}\n </Trans>\n ),\n})\n","import React, { useState, useEffect, useMemo } from \"react\"\nimport { TrpcClient } from \"@/client/trpcClient\"\nimport { useLingui } from \"@lingui/react/macro\"\nimport { useErrorTranslation } from \"@/client/utils/useErrorTranslation\"\nimport {\n Modal,\n Message,\n DescriptionList,\n DescriptionTerm,\n DescriptionDefinition,\n Stack,\n Status,\n Button,\n TextInput,\n toast,\n} from \"@cloudoperators/juno-ui-components\"\nimport { Flavor } from \"@/server/Compute/types/flavor\"\nimport {\n getFlavorAccessAddedToast,\n getFlavorAccessRemovedToast,\n getFlavorAccessRemoveErrorToast,\n} from \"./FlavorToastNotifications\"\n\ninterface ManageAccessProps {\n client: TrpcClient\n isOpen: boolean\n onClose: () => void\n project: string\n flavor: Flavor | null\n}\n\ninterface FlavorAccess {\n flavor_id: string\n tenant_id: string\n}\n\ninterface AccessEntry {\n projectId: string\n}\n\nfunction buildInitialAccess(flavorAccess: FlavorAccess[]): AccessEntry[] {\n return flavorAccess.map((access) => ({\n projectId: access.tenant_id,\n }))\n}\n\nconst createPermissionsPromise = (client: TrpcClient, project: string) => {\n return client.compute.canUser\n .query({\n project_id: project,\n permission: [\"flavors:add_project\", \"flavors:remove_project\"],\n })\n .then(([canAdd, canRemove]) => ({ canAdd, canRemove }))\n}\n\nconst createFlavorAccessPromise = (client: TrpcClient, project: string, flavorId: string) => {\n return client.compute.getFlavorAccess.query({\n project_id: project,\n flavorId: flavorId,\n })\n}\n\nfunction ManageAccessModalInner({\n client,\n project,\n flavor,\n isLoading,\n onClose,\n initialAccess,\n canAdd,\n canRemove,\n}: {\n client: TrpcClient\n project: string\n flavor: Flavor\n isLoading: boolean\n onClose: () => void\n initialAccess: AccessEntry[]\n canAdd: boolean\n canRemove: boolean\n}) {\n const { t } = useLingui()\n const { translateError } = useErrorTranslation()\n\n const [access, setAccess] = useState<AccessEntry[]>(initialAccess)\n const [errors, setErrors] = useState<{ [key: string]: string }>({})\n const [isAddingNew, setIsAddingNew] = useState(false)\n const [newProjectId, setNewProjectId] = useState(\"\")\n const [deletingProjectIds, setDeletingProjectIds] = useState<Set<string>>(new Set())\n const [addingProjectId, setAddingProjectId] = useState(false)\n\n const isPublicFlavor = flavor[\"os-flavor-access:is_public\"] !== false\n\n const validateProjectId = (projectId: string): string | null => {\n const normalized = projectId?.trim()\n if (!normalized) {\n return t`Project ID is required`\n }\n const isDuplicate = access.some((entry) => entry.projectId.trim() === normalized)\n if (isDuplicate) {\n return t`This project already has access`\n }\n return null\n }\n\n const handleAddNew = async () => {\n const error = validateProjectId(newProjectId)\n if (error) {\n setErrors({ newProjectId: error })\n return\n }\n\n const trimmedProjectId = newProjectId.trim()\n setAddingProjectId(true)\n setErrors({})\n\n try {\n await client.compute.addTenantAccess.mutate({\n project_id: project,\n flavorId: flavor.id,\n targetProjectId: trimmedProjectId,\n })\n\n setAccess((prev) => [...prev, { projectId: trimmedProjectId }])\n setNewProjectId(\"\")\n setIsAddingNew(false)\n\n const { message, ...options } = getFlavorAccessAddedToast(trimmedProjectId, flavor.name)\n toast.success(message, options)\n } catch (error) {\n const errorMessage = translateError(error instanceof Error ? error.message : \"Failed to add access\")\n setErrors({ newProjectId: errorMessage })\n // Error shown inline via Message component above the form\n } finally {\n setAddingProjectId(false)\n }\n }\n\n const handleCancelAdd = () => {\n setNewProjectId(\"\")\n setIsAddingNew(false)\n setErrors({})\n }\n\n const handleDelete = async (projectId: string) => {\n setErrors({})\n setDeletingProjectIds((prev) => new Set(prev).add(projectId))\n\n try {\n await client.compute.removeTenantAccess.mutate({\n project_id: project,\n flavorId: flavor.id,\n targetProjectId: projectId,\n })\n\n setAccess((prev) => prev.filter((a) => a.projectId !== projectId))\n\n const { message, ...options } = getFlavorAccessRemovedToast(projectId, flavor.name)\n toast.success(message, options)\n } catch (error) {\n const errorMessage = translateError(error instanceof Error ? error.message : \"Failed to remove access\")\n const { message, ...options } = getFlavorAccessRemoveErrorToast(projectId, errorMessage)\n toast.error(message, options)\n } finally {\n setDeletingProjectIds((prev) => {\n const next = new Set(prev)\n next.delete(projectId)\n return next\n })\n }\n }\n\n const handleClose = () => {\n setIsAddingNew(false)\n setNewProjectId(\"\")\n setErrors({})\n onClose()\n }\n\n if (isPublicFlavor) {\n const flavorName = flavor.name\n return (\n <Modal open onCancel={handleClose} size=\"large\" title={t`Manage Access - ${flavorName}`}>\n <p className=\"jn:text-theme-light py-8 text-center\">\n {t`This is a public flavor. All projects have access to it.`}\n </p>\n </Modal>\n )\n }\n\n const flavorName = flavor.name\n const isAnyOperationInProgress = addingProjectId || deletingProjectIds.size > 0\n\n return (\n <Modal open onCancel={handleClose} size=\"large\" title={t`Manage Access - ${flavorName}`}>\n {isLoading ? (\n <Status status=\"progress\" title={t`Loading Access...`} className=\"mt-0\" />\n ) : (\n <div>\n {errors.newProjectId && <Message variant=\"error\" text={errors.newProjectId} className=\"mb-4\" />}\n\n {canAdd && (\n <Stack direction=\"horizontal\" className=\"mb-4 justify-end\">\n <Button\n label={t`Add Project`}\n onClick={() => setIsAddingNew(true)}\n disabled={isAddingNew || isAnyOperationInProgress}\n />\n </Stack>\n )}\n\n {access.length === 0 && !isAddingNew ? (\n <p className=\"jn:text-theme-light py-8 text-center\">\n {canAdd\n ? t`No project access configured. Click \"Add Project\" to grant access.`\n : t`No project access configured.`}\n </p>\n ) : (\n <DescriptionList className=\"mb-6\">\n <>\n {isAddingNew && (\n <>\n <DescriptionTerm className=\"flex items-center justify-end\">\n <span className=\"jn:text-theme-high\">{t`Project`}</span>\n </DescriptionTerm>\n <DescriptionDefinition>\n <div className=\"flex w-full items-center gap-2\">\n <div className=\"flex-1\">\n <TextInput\n value={newProjectId}\n onChange={(e) => {\n setNewProjectId(e.target.value)\n if (errors.newProjectId) {\n setErrors({})\n }\n }}\n placeholder={t`Enter project ID`}\n invalid={!!errors.newProjectId}\n autoFocus\n wrapperClassName=\"w-full\"\n disabled={addingProjectId}\n />\n </div>\n <div className=\"flex shrink-0 gap-2\">\n <Button\n size=\"small\"\n variant=\"primary\"\n onClick={handleAddNew}\n icon=\"check\"\n title={t`Add`}\n disabled={addingProjectId}\n progress={addingProjectId}\n />\n <Button\n size=\"small\"\n variant=\"subdued\"\n onClick={handleCancelAdd}\n icon=\"close\"\n title={t`Cancel`}\n disabled={addingProjectId}\n />\n </div>\n </div>\n </DescriptionDefinition>\n </>\n )}\n </>\n\n <>\n {access.map((entry) => {\n const isDeleting = deletingProjectIds.has(entry.projectId)\n return (\n <React.Fragment key={entry.projectId}>\n <DescriptionTerm>\n <span className=\"jn:text-theme-high\">{t`Project`}</span>\n </DescriptionTerm>\n <DescriptionDefinition>\n <Stack direction=\"horizontal\" gap=\"2\" alignment=\"center\" className=\"justify-between\">\n <span className=\"jn:text-theme-high block max-w-xs truncate\" title={entry.projectId}>\n {entry.projectId}\n </span>\n {canRemove && (\n <Button\n size=\"small\"\n onClick={() => handleDelete(entry.projectId)}\n icon=\"deleteForever\"\n data-testid={`delete-${entry.projectId}`}\n title={t`Remove`}\n disabled={isDeleting || isAddingNew}\n progress={isDeleting}\n />\n )}\n </Stack>\n </DescriptionDefinition>\n </React.Fragment>\n )\n })}\n </>\n </DescriptionList>\n )}\n </div>\n )}\n </Modal>\n )\n}\n\nexport const ManageAccessModal: React.FC<ManageAccessProps> = ({ client, isOpen, onClose, project, flavor }) => {\n const { t } = useLingui()\n const { translateError } = useErrorTranslation()\n\n const [flavorAccessData, setFlavorAccessData] = useState<FlavorAccess[] | null>(null)\n const [permissionsData, setPermissionsData] = useState<{ canAdd: boolean; canRemove: boolean } | null>(null)\n const [isLoadingData, setIsLoadingData] = useState(true)\n const [loadError, setLoadError] = useState<string | null>(null)\n\n useEffect(() => {\n if (!isOpen || !flavor?.id) {\n setFlavorAccessData(null)\n setPermissionsData(null)\n setLoadError(null)\n return\n }\n\n let cancelled = false\n setIsLoadingData(true)\n setLoadError(null)\n\n const loadData = async () => {\n try {\n const [accessData, permissions] = await Promise.all([\n createFlavorAccessPromise(client, project, flavor.id),\n createPermissionsPromise(client, project),\n ])\n if (cancelled) return\n // Deduplicate\n const deduped = accessData.filter(\n (entry, idx, arr) => arr.findIndex((e) => e.tenant_id === entry.tenant_id) === idx\n )\n setFlavorAccessData(deduped)\n setPermissionsData(permissions)\n } catch (error) {\n if (cancelled) return\n setLoadError(error instanceof Error ? error.message : \"Failed to Load Access Data\")\n } finally {\n if (!cancelled) setIsLoadingData(false)\n }\n }\n\n loadData()\n return () => {\n cancelled = true\n }\n }, [isOpen, flavor?.id, client, project])\n\n const initialAccess = useMemo(\n () => (flavorAccessData ? buildInitialAccess(flavorAccessData) : []),\n [flavorAccessData]\n )\n\n if (!isOpen || !flavor) {\n return null\n }\n\n const flavorName = flavor.name\n\n if (isLoadingData) {\n return (\n <Modal open onCancel={onClose} size=\"large\" title={t`Manage Access - ${flavorName}`}>\n <Status status=\"progress\" title={t`Loading Access...`} className=\"mt-0\" />\n </Modal>\n )\n }\n\n if (loadError) {\n return (\n <Modal open onCancel={onClose} size=\"large\" title={t`Manage Access - ${flavorName}`}>\n <Status status=\"error\" title={t`Failed to Load Access`} body={translateError(loadError)} className=\"mt-0\" />\n </Modal>\n )\n }\n\n return (\n <ManageAccessModalInner\n key={flavor.id}\n client={client}\n project={project}\n flavor={flavor}\n isLoading={false}\n onClose={onClose}\n initialAccess={initialAccess}\n canAdd={permissionsData?.canAdd ?? false}\n canRemove={permissionsData?.canRemove ?? false}\n />\n )\n}\n","import { z } from \"zod\"\nimport { useForm, useStore } from \"@tanstack/react-form\"\nimport React, { useState } from \"react\"\nimport { useLingui } from \"@lingui/react/macro\"\nimport { TrpcClient } from \"@/client/trpcClient\"\nimport {\n Modal,\n Stack,\n Form,\n FormSection,\n TextInput,\n DescriptionList,\n DescriptionTerm,\n DescriptionDefinition,\n Message,\n} from \"@cloudoperators/juno-ui-components\"\nimport { Flavor } from \"@/server/Compute/types/flavor\"\nimport { Trans } from \"@lingui/react/macro\"\nimport { useErrorTranslation } from \"@/client/utils/useErrorTranslation\"\nimport { useModalTracking } from \"@/client/hooks/useModalTracking\"\n\ninterface DeleteFlavorModalProps {\n client: TrpcClient\n isOpen: boolean\n onClose: () => void\n project: string\n flavor: Flavor | null\n onSuccess: () => void\n}\n\nexport const DeleteFlavorModal: React.FC<DeleteFlavorModalProps> = ({\n client,\n isOpen,\n onClose,\n project,\n flavor,\n onSuccess,\n}) => {\n const { t } = useLingui()\n const { translateError } = useErrorTranslation()\n const [isLoading, setIsLoading] = useState(false)\n const [formError, setFormError] = useState<string | null>(null)\n\n const { trackClose, markSubmitted, resetTracking } = useModalTracking({\n isOpen,\n actionPrefix: \"compute.flavor.delete\",\n })\n\n const formSchema = z.object({\n confirm: z.string().refine((value) => value === \"delete\", {\n message: t`Type \"delete\" to confirm`,\n }),\n })\n\n const form = useForm({\n defaultValues: {\n confirm: \"\",\n },\n validators: {\n onSubmit: formSchema,\n },\n onSubmit: async () => {\n if (!flavor?.id) {\n setFormError(t`No flavor selected for deletion.`)\n return\n }\n\n if (isLoading) return\n\n markSubmitted()\n setFormError(null)\n\n try {\n setIsLoading(true)\n\n await client.compute.deleteFlavor.mutate({\n project_id: project,\n flavorId: flavor.id,\n })\n onSuccess()\n handleClose()\n } catch (error) {\n const errorMessage = (error as Error)?.message\n ? translateError((error as Error).message)\n : t`Failed to delete flavor. Please try again.`\n setFormError(errorMessage)\n } finally {\n setIsLoading(false)\n }\n },\n })\n\n const canDelete = useStore(form.store, (state) => state.isSubmitting || state.values.confirm !== \"delete\")\n\n const handleClose = () => {\n trackClose()\n setIsLoading(false)\n setFormError(null)\n form.reset()\n resetTracking()\n onClose()\n }\n\n const confirmLabel = isLoading ? t`Deleting...` : t`Delete Flavor`\n const flavorName = flavor?.name\n\n return (\n <Modal\n open={isOpen}\n onCancel={handleClose}\n title={t`Delete Flavor \"${flavorName}\"`}\n size=\"small\"\n confirmButtonLabel={confirmLabel}\n confirmButtonVariant=\"primary-danger\"\n onConfirm={form.handleSubmit}\n cancelButtonLabel={t`Cancel`}\n disableConfirmButton={canDelete || isLoading}\n disableCancelButton={isLoading}\n disableCloseButton={isLoading}\n >\n <Stack direction=\"vertical\" gap=\"4\">\n {formError && <Message variant=\"error\">{formError}</Message>}\n\n <p className=\"text-theme-default\">\n <Trans>This action cannot be undone. The flavor will be permanently deleted.</Trans>\n </p>\n\n {flavor && (\n <DescriptionList>\n <DescriptionTerm>{t`Name`}</DescriptionTerm>\n <DescriptionDefinition>{flavor.name}</DescriptionDefinition>\n\n <DescriptionTerm>{t`ID`}</DescriptionTerm>\n <DescriptionDefinition>{flavor.id}</DescriptionDefinition>\n\n <DescriptionTerm>{t`VCPUs`}</DescriptionTerm>\n <DescriptionDefinition>{flavor.vcpus}</DescriptionDefinition>\n\n <DescriptionTerm>{t`RAM`}</DescriptionTerm>\n <DescriptionDefinition>{flavor.ram} MiB</DescriptionDefinition>\n\n <DescriptionTerm>{t`Disk`}</DescriptionTerm>\n <DescriptionDefinition>{flavor.disk} GiB</DescriptionDefinition>\n\n <DescriptionTerm>{t`Swap`}</DescriptionTerm>\n <DescriptionDefinition>\n {flavor.swap === 0 || flavor.swap === \"\" ? <Trans>None</Trans> : `${Number(flavor.swap)} MiB`}\n </DescriptionDefinition>\n </DescriptionList>\n )}\n\n <Form\n className=\"mb-0\"\n id=\"delete-flavor-form\"\n onSubmit={(e) => {\n e.preventDefault()\n form.handleSubmit()\n }}\n >\n <FormSection>\n <form.Field\n name=\"confirm\"\n children={(field) => (\n <TextInput\n id={field.name}\n name={field.name}\n label={t`Type \"delete\" to confirm`}\n value={field.state.value}\n onChange={(e) => field.handleChange(e.target.value)}\n placeholder=\"delete\"\n autoFocus\n disabled={isLoading}\n required\n />\n )}\n />\n </FormSection>\n </Form>\n </Stack>\n </Modal>\n )\n}\n"],"mappings":";;;;;;;;;AAiCA,SAASe,EAAkBC,GAAkC;CAC3D,OAAOC,OAAOC,QAAQF,CAAAA,CAAAA,CAAYG,KAAK,CAACC,GAAKC,QAAY;EACvDD;EACAC;EACAC,WAAW;CACb,EAAA;AACF;AAEA,IAAMC,KAA2BC,GAAoBC,GAAiBC,MAC7DF,EAAOG,QAAQC,cAAcC,MAAM;CACxCC,YAAYL;CACFC;AACZ,CAAA;AAGF,SAASK,EAAmB,EAC1BP,WACAC,YACAO,WACAC,cACAC,YACAC,mBAQD;CACC,IAAM,EAAA,MAAA,GAAA,GAAA,MAAQC,EAAAA,GACR,EAAEC,sBAAmBjC,EAAAA,GAErB,CAACkC,GAAOC,KAAYtC,EAAsBkC,CAAAA,GAC1C,CAACK,GAAQC,KAAaxC,EAAoC,CAAC,CAAA,GAC3D,CAACyC,GAAaC,KAAkB1C,EAAS,EAAA,GACzC,CAAC2C,GAAQC,KAAa5C,EAAS,EAAA,GAC/B,CAAC6C,GAAUC,KAAe9C,EAAS,EAAA,GACnC,CAAC+C,GAAqBC,KAA0BhD,EAAS,EAAA,GACzD,CAACiD,GAAmBC,KAAwBlD,EAAwB,IAAA,GAEpEmD,IAAkBJ,KAAuBN,KAAeJ,EAAMe,MAAMC,MAAMA,EAAEhC,SAAS,GAErFiC,KAAenC,GAAaoC,MAAAA;EAChC,IAAMC,IAAarC,GAAKsC,KAAAA;EAQxB,OAPKD,IAGenB,EAAMe,MAAMQ,GAAOC,MAAQD,EAAMzC,IAAIsC,KAAI,MAAOD,KAAcK,MAAQN,CACtFI,IACKD,EAAAA,EAAC,EAAA,IAAA,SAAwC,CAAA,IAE3C,OANEA,EAAAA,EAAC,EAAA,IAAA,SAAgB,CAAA;CAO5B,GAEMI,IAAe,YAAA;EACnB,IAAMC,IAAWT,EAAYX,GAAQN,EAAM2B,MAAM;EACjD,IAAID,GAAU;GAEZb,AADAV,EAAU,EAAEG,QAAQ,QAAQ,CAAA,GAC5BO,EAAqBa,CAAAA;GACrB;EACF;EACA,IAAI,CAAClB,EAASY,KAAI,GAAI;GAEpBP,AADAV,EAAU,EAAEK,UAAU,QAAQ,CAAA,GAC9BK,EAAqBQ,EAAAA,EAAC,EAAA,IAAA,SAAkB,CAAA,CAAA;GACxC;EACF;EAEAV,EAAuB,EAAA;EACvB,IAAI;GAcFnC,AAbA,MAAMU,EAAOG,QAAQuC,iBAAiBC,OAAO;IAC3CrC,YAAYL;IACZC,UAAUM,EAAOoC;IACjBC,aAAa,GAAGzB,EAAOc,KAAI,IAAKZ,EAASY,KAAI,EAAG;GAClD,CAAA,GAEAnB,EAAS,CAAID,GAAAA,GAAO;IAAElB,KAAKwB,EAAOc,KAAI;IAAIrC,OAAOyB,EAASY,KAAI;IAAIpC,WAAW;GAAM,CAAE,CAAA,GACrFuB,EAAU,EAAA,GACVE,EAAY,EAAA,GACZJ,EAAe,EAAA,GACfF,EAAU,CAAC,CAAA,GACXU,EAAqB,IAAA,GAErBrC,EAAMwD,QAAQX,EAAAA,EAAC,EAAA,IAAA,SAAiB,CAAA,GAAG,EACjCY,aAAaZ,EAAAA,EAAC,EAAA,IAAA,SAAmC,CAAA,EACnD,CAAA;EACF,SAASa,GAAO;GACd,IAAMC,IAAWpC,EAAemC,aAAiBE,QAAQF,EAAMG,UAAU,2BAAA;GACzExB,EAAqBsB,CAAAA;EACvB,UAAU;GACRxB,EAAuB,EAAA;EACzB;CACF,GAEM2B,UAAkB;EAKtBzB,AAJAN,EAAU,EAAA,GACVE,EAAY,EAAA,GACZJ,EAAe,EAAA,GACfF,EAAU,CAAC,CAAA,GACXU,EAAqB,IAAA;CACvB,GAEM0B,KAAcC,MAAAA;EAIlBnC,AAHAJ,EACED,EAAMnB,KAAKmC,GAAGyB,MAAOA,MAAMD,IAAQ;GAAE,GAAGxB;GAAGhC,WAAW;GAAM0D,cAAc1B,EAAEjC;EAAM,IAAI;GAAE,GAAGiC;GAAGhC,WAAW;EAAM,CAAA,CAAA,GAEjHqB,EAAe,EAAA;CACjB,GAEMsC,IAAiB,OAAOH,MAAAA;EAC5B,IAAMI,IAAO5C,EAAMwC;EAEnB,IAAI,CAACI,EAAK7D,MAAMqC,KAAI,GAAI;GAEtBP,AADAV,EAAU,GAAG,cAAcqC,MAAU,QAAQ,CAAA,GAC7C3B,EAAqBQ,EAAAA,EAAC,EAAA,IAAA,SAAkB,CAAA,CAAA;GACxC;EACF;EAEAV,EAAuB,EAAA;EACvB,IAAI;GACF,IAAMkC,IAAeD,EAAK7D,MAAMqC,KAAI;GAapC5C,AAVA,MAAMU,EAAOG,QAAQuC,iBAAiBC,OAAO;IAC3CrC,YAAYL;IACZC,UAAUM,EAAOoC;IACjBC,aAAa,GAAGa,EAAK9D,MAAM+D,EAAa;GAC1C,CAAA,GAEA5C,EAASD,EAAMnB,KAAKmC,GAAGyB,MAAOA,MAAMD,IAAQ;IAAE1D,KAAK8D,EAAK9D;IAAKC,OAAO8D;IAAc7D,WAAW;GAAM,IAAIgC,CAAAA,CAAAA,GACvGb,EAAU,CAAC,CAAA,GACXU,EAAqB,IAAA,GAErBrC,EAAMwD,QAAQX,EAAAA,EAAC,EAAA,IAAA,SAAiB,CAAA,GAAG,EACjCY,aAAaZ,EAAAA,EAAC,EAAA,IAAA,SAAmC,CAAA,EACnD,CAAA;EACF,SAASa,GAAO;GACd,IAAMC,IAAWpC,EAAemC,aAAiBE,QAAQF,EAAMG,UAAU,2BAAA;GACzExB,EAAqBsB,CAAAA;EACvB,UAAU;GACRxB,EAAuB,EAAA;EACzB;CACF,GAEMmC,KAAoBN,MAAAA;EAKxB3B,AAJAZ,EACED,EAAMnB,KAAKmC,GAAGyB,MAAOA,MAAMD,IAAQ;GAAE1D,KAAKkC,EAAElC;GAAKC,OAAOiC,EAAE0B,gBAAgB1B,EAAEjC;GAAOC,WAAW;EAAM,IAAIgC,CAAAA,CAAAA,GAE1Gb,EAAU,CAAC,CAAA,GACXU,EAAqB,IAAA;CACvB,GAEMkC,IAAe,OAAOP,MAAAA;EAC1B,IAAMI,IAAO5C,EAAMwC;EACnB7B,EAAuB,EAAA;EAEvB,IAAI;GAWFnC,AAVA,MAAMU,EAAOG,QAAQ2D,gBAAgBnB,OAAO;IAC1CrC,YAAYL;IACZC,UAAUM,EAAOoC;IACjBhD,KAAK8D,EAAK9D;GACZ,CAAA,GAEAmB,EAASD,EAAMiD,QAAQC,GAAGT,MAAMA,MAAMD,CAAAA,CAAAA,GACtCrC,EAAU,CAAC,CAAA,GACXU,EAAqB,IAAA,GAErBrC,EAAMwD,QAAQX,EAAAA,EAAC,EAAA,IAAA,SAAiB,CAAA,GAAG,EACjCY,aAAaZ,EAAAA,EAAC,EAAA,IAAA,SAAmC,CAAA,EACnD,CAAA;EACF,SAASa,GAAO;GACd,IAAMC,IAAWpC,EAAemC,aAAiBE,QAAQF,EAAMG,UAAU,2BAAA;GACzExB,EAAqBsB,CAAAA;EACvB,UAAU;GACRxB,EAAuB,EAAA;EACzB;CACF,GAEMwC,KAAqBX,GAAezD,MAAAA;EAExC,AADAkB,EAASD,EAAMnB,KAAK0C,GAAOkB,MAAOA,MAAMD,IAAQ;GAAE,GAAGjB;GAAOxC;EAAM,IAAIwC,CAAAA,CAAAA,GAClErB,EAAO,cAAcsC,SACvBrC,GAAWiD,MAAAA;GACT,IAAMC,IAAO,EAAE,GAAGD,EAAK;GAEvB,OADA,OAAOC,EAAK,cAAcb,MACnBa;EACT,CAAA,GACAxC,EAAqB,IAAA;CAEzB;CAaA,OACE,gBAAC9C,GAAAA;EACCwF,MAAI;EACJC,gBAdgB;GAClB,AAAK9C,MACHL,EAAe,EAAA,GACfE,EAAU,EAAA,GACVE,EAAY,EAAA,GACZN,EAAU,CAAC,CAAA,GACXU,EAAqB,IAAA,GACrBjB,EAAAA;EAEJ;EAMI6D,MAAK;EACLC,OAAOrC,EAAAA,EAAC,EAAA,IAAA,SAAc,CAAA;EACtBsC,mBAAmBtC,EAAAA,EAAC,EAAA,IAAA,SAAM,CAAA;EAC1BuC,qBAAqBlD;EAEpBf,UAAAA,IACC,gBAAC1B,GAAAA;GAAO4F,QAAO;GAAWH,OAAOrC,EAAAA,EAAC,EAAA,IAAA,SAAoB,CAAA;GAAGyC,WAAU;EAEnE,CAAA,IAAA,gBAACC,OAAAA,EAAAA,UAAAA;GACEnD,KAAqB,gBAACrC,GAAAA;IAAQyF,SAAQ;IAAQC,MAAMrD;IAAmBkD,WAAU;;GAElF,gBAAC5F,GAAAA;IAAMgG,WAAU;IAAaJ,WAAU;IACtC,UAAA,gBAAC9F,GAAAA;KAAOmG,OAAO9C,EAAAA,EAAC,EAAA,IAAA,SAAa,CAAA;KAAG+C,eAAe/D,EAAe,EAAA;KAAOgE,UAAUvD;;;GAGhFd,EAAM2B,WAAW,KAAK,CAACvB,IACtB,gBAACnC,GAAAA;IACC4F,QAAO;IACPH,OAAOrC,EAAAA,EAAC,EAAA,IAAA,SAA6B,CAAA;IACrCiD,MAAMjD,EAAAA,EAAC,EAAA,IAAA,SAAoC,CAAA;IAC3CyC,WAAU;GAGZ,CAAA,IAAA,gBAAC3F,GAAAA;IAAgB2F,WAAU;IAAmBS,YAAW;IACvD,UAAA,CAAA,gBAAA,GAAA,EACGnE,UAAAA,KACC,gBAAA,GAAA,EAAA,UAAA,CACE,gBAAChC,GAAAA;KAAgB0F,WAAU;KACzB,UAAA,gBAACxF,GAAAA;MACCS,OAAOuB;MACPkE,WAAWxD,MAAAA;OAET,AADAT,EAAUS,EAAEyD,OAAO1F,KAAK,GACpBmB,EAAOI,WACTH,GAAWiD,MAAAA;QACT,IAAMC,IAAO,EAAE,GAAGD,EAAK;QAEvB,OADA,OAAOC,EAAK/C,QACL+C;OACT,CAAA,GACAxC,EAAqB,IAAA;MAEzB;MACA6D,aAAarD,EAAAA,EAAC,EAAA,IAAA,SAAa,CAAA;MAC3BsD,SAAS,CAAC,CAACzE,EAAOI;MAClBsE,WAAS;MACTP,UAAU3D;;IAGd,CAAA,GAAA,gBAACrC,GAAAA;KAAsByF,WAAU;KAC/B,UAAA,CAAA,gBAACC,OAAAA;MAAID,WAAU;MACb,UAAA,gBAACxF,GAAAA;OACCS,OAAOyB;OACPgE,WAAWxD,MAAAA;QAET,AADAP,EAAYO,EAAEyD,OAAO1F,KAAK,GACtBmB,EAAOM,aACTL,GAAWiD,MAAAA;SACT,IAAMC,IAAO,EAAE,GAAGD,EAAK;SAEvB,OADA,OAAOC,EAAK7C,UACL6C;QACT,CAAA,GACAxC,EAAqB,IAAA;OAEzB;OACA6D,aAAarD,EAAAA,EAAC,EAAA,IAAA,SAAM,CAAA;OACpBsD,SAAS,CAAC,CAACzE,EAAOM;OAClB6D,UAAU3D;;KAGd,CAAA,GAAA,gBAACxC,GAAAA;MAAMgG,WAAU;MAAaW,KAAI;MAAIf,WAAU;MAC9C,UAAA,CAAA,gBAAC9F,GAAAA;OACCyF,MAAK;OACLO,SAAQ;OACRI,SAAS3C;OACTqD,MAAK;OACLpB,OAAOrC,EAAAA,EAAC,EAAA,IAAA,SAAK,CAAA;OACb0D,cAAY1D,EAAAA,EAAC,EAAA,IAAA,SAAK,CAAA;OAClBgD,UAAU3D;MAEZ,CAAA,GAAA,gBAAC1C,GAAAA;OACCyF,MAAK;OACLO,SAAQ;OACRI,SAAS9B;OACTwC,MAAK;OACLpB,OAAOrC,EAAAA,EAAC,EAAA,IAAA,SAAQ,CAAA;OAChB0D,cAAY1D,EAAAA,EAAC,EAAA,IAAA,SAAQ,CAAA;OACrBgD,UAAU3D;;;IAQtB,CAAA,CAAA,EAAA,CAAA,EAAA,CAAA,GAAA,gBAAA,GAAA,EACGV,UAAAA,EAAMnB,KAAK0C,GAAOiB,MACjB,gBAAC9E,EAAMsH,UAAQ,EAAA,UAAA,CACb,gBAAC5G,GAAAA;KAAgB0F,WAAU;KACxBvC,WAAAA,EAAMvC,WACL,gBAACiG,QAAAA;MAAKnB,WAAU;MAAqCJ,OAAOnC,EAAMzC;MAC/DyC,UAAAA,EAAMzC;KAGT,CAAA;IAKJ,CAAA,GAAA,gBAACT,GAAAA;KAAsByF,WAAU;KAC9BvC,UAAAA,EAAMvC,YACL,gBAAA,GAAA,EAAA,UAAA,CACE,gBAAC+E,OAAAA;MAAID,WAAU;MACb,UAAA,gBAACxF,GAAAA;OACCS,OAAOwC,EAAMxC;OACbyF,WAAWxD,MAAMmC,EAAkBX,GAAOxB,EAAEyD,OAAO1F,KAAK;OACxD4F,SAAS,CAAC,CAACzE,EAAO,cAAcsC;OAChC6B,UAAU3D;;KAGd,CAAA,GAAA,gBAACxC,GAAAA;MAAMgG,WAAU;MAAaW,KAAI;MAAIf,WAAU;MAC9C,UAAA,CAAA,gBAAC9F,GAAAA;OACCyF,MAAK;OACLO,SAAQ;OACRI,eAAezB,EAAeH,CAAAA;OAC9BsC,MAAK;OACLpB,OAAOrC,EAAAA,EAAC,EAAA,IAAA,SAAK,CAAA;OACb0D,cAAY1D,EAAAA,EAAC,EAAA,IAAA,SAAK,CAAA;OAClBgD,UAAU3D;MAEZ,CAAA,GAAA,gBAAC1C,GAAAA;OACCyF,MAAK;OACLO,SAAQ;OACRI,eAAetB,EAAiBN,CAAAA;OAChCsC,MAAK;OACLpB,OAAOrC,EAAAA,EAAC,EAAA,IAAA,SAAQ,CAAA;OAChB0D,cAAY1D,EAAAA,EAAC,EAAA,IAAA,SAAQ,CAAA;OACrBgD,UAAU3D;;KAKhB,CAAA,CAAA,EAAA,CAAA,IAAA,gBAAA,GAAA,EAAA,UAAA,CACE,gBAACuE,QAAAA;MAAKnB,WAAU;MAAyCJ,OAAOnC,EAAMxC;MACnEwC,UAAAA,EAAMxC;KAET,CAAA,GAAA,gBAACb,GAAAA;MAAMgG,WAAU;MAAaW,KAAI;MAAIf,WAAU;MAC9C,UAAA,CAAA,gBAAC9F,GAAAA;OACCyF,MAAK;OACLO,SAAQ;OACRI,eAAe7B,EAAWC,CAAAA;OAC1BsC,MAAK;OACLI,eAAa,QAAQ3D,EAAMzC;OAC3B4E,OAAOrC,EAAAA,EAAC,EAAA,IAAA,SAAK,CAAA;OACbgD,UAAUvD;MAEZ,CAAA,GAAA,gBAAC9C,GAAAA;OACCyF,MAAK;OACLW,eAAerB,EAAaP,CAAAA;OAC5BsC,MAAK;OACLI,eAAa,UAAU3D,EAAMzC;OAC7B4E,OAAOrC,EAAAA,EAAC,EAAA,IAAA,SAAO,CAAA;OACf0D,cAAY1D,EAAAA,EAAC,EAAA,IAAA,SAAO,CAAA;OACpBgD,UAAUvD;;;IAlED0B,CAAAA,CAAAA,EAAAA,GAAAA,CAAAA,CAAAA,EAAAA,CAAAA,CAAAA;;;;AAiFvC;AAEA,IAAa2C,KAA+C,EAAEjG,WAAQkG,WAAQxF,YAAST,YAASO,gBAAQ;CACtG,IAAM,EAAA,MAAA,GAAA,GAAA,MAAQI,EAAAA,GACR,EAAEC,sBAAmBjC,EAAAA,GAErB,CAACuH,GAAgBC,KAAqB3H,EAAwC,IAAA,GAC9E,CAAC4H,GAAgBC,KAAqB7H,EAAS,EAAA,GAC/C,CAAC8H,GAAWC,KAAgB/H,EAAwB,IAAA;CAE1DC,QAAU;EACR,IAAI,CAACwH,KAAU,CAAC1F,GAAQoC,IAAI;GAE1B4D,AADAJ,EAAkB,IAAA,GAClBI,EAAa,IAAA;GACb;EACF;EAEA,IAAIC,IAAY;EAkBhB,OAjBAH,EAAkB,EAAA,GAClBE,EAAa,IAAA,IAebE,YAbiB;GACf,IAAI;IACF,IAAM5F,IAAQ,MAAMf,EAAwBC,GAAQC,GAASO,EAAOoC,EAAE;IACtE,IAAI6D,GAAW;IACfL,EAAkBtF,CAAAA;GACpB,SAASkC,GAAO;IACd,IAAIyD,GAAW;IACfD,EAAaxD,aAAiBE,QAAQF,EAAMG,UAAU,yBAAA;GACxD,UAAU;IACR,AAAKsD,KAAWH,EAAkB,EAAA;GACpC;EACF,EAEAI,CAAAA,SACO;GACLD,IAAY;EACd;CACF,GAAG;EAACP;EAAQ1F,GAAQoC;EAAI5C;EAAQC;CAAQ,CAAA;CAExC,IAAMU,IAAehC,QAAewH,IAAiB5G,EAAkB4G,CAAAA,IAAkB,CAAA,GAAK,CAACA,CAAe,CAAA;CAsB9G,OApBI,CAACD,KAAU,CAAC1F,IACP,OAGL6F,IAEA,gBAACxH,GAAAA;EAAMwF,MAAI;EAACC,UAAU5D;EAAS6D,MAAK;EAAKC,OAAOrC,EAAAA,EAAC,EAAA,IAAA,SAAc,CAAA;EAC7D,UAAA,gBAACpD,GAAAA;GAAO4F,QAAO;GAAWH,OAAOrC,EAAAA,EAAC,EAAA,IAAA,SAAoB,CAAA;GAAGyC,WAAU;;MAKrE2B,IAEA,gBAAC1H,GAAAA;EAAMwF,MAAI;EAACC,UAAU5D;EAAS6D,MAAK;EAAKC,OAAOrC,EAAAA,EAAC,EAAA,IAAA,SAAc,CAAA;EAC7D,UAAA,gBAACpD,GAAAA;GAAO4F,QAAO;GAAQH,OAAOrC,EAAAA,EAAC,EAAA,IAAA,SAAwB,CAAA;GAAGiD,MAAMvE,EAAe0F,CAAAA;GAAY3B,WAAU;;MAMzG,gBAACrE,GAAAA;EAESP;EACCC;EACDO;EACRC,WAAW;EACFC;EACKC;CANTH,GAAAA,EAAOoC,EAAE;AASpB,GChea+D,KAAyBC,OAAmC;CACvEC,SAAS,gBAAA,GAAA,EAAA,IAAA,SAAA,CAAA;CACTC,aAAa,gBAAA,GAAA;;EAAgBF,QAAAA,EAAAA,QAAAA;;AAC/B,IAEaG,KAAyBH,OAAmC;CACvEC,SAAS,gBAAA,GAAA,EAAA,IAAA,SAAA,CAAA;CACTC,aAAa,gBAAA,GAAA;;EAAgBF,QAAAA,EAAAA,QAAAA;;AAC/B,IAEaI,KAA6BC,GAAmBC,OAAyC;CACpGL,SAAS,gBAAA,GAAA,EAAA,IAAA,SAAA,CAAA;CACTC,aACE,gBAAA,GAAA;;;GACYG;GAAuCC;;;AAGvD,IAEaC,KAA+BF,GAAmBC,OAAyC;CACtGL,SAAS,gBAAA,GAAA,EAAA,IAAA,SAAA,CAAA;CACTC,aACE,gBAAA,GAAA;;;GACuBG;GAAwBC;;;AAGnD,IAWaI,KAAmCL,GAAmBI,OAA2C;CAC5GR,SAAS,gBAAA,GAAA,EAAA,IAAA,SAAA,CAAA;CACTC,aACE,gBAAA,GAAA;;;GACwCG;GAAcI;;;AAG1D;;;ACVA,SAASoB,EAAmBC,GAA4B;CACtD,OAAOA,EAAaC,KAAKC,OAAY,EACnCC,WAAWD,EAAOE,UACpB,EAAA;AACF;AAEA,IAAMC,KAA4BC,GAAoBC,MAC7CD,EAAOE,QAAQC,QACnBC,MAAM;CACLC,YAAYJ;CACZK,YAAY,CAAC,uBAAuB,wBAAyB;AAC/D,CAAA,CAAA,CACCC,MAAM,CAACC,GAAQC,QAAgB;CAAED;CAAQC;AAAU,EAAA,GAGlDC,KAA6BV,GAAoBC,GAAiBU,MAC/DX,EAAOE,QAAQU,gBAAgBR,MAAM;CAC1CC,YAAYJ;CACFU;AACZ,CAAA;AAGF,SAASE,EAAuB,EAC9Bb,WACAC,YACAa,WACAC,cACAC,YACAC,kBACAT,WACAC,gBAUD;CACC,IAAM,EAAA,MAAA,GAAA,GAAA,MAAQS,EAAAA,GACR,EAAEC,sBAAmBxC,EAAAA,GAErB,CAACiB,GAAQwB,KAAa5C,EAAwByC,CAAAA,GAC9C,CAACI,GAAQC,KAAa9C,EAAoC,CAAC,CAAA,GAC3D,CAAC+C,GAAaC,KAAkBhD,EAAS,EAAA,GACzC,CAACiD,GAAcC,KAAmBlD,EAAS,EAAA,GAC3C,CAACmD,GAAoBC,KAAyBpD,kBAAsB,IAAIqD,IAAAA,CAAAA,GACxE,CAACC,GAAiBC,KAAsBvD,EAAS,EAAA,GAEjDwD,IAAiBlB,EAAO,kCAAkC,IAE1DmB,KAAqBpC,MAAAA;EACzB,IAAMqC,IAAarC,GAAWsC,KAAAA;EAQ9B,OAPKD,IAGetC,EAAO0C,MAAMC,MAAUA,EAAM1C,UAAUsC,KAAI,MAAOD,CAClEG,IACKD,EAAAA,EAAC,EAAA,IAAA,SAAgC,CAAA,IAEnC,OANEA,EAAAA,EAAC,EAAA,IAAA,SAAuB,CAAA;CAOnC,GAEMI,IAAe,YAAA;EACnB,IAAMC,IAAQR,EAAkBR,CAAAA;EAChC,IAAIgB,GAAO;GACTnB,EAAU,EAAEG,cAAcgB,EAAM,CAAA;GAChC;EACF;EAEA,IAAMC,IAAmBjB,EAAaU,KAAI;EAE1Cb,AADAS,EAAmB,EAAA,GACnBT,EAAU,CAAC,CAAA;EAEX,IAAI;GASFE,AARA,MAAMxB,EAAOE,QAAQyC,gBAAgBC,OAAO;IAC1CvC,YAAYJ;IACZU,UAAUG,EAAO+B;IACjBC,iBAAiBJ;GACnB,CAAA,GAEAtB,GAAW2B,MAAS,CAAIA,GAAAA,GAAM,EAAElD,WAAW6C,EAAiB,CAAE,CAAA,GAC9DhB,EAAgB,EAAA,GAChBF,EAAe,EAAA;GAEf,IAAM,EAAEwB,YAAS,GAAGC,MAAY3D,EAA0BoD,GAAkB5B,EAAOoC,IAAI;GACvF7D,EAAM8D,QAAQH,GAASC,CAAAA;EACzB,SAASR,GAAO;GACd,IAAMW,IAAejC,EAAesB,aAAiBY,QAAQZ,EAAMO,UAAU,sBAAA;GAC7E1B,EAAU,EAAEG,cAAc2B,EAAa,CAAA;EAEzC,UAAU;GACRrB,EAAmB,EAAA;EACrB;CACF,GAEMuB,UAAkB;EAGtBhC,AAFAI,EAAgB,EAAA,GAChBF,EAAe,EAAA,GACfF,EAAU,CAAC,CAAA;CACb,GAEMiC,IAAe,OAAO1D,MAAAA;EAE1B+B,AADAN,EAAU,CAAC,CAAA,GACXM,GAAuBmB,MAAS,IAAIlB,IAAIkB,CAAAA,CAAAA,CAAMS,IAAI3D,CAAAA,CAAAA;EAElD,IAAI;GAOFuB,AANA,MAAMpB,EAAOE,QAAQuD,mBAAmBb,OAAO;IAC7CvC,YAAYJ;IACZU,UAAUG,EAAO+B;IACjBC,iBAAiBjD;GACnB,CAAA,GAEAuB,GAAW2B,MAASA,EAAKW,QAAQC,MAAMA,EAAE9D,cAAcA,CAAAA,CAAAA;GAEvD,IAAM,EAAEmD,YAAS,GAAGC,MAAY1D,EAA4BM,GAAWiB,EAAOoC,IAAI;GAClF7D,EAAM8D,QAAQH,GAASC,CAAAA;EACzB,SAASR,GAAO;GAEd,IAAM,EAAEO,YAAS,GAAGC,MAAYzD,EAAgCK,GAD3CsB,EAAesB,aAAiBY,QAAQZ,EAAMO,UAAU,yBACFI,CAAAA;GAC3E/D,EAAMoD,MAAMO,GAASC,CAAAA;EACvB,UAAU;GACRrB,GAAuBmB,MAAAA;IACrB,IAAMa,IAAO,IAAI/B,IAAIkB,CAAAA;IAErB,OADAa,EAAKC,OAAOhE,CAAAA,GACL+D;GACT,CAAA;EACF;CACF,GAEME,UAAc;EAIlB9C,AAHAQ,EAAe,EAAA,GACfE,EAAgB,EAAA,GAChBJ,EAAU,CAAC,CAAA,GACXN,EAAAA;CACF;CAEA,IAAIgB,GAAgB;EAClB,IAAM+B,IAAajD,EAAOoC;EAC1B,OACE,gBAACtE,GAAAA;GAAMoF,MAAI;GAACC,UAAUH;GAAaI,MAAK;GAAQC,OAAO/B,EAAAA,EAAC;;IAAmB2B,QAAAA,EAAAA,cAAAA;GAAW,CAAA;GACpF,UAAA,gBAACK,KAAAA;IAAEC,WAAU;IACVjC,UAAAA,EAAAA,EAAC,EAAA,IAAA,SAAyD,CAAA;;;CAInE;CAEA,IAAM2B,IAAajD,EAAOoC,MACpBoB,IAA2BxC,KAAmBH,EAAmBuC,OAAO;CAE9E,OACE,gBAACtF,GAAAA;EAAMoF,MAAI;EAACC,UAAUH;EAAaI,MAAK;EAAQC,OAAO/B,EAAAA,EAAC;;GAAmB2B,QAAAA,EAAAA,cAAAA;EAAW,CAAA;EACnFhD,UAAAA,IACC,gBAAC7B,GAAAA;GAAOqF,QAAO;GAAWJ,OAAO/B,EAAAA,EAAC,EAAA,IAAA,SAAkB,CAAA;GAAGiC,WAAU;EAEjE,CAAA,IAAA,gBAACG,OAAAA,EAAAA,UAAAA;GACEnD,EAAOI,gBAAgB,gBAAC5C,GAAAA;IAAQ4F,SAAQ;IAAQC,MAAMrD,EAAOI;IAAc4C,WAAU;;GAErF7D,KACC,gBAACvB,GAAAA;IAAM0F,WAAU;IAAaN,WAAU;IACtC,UAAA,gBAAClF,GAAAA;KACCyF,OAAOxC,EAAAA,EAAC,EAAA,IAAA,SAAY,CAAA;KACpByC,eAAerD,EAAe,EAAA;KAC9BsD,UAAUvD,KAAe+C;;;GAK9B1E,EAAOmF,WAAW,KAAK,CAACxD,IACvB,gBAAC6C,KAAAA;IAAEC,WAAU;IACV7D,UAAAA,IACG4B,EAAAA,EAAC,EAAA,IAAA,SAAmE,CAAA,IACpEA,EAAAA,EAAC,EAAA,IAAA,SAA8B,CAAA;GAGrC,CAAA,IAAA,gBAACtD,GAAAA;IAAgBuF,WAAU;IACzB,UAAA,CAAA,gBAAA,GAAA,EACG9C,UAAAA,KACC,gBAAA,GAAA,EAAA,UAAA,CACE,gBAACxC,GAAAA;KAAgBsF,WAAU;KACzB,UAAA,gBAACW,QAAAA;MAAKX,WAAU;MAAsBjC,UAAAA,EAAAA,EAAC,EAAA,IAAA,SAAQ,CAAA;;IAEjD,CAAA,GAAA,gBAACpD,GAAAA,EACC,UAAA,gBAACwF,OAAAA;KAAIH,WAAU;KACb,UAAA,CAAA,gBAACG,OAAAA;MAAIH,WAAU;MACb,UAAA,gBAACjF,GAAAA;OACC6F,OAAOxD;OACPyD,WAAWC,MAAAA;QAET,AADAzD,EAAgByD,EAAEC,OAAOH,KAAK,GAC1B5D,EAAOI,gBACTH,EAAU,CAAC,CAAA;OAEf;OACA+D,aAAajD,EAAAA,EAAC,EAAA,IAAA,SAAiB,CAAA;OAC/BkD,SAAS,CAAC,CAACjE,EAAOI;OAClB8D,WAAS;OACTC,kBAAiB;OACjBV,UAAUhD;;KAGd,CAAA,GAAA,gBAAC0C,OAAAA;MAAIH,WAAU;MACb,UAAA,CAAA,gBAAClF,GAAAA;OACC+E,MAAK;OACLO,SAAQ;OACRI,SAASrC;OACTiD,MAAK;OACLtB,OAAO/B,EAAAA,EAAC,EAAA,IAAA,SAAI,CAAA;OACZ0C,UAAUhD;OACV4D,UAAU5D;MAEZ,CAAA,GAAA,gBAAC3C,GAAAA;OACC+E,MAAK;OACLO,SAAQ;OACRI,SAASvB;OACTmC,MAAK;OACLtB,OAAO/B,EAAAA,EAAC,EAAA,IAAA,SAAO,CAAA;OACf0C,UAAUhD;;;IASxB,CAAA,EAAA,CAAA,CAAA,EAAA,CAAA,EAAA,CAAA,GAAA,gBAAA,GAAA,EACGlC,UAAAA,EAAOD,KAAK4C,MAAAA;KACX,IAAMoD,IAAahE,EAAmBiE,IAAIrD,EAAM1C,SAAS;KACzD,OACE,gBAACtB,EAAMsH,UAAQ,EAAA,UAAA,CACb,gBAAC9G,GAAAA,EACC,UAAA,gBAACiG,QAAAA;MAAKX,WAAU;MAAsBjC,UAAAA,EAAAA,EAAC,EAAA,IAAA,SAAQ,CAAA;KAEjD,CAAA,EAAA,CAAA,GAAA,gBAACpD,GAAAA,EACC,UAAA,gBAACC,GAAAA;MAAM0F,WAAU;MAAamB,KAAI;MAAIC,WAAU;MAAS1B,WAAU;MACjE,UAAA,CAAA,gBAACW,QAAAA;OAAKX,WAAU;OAA6CF,OAAO5B,EAAM1C;OACvE0C,UAAAA,EAAM1C;MAERY,CAAAA,GAAAA,KACC,gBAACtB,GAAAA;OACC+E,MAAK;OACLW,eAAetB,EAAahB,EAAM1C,SAAS;OAC3C4F,MAAK;OACLO,eAAa,UAAUzD,EAAM1C;OAC7BsE,OAAO/B,EAAAA,EAAC,EAAA,IAAA,SAAO,CAAA;OACf0C,UAAUa,KAAcpE;OACxBmE,UAAUC;;KAjBCpD,CAAAA,EAAAA,CAAAA,CAAAA,EAAAA,GAAAA,EAAM1C,SAAS;IAwBxC,CAAA,EAAA,CAAA,CAAA;;;;AAQhB;AAEA,IAAaoG,KAAkD,EAAEjG,WAAQkG,WAAQlF,YAASf,YAASa,gBAAQ;CACzG,IAAM,EAAA,MAAA,GAAA,GAAA,MAAQI,EAAAA,GACR,EAAEC,sBAAmBxC,EAAAA,GAErB,CAACwH,GAAkBC,KAAuB5H,EAAgC,IAAA,GAC1E,CAAC6H,GAAiBC,KAAsB9H,EAAyD,IAAA,GACjG,CAAC+H,GAAeC,KAAoBhI,EAAS,EAAA,GAC7C,CAACiI,GAAWC,KAAgBlI,EAAwB,IAAA;CAE1DC,QAAU;EACR,IAAI,CAACyH,KAAU,CAACpF,GAAQ+B,IAAI;GAG1B6D,AAFAN,EAAoB,IAAA,GACpBE,EAAmB,IAAA,GACnBI,EAAa,IAAA;GACb;EACF;EAEA,IAAIC,IAAY;EA0BhB,OAzBAH,EAAiB,EAAA,GACjBE,EAAa,IAAA,IAuBbE,YArBiB;GACf,IAAI;IACF,IAAM,CAACC,GAAYC,KAAe,MAAMC,QAAQC,IAAI,CAClDtG,EAA0BV,GAAQC,GAASa,EAAO+B,EAAE,GACpD9C,EAAyBC,GAAQC,CAAAA,CAClC,CAAA;IACD,IAAI0G,GAAW;IAEf,IAAMM,IAAUJ,EAAWnD,QACxBnB,GAAO2E,GAAKC,MAAQA,EAAIC,WAAWjC,MAAMA,EAAErF,cAAcyC,EAAMzC,SAAS,MAAMoH,CAAAA;IAGjFZ,AADAF,EAAoBa,CAAAA,GACpBX,EAAmBQ,CAAAA;GACrB,SAASrE,GAAO;IACd,IAAIkE,GAAW;IACfD,EAAajE,aAAiBY,QAAQZ,EAAMO,UAAU,4BAAA;GACxD,UAAU;IACR,AAAK2D,KAAWH,EAAiB,EAAA;GACnC;EACF,EAEAI,CAAAA,SACO;GACLD,IAAY;EACd;CACF,GAAG;EAACT;EAAQpF,GAAQ+B;EAAI7C;EAAQC;CAAQ,CAAA;CAExC,IAAMgB,IAAgBvC,QACbyH,IAAmB1G,EAAmB0G,CAAAA,IAAoB,CAAA,GACjE,CAACA,CAAiB,CAAA;CAGpB,IAAI,CAACD,KAAU,CAACpF,GACd,OAAO;CAGT,IAAMiD,IAAajD,EAAOoC;CAkB1B,OAhBIqD,IAEA,gBAAC3H,GAAAA;EAAMoF,MAAI;EAACC,UAAUjD;EAASkD,MAAK;EAAQC,OAAO/B,EAAAA,EAAC;;GAAmB2B,QAAAA,EAAAA,cAAAA;EAAW,CAAA;EAChF,UAAA,gBAAC7E,GAAAA;GAAOqF,QAAO;GAAWJ,OAAO/B,EAAAA,EAAC,EAAA,IAAA,SAAkB,CAAA;GAAGiC,WAAU;;MAKnEoC,IAEA,gBAAC7H,GAAAA;EAAMoF,MAAI;EAACC,UAAUjD;EAASkD,MAAK;EAAQC,OAAO/B,EAAAA,EAAC;;GAAmB2B,QAAAA,EAAAA,cAAAA;EAAW,CAAA;EAChF,UAAA,gBAAC7E,GAAAA;GAAOqF,QAAO;GAAQJ,OAAO/B,EAAAA,EAAC,EAAA,IAAA,SAAsB,CAAA;GAAGiF,MAAMlG,EAAesF,CAAAA;GAAYpC,WAAU;;MAMvG,gBAACxD,GAAAA;EAESb;EACCC;EACDa;EACRC,WAAW;EACFC;EACMC;EACfT,QAAQ6F,GAAiB7F,UAAU;EACnCC,WAAW4F,GAAiB5F,aAAa;CARpCK,GAAAA,EAAO+B,EAAE;AAWpB,GC5WayF,KAAuD,EAClEC,WACAC,WACAC,YACAC,YACAC,WACAC,mBACD;CACC,IAAM,EAAA,MAAA,GAAA,GAAA,MAAQC,EAAAA,GACR,EAAEC,sBAAmBV,EAAAA,GACrB,CAACW,GAAWC,KAAgBtB,EAAS,EAAA,GACrC,CAACuB,GAAWC,KAAgBxB,EAAwB,IAAA,GAEpD,EAAEyB,eAAYC,kBAAeC,qBAAkBhB,EAAiB;EACpEG;EACAc,cAAc;CAChB,CAAA,GAEMC,IAAajC,EAAEkC,OAAO,EAC1BC,SAASnC,EAAEoC,OAAM,CAAA,CAAGC,QAAQC,MAAUA,MAAU,UAAU,EACxDC,SAASC,EAAAA,EAAC,EAAA,IAAA,SAAyB,CAAA,EACrC,CAAA,EACF,CAAA,GAEMC,IAAOxC,EAAQ;EACnByC,eAAe,EACbP,SAAS,GACX;EACAQ,YAAY,EACVC,UAAUX,EACZ;EACAW,UAAU,YAAA;GACR,IAAI,CAACvB,GAAQwB,IAAI;IACfjB,EAAaY,EAAAA,EAAC,EAAA,IAAA,SAAiC,CAAA,CAAA;IAC/C;GACF;GAEIf,QAGJG;IADAE,EAAAA,GACAF,EAAa,IAAA;IAEb,IAAI;KAQFuB,AAPAzB,EAAa,EAAA,GAEb,MAAMT,EAAO6B,QAAQC,aAAaC,OAAO;MACvCC,YAAY7B;MACZ8B,UAAU7B,EAAOwB;KACnB,CAAA,GACAvB,EAAAA,GACA6B,EAAAA;IACF,SAASC,GAAO;KACd,IAAMC,IAAe,GAAkBd,UACnCf,EAAe,EAAiBe,OAAO,IACvCC,EAAAA,EAAC,EAAA,IAAA,SAA2C,CAAA;KAChDZ,EAAayB,CAAAA;IACf,UAAU;KACR3B,EAAa,EAAA;IACf;GAlBa;EAmBf;CACF,CAAA,GAEM4B,IAAYpD,EAASuC,EAAKc,QAAQC,MAAUA,EAAMC,gBAAgBD,EAAME,OAAOvB,YAAY,QAAA,GAE3FgB,UAAc;EAMlBhC,AALAU,EAAAA,GACAH,EAAa,EAAA,GACbE,EAAa,IAAA,GACba,EAAKkB,MAAK,GACV5B,EAAAA,GACAZ,EAAAA;CACF,GAEMyC,IAAenC,IAAYe,EAAAA,EAAC,EAAA,IAAA,SAAY,CAAA,IAAIA,EAAAA,EAAC,EAAA,IAAA,SAAc,CAAA,GAC3DqB,IAAaxC,GAAQyC;CAE3B,OACE,gBAACzD,GAAAA;EACC0D,MAAM7C;EACN8C,UAAUb;EACVc,OAAOzB,EAAAA,EAAC;;GAAkBqB,QAAAA,EAAAA,cAAAA;EAAY,CAAA;EACtCK,MAAK;EACLC,oBAAoBP;EACpBQ,sBAAqB;EACrBC,WAAW5B,EAAK6B;EAChBC,mBAAmB/B,EAAAA,EAAC,EAAA,IAAA,SAAO,CAAA;EAC3BgC,sBAAsBlB,KAAa7B;EACnCgD,qBAAqBhD;EACrBiD,oBAAoBjD;EAEpB,UAAA,gBAACnB,GAAAA;GAAMqE,WAAU;GAAWC,KAAI;;IAC7BjD,KAAa,gBAACd,GAAAA;KAAQgE,SAAQ;KAASlD,UAAAA;;IAExC,gBAACmD,KAAAA;KAAEC,WAAU;KACX,UAAA,gBAAA,GAAA,EAAA,IAAA,SAAA,CAAA;;IAGD1D,KACC,gBAACX,GAAAA,EAAAA,UAAAA;KACC,gBAACC,GAAAA,EAAiB6B,UAAAA,EAAAA,EAAC,EAAA,IAAA,SAAK,CAAA,EAAA,CAAA;KACxB,gBAAC5B,GAAAA,EAAuBS,UAAAA,EAAOyC,KAAAA,CAAAA;KAE/B,gBAACnD,GAAAA,EAAiB6B,UAAAA,EAAAA,EAAC,EAAA,IAAA,SAAG,CAAA,EAAA,CAAA;KACtB,gBAAC5B,GAAAA,EAAuBS,UAAAA,EAAOwB,GAAAA,CAAAA;KAE/B,gBAAClC,GAAAA,EAAiB6B,UAAAA,EAAAA,EAAC,EAAA,IAAA,SAAM,CAAA,EAAA,CAAA;KACzB,gBAAC5B,GAAAA,EAAuBS,UAAAA,EAAO2D,MAAAA,CAAAA;KAE/B,gBAACrE,GAAAA,EAAiB6B,UAAAA,EAAAA,EAAC,EAAA,IAAA,SAAI,CAAA,EAAA,CAAA;KACvB,gBAAC5B,GAAAA,EAAAA,UAAAA,CAAuBS,EAAO4D,KAAI,MAAA,EAAA,CAAA;KAEnC,gBAACtE,GAAAA,EAAiB6B,UAAAA,EAAAA,EAAC,EAAA,IAAA,SAAK,CAAA,EAAA,CAAA;KACxB,gBAAC5B,GAAAA,EAAAA,UAAAA,CAAuBS,EAAO6D,MAAK,MAAA,EAAA,CAAA;KAEpC,gBAACvE,GAAAA,EAAiB6B,UAAAA,EAAAA,EAAC,EAAA,IAAA,SAAK,CAAA,EAAA,CAAA;KACxB,gBAAC5B,GAAAA,EACES,UAAAA,EAAO8D,SAAS,KAAK9D,EAAO8D,SAAS,KAAK,gBAAA,GAAA,EAAA,IAAA,SAAsB,CAAA,IAAA,GAAGC,OAAO/D,EAAO8D,IAAI,EAAE,MAAA,CAAA;;IAK9F,gBAAC5E,GAAAA;KACCwE,WAAU;KACVlC,IAAG;KACHD,WAAWyC,MAAAA;MAET5C,AADA4C,EAAEC,eAAc,GAChB7C,EAAK6B,aAAY;KACnB;KAEA,UAAA,gBAAC9D,GAAAA,EACC,UAAA,gBAACiC,EAAK8C,OAAK;MACTzB,MAAK;MACL0B,WAAWC,MACT,gBAAChF,GAAAA;OACCoC,IAAI4C,EAAM3B;OACVA,MAAM2B,EAAM3B;OACZ4B,OAAOlD,EAAAA,EAAC,EAAA,IAAA,SAAyB,CAAA;OACjCF,OAAOmD,EAAMjC,MAAMlB;OACnBqD,WAAWN,MAAMI,EAAMG,aAAaP,EAAEQ,OAAOvD,KAAK;OAClDwD,aAAY;OACZC,WAAS;OACTC,UAAUvE;OACVwE,UAAQ;;;;;;;AAS1B"}
|
|
@@ -0,0 +1,277 @@
|
|
|
1
|
+
import { A as e, D as t, E as n, M as r, Q as i, c as a, g as o, i as s, n as c, r as l, rt as u, s as d, x as f } from "./build-WuxXRAqf.mjs";
|
|
2
|
+
import { a as p } from "./trpcClient-D7gpR7YG.mjs";
|
|
3
|
+
import { t as m } from "./_flavorId-CFUBcU-l.mjs";
|
|
4
|
+
import { t as h } from "./useProjectId-DBc5lpoU.mjs";
|
|
5
|
+
import { n as g, t as _ } from "./ContentHeader-fKKZVu-o.mjs";
|
|
6
|
+
import { t as v } from "./useSetBreadcrumb-tn7lBaQV.mjs";
|
|
7
|
+
import { t as y } from "./useErrorTranslation-Dc0eE8Zt.mjs";
|
|
8
|
+
import { a as b, n as x, t as S } from "./DeleteFlavorModal-C4nAi7gY.mjs";
|
|
9
|
+
import { t as C } from "./useModal-DCs1OJh7.mjs";
|
|
10
|
+
import { Fragment as w, jsx as T, jsxs as E } from "react/jsx-runtime";
|
|
11
|
+
import { Fragment as D } from "react";
|
|
12
|
+
import { useNavigate as O, useParams as ee } from "@tanstack/react-router";
|
|
13
|
+
import { Trans as k, useLingui as A } from "@lingui/react";
|
|
14
|
+
//#region src/client/routes/_auth/projects/$projectId/compute/flavors/-components/FlavorDetailsView.tsx
|
|
15
|
+
function te({ flavor: e, canListSpecs: t = !1 }) {
|
|
16
|
+
let { i18n: r, _: a } = A(), o = h(), s = (e, t) => `${e} ${t}`, { data: l, isLoading: f, isError: m } = p.compute.getExtraSpecs.useQuery({
|
|
17
|
+
project_id: o,
|
|
18
|
+
flavorId: e.id
|
|
19
|
+
}, { enabled: !!o && !!e.id && t }), _ = [
|
|
20
|
+
{
|
|
21
|
+
label: r._({ id: "S0kLOH" }),
|
|
22
|
+
value: /*#__PURE__*/ T(g, { text: e.id })
|
|
23
|
+
},
|
|
24
|
+
{
|
|
25
|
+
label: r._({ id: "6YtxFj" }),
|
|
26
|
+
value: e.name
|
|
27
|
+
},
|
|
28
|
+
{
|
|
29
|
+
label: r._({ id: "Nu4oKW" }),
|
|
30
|
+
value: e?.description ?? ""
|
|
31
|
+
},
|
|
32
|
+
{
|
|
33
|
+
label: r._({ id: "7d1a0d" }),
|
|
34
|
+
value: e["os-flavor-access:is_public"] ? /*#__PURE__*/ T(k, { id: "l75CjT" }) : /*#__PURE__*/ T(k, { id: "1UzENP" })
|
|
35
|
+
},
|
|
36
|
+
{
|
|
37
|
+
label: r._({ id: "E/QGRL" }),
|
|
38
|
+
value: e["OS-FLV-DISABLED:disabled"] ? /*#__PURE__*/ T(k, { id: "l75CjT" }) : /*#__PURE__*/ T(k, { id: "1UzENP" })
|
|
39
|
+
}
|
|
40
|
+
], v = [
|
|
41
|
+
{
|
|
42
|
+
label: r._({ id: "MZGbkp" }),
|
|
43
|
+
value: e.vcpus
|
|
44
|
+
},
|
|
45
|
+
{
|
|
46
|
+
label: r._({ id: "RGhYAo" }),
|
|
47
|
+
value: s(e.ram, "MiB")
|
|
48
|
+
},
|
|
49
|
+
{
|
|
50
|
+
label: r._({ id: "cJDQIO" }),
|
|
51
|
+
value: s(e.disk, "GiB")
|
|
52
|
+
},
|
|
53
|
+
{
|
|
54
|
+
label: r._({ id: "r9Aac8" }),
|
|
55
|
+
value: s(e["OS-FLV-EXT-DATA:ephemeral"] || 0, "GiB")
|
|
56
|
+
},
|
|
57
|
+
{
|
|
58
|
+
label: r._({ id: "vH2C/2" }),
|
|
59
|
+
value: e.swap === 0 || e.swap === "" ? /*#__PURE__*/ T(k, { id: "EdQY6l" }) : s(Number(e.swap), "MiB")
|
|
60
|
+
},
|
|
61
|
+
{
|
|
62
|
+
label: r._({ id: "u5HztT" }),
|
|
63
|
+
value: e.rxtx_factor ?? ""
|
|
64
|
+
}
|
|
65
|
+
], y = l ? Object.entries(l).map(([e, t]) => ({
|
|
66
|
+
label: e,
|
|
67
|
+
value: t
|
|
68
|
+
})) : [];
|
|
69
|
+
return /*#__PURE__*/ E(i, {
|
|
70
|
+
direction: "vertical",
|
|
71
|
+
gap: "6",
|
|
72
|
+
className: "mt-6",
|
|
73
|
+
children: [/*#__PURE__*/ E(i, {
|
|
74
|
+
direction: "horizontal",
|
|
75
|
+
gap: "6",
|
|
76
|
+
className: "grid grid-cols-2",
|
|
77
|
+
children: [/*#__PURE__*/ E(i, {
|
|
78
|
+
direction: "vertical",
|
|
79
|
+
gap: "2",
|
|
80
|
+
children: [/*#__PURE__*/ T("h2", { children: /*#__PURE__*/ T(k, { id: "JlSgnX" }) }), /*#__PURE__*/ T(d, {
|
|
81
|
+
alignTerms: "right",
|
|
82
|
+
children: _.map(({ label: e, value: t }, r) => /*#__PURE__*/ E(D, { children: [/*#__PURE__*/ T(c, { children: e }), /*#__PURE__*/ T(n, { children: /*#__PURE__*/ T("div", {
|
|
83
|
+
className: "truncate",
|
|
84
|
+
children: t
|
|
85
|
+
}) })] }, `basic-${r}`))
|
|
86
|
+
})]
|
|
87
|
+
}), /*#__PURE__*/ E(i, {
|
|
88
|
+
direction: "vertical",
|
|
89
|
+
gap: "2",
|
|
90
|
+
children: [/*#__PURE__*/ T("h2", { children: /*#__PURE__*/ T(k, { id: "qQ1QBh" }) }), /*#__PURE__*/ T(d, {
|
|
91
|
+
alignTerms: "right",
|
|
92
|
+
children: v.map(({ label: e, value: t }, r) => /*#__PURE__*/ E(D, { children: [/*#__PURE__*/ T(c, { children: e }), /*#__PURE__*/ T(n, { children: /*#__PURE__*/ T("div", {
|
|
93
|
+
className: "truncate",
|
|
94
|
+
children: t
|
|
95
|
+
}) })] }, `hardware-${r}`))
|
|
96
|
+
})]
|
|
97
|
+
})]
|
|
98
|
+
}), t && /*#__PURE__*/ E(i, {
|
|
99
|
+
direction: "vertical",
|
|
100
|
+
gap: "2",
|
|
101
|
+
children: [/*#__PURE__*/ T("h2", { children: /*#__PURE__*/ T(k, { id: "6GBt0m" }) }), f ? /*#__PURE__*/ T(u, { status: "progress" }) : m ? /*#__PURE__*/ T(u, {
|
|
102
|
+
status: "error",
|
|
103
|
+
title: r._({ id: "mXHHga" })
|
|
104
|
+
}) : l && Object.keys(l).length > 0 ? /*#__PURE__*/ T(d, {
|
|
105
|
+
alignTerms: "right",
|
|
106
|
+
className: "grid-cols-2",
|
|
107
|
+
children: y.map(({ label: e, value: t }, r) => /*#__PURE__*/ E(D, { children: [/*#__PURE__*/ T(c, {
|
|
108
|
+
className: "col-span-1 break-all",
|
|
109
|
+
children: e
|
|
110
|
+
}), /*#__PURE__*/ T(n, {
|
|
111
|
+
className: "col-span-1",
|
|
112
|
+
children: /*#__PURE__*/ T("div", {
|
|
113
|
+
className: "break-all",
|
|
114
|
+
children: t
|
|
115
|
+
})
|
|
116
|
+
})] }, `extra-${r}`))
|
|
117
|
+
}) : /*#__PURE__*/ T(u, {
|
|
118
|
+
status: "empty",
|
|
119
|
+
title: r._({ id: "qTRcSX" })
|
|
120
|
+
})]
|
|
121
|
+
})]
|
|
122
|
+
});
|
|
123
|
+
}
|
|
124
|
+
//#endregion
|
|
125
|
+
//#region src/client/routes/_auth/projects/$projectId/compute/flavors/$flavorId.tsx?tsr-split=component
|
|
126
|
+
function j() {
|
|
127
|
+
let { projectId: n, flavorId: c } = ee({ from: "/_auth/projects/$projectId/compute/flavors/$flavorId" }), { trpcClient: d } = m.useRouteContext(), h = O(), { i18n: g, _: D } = A(), { translateError: j, isRetryableError: M } = y(), N = p.useUtils(), { data: P, status: F, error: I, refetch: L } = p.compute.getFlavorById.useQuery({
|
|
128
|
+
project_id: n,
|
|
129
|
+
flavorId: c
|
|
130
|
+
});
|
|
131
|
+
v(m.id, P?.name);
|
|
132
|
+
let { data: R } = p.compute.canUser.useQuery({
|
|
133
|
+
project_id: n,
|
|
134
|
+
permission: [
|
|
135
|
+
"flavors:delete",
|
|
136
|
+
"flavors:add_project",
|
|
137
|
+
"flavors:remove_project",
|
|
138
|
+
"flavor_specs:list",
|
|
139
|
+
"flavor_specs:create",
|
|
140
|
+
"flavor_specs:delete"
|
|
141
|
+
]
|
|
142
|
+
}), z = R?.[0] ?? !1, B = (R?.[1] ?? !1) || (R?.[2] ?? !1), V = R?.[3] ?? !1, ne = (R?.[4] ?? !1) || (R?.[5] ?? !1), [H, U] = C(), [W, G] = C(), [K, q] = C(), J = () => {
|
|
143
|
+
U(), N.compute.getExtraSpecs.invalidate({
|
|
144
|
+
project_id: n,
|
|
145
|
+
flavorId: c
|
|
146
|
+
});
|
|
147
|
+
}, Y = () => {
|
|
148
|
+
h({
|
|
149
|
+
to: "/projects/$projectId/compute/flavors",
|
|
150
|
+
params: { projectId: n }
|
|
151
|
+
});
|
|
152
|
+
}, X = () => {
|
|
153
|
+
h({
|
|
154
|
+
to: "/projects/$projectId",
|
|
155
|
+
params: { projectId: n }
|
|
156
|
+
});
|
|
157
|
+
}, re = () => {
|
|
158
|
+
L();
|
|
159
|
+
};
|
|
160
|
+
if (F === "pending") return /*#__PURE__*/ T(u, {
|
|
161
|
+
status: "progress",
|
|
162
|
+
title: g._({ id: "YNgcgc" })
|
|
163
|
+
});
|
|
164
|
+
if (F === "error") {
|
|
165
|
+
let t = I?.message || "UNKNOWN_ERROR", n = j(t), i = M(t);
|
|
166
|
+
return /*#__PURE__*/ T(e, {
|
|
167
|
+
className: "py-8",
|
|
168
|
+
children: /*#__PURE__*/ T(u, {
|
|
169
|
+
status: "error",
|
|
170
|
+
code: ((e) => {
|
|
171
|
+
if (e.includes("UNAUTHORIZED")) return 401;
|
|
172
|
+
if (e.includes("FORBIDDEN")) return 403;
|
|
173
|
+
if (e.includes("NOT_FOUND")) return 404;
|
|
174
|
+
if (e.includes("SERVER_ERROR")) return 500;
|
|
175
|
+
})(t),
|
|
176
|
+
title: g._({ id: "FjONW3" }),
|
|
177
|
+
body: n,
|
|
178
|
+
action: /*#__PURE__*/ E(r, { children: [
|
|
179
|
+
/*#__PURE__*/ T(s, {
|
|
180
|
+
variant: "primary",
|
|
181
|
+
onClick: Y,
|
|
182
|
+
children: /*#__PURE__*/ T(k, { id: "iH8pgl" })
|
|
183
|
+
}),
|
|
184
|
+
/*#__PURE__*/ T(s, {
|
|
185
|
+
onClick: X,
|
|
186
|
+
children: /*#__PURE__*/ T(k, { id: "i0qMbr" })
|
|
187
|
+
}),
|
|
188
|
+
i && /*#__PURE__*/ T(s, {
|
|
189
|
+
onClick: re,
|
|
190
|
+
children: /*#__PURE__*/ T(k, { id: "qJb6G2" })
|
|
191
|
+
})
|
|
192
|
+
] })
|
|
193
|
+
})
|
|
194
|
+
});
|
|
195
|
+
}
|
|
196
|
+
if (!P) return /*#__PURE__*/ T(e, {
|
|
197
|
+
className: "py-8",
|
|
198
|
+
children: /*#__PURE__*/ T(u, {
|
|
199
|
+
status: "error",
|
|
200
|
+
code: 404,
|
|
201
|
+
title: g._({ id: "bpme7e" }),
|
|
202
|
+
body: g._({ id: "y0u86k" }),
|
|
203
|
+
action: /*#__PURE__*/ E(r, { children: [/*#__PURE__*/ T(s, {
|
|
204
|
+
variant: "primary",
|
|
205
|
+
onClick: Y,
|
|
206
|
+
children: /*#__PURE__*/ T(k, { id: "iH8pgl" })
|
|
207
|
+
}), /*#__PURE__*/ T(s, {
|
|
208
|
+
onClick: X,
|
|
209
|
+
children: /*#__PURE__*/ T(k, { id: "i0qMbr" })
|
|
210
|
+
})] })
|
|
211
|
+
})
|
|
212
|
+
});
|
|
213
|
+
let Z = P["os-flavor-access:is_public"] !== !1, Q = B && !Z || z, $ = ne && V, ie = Q || $ ? /*#__PURE__*/ E(i, {
|
|
214
|
+
gap: "0.5",
|
|
215
|
+
alignment: "center",
|
|
216
|
+
children: [Q && /*#__PURE__*/ E(t, { children: [/*#__PURE__*/ T(a, {
|
|
217
|
+
as: "div",
|
|
218
|
+
children: /*#__PURE__*/ T(s, {
|
|
219
|
+
icon: "moreVert",
|
|
220
|
+
title: g._({ id: "PgNNGl" }),
|
|
221
|
+
"aria-label": g._({ id: "PgNNGl" })
|
|
222
|
+
})
|
|
223
|
+
}), /*#__PURE__*/ E(o, { children: [B && !Z && /*#__PURE__*/ T(f, {
|
|
224
|
+
label: g._({ id: "cWbW6w" }),
|
|
225
|
+
onClick: G
|
|
226
|
+
}), z && /*#__PURE__*/ E(w, { children: [/*#__PURE__*/ T(l, {}), /*#__PURE__*/ T(f, {
|
|
227
|
+
label: g._({ id: "JT3I1g" }),
|
|
228
|
+
onClick: q
|
|
229
|
+
})] })] })] }), $ && /*#__PURE__*/ T(s, {
|
|
230
|
+
variant: "primary",
|
|
231
|
+
onClick: U,
|
|
232
|
+
children: /*#__PURE__*/ T(k, { id: "SIfYq6" })
|
|
233
|
+
})]
|
|
234
|
+
}) : void 0;
|
|
235
|
+
return /*#__PURE__*/ E(w, { children: [
|
|
236
|
+
/*#__PURE__*/ T(_, {
|
|
237
|
+
title: P.name,
|
|
238
|
+
projectId: n,
|
|
239
|
+
actions: ie
|
|
240
|
+
}),
|
|
241
|
+
/*#__PURE__*/ T(i, {
|
|
242
|
+
direction: "vertical",
|
|
243
|
+
children: /*#__PURE__*/ T(te, {
|
|
244
|
+
flavor: P,
|
|
245
|
+
canListSpecs: V
|
|
246
|
+
})
|
|
247
|
+
}),
|
|
248
|
+
d && /*#__PURE__*/ E(w, { children: [
|
|
249
|
+
H && /*#__PURE__*/ T(b, {
|
|
250
|
+
client: d,
|
|
251
|
+
isOpen: H,
|
|
252
|
+
onClose: J,
|
|
253
|
+
project: n,
|
|
254
|
+
flavor: P
|
|
255
|
+
}),
|
|
256
|
+
W && /*#__PURE__*/ T(x, {
|
|
257
|
+
client: d,
|
|
258
|
+
isOpen: W,
|
|
259
|
+
onClose: G,
|
|
260
|
+
project: n,
|
|
261
|
+
flavor: P
|
|
262
|
+
}),
|
|
263
|
+
K && /*#__PURE__*/ T(S, {
|
|
264
|
+
client: d,
|
|
265
|
+
isOpen: K,
|
|
266
|
+
onClose: q,
|
|
267
|
+
project: n,
|
|
268
|
+
flavor: P,
|
|
269
|
+
onSuccess: Y
|
|
270
|
+
})
|
|
271
|
+
] })
|
|
272
|
+
] });
|
|
273
|
+
}
|
|
274
|
+
//#endregion
|
|
275
|
+
export { j as component };
|
|
276
|
+
|
|
277
|
+
//# sourceMappingURL=_flavorId-BPvssEzn.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"_flavorId-BPvssEzn.mjs","names":["Stack","DescriptionList","DescriptionTerm","DescriptionDefinition","Status","Fragment","ClipboardText","trpcReact","useProjectId","FlavorDetailsView","flavor","canListSpecs","useLingui","projectId","formatWithUnit","value","unit","data","extraSpecs","isLoading","isError","compute","getExtraSpecs","useQuery","project_id","flavorId","id","enabled","basicInfoItems","label","t","text","name","description","hardwareSpecItems","vcpus","ram","disk","swap","Number","rxtx_factor","extraSpecItems","Object","entries","map","key","direction","gap","className","h2","alignTerms","index","div","status","title","keys","length","Button","ButtonRow","Stack","PopupMenu","PopupMenuToggle","PopupMenuOptions","PopupMenuItem","PopupMenuSectionSeparator","Container","Status","useNavigate","useParams","Trans","useLingui","trpcReact","useSetBreadcrumb","FlavorDetailsView","useErrorTranslation","EditSpecModal","ManageAccessModal","DeleteFlavorModal","useModal","ContentHeader","Route","RouteComponent","projectId","flavorId","from","trpcClient","useRouteContext","navigate","t","translateError","isRetryableError","utils","useUtils","data","flavor","status","error","refetch","compute","getFlavorById","useQuery","project_id","id","name","permissionsData","canUser","permission","canDeleteFlavor","canManageAccess","canListSpecs","canManageSpecs","specModalOpen","toggleSpecModal","accessModalOpen","toggleAccessModal","deleteModalOpen","toggleDeleteModal","handleSpecModalClose","getExtraSpecs","invalidate","handleBack","to","params","handleHome","handleRetry","errorCode","message","translatedError","canRetry","getStatusCode","code","includes","undefined","isPublicFlavor","hasPopupMenuItems","canEditMetadata","hasMoreActions","headerActions","component"],"sources":["../../src/client/routes/_auth/projects/$projectId/compute/flavors/-components/FlavorDetailsView.tsx","../../src/client/routes/_auth/projects/$projectId/compute/flavors/$flavorId.tsx?tsr-split=component"],"sourcesContent":["import {\n Stack,\n DescriptionList,\n DescriptionTerm,\n DescriptionDefinition,\n Status,\n} from \"@cloudoperators/juno-ui-components/index\"\nimport { Trans, useLingui } from \"@lingui/react/macro\"\nimport { Fragment } from \"react\"\nimport type { Flavor } from \"@/server/Compute/types/flavor\"\nimport ClipboardText from \"@/client/components/ClipboardText\"\nimport { trpcReact } from \"@/client/trpcClient\"\nimport { useProjectId } from \"@/client/hooks/useProjectId\"\n\ninterface FlavorDetailsViewProps {\n flavor: Flavor\n canListSpecs?: boolean\n}\n\nexport function FlavorDetailsView({ flavor, canListSpecs = false }: FlavorDetailsViewProps) {\n const { t } = useLingui()\n const projectId = useProjectId()\n const formatWithUnit = (value: number, unit: string) => `${value} ${unit}`\n\n const {\n data: extraSpecs,\n isLoading,\n isError,\n } = trpcReact.compute.getExtraSpecs.useQuery(\n {\n project_id: projectId,\n flavorId: flavor.id,\n },\n {\n enabled: !!projectId && !!flavor.id && canListSpecs,\n }\n )\n\n const basicInfoItems = [\n { label: t`ID`, value: <ClipboardText text={flavor.id} /> },\n { label: t`Name`, value: flavor.name },\n { label: t`Description`, value: flavor?.description ?? \"\" },\n {\n label: t`Public`,\n value: flavor[\"os-flavor-access:is_public\"] ? <Trans>Yes</Trans> : <Trans>No</Trans>,\n },\n {\n label: t`Disabled`,\n value: flavor[\"OS-FLV-DISABLED:disabled\"] ? <Trans>Yes</Trans> : <Trans>No</Trans>,\n },\n ]\n\n const hardwareSpecItems = [\n { label: t`VCPUs`, value: flavor.vcpus },\n { label: t`RAM`, value: formatWithUnit(flavor.ram, \"MiB\") },\n { label: t`Root Disk`, value: formatWithUnit(flavor.disk, \"GiB\") },\n {\n label: t`Ephemeral Disk`,\n value: formatWithUnit(flavor[\"OS-FLV-EXT-DATA:ephemeral\"] || 0, \"GiB\"),\n },\n {\n label: t`Swap`,\n value: flavor.swap === 0 || flavor.swap === \"\" ? <Trans>None</Trans> : formatWithUnit(Number(flavor.swap), \"MiB\"),\n },\n { label: t`RX/TX Factor`, value: flavor.rxtx_factor ?? \"\" },\n ]\n\n const extraSpecItems = extraSpecs ? Object.entries(extraSpecs).map(([key, value]) => ({ label: key, value })) : []\n\n return (\n <Stack direction=\"vertical\" gap=\"6\" className=\"mt-6\">\n <Stack direction=\"horizontal\" gap=\"6\" className=\"grid grid-cols-2\">\n <Stack direction=\"vertical\" gap=\"2\">\n <h2>\n <Trans>Flavor Information</Trans>\n </h2>\n <DescriptionList alignTerms=\"right\">\n {basicInfoItems.map(({ label, value }, index) => (\n <Fragment key={`basic-${index}`}>\n <DescriptionTerm>{label}</DescriptionTerm>\n <DescriptionDefinition>\n <div className=\"truncate\">{value}</div>\n </DescriptionDefinition>\n </Fragment>\n ))}\n </DescriptionList>\n </Stack>\n\n <Stack direction=\"vertical\" gap=\"2\">\n <h2>\n <Trans>Hardware Specifications</Trans>\n </h2>\n <DescriptionList alignTerms=\"right\">\n {hardwareSpecItems.map(({ label, value }, index) => (\n <Fragment key={`hardware-${index}`}>\n <DescriptionTerm>{label}</DescriptionTerm>\n <DescriptionDefinition>\n <div className=\"truncate\">{value}</div>\n </DescriptionDefinition>\n </Fragment>\n ))}\n </DescriptionList>\n </Stack>\n </Stack>\n\n {canListSpecs && (\n <Stack direction=\"vertical\" gap=\"2\">\n <h2>\n <Trans>Metadata</Trans>\n </h2>\n {isLoading ? (\n <Status status=\"progress\" />\n ) : isError ? (\n <Status status=\"error\" title={t`Failed to Load Metadata`} />\n ) : extraSpecs && Object.keys(extraSpecs).length > 0 ? (\n <DescriptionList alignTerms=\"right\" className=\"grid-cols-2\">\n {extraSpecItems.map(({ label, value }, index) => (\n <Fragment key={`extra-${index}`}>\n <DescriptionTerm className=\"col-span-1 break-all\">{label}</DescriptionTerm>\n <DescriptionDefinition className=\"col-span-1\">\n <div className=\"break-all\">{value}</div>\n </DescriptionDefinition>\n </Fragment>\n ))}\n </DescriptionList>\n ) : (\n <Status status=\"empty\" title={t`No Metadata Properties Found`} />\n )}\n </Stack>\n )}\n </Stack>\n )\n}\n","import {\n Button,\n ButtonRow,\n Stack,\n PopupMenu,\n PopupMenuToggle,\n PopupMenuOptions,\n PopupMenuItem,\n PopupMenuSectionSeparator,\n Container,\n Status,\n} from \"@cloudoperators/juno-ui-components/index\"\nimport { createFileRoute, redirect, useNavigate, useParams } from \"@tanstack/react-router\"\nimport type { RouteInfo } from \"@/client/routes/routeInfo\"\nimport { Trans, useLingui } from \"@lingui/react/macro\"\nimport { getServiceIndex } from \"@/server/Authentication/helpers\"\nimport { trpcReact } from \"@/client/trpcClient\"\nimport { useSetBreadcrumb } from \"@/client/hooks/useSetBreadcrumb\"\nimport { FlavorDetailsView } from \"./-components/FlavorDetailsView\"\nimport { useErrorTranslation } from \"@/client/utils/useErrorTranslation\"\nimport { EditSpecModal } from \"./-components/EditSpecModal\"\nimport { ManageAccessModal } from \"./-components/ManageAccessModal\"\nimport { DeleteFlavorModal } from \"./-components/DeleteFlavorModal\"\nimport { useModal } from \"@/client/utils/useModal\"\nimport { ContentHeader } from \"@/client/components/ContentHeader/ContentHeader\"\nimport { RouteIdLevelDefaultError } from \"@/client/components/Errors/RouteIdLevelDefaultError\"\n\nfunction FlavorErrorComponent() {\n const { t } = useLingui()\n const navigate = useNavigate()\n const { projectId } = Route.useParams()\n\n return (\n <RouteIdLevelDefaultError\n action={\n <Button\n variant=\"primary\"\n onClick={() => navigate({ to: \"/projects/$projectId/compute/flavors\", params: { projectId } })}\n >\n {t`Back to Flavors`}\n </Button>\n }\n />\n )\n}\n\nexport const Route = createFileRoute(\"/_auth/projects/$projectId/compute/flavors/$flavorId\")({\n staticData: {\n section: \"compute\",\n service: \"flavors\",\n analytics: {\n name: \"compute.flavors.detail\",\n },\n } satisfies RouteInfo,\n loader: async ({ context, params }) => {\n const flavor = await context.trpcClient?.compute.getFlavorById.query({\n project_id: params.projectId,\n flavorId: params.flavorId,\n })\n return { flavorName: flavor?.name ?? null }\n },\n head: ({ loaderData }) => ({\n meta: [{ title: loaderData?.flavorName ?? \"Flavor Details\" }],\n }),\n component: RouteComponent,\n beforeLoad: async ({ context, params }) => {\n const { trpcClient } = context\n const { projectId } = params\n\n const availableServices = (await trpcClient?.auth.getAvailableServices.query()) || []\n\n const serviceIndex = getServiceIndex(availableServices)\n\n if (!serviceIndex[\"flavor\"] && !serviceIndex[\"compute\"]) {\n throw redirect({\n to: \"/projects/$projectId\",\n params: { projectId },\n })\n }\n },\n errorComponent: FlavorErrorComponent,\n})\n\nfunction RouteComponent() {\n const { projectId, flavorId } = useParams({\n from: \"/_auth/projects/$projectId/compute/flavors/$flavorId\",\n })\n const { trpcClient } = Route.useRouteContext()\n const navigate = useNavigate()\n const { t } = useLingui()\n const { translateError, isRetryableError } = useErrorTranslation()\n const utils = trpcReact.useUtils()\n\n const {\n data: flavor,\n status,\n error,\n refetch,\n } = trpcReact.compute.getFlavorById.useQuery({\n project_id: projectId,\n flavorId,\n })\n\n useSetBreadcrumb(Route.id, flavor?.name)\n\n const { data: permissionsData } = trpcReact.compute.canUser.useQuery({\n project_id: projectId,\n permission: [\n \"flavors:delete\",\n \"flavors:add_project\",\n \"flavors:remove_project\",\n \"flavor_specs:list\",\n \"flavor_specs:create\",\n \"flavor_specs:delete\",\n ],\n })\n\n const canDeleteFlavor = permissionsData?.[0] ?? false\n const canManageAccess = (permissionsData?.[1] ?? false) || (permissionsData?.[2] ?? false)\n const canListSpecs = permissionsData?.[3] ?? false\n const canManageSpecs = (permissionsData?.[4] ?? false) || (permissionsData?.[5] ?? false)\n\n const [specModalOpen, toggleSpecModal] = useModal()\n const [accessModalOpen, toggleAccessModal] = useModal()\n const [deleteModalOpen, toggleDeleteModal] = useModal()\n\n const handleSpecModalClose = () => {\n toggleSpecModal()\n utils.compute.getExtraSpecs.invalidate({ project_id: projectId, flavorId })\n }\n\n const handleBack = () => {\n navigate({\n to: \"/projects/$projectId/compute/flavors\",\n params: { projectId },\n })\n }\n\n const handleHome = () => {\n navigate({\n to: \"/projects/$projectId\",\n params: { projectId },\n })\n }\n\n const handleRetry = () => {\n refetch()\n }\n\n if (status === \"pending\") {\n return <Status status=\"progress\" title={t`Loading Flavor Details...`} />\n }\n\n if (status === \"error\") {\n const errorCode = error?.message || \"UNKNOWN_ERROR\"\n const translatedError = translateError(errorCode)\n const canRetry = isRetryableError(errorCode)\n\n const getStatusCode = (code: string): number | undefined => {\n if (code.includes(\"UNAUTHORIZED\")) return 401\n if (code.includes(\"FORBIDDEN\")) return 403\n if (code.includes(\"NOT_FOUND\")) return 404\n if (code.includes(\"SERVER_ERROR\")) return 500\n return undefined\n }\n\n return (\n <Container className=\"py-8\">\n <Status\n status=\"error\"\n code={getStatusCode(errorCode)}\n title={t`Error Loading Flavor`}\n body={translatedError}\n action={\n <ButtonRow>\n <Button variant=\"primary\" onClick={handleBack}>\n <Trans>Back</Trans>\n </Button>\n <Button onClick={handleHome}>\n <Trans>Home</Trans>\n </Button>\n {canRetry && (\n <Button onClick={handleRetry}>\n <Trans>Try Again</Trans>\n </Button>\n )}\n </ButtonRow>\n }\n />\n </Container>\n )\n }\n\n if (!flavor) {\n return (\n <Container className=\"py-8\">\n <Status\n status=\"error\"\n code={404}\n title={t`Flavor Not Found`}\n body={t`The requested flavor could not be found. It may have been deleted or you may not have access to it.`}\n action={\n <ButtonRow>\n <Button variant=\"primary\" onClick={handleBack}>\n <Trans>Back</Trans>\n </Button>\n <Button onClick={handleHome}>\n <Trans>Home</Trans>\n </Button>\n </ButtonRow>\n }\n />\n </Container>\n )\n }\n\n const isPublicFlavor = flavor[\"os-flavor-access:is_public\"] !== false\n const hasPopupMenuItems = (canManageAccess && !isPublicFlavor) || canDeleteFlavor\n const canEditMetadata = canManageSpecs && canListSpecs\n const hasMoreActions = hasPopupMenuItems || canEditMetadata\n\n const headerActions = hasMoreActions ? (\n <Stack gap=\"0.5\" alignment=\"center\">\n {hasPopupMenuItems && (\n <PopupMenu>\n <PopupMenuToggle as=\"div\">\n <Button icon=\"moreVert\" title={t`More Actions`} aria-label={t`More Actions`} />\n </PopupMenuToggle>\n <PopupMenuOptions>\n {canManageAccess && !isPublicFlavor && (\n <PopupMenuItem label={t`Manage Access`} onClick={toggleAccessModal} />\n )}\n {canDeleteFlavor && (\n <>\n <PopupMenuSectionSeparator />\n <PopupMenuItem label={t`Delete Flavor`} onClick={toggleDeleteModal} />\n </>\n )}\n </PopupMenuOptions>\n </PopupMenu>\n )}\n {canEditMetadata && (\n <Button variant=\"primary\" onClick={toggleSpecModal}>\n <Trans>Edit Metadata</Trans>\n </Button>\n )}\n </Stack>\n ) : undefined\n\n return (\n <>\n <ContentHeader title={flavor.name} projectId={projectId} actions={headerActions} />\n <Stack direction=\"vertical\">\n <FlavorDetailsView flavor={flavor} canListSpecs={canListSpecs} />\n </Stack>\n\n {trpcClient && (\n <>\n {specModalOpen && (\n <EditSpecModal\n client={trpcClient}\n isOpen={specModalOpen}\n onClose={handleSpecModalClose}\n project={projectId}\n flavor={flavor}\n />\n )}\n\n {accessModalOpen && (\n <ManageAccessModal\n client={trpcClient}\n isOpen={accessModalOpen}\n onClose={toggleAccessModal}\n project={projectId}\n flavor={flavor}\n />\n )}\n\n {deleteModalOpen && (\n <DeleteFlavorModal\n client={trpcClient}\n isOpen={deleteModalOpen}\n onClose={toggleDeleteModal}\n project={projectId}\n flavor={flavor}\n onSuccess={handleBack}\n />\n )}\n </>\n )}\n </>\n )\n}\n"],"mappings":"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"}
|
|
@@ -11,7 +11,7 @@ var i = t("/_auth/projects/$projectId/compute/flavors/$flavorId")({
|
|
|
11
11
|
flavorId: t.flavorId
|
|
12
12
|
}))?.name ?? null }),
|
|
13
13
|
head: ({ loaderData: e }) => ({ meta: [{ title: e?.flavorName ?? "Flavor Details" }] }),
|
|
14
|
-
component: n(() => import("./_flavorId-
|
|
14
|
+
component: n(() => import("./_flavorId-BPvssEzn.mjs"), "component"),
|
|
15
15
|
beforeLoad: async ({ context: t, params: n }) => {
|
|
16
16
|
let { trpcClient: i } = t, { projectId: a } = n, o = await i?.auth.getAvailableServices.query() || [], s = e(o);
|
|
17
17
|
if (!s.flavor && !s.compute) throw r({
|
|
@@ -19,9 +19,9 @@ var i = t("/_auth/projects/$projectId/compute/flavors/$flavorId")({
|
|
|
19
19
|
params: { projectId: a }
|
|
20
20
|
});
|
|
21
21
|
},
|
|
22
|
-
errorComponent: n(() => import("./_flavorId-
|
|
22
|
+
errorComponent: n(() => import("./_flavorId-CZcIp0Ih.mjs"), "errorComponent")
|
|
23
23
|
});
|
|
24
24
|
//#endregion
|
|
25
25
|
export { i as t };
|
|
26
26
|
|
|
27
|
-
//# sourceMappingURL=_flavorId-
|
|
27
|
+
//# sourceMappingURL=_flavorId-CFUBcU-l.mjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"_flavorId-CgueqKTs.mjs","names":["createFileRoute","redirect","getServiceIndex","Route","staticData","section","service","analytics","name","RouteInfo","loader","context","params","flavor","trpcClient","compute","getFlavorById","query","project_id","projectId","flavorId","flavorName","head","loaderData","meta","title","component","lazyRouteComponent","$$splitComponentImporter","beforeLoad","availableServices","auth","getAvailableServices","serviceIndex","to","errorComponent","$$splitErrorComponentImporter"],"sources":["../../src/client/routes/_auth/projects/$projectId/compute/flavors/$flavorId.tsx"],"sourcesContent":["import {\n Button,\n ButtonRow,\n Stack,\n PopupMenu,\n PopupMenuToggle,\n PopupMenuOptions,\n PopupMenuItem,\n PopupMenuSectionSeparator,\n Container,\n Status,\n} from \"@cloudoperators/juno-ui-components/index\"\nimport { createFileRoute, redirect, useNavigate, useParams } from \"@tanstack/react-router\"\nimport type { RouteInfo } from \"@/client/routes/routeInfo\"\nimport { Trans, useLingui } from \"@lingui/react/macro\"\nimport { getServiceIndex } from \"@/server/Authentication/helpers\"\nimport { trpcReact } from \"@/client/trpcClient\"\nimport { useSetBreadcrumb } from \"@/client/hooks/useSetBreadcrumb\"\nimport { FlavorDetailsView } from \"./-components/FlavorDetailsView\"\nimport { useErrorTranslation } from \"@/client/utils/useErrorTranslation\"\nimport { EditSpecModal } from \"./-components/EditSpecModal\"\nimport { ManageAccessModal } from \"./-components/ManageAccessModal\"\nimport { DeleteFlavorModal } from \"./-components/DeleteFlavorModal\"\nimport { useModal } from \"@/client/utils/useModal\"\nimport { ContentHeader } from \"@/client/components/ContentHeader/ContentHeader\"\nimport { RouteIdLevelDefaultError } from \"@/client/components/Errors/RouteIdLevelDefaultError\"\n\nfunction FlavorErrorComponent() {\n const { t } = useLingui()\n const navigate = useNavigate()\n const { projectId } = Route.useParams()\n\n return (\n <RouteIdLevelDefaultError\n action={\n <Button\n variant=\"primary\"\n onClick={() => navigate({ to: \"/projects/$projectId/compute/flavors\", params: { projectId } })}\n >\n {t`Back to Flavors`}\n </Button>\n }\n />\n )\n}\n\nexport const Route = createFileRoute(\"/_auth/projects/$projectId/compute/flavors/$flavorId\")({\n staticData: {\n section: \"compute\",\n service: \"flavors\",\n analytics: {\n name: \"compute.flavors.detail\",\n },\n } satisfies RouteInfo,\n loader: async ({ context, params }) => {\n const flavor = await context.trpcClient?.compute.getFlavorById.query({\n project_id: params.projectId,\n flavorId: params.flavorId,\n })\n return { flavorName: flavor?.name ?? null }\n },\n head: ({ loaderData }) => ({\n meta: [{ title: loaderData?.flavorName ?? \"Flavor Details\" }],\n }),\n component: RouteComponent,\n beforeLoad: async ({ context, params }) => {\n const { trpcClient } = context\n const { projectId } = params\n\n const availableServices = (await trpcClient?.auth.getAvailableServices.query()) || []\n\n const serviceIndex = getServiceIndex(availableServices)\n\n if (!serviceIndex[\"flavor\"] && !serviceIndex[\"compute\"]) {\n throw redirect({\n to: \"/projects/$projectId\",\n params: { projectId },\n })\n }\n },\n errorComponent: FlavorErrorComponent,\n})\n\nfunction RouteComponent() {\n const { projectId, flavorId } = useParams({\n from: \"/_auth/projects/$projectId/compute/flavors/$flavorId\",\n })\n const { trpcClient } = Route.useRouteContext()\n const navigate = useNavigate()\n const { t } = useLingui()\n const { translateError, isRetryableError } = useErrorTranslation()\n const utils = trpcReact.useUtils()\n\n const {\n data: flavor,\n status,\n error,\n refetch,\n } = trpcReact.compute.getFlavorById.useQuery({\n project_id: projectId,\n flavorId,\n })\n\n useSetBreadcrumb(Route.id, flavor?.name)\n\n const { data: permissionsData } = trpcReact.compute.canUser.useQuery({\n project_id: projectId,\n permission: [\n \"flavors:delete\",\n \"flavors:add_project\",\n \"flavors:remove_project\",\n \"flavor_specs:list\",\n \"flavor_specs:create\",\n \"flavor_specs:delete\",\n ],\n })\n\n const canDeleteFlavor = permissionsData?.[0] ?? false\n const canManageAccess = (permissionsData?.[1] ?? false) || (permissionsData?.[2] ?? false)\n const canListSpecs = permissionsData?.[3] ?? false\n const canManageSpecs = (permissionsData?.[4] ?? false) || (permissionsData?.[5] ?? false)\n\n const [specModalOpen, toggleSpecModal] = useModal()\n const [accessModalOpen, toggleAccessModal] = useModal()\n const [deleteModalOpen, toggleDeleteModal] = useModal()\n\n const handleSpecModalClose = () => {\n toggleSpecModal()\n utils.compute.getExtraSpecs.invalidate({ project_id: projectId, flavorId })\n }\n\n const handleBack = () => {\n navigate({\n to: \"/projects/$projectId/compute/flavors\",\n params: { projectId },\n })\n }\n\n const handleHome = () => {\n navigate({\n to: \"/projects/$projectId\",\n params: { projectId },\n })\n }\n\n const handleRetry = () => {\n refetch()\n }\n\n if (status === \"pending\") {\n return <Status status=\"progress\" title={t`Loading Flavor Details...`} />\n }\n\n if (status === \"error\") {\n const errorCode = error?.message || \"UNKNOWN_ERROR\"\n const translatedError = translateError(errorCode)\n const canRetry = isRetryableError(errorCode)\n\n const getStatusCode = (code: string): number | undefined => {\n if (code.includes(\"UNAUTHORIZED\")) return 401\n if (code.includes(\"FORBIDDEN\")) return 403\n if (code.includes(\"NOT_FOUND\")) return 404\n if (code.includes(\"SERVER_ERROR\")) return 500\n return undefined\n }\n\n return (\n <Container className=\"py-8\">\n <Status\n status=\"error\"\n code={getStatusCode(errorCode)}\n title={t`Error Loading Flavor`}\n body={translatedError}\n action={\n <ButtonRow>\n <Button variant=\"primary\" onClick={handleBack}>\n <Trans>Back</Trans>\n </Button>\n <Button onClick={handleHome}>\n <Trans>Home</Trans>\n </Button>\n {canRetry && (\n <Button onClick={handleRetry}>\n <Trans>Try Again</Trans>\n </Button>\n )}\n </ButtonRow>\n }\n />\n </Container>\n )\n }\n\n if (!flavor) {\n return (\n <Container className=\"py-8\">\n <Status\n status=\"error\"\n code={404}\n title={t`Flavor Not Found`}\n body={t`The requested flavor could not be found. It may have been deleted or you may not have access to it.`}\n action={\n <ButtonRow>\n <Button variant=\"primary\" onClick={handleBack}>\n <Trans>Back</Trans>\n </Button>\n <Button onClick={handleHome}>\n <Trans>Home</Trans>\n </Button>\n </ButtonRow>\n }\n />\n </Container>\n )\n }\n\n const isPublicFlavor = flavor[\"os-flavor-access:is_public\"] !== false\n const hasPopupMenuItems = (canManageAccess && !isPublicFlavor) || canDeleteFlavor\n const canEditMetadata = canManageSpecs && canListSpecs\n const hasMoreActions = hasPopupMenuItems || canEditMetadata\n\n const headerActions = hasMoreActions ? (\n <Stack gap=\"0.5\" alignment=\"center\">\n {hasPopupMenuItems && (\n <PopupMenu>\n <PopupMenuToggle as=\"div\">\n <Button icon=\"moreVert\" title={t`More Actions`} aria-label={t`More Actions`} />\n </PopupMenuToggle>\n <PopupMenuOptions>\n {canManageAccess && !isPublicFlavor && (\n <PopupMenuItem label={t`Manage Access`} onClick={toggleAccessModal} />\n )}\n {canDeleteFlavor && (\n <>\n <PopupMenuSectionSeparator />\n <PopupMenuItem label={t`Delete Flavor`} onClick={toggleDeleteModal} />\n </>\n )}\n </PopupMenuOptions>\n </PopupMenu>\n )}\n {canEditMetadata && (\n <Button variant=\"primary\" onClick={toggleSpecModal}>\n <Trans>Edit Metadata</Trans>\n </Button>\n )}\n </Stack>\n ) : undefined\n\n return (\n <>\n <ContentHeader title={flavor.name} projectId={projectId} actions={headerActions} />\n <Stack direction=\"vertical\">\n <FlavorDetailsView flavor={flavor} canListSpecs={canListSpecs} />\n </Stack>\n\n {trpcClient && (\n <>\n {specModalOpen && (\n <EditSpecModal\n client={trpcClient}\n isOpen={specModalOpen}\n onClose={handleSpecModalClose}\n project={projectId}\n flavor={flavor}\n />\n )}\n\n {accessModalOpen && (\n <ManageAccessModal\n client={trpcClient}\n isOpen={accessModalOpen}\n onClose={toggleAccessModal}\n project={projectId}\n flavor={flavor}\n />\n )}\n\n {deleteModalOpen && (\n <DeleteFlavorModal\n client={trpcClient}\n isOpen={deleteModalOpen}\n onClose={toggleDeleteModal}\n project={projectId}\n flavor={flavor}\n onSuccess={handleBack}\n />\n )}\n </>\n )}\n </>\n )\n}\n"],"mappings":";;AA8CA,IAAaG,IAAQH,EAAgB,sDAAA,CAAA,CAAwD;CAC3FI,YAAY;EACVC,SAAS;EACTC,SAAS;EACTC,WAAW,EACTC,MAAM,yBACR;CACF;CACAE,QAAQ,OAAO,EAAEC,YAASC,iBAKjB,EAAES,aAAYR,MAJAF,EAAQG,YAAYC,QAAQC,cAAcC,MAAM;EACnEC,YAAYN,EAAOO;EACnBC,UAAUR,EAAOQ;CACnB,CAAA,EAAA,EAC6BZ,QAAQ,KAAK;CAE5Cc,OAAO,EAAEC,qBAAkB,EACzBC,MAAM,CAAC,EAAEC,OAAOF,GAAYF,cAAc,iBAAiB,CAAC,EAC9D;CACAK,WAASC,4CAAA,WAAA;CACTE,YAAY,OAAO,EAAElB,YAASC,gBAAQ;EACpC,IAAM,EAAEE,kBAAeH,GACjB,EAAEQ,iBAAcP,GAEhBkB,IAAoB,MAAOhB,GAAYiB,KAAKC,qBAAqBf,MAAAA,KAAY,CAAA,GAE7EgB,IAAe/B,EAAgB4B,CAAAA;EAErC,IAAI,CAACG,EAAa,UAAa,CAACA,EAAa,SAC3C,MAAMhC,EAAS;GACbiC,IAAI;GACJtB,QAAQ,EAAEO,aAAU;EACtB,CAAA;CAEJ;CACAgB,gBAAcR,4CAAA,gBAAA;AAChB,CAAA"}
|
|
1
|
+
{"version":3,"file":"_flavorId-CFUBcU-l.mjs","names":["createFileRoute","redirect","getServiceIndex","Route","staticData","section","service","analytics","name","RouteInfo","loader","context","params","flavor","trpcClient","compute","getFlavorById","query","project_id","projectId","flavorId","flavorName","head","loaderData","meta","title","component","lazyRouteComponent","$$splitComponentImporter","beforeLoad","availableServices","auth","getAvailableServices","serviceIndex","to","errorComponent","$$splitErrorComponentImporter"],"sources":["../../src/client/routes/_auth/projects/$projectId/compute/flavors/$flavorId.tsx"],"sourcesContent":["import {\n Button,\n ButtonRow,\n Stack,\n PopupMenu,\n PopupMenuToggle,\n PopupMenuOptions,\n PopupMenuItem,\n PopupMenuSectionSeparator,\n Container,\n Status,\n} from \"@cloudoperators/juno-ui-components/index\"\nimport { createFileRoute, redirect, useNavigate, useParams } from \"@tanstack/react-router\"\nimport type { RouteInfo } from \"@/client/routes/routeInfo\"\nimport { Trans, useLingui } from \"@lingui/react/macro\"\nimport { getServiceIndex } from \"@/server/Authentication/helpers\"\nimport { trpcReact } from \"@/client/trpcClient\"\nimport { useSetBreadcrumb } from \"@/client/hooks/useSetBreadcrumb\"\nimport { FlavorDetailsView } from \"./-components/FlavorDetailsView\"\nimport { useErrorTranslation } from \"@/client/utils/useErrorTranslation\"\nimport { EditSpecModal } from \"./-components/EditSpecModal\"\nimport { ManageAccessModal } from \"./-components/ManageAccessModal\"\nimport { DeleteFlavorModal } from \"./-components/DeleteFlavorModal\"\nimport { useModal } from \"@/client/utils/useModal\"\nimport { ContentHeader } from \"@/client/components/ContentHeader/ContentHeader\"\nimport { RouteIdLevelDefaultError } from \"@/client/components/Errors/RouteIdLevelDefaultError\"\n\nfunction FlavorErrorComponent() {\n const { t } = useLingui()\n const navigate = useNavigate()\n const { projectId } = Route.useParams()\n\n return (\n <RouteIdLevelDefaultError\n action={\n <Button\n variant=\"primary\"\n onClick={() => navigate({ to: \"/projects/$projectId/compute/flavors\", params: { projectId } })}\n >\n {t`Back to Flavors`}\n </Button>\n }\n />\n )\n}\n\nexport const Route = createFileRoute(\"/_auth/projects/$projectId/compute/flavors/$flavorId\")({\n staticData: {\n section: \"compute\",\n service: \"flavors\",\n analytics: {\n name: \"compute.flavors.detail\",\n },\n } satisfies RouteInfo,\n loader: async ({ context, params }) => {\n const flavor = await context.trpcClient?.compute.getFlavorById.query({\n project_id: params.projectId,\n flavorId: params.flavorId,\n })\n return { flavorName: flavor?.name ?? null }\n },\n head: ({ loaderData }) => ({\n meta: [{ title: loaderData?.flavorName ?? \"Flavor Details\" }],\n }),\n component: RouteComponent,\n beforeLoad: async ({ context, params }) => {\n const { trpcClient } = context\n const { projectId } = params\n\n const availableServices = (await trpcClient?.auth.getAvailableServices.query()) || []\n\n const serviceIndex = getServiceIndex(availableServices)\n\n if (!serviceIndex[\"flavor\"] && !serviceIndex[\"compute\"]) {\n throw redirect({\n to: \"/projects/$projectId\",\n params: { projectId },\n })\n }\n },\n errorComponent: FlavorErrorComponent,\n})\n\nfunction RouteComponent() {\n const { projectId, flavorId } = useParams({\n from: \"/_auth/projects/$projectId/compute/flavors/$flavorId\",\n })\n const { trpcClient } = Route.useRouteContext()\n const navigate = useNavigate()\n const { t } = useLingui()\n const { translateError, isRetryableError } = useErrorTranslation()\n const utils = trpcReact.useUtils()\n\n const {\n data: flavor,\n status,\n error,\n refetch,\n } = trpcReact.compute.getFlavorById.useQuery({\n project_id: projectId,\n flavorId,\n })\n\n useSetBreadcrumb(Route.id, flavor?.name)\n\n const { data: permissionsData } = trpcReact.compute.canUser.useQuery({\n project_id: projectId,\n permission: [\n \"flavors:delete\",\n \"flavors:add_project\",\n \"flavors:remove_project\",\n \"flavor_specs:list\",\n \"flavor_specs:create\",\n \"flavor_specs:delete\",\n ],\n })\n\n const canDeleteFlavor = permissionsData?.[0] ?? false\n const canManageAccess = (permissionsData?.[1] ?? false) || (permissionsData?.[2] ?? false)\n const canListSpecs = permissionsData?.[3] ?? false\n const canManageSpecs = (permissionsData?.[4] ?? false) || (permissionsData?.[5] ?? false)\n\n const [specModalOpen, toggleSpecModal] = useModal()\n const [accessModalOpen, toggleAccessModal] = useModal()\n const [deleteModalOpen, toggleDeleteModal] = useModal()\n\n const handleSpecModalClose = () => {\n toggleSpecModal()\n utils.compute.getExtraSpecs.invalidate({ project_id: projectId, flavorId })\n }\n\n const handleBack = () => {\n navigate({\n to: \"/projects/$projectId/compute/flavors\",\n params: { projectId },\n })\n }\n\n const handleHome = () => {\n navigate({\n to: \"/projects/$projectId\",\n params: { projectId },\n })\n }\n\n const handleRetry = () => {\n refetch()\n }\n\n if (status === \"pending\") {\n return <Status status=\"progress\" title={t`Loading Flavor Details...`} />\n }\n\n if (status === \"error\") {\n const errorCode = error?.message || \"UNKNOWN_ERROR\"\n const translatedError = translateError(errorCode)\n const canRetry = isRetryableError(errorCode)\n\n const getStatusCode = (code: string): number | undefined => {\n if (code.includes(\"UNAUTHORIZED\")) return 401\n if (code.includes(\"FORBIDDEN\")) return 403\n if (code.includes(\"NOT_FOUND\")) return 404\n if (code.includes(\"SERVER_ERROR\")) return 500\n return undefined\n }\n\n return (\n <Container className=\"py-8\">\n <Status\n status=\"error\"\n code={getStatusCode(errorCode)}\n title={t`Error Loading Flavor`}\n body={translatedError}\n action={\n <ButtonRow>\n <Button variant=\"primary\" onClick={handleBack}>\n <Trans>Back</Trans>\n </Button>\n <Button onClick={handleHome}>\n <Trans>Home</Trans>\n </Button>\n {canRetry && (\n <Button onClick={handleRetry}>\n <Trans>Try Again</Trans>\n </Button>\n )}\n </ButtonRow>\n }\n />\n </Container>\n )\n }\n\n if (!flavor) {\n return (\n <Container className=\"py-8\">\n <Status\n status=\"error\"\n code={404}\n title={t`Flavor Not Found`}\n body={t`The requested flavor could not be found. It may have been deleted or you may not have access to it.`}\n action={\n <ButtonRow>\n <Button variant=\"primary\" onClick={handleBack}>\n <Trans>Back</Trans>\n </Button>\n <Button onClick={handleHome}>\n <Trans>Home</Trans>\n </Button>\n </ButtonRow>\n }\n />\n </Container>\n )\n }\n\n const isPublicFlavor = flavor[\"os-flavor-access:is_public\"] !== false\n const hasPopupMenuItems = (canManageAccess && !isPublicFlavor) || canDeleteFlavor\n const canEditMetadata = canManageSpecs && canListSpecs\n const hasMoreActions = hasPopupMenuItems || canEditMetadata\n\n const headerActions = hasMoreActions ? (\n <Stack gap=\"0.5\" alignment=\"center\">\n {hasPopupMenuItems && (\n <PopupMenu>\n <PopupMenuToggle as=\"div\">\n <Button icon=\"moreVert\" title={t`More Actions`} aria-label={t`More Actions`} />\n </PopupMenuToggle>\n <PopupMenuOptions>\n {canManageAccess && !isPublicFlavor && (\n <PopupMenuItem label={t`Manage Access`} onClick={toggleAccessModal} />\n )}\n {canDeleteFlavor && (\n <>\n <PopupMenuSectionSeparator />\n <PopupMenuItem label={t`Delete Flavor`} onClick={toggleDeleteModal} />\n </>\n )}\n </PopupMenuOptions>\n </PopupMenu>\n )}\n {canEditMetadata && (\n <Button variant=\"primary\" onClick={toggleSpecModal}>\n <Trans>Edit Metadata</Trans>\n </Button>\n )}\n </Stack>\n ) : undefined\n\n return (\n <>\n <ContentHeader title={flavor.name} projectId={projectId} actions={headerActions} />\n <Stack direction=\"vertical\">\n <FlavorDetailsView flavor={flavor} canListSpecs={canListSpecs} />\n </Stack>\n\n {trpcClient && (\n <>\n {specModalOpen && (\n <EditSpecModal\n client={trpcClient}\n isOpen={specModalOpen}\n onClose={handleSpecModalClose}\n project={projectId}\n flavor={flavor}\n />\n )}\n\n {accessModalOpen && (\n <ManageAccessModal\n client={trpcClient}\n isOpen={accessModalOpen}\n onClose={toggleAccessModal}\n project={projectId}\n flavor={flavor}\n />\n )}\n\n {deleteModalOpen && (\n <DeleteFlavorModal\n client={trpcClient}\n isOpen={deleteModalOpen}\n onClose={toggleDeleteModal}\n project={projectId}\n flavor={flavor}\n onSuccess={handleBack}\n />\n )}\n </>\n )}\n </>\n )\n}\n"],"mappings":";;AA8CA,IAAaG,IAAQH,EAAgB,sDAAA,CAAA,CAAwD;CAC3FI,YAAY;EACVC,SAAS;EACTC,SAAS;EACTC,WAAW,EACTC,MAAM,yBACR;CACF;CACAE,QAAQ,OAAO,EAAEC,YAASC,iBAKjB,EAAES,aAAYR,MAJAF,EAAQG,YAAYC,QAAQC,cAAcC,MAAM;EACnEC,YAAYN,EAAOO;EACnBC,UAAUR,EAAOQ;CACnB,CAAA,EAAA,EAC6BZ,QAAQ,KAAK;CAE5Cc,OAAO,EAAEC,qBAAkB,EACzBC,MAAM,CAAC,EAAEC,OAAOF,GAAYF,cAAc,iBAAiB,CAAC,EAC9D;CACAK,WAASC,4CAAA,WAAA;CACTE,YAAY,OAAO,EAAElB,YAASC,gBAAQ;EACpC,IAAM,EAAEE,kBAAeH,GACjB,EAAEQ,iBAAcP,GAEhBkB,IAAoB,MAAOhB,GAAYiB,KAAKC,qBAAqBf,MAAAA,KAAY,CAAA,GAE7EgB,IAAe/B,EAAgB4B,CAAAA;EAErC,IAAI,CAACG,EAAa,UAAa,CAACA,EAAa,SAC3C,MAAMhC,EAAS;GACbiC,IAAI;GACJtB,QAAQ,EAAEO,aAAU;EACtB,CAAA;CAEJ;CACAgB,gBAAcR,4CAAA,gBAAA;AAChB,CAAA"}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { i as e } from "./build-WuxXRAqf.mjs";
|
|
2
|
-
import { t } from "./_flavorId-
|
|
2
|
+
import { t } from "./_flavorId-CFUBcU-l.mjs";
|
|
3
3
|
import { t as n } from "./RouteIdLevelDefaultError-DPF_x2tG.mjs";
|
|
4
4
|
import { jsx as r } from "react/jsx-runtime";
|
|
5
5
|
import { useNavigate as i } from "@tanstack/react-router";
|
|
@@ -19,4 +19,4 @@ function o() {
|
|
|
19
19
|
//#endregion
|
|
20
20
|
export { o as errorComponent };
|
|
21
21
|
|
|
22
|
-
//# sourceMappingURL=_flavorId-
|
|
22
|
+
//# sourceMappingURL=_flavorId-CZcIp0Ih.mjs.map
|