diff --git a/app/common/src/services/Backend.ts b/app/common/src/services/Backend.ts index 15e01e9a15fd..452d08ef633e 100644 --- a/app/common/src/services/Backend.ts +++ b/app/common/src/services/Backend.ts @@ -1290,7 +1290,8 @@ export interface CreateSecretRequestBody { /** HTTP request body for the "update secret" endpoint. */ export interface UpdateSecretRequestBody { - readonly value: string + readonly title: string | null + readonly value: string | null } /** HTTP request body for the "create datalink" endpoint. */ diff --git a/app/gui/src/dashboard/components/dashboard/SecretNameColumn.tsx b/app/gui/src/dashboard/components/dashboard/SecretNameColumn.tsx index ba03a2c1b0e8..4efeb3503160 100644 --- a/app/gui/src/dashboard/components/dashboard/SecretNameColumn.tsx +++ b/app/gui/src/dashboard/components/dashboard/SecretNameColumn.tsx @@ -8,14 +8,15 @@ import * as toastAndLogHooks from '#/hooks/toastAndLogHooks' import * as modalProvider from '#/providers/ModalProvider' -import * as ariaComponents from '#/components/AriaComponents' import type * as column from '#/components/dashboard/column' import SvgMask from '#/components/SvgMask' import UpsertSecretModal from '#/modals/UpsertSecretModal' -import type * as backendModule from '#/services/Backend' +import * as backendModule from '#/services/Backend' +import EditableSpan from '#/components/EditableSpan' +import { useText } from '#/providers/TextProvider' import * as eventModule from '#/utilities/event' import * as indent from '#/utilities/indent' import * as object from '#/utilities/object' @@ -37,12 +38,18 @@ export interface SecretNameColumnProps extends column.AssetColumnProps { */ export default function SecretNameColumn(props: SecretNameColumnProps) { const { item, selected, state, rowState, setRowState, isEditable, depth } = props - const { backend } = state + const { backend, nodeMap } = state const toastAndLog = toastAndLogHooks.useToastAndLog() + const { getText } = useText() const { setModal } = modalProvider.useSetModal() const updateSecretMutation = useMutation(backendMutationOptions(backend, 'updateSecret')) + const doRename = async (newTitle: string) => { + await updateSecretMutation.mutateAsync([item.id, { title: newTitle, value: null }, item.title]) + setIsEditing(false) + } + const setIsEditing = (isEditingName: boolean) => { if (isEditable) { setRowState(object.merger({ isEditingName })) @@ -69,9 +76,9 @@ export default function SecretNameColumn(props: SecretNameColumnProps) { { + doCreate={async (title, value) => { try { - await updateSecretMutation.mutateAsync([item.id, { value }, item.title]) + await updateSecretMutation.mutateAsync([item.id, { title, value }, item.title]) } catch (error) { toastAndLog(null, error) } @@ -82,14 +89,28 @@ export default function SecretNameColumn(props: SecretNameColumnProps) { }} > - {/* Secrets cannot be renamed. */} - { + setIsEditing(false) + }} + schema={(z) => + z.refine( + (value) => + backendModule.isNewTitleUnique( + item, + value, + nodeMap.current.get(item.parentId)?.children?.map((child) => child.item), + ), + { message: getText('nameShouldBeUnique') }, + ) + } > {item.title} - + ) } diff --git a/app/gui/src/dashboard/layouts/AssetProperties.tsx b/app/gui/src/dashboard/layouts/AssetProperties.tsx index 1ebcf95ea778..32d6266609d3 100644 --- a/app/gui/src/dashboard/layouts/AssetProperties.tsx +++ b/app/gui/src/dashboard/layouts/AssetProperties.tsx @@ -356,8 +356,8 @@ function AssetPropertiesInternal(props: AssetPropertiesInternalProps) { canCancel={false} id={item.id} name={item.title} - doCreate={async (name, value) => { - await updateSecretMutation.mutateAsync([item.id, { value }, name]) + doCreate={async (title, value) => { + await updateSecretMutation.mutateAsync([item.id, { title, value }, title]) }} /> diff --git a/app/gui/src/dashboard/layouts/AssetsTable.tsx b/app/gui/src/dashboard/layouts/AssetsTable.tsx index 2b1e2fc59144..a8829822c218 100644 --- a/app/gui/src/dashboard/layouts/AssetsTable.tsx +++ b/app/gui/src/dashboard/layouts/AssetsTable.tsx @@ -948,9 +948,13 @@ function AssetsTable(props: AssetsTableProps) { { + doCreate={async (title, value) => { try { - await updateSecretMutation.mutateAsync([id, { value }, item.item.title]) + await updateSecretMutation.mutateAsync([ + id, + { title, value }, + item.item.title, + ]) } catch (error) { toastAndLog(null, error) } diff --git a/app/gui/src/dashboard/modals/UpsertSecretModal.tsx b/app/gui/src/dashboard/modals/UpsertSecretModal.tsx index cfd150460a3d..ba3477feb056 100644 --- a/app/gui/src/dashboard/modals/UpsertSecretModal.tsx +++ b/app/gui/src/dashboard/modals/UpsertSecretModal.tsx @@ -27,40 +27,36 @@ export default function UpsertSecretModal(props: UpsertSecretModalProps) { const { getText } = useText() const isCreatingSecret = id == null - const isNameEditable = nameRaw == null const form = Form.useForm({ method: 'dialog', schema: (z) => - z.object({ name: z.string().min(1, getText('emptyStringError')), value: z.string() }), - defaultValues: { name: nameRaw ?? '', value: '' }, - onSubmit: async ({ name, value }) => { - await doCreate(name, value) + z.object({ title: z.string().min(1, getText('emptyStringError')), value: z.string() }), + defaultValues: { title: nameRaw ?? '', value: '' }, + onSubmit: async ({ title, value }) => { + await doCreate(title, value) + form.reset({ title, value }) }, }) const content = (
- {isNameEditable && ( - - )} +