@datalayer/core
Version:
[](https://datalayer.io)
150 lines (149 loc) • 8.6 kB
JavaScript
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;