From 7af506b47e5edfc748ab0f593072a70321bda23e Mon Sep 17 00:00:00 2001 From: Vardan Bansal Date: Tue, 12 Sep 2023 18:00:28 -0700 Subject: [PATCH 1/4] integrate run pipeline modal on executions page --- web/src/pages/ExecutionList/ExecutionList.tsx | 22 +++++-------------- 1 file changed, 6 insertions(+), 16 deletions(-) diff --git a/web/src/pages/ExecutionList/ExecutionList.tsx b/web/src/pages/ExecutionList/ExecutionList.tsx index 277bc2312..aa051a7bc 100644 --- a/web/src/pages/ExecutionList/ExecutionList.tsx +++ b/web/src/pages/ExecutionList/ExecutionList.tsx @@ -8,14 +8,13 @@ import { PageBody, TableV2 as Table, Text, - Utils, - useToaster + Utils } from '@harnessio/uicore' import { Color } from '@harnessio/design-system' import cx from 'classnames' import type { CellProps, Column } from 'react-table' import { useHistory, useParams } from 'react-router-dom' -import { useGet, useMutate } from 'restful-react' +import { useGet } from 'restful-react' import { Timer, Calendar } from 'iconoir-react' import { useStrings } from 'framework/strings' import { LoadingSpinner } from 'components/LoadingSpinner/LoadingSpinner' @@ -33,6 +32,7 @@ import { ExecutionStatus } from 'components/ExecutionStatus/ExecutionStatus' import { getStatus } from 'utils/PipelineUtils' import useSpaceSSE from 'hooks/useSpaceSSE' import { ExecutionText, ExecutionTrigger } from 'components/ExecutionText/ExecutionText' +import useRunPipelineModal from 'components/RunPipelineModal/RunPipelineModal' import noExecutionImage from '../RepositoriesListing/no-repo.svg' import css from './ExecutionList.module.scss' @@ -44,7 +44,6 @@ const ExecutionList = () => { const pageBrowser = useQueryParams() const pageInit = pageBrowser.page ? parseInt(pageBrowser.page) : 1 const [page, setPage] = usePageIndex(pageInit) - const { showError, showSuccess } = useToaster() const { repoMetadata, error, loading, refetch, space } = useGetRepositoryMetadata() @@ -84,19 +83,11 @@ const ExecutionList = () => { } }) - const { mutate, loading: mutateLoading } = useMutate({ - verb: 'POST', - path: `/api/v1/repos/${repoMetadata?.path}/+/pipelines/${pipeline}/executions` - }) + const { openModal: openRunPipelineModal } = useRunPipelineModal() const handleClick = async () => { - try { - //TODO - this should NOT be hardcoded to master branch - need a modal to insert branch - but useful for testing until then - await mutate({ branch: 'master' }) - showSuccess('Build started') - executionsRefetch() - } catch { - showError('Failed to start build') + if (repoMetadata && pipeline) { + openRunPipelineModal({ repoMetadata, pipeline }) } } @@ -105,7 +96,6 @@ const ExecutionList = () => { text={getString('executions.newExecutionButton')} variation={ButtonVariation.PRIMARY} icon="play-outline" - disabled={mutateLoading} onClick={handleClick}> ) From c7390d77b42648e1772ba56294321c2691cfb2b8 Mon Sep 17 00:00:00 2001 From: Vardan Bansal Date: Tue, 12 Sep 2023 19:05:08 -0700 Subject: [PATCH 2/4] Update secret --- .../NewSecretModalButton.tsx | 7 +- .../UpdateSecretModal/UpdateSecretModal.tsx | 147 ++++++++++++++++++ web/src/framework/strings/stringTypes.ts | 4 + web/src/i18n/strings.en.yaml | 6 +- web/src/pages/SecretList/SecretList.tsx | 10 +- 5 files changed, 167 insertions(+), 7 deletions(-) create mode 100644 web/src/components/UpdateSecretModal/UpdateSecretModal.tsx 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, From bc19ec33f8d7ee1c940efe2bf7e8573444c74aea Mon Sep 17 00:00:00 2001 From: Vardan Bansal Date: Tue, 12 Sep 2023 19:07:36 -0700 Subject: [PATCH 3/4] Cleanup --- web/src/framework/strings/stringTypes.ts | 1 - web/src/i18n/strings.en.yaml | 1 - 2 files changed, 2 deletions(-) diff --git a/web/src/framework/strings/stringTypes.ts b/web/src/framework/strings/stringTypes.ts index e305c43d5..0b3ac30a1 100644 --- a/web/src/framework/strings/stringTypes.ts +++ b/web/src/framework/strings/stringTypes.ts @@ -558,7 +558,6 @@ 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 07e067864..83cd7d5a5 100644 --- a/web/src/i18n/strings.en.yaml +++ b/web/src/i18n/strings.en.yaml @@ -137,7 +137,6 @@ 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 From 3a664163441b6a7d3e06fce5f7b52a86a20653dc Mon Sep 17 00:00:00 2001 From: Vardan Bansal Date: Tue, 12 Sep 2023 19:16:36 -0700 Subject: [PATCH 4/4] Handling post save --- .../UpdateSecretModal/UpdateSecretModal.tsx | 13 +++++++++++-- web/src/pages/SecretList/SecretList.tsx | 4 ++-- 2 files changed, 13 insertions(+), 4 deletions(-) diff --git a/web/src/components/UpdateSecretModal/UpdateSecretModal.tsx b/web/src/components/UpdateSecretModal/UpdateSecretModal.tsx index 914c0754b..4b8b0f9c4 100644 --- a/web/src/components/UpdateSecretModal/UpdateSecretModal.tsx +++ b/web/src/components/UpdateSecretModal/UpdateSecretModal.tsx @@ -1,4 +1,4 @@ -import React, { useState } from 'react' +import React, { useRef, useState } from 'react' import * as yup from 'yup' import { useMutate } from 'restful-react' import { FontVariation, Intent } from '@harnessio/design-system' @@ -28,6 +28,7 @@ const useUpdateSecretModal = () => { const space = useGetSpaceParam() const { showError, showSuccess } = useToaster() const [secret, setSecret] = useState() + const postUpdate = useRef() const { mutate: updateSecret, loading } = useMutate({ verb: 'PATCH', @@ -51,6 +52,7 @@ const useUpdateSecretModal = () => { }} /> ) + postUpdate.current?.() } catch (exception) { showError(getErrorMessage(exception), 0, getString('secrets.failedToUpdateSecret')) } @@ -137,8 +139,15 @@ const useUpdateSecretModal = () => { }, [secret]) return { - openModal: ({ secretToUpdate }: { secretToUpdate: TypesSecret }) => { + openModal: ({ + secretToUpdate, + openSecretUpdate + }: { + secretToUpdate: TypesSecret + openSecretUpdate: () => Promise + }) => { setSecret(secretToUpdate) + postUpdate.current = openSecretUpdate openModal() } } diff --git a/web/src/pages/SecretList/SecretList.tsx b/web/src/pages/SecretList/SecretList.tsx index 25ed9cf6a..aca84b286 100644 --- a/web/src/pages/SecretList/SecretList.tsx +++ b/web/src/pages/SecretList/SecretList.tsx @@ -1,4 +1,4 @@ -import React, { useCallback, useMemo, useState } from 'react' +import React, { useMemo, useState } from 'react' import { ButtonVariation, Container, @@ -119,7 +119,7 @@ const SecretList = () => { { text: getString('edit'), isDanger: true, - onClick: () => openUpdateSecretModal({ secretToUpdate: row.original }) + onClick: () => openUpdateSecretModal({ secretToUpdate: row.original, openSecretUpdate: refetch }) }, { text: getString('delete'),