UNPKG

@datalayer/core

Version:

[![Datalayer](https://assets.datalayer.tech/datalayer-25.svg)](https://datalayer.io)

150 lines (149 loc) 8.6 kB
import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime"; /* * Copyright (c) 2023-2025 Datalayer, Inc. * Distributed under the terms of the Modified BSD License. */ import { useState, useEffect } from 'react'; import { useParams } from 'react-router-dom'; import { PageHeader, Heading, Text, Button, TextInput, FormControl, Textarea, Label, } from '@primer/react'; import { Box } from '@datalayer/primer-addons'; import { EyeIcon, EyeClosedIcon } from '@primer/octicons-react'; import { BoringAvatar } from '../../components/avatars'; import { useCache, useNavigate, useToast } from '../../hooks'; import { useRunStore } from '../../state'; export const SecretEdit = () => { const { secretId } = useParams(); const runStore = useRunStore(); const navigate = useNavigate(); const { enqueueToast } = useToast(); const { useUpdateSecret, useSecret, useDeleteSecret } = useCache(); const updateSecretMutation = useUpdateSecret(); const deleteSecretMutation = useDeleteSecret(); const secretQuery = useSecret(secretId, { refetchOnMount: true, }); const [secret, setSecret] = useState(); const [formValues, setFormValues] = useState({ name: '', nameConfirm: '', description: '', value: '', }); const [validationResult, setValidationResult] = useState({ name: undefined, nameConfirm: undefined, description: undefined, value: undefined, }); const [passwordVisible, setPasswordVisible] = useState(false); useEffect(() => { if (secretQuery.data) { const secret = secretQuery.data; setSecret(secret); setFormValues({ name: secret.name || '', nameConfirm: '', description: secret.description || '', value: secret.value ? atob(secret.value) : '', }); } }, [secretQuery.data]); const secretNameChanged = (event) => { setFormValues(prevFormValues => ({ ...prevFormValues, name: event.target.value, })); }; const secretNameConfirmChanged = (event) => { setFormValues(prevFormValues => ({ ...prevFormValues, nameConfirm: event.target.value, })); }; const secretDescriptionChanged = (event) => { setFormValues(prevFormValues => ({ ...prevFormValues, description: event.target.value, })); }; const secretValueChanged = (event) => { setFormValues(prevFormValues => ({ ...prevFormValues, value: event.target.value, })); }; useEffect(() => { setValidationResult({ ...validationResult, name: formValues.name === undefined ? undefined : formValues.name.length > 2 ? true : false, nameConfirm: formValues.nameConfirm === secret?.name ? true : false, description: formValues.description === undefined ? undefined : formValues.description.length > 2 ? true : false, value: formValues.value === undefined ? undefined : formValues.value.length > 0 && formValues.value.length < 4096 ? true : false, }); }, [formValues]); const submitUpdate = async () => { runStore.layout().showBackdrop('Updating the secret...'); secret.name = formValues.name; secret.description = formValues.description; secret.value = btoa(formValues.value); updateSecretMutation.mutate(secret, { onSuccess: (resp) => { if (resp.success) { enqueueToast('The secret is successfully updated.', { variant: 'success', }); setSecret(secret); } }, onSettled: () => { runStore.layout().hideBackdrop(); }, }); }; const submitDelete = async () => { runStore.layout().showBackdrop('Deleting the secret...'); deleteSecretMutation.mutate(secret.id, { onSuccess: (resp) => { if (resp.success) { enqueueToast('The secret is successfully deleted.', { variant: 'success', }); navigate(`/settings/iam/secrets`); } }, onSettled: () => { runStore.layout().hideBackdrop(); }, }); }; return (_jsxs(_Fragment, { children: [_jsx(PageHeader, { children: _jsx(Heading, { sx: { fontSize: 3 }, children: "Secret" }) }), _jsxs(Box, { display: "flex", children: [_jsxs(Box, { children: [_jsx(BoringAvatar, { displayName: secret?.name, size: 100, style: { paddingRight: 10 } }), _jsx(Text, { as: "h2", sx: { paddingTop: 3 }, children: secret?.name }), _jsx(Box, { mt: 3, children: _jsx(Label, { size: "large", children: secret?.variant }) })] }), _jsxs(Box, { ml: 10, children: [_jsxs(Box, { sx: { label: { marginTop: 2 } }, children: [_jsxs(FormControl, { children: [_jsx(FormControl.Label, { children: "Name" }), _jsx(TextInput, { block: true, value: formValues.name, onChange: secretNameChanged }), validationResult.name === false && (_jsx(FormControl.Validation, { variant: "error", children: "Name must have more than 2 characters." }))] }), _jsxs(FormControl, { children: [_jsx(FormControl.Label, { children: "Description" }), _jsx(Textarea, { block: true, value: formValues.description, onChange: secretDescriptionChanged, rows: 5 }), validationResult.description === false && (_jsx(FormControl.Validation, { variant: "error", children: "Description must have more than 2 characters." }))] }), _jsxs(FormControl, { children: [_jsx(FormControl.Label, { children: "Value" }), _jsx(TextInput, { placeholder: "Value", monospace: true, size: "large", contrast: !passwordVisible, disabled: !passwordVisible, onChange: secretValueChanged, type: passwordVisible ? 'text' : 'password', value: formValues.value, trailingAction: _jsx(TextInput.Action, { onClick: () => { setPasswordVisible(!passwordVisible); }, icon: passwordVisible ? EyeClosedIcon : EyeIcon, "aria-label": passwordVisible ? 'Hide secret' : 'Reveal secret', sx: { color: 'var(--fgColor-muted)' } }), sx: { overflow: 'visible' } }), validationResult.value === false && (_jsx(FormControl.Validation, { variant: "error", children: "Value must have more than 1 and less than 4096 characters." }))] }), _jsx(Box, { sx: { marginTop: 3 }, children: _jsx(Button, { variant: "primary", disabled: !validationResult.name || !validationResult.description, onClick: submitUpdate, children: "Update secret" }) })] }), _jsxs(Box, { sx: { marginTop: 3 }, children: [_jsx(Heading, { as: "h2", sx: { fontSize: 4, fontWeight: 'normal', color: 'danger.fg', mb: 2, }, children: "Danger zone" }), _jsxs(Box, { sx: { border: '1px solid', borderColor: 'danger.emphasis', borderRadius: 2, p: 3, display: 'flex', alignItems: 'center', justifyContent: 'space-between', gap: 3, }, children: [_jsxs(Box, { sx: { display: 'grid', gap: 1 }, children: [_jsx(Text, { sx: { fontSize: 1, fontWeight: 'bold', color: 'danger.fg' }, children: "Confirm the secret name to delete" }), _jsx(FormControl, { children: _jsx(TextInput, { block: true, value: formValues.nameConfirm, onChange: secretNameConfirmChanged }) }), _jsx(Text, { sx: { fontSize: 1, color: 'fg.muted' }, children: "This operation is not reversible." })] }), _jsx(Button, { variant: "danger", disabled: !validationResult.nameConfirm, onClick: submitDelete, children: "Delete secret" })] })] })] })] })] })); }; export default SecretEdit;