diff --git a/web/src/components/NewSecretModalButton/NewSecretModalButton.tsx b/web/src/components/NewSecretModalButton/NewSecretModalButton.tsx index ff63e36c8..e82862761 100644 --- a/web/src/components/NewSecretModalButton/NewSecretModalButton.tsx +++ b/web/src/components/NewSecretModalButton/NewSecretModalButton.tsx @@ -21,7 +21,7 @@ import { useStrings } from 'framework/strings' import type { OpenapiCreateSecretRequest, TypesSecret } from 'services/code' import { getErrorMessage } from 'utils/Utils' -interface SecretFormData { +export interface SecretFormData { value: string description: string name: string @@ -82,10 +82,7 @@ export const NewSecretModalButton: React.FC = ({ onClose={hideModal} title={''} style={{ width: 700, maxHeight: '95vh', overflow: 'auto' }}> - + {modalTitle} diff --git a/web/src/components/UpdateSecretModal/UpdateSecretModal.tsx b/web/src/components/UpdateSecretModal/UpdateSecretModal.tsx new file mode 100644 index 000000000..914c0754b --- /dev/null +++ b/web/src/components/UpdateSecretModal/UpdateSecretModal.tsx @@ -0,0 +1,147 @@ +import React, { useState } from 'react' +import * as yup from 'yup' +import { useMutate } from 'restful-react' +import { FontVariation, Intent } from '@harnessio/design-system' +import { + Button, + Dialog, + Layout, + Heading, + Container, + Formik, + FormikForm, + FormInput, + FlexExpander, + useToaster, + StringSubstitute +} from '@harnessio/uicore' +import { Icon } from '@harnessio/icons' +import { useStrings } from 'framework/strings' +import { useModalHook } from 'hooks/useModalHook' +import { useGetSpaceParam } from 'hooks/useGetSpaceParam' +import type { OpenapiUpdateSecretRequest, TypesSecret } from 'services/code' +import type { SecretFormData } from 'components/NewSecretModalButton/NewSecretModalButton' +import { getErrorMessage } from 'utils/Utils' + +const useUpdateSecretModal = () => { + const { getString } = useStrings() + const space = useGetSpaceParam() + const { showError, showSuccess } = useToaster() + const [secret, setSecret] = useState() + + const { mutate: updateSecret, loading } = useMutate({ + verb: 'PATCH', + path: `/api/v1/secrets/${space}/${secret?.uid}/+` + }) + + const handleSubmit = async (formData: SecretFormData) => { + try { + const payload: OpenapiUpdateSecretRequest = { + data: formData.value, + description: formData.description, + uid: formData.name + } + await updateSecret(payload) + hideModal() + showSuccess( + + ) + } catch (exception) { + showError(getErrorMessage(exception), 0, getString('secrets.failedToUpdateSecret')) + } + } + + const [openModal, hideModal] = useModalHook(() => { + const onClose = () => { + hideModal() + } + + return ( + + + + {getString('secrets.updateSecret')} + + + + + + + + + + + + ) + }, [secret]) + + return { + openModal: ({ secretToUpdate }: { secretToUpdate: TypesSecret }) => { + setSecret(secretToUpdate) + openModal() + } + } +} + +export default useUpdateSecretModal diff --git a/web/src/framework/strings/stringTypes.ts b/web/src/framework/strings/stringTypes.ts index afa659c1e..e305c43d5 100644 --- a/web/src/framework/strings/stringTypes.ts +++ b/web/src/framework/strings/stringTypes.ts @@ -496,10 +496,13 @@ export interface StringsMap { 'secrets.enterSecretName': string 'secrets.failedToCreate': string 'secrets.failedToDeleteSecret': string + 'secrets.failedToUpdateSecret': string 'secrets.name': string 'secrets.newSecretButton': string 'secrets.noData': string 'secrets.secretDeleted': string + 'secrets.secretUpdated': string + 'secrets.updateSecret': string 'secrets.value': string selectBranchPlaceHolder: string selectRange: string @@ -555,6 +558,7 @@ export interface StringsMap { 'unsavedChanges.message': string 'unsavedChanges.stay': string 'unsavedChanges.title': string + update: string updateFile: string updateUser: string updateWebhook: string diff --git a/web/src/i18n/strings.en.yaml b/web/src/i18n/strings.en.yaml index 885170f15..07e067864 100644 --- a/web/src/i18n/strings.en.yaml +++ b/web/src/i18n/strings.en.yaml @@ -137,6 +137,7 @@ createABranch: Create a branch createATag: Create a tag delete: Delete edit: Edit +update: Update editAsText: Edit as Text branchName: Branch name enterBranchPlaceholder: Enter the branch name here @@ -666,9 +667,12 @@ secrets: createSecret: Create Secret createSuccess: Secret created successfully secretDeleted: Secret {uid} deleted. + secretUpdated: Secret {uid} updated. deleteSecretConfirm: Are you sure you want to delete secret {{uid}}? You can't undo this action. failedToDeleteSecret: Failed to delete Secret. Please try again. - deleteSecret: Delete Secrets + failedToUpdateSecret: Failed to update Secret. Please try again. + deleteSecret: Delete secret + updateSecret: Update secret userUpdateSuccess: 'User updated successfully' viewFile: View File searchResult: 'Search Result {count}' diff --git a/web/src/pages/SecretList/SecretList.tsx b/web/src/pages/SecretList/SecretList.tsx index a0b162639..25ed9cf6a 100644 --- a/web/src/pages/SecretList/SecretList.tsx +++ b/web/src/pages/SecretList/SecretList.tsx @@ -1,4 +1,4 @@ -import React, { useMemo, useState } from 'react' +import React, { useCallback, useMemo, useState } from 'react' import { ButtonVariation, Container, @@ -29,6 +29,7 @@ import { ResourceListingPagination } from 'components/ResourceListingPagination/ import { NewSecretModalButton } from 'components/NewSecretModalButton/NewSecretModalButton' import { useConfirmAct } from 'hooks/useConfirmAction' import { OptionsMenuButton } from 'components/OptionsMenuButton/OptionsMenuButton' +import useUpdateSecretModal from 'components/UpdateSecretModal/UpdateSecretModal' import noSecretsImage from '../RepositoriesListing/no-repo.svg' import css from './SecretList.module.scss' @@ -61,6 +62,8 @@ const SecretList = () => { onSuccess={() => refetch()}> ) + const { openModal: openUpdateSecretModal } = useUpdateSecretModal() + const columns: Column[] = useMemo( () => [ { @@ -113,6 +116,11 @@ const SecretList = () => { isDark width="100px" items={[ + { + text: getString('edit'), + isDanger: true, + onClick: () => openUpdateSecretModal({ secretToUpdate: row.original }) + }, { text: getString('delete'), isDanger: true,