From d481da183fdf338c7537c0936f7cb420aae53c31 Mon Sep 17 00:00:00 2001 From: bosiraphael <71827178+bosiraphael@users.noreply.github.com> Date: Fri, 17 Nov 2023 19:12:22 +0100 Subject: [PATCH] V2 opportunities (#2565) * changed isSystem to false * wip * wip * wip * add amount viewfield seed * seed other viewFields * upate tenant seeds * Remove calls to old pipelines --------- Co-authored-by: Charles Bochet Co-authored-by: Charles Bochet --- front/src/AppNavbar.tsx | 7 + front/src/generated/graphql.tsx | 417 ------------------ .../useHandleCheckableActivityTargetChange.ts | 2 +- .../components/ActivityActionBar.tsx | 2 +- .../companies/components/CompanyBoardCard.tsx | 29 +- .../components/HooksCompanyBoardEffect.tsx | 138 +++--- .../hooks/useCreateCompanyProgress.ts | 27 +- .../companies/hooks/useUpdateBoardCardIds.ts | 6 +- .../hooks/useUpdateCompanyBoardColumns.ts | 31 +- .../companies/types/CompanyProgress.ts | 15 +- .../components/ObjectMetadataNavItems.tsx | 1 + .../hooks/useDeleteOneObjectRecord.ts | 33 +- .../useRecordTableContextMenuEntries.tsx | 8 +- .../createCompanyPipelineProgress.ts | 21 - .../graphql/mutations/createPipelineStage.ts | 11 - .../mutations/deletePipelineProgress.ts | 9 - .../graphql/mutations/deletePipelineStage.ts | 11 - .../mutations/updatePipelineProgress.ts | 18 - .../mutations/updatePipelineProgressStage.ts | 15 - .../graphql/mutations/updatePipelineStage.ts | 11 - .../graphql/queries/getPipelineProgress.ts | 26 -- .../pipeline/graphql/queries/getPipelines.ts | 17 - .../pipeline/hooks/usePipelineStages.ts | 28 +- .../states/currentPipelineStepsState.ts | 8 + .../src/modules/pipeline/types/Opportunity.ts | 17 + .../modules/pipeline/types/PipelineStep.ts | 6 + .../layout/board/components/EntityBoard.tsx | 57 ++- .../board/hooks/useBoardActionBarEntries.tsx | 3 +- .../ui/layout/board/hooks/useBoardColumns.ts | 18 +- .../hooks/useBoardContextMenuEntries.tsx | 3 +- .../hooks/useDeleteSelectedBoardCards.ts | 47 +- .../src/pages/opportunities/Opportunities.tsx | 41 +- .../settings/SettingsWorkspaceMembers.tsx | 4 +- front/src/testing/graphqlMocks.ts | 23 +- .../commands/data-seed-workspace.command.ts | 4 + .../typeorm-seeds/metadata/object-metadata.ts | 2 +- .../typeorm-seeds/workspace/opportunity.ts | 38 ++ .../typeorm-seeds/workspace/pipeline-step.ts | 47 ++ .../typeorm-seeds/workspace/view-fields.ts | 59 ++- .../database/typeorm-seeds/workspace/views.ts | 21 - .../opportunity.ts | 33 ++ .../standard-objects-prefill-data.ts | 2 + .../standard-objects/opportunity.ts | 2 +- 43 files changed, 454 insertions(+), 864 deletions(-) delete mode 100644 front/src/modules/pipeline/graphql/mutations/createCompanyPipelineProgress.ts delete mode 100644 front/src/modules/pipeline/graphql/mutations/createPipelineStage.ts delete mode 100644 front/src/modules/pipeline/graphql/mutations/deletePipelineProgress.ts delete mode 100644 front/src/modules/pipeline/graphql/mutations/deletePipelineStage.ts delete mode 100644 front/src/modules/pipeline/graphql/mutations/updatePipelineProgress.ts delete mode 100644 front/src/modules/pipeline/graphql/mutations/updatePipelineProgressStage.ts delete mode 100644 front/src/modules/pipeline/graphql/mutations/updatePipelineStage.ts delete mode 100644 front/src/modules/pipeline/graphql/queries/getPipelineProgress.ts delete mode 100644 front/src/modules/pipeline/graphql/queries/getPipelines.ts create mode 100644 front/src/modules/pipeline/states/currentPipelineStepsState.ts create mode 100644 front/src/modules/pipeline/types/Opportunity.ts create mode 100644 front/src/modules/pipeline/types/PipelineStep.ts create mode 100644 server/src/database/typeorm-seeds/workspace/opportunity.ts create mode 100644 server/src/database/typeorm-seeds/workspace/pipeline-step.ts create mode 100644 server/src/workspace/workspace-manager/standard-objects-prefill-data/opportunity.ts diff --git a/front/src/AppNavbar.tsx b/front/src/AppNavbar.tsx index e31850f59..fe95edf66 100644 --- a/front/src/AppNavbar.tsx +++ b/front/src/AppNavbar.tsx @@ -10,6 +10,7 @@ import { IconCheckbox, IconSearch, IconSettings, + IconTargetArrow, } from '@/ui/display/icon/index'; import { useIsSubMenuNavbarDisplayed } from '@/ui/layout/hooks/useIsSubMenuNavbarDisplayed'; import MainNavbar from '@/ui/navigation/navbar/components/MainNavbar'; @@ -56,6 +57,12 @@ export const AppNavbar = () => { + ) : ( diff --git a/front/src/generated/graphql.tsx b/front/src/generated/graphql.tsx index 7c602aab1..29a89919f 100644 --- a/front/src/generated/graphql.tsx +++ b/front/src/generated/graphql.tsx @@ -3534,76 +3534,6 @@ export type GetPersonPhoneByIdQueryVariables = Exact<{ export type GetPersonPhoneByIdQuery = { __typename?: 'Query', person: { __typename?: 'Person', id: string, phone?: string | null } }; -export type CreateOneCompanyPipelineProgressMutationVariables = Exact<{ - uuid: Scalars['String']; - companyId: Scalars['String']; - pipelineId: Scalars['String']; - pipelineStageId: Scalars['String']; -}>; - - -export type CreateOneCompanyPipelineProgressMutation = { __typename?: 'Mutation', createOnePipelineProgress: { __typename?: 'PipelineProgress', id: string } }; - -export type CreatePipelineStageMutationVariables = Exact<{ - data: PipelineStageCreateInput; -}>; - - -export type CreatePipelineStageMutation = { __typename?: 'Mutation', pipelineStage: { __typename?: 'PipelineStage', id: string, name: string, color: string } }; - -export type DeleteManyPipelineProgressMutationVariables = Exact<{ - ids?: InputMaybe | Scalars['String']>; -}>; - - -export type DeleteManyPipelineProgressMutation = { __typename?: 'Mutation', deleteManyPipelineProgress: { __typename?: 'AffectedRows', count: number } }; - -export type DeletePipelineStageMutationVariables = Exact<{ - where: PipelineStageWhereUniqueInput; -}>; - - -export type DeletePipelineStageMutation = { __typename?: 'Mutation', pipelineStage: { __typename?: 'PipelineStage', id: string, name: string, color: string } }; - -export type UpdateOnePipelineProgressMutationVariables = Exact<{ - data: PipelineProgressUpdateInput; - where: PipelineProgressWhereUniqueInput; -}>; - - -export type UpdateOnePipelineProgressMutation = { __typename?: 'Mutation', updateOnePipelineProgress?: { __typename?: 'PipelineProgress', id: string, amount?: number | null, closeDate?: string | null, probability?: number | null, pointOfContact?: { __typename?: 'Person', id: string } | null } | null }; - -export type UpdateOnePipelineProgressStageMutationVariables = Exact<{ - id?: InputMaybe; - pipelineStageId?: InputMaybe; -}>; - - -export type UpdateOnePipelineProgressStageMutation = { __typename?: 'Mutation', updateOnePipelineProgress?: { __typename?: 'PipelineProgress', id: string } | null }; - -export type UpdatePipelineStageMutationVariables = Exact<{ - id?: InputMaybe; - data: PipelineStageUpdateInput; -}>; - - -export type UpdatePipelineStageMutation = { __typename?: 'Mutation', updateOnePipelineStage?: { __typename?: 'PipelineStage', id: string, name: string, color: string } | null }; - -export type GetPipelineProgressQueryVariables = Exact<{ - where?: InputMaybe; - orderBy?: InputMaybe | PipelineProgressOrderByWithRelationInput>; -}>; - - -export type GetPipelineProgressQuery = { __typename?: 'Query', findManyPipelineProgress: Array<{ __typename?: 'PipelineProgress', id: string, pipelineStageId: string, companyId?: string | null, personId?: string | null, amount?: number | null, closeDate?: string | null, pointOfContactId?: string | null, probability?: number | null, pointOfContact?: { __typename?: 'Person', id: string, firstName?: string | null, lastName?: string | null, displayName: string, avatarUrl?: string | null } | null }> }; - -export type GetPipelinesQueryVariables = Exact<{ - where?: InputMaybe; -}>; - - -export type GetPipelinesQuery = { __typename?: 'Query', findManyPipeline: Array<{ __typename?: 'Pipeline', id: string, name: string, pipelineProgressableType: PipelineProgressableType, pipelineStages?: Array<{ __typename?: 'PipelineStage', id: string, name: string, color: string, position?: number | null }> | null }> }; - export type SearchActivityQueryVariables = Exact<{ where?: InputMaybe; limit?: InputMaybe; @@ -5128,353 +5058,6 @@ export function useGetPersonPhoneByIdLazyQuery(baseOptions?: Apollo.LazyQueryHoo export type GetPersonPhoneByIdQueryHookResult = ReturnType; export type GetPersonPhoneByIdLazyQueryHookResult = ReturnType; export type GetPersonPhoneByIdQueryResult = Apollo.QueryResult; -export const CreateOneCompanyPipelineProgressDocument = gql` - mutation CreateOneCompanyPipelineProgress($uuid: String!, $companyId: String!, $pipelineId: String!, $pipelineStageId: String!) { - createOnePipelineProgress( - data: {id: $uuid, company: {connect: {id: $companyId}}, pipeline: {connect: {id: $pipelineId}}, pipelineStage: {connect: {id: $pipelineStageId}}} - ) { - id - } -} - `; -export type CreateOneCompanyPipelineProgressMutationFn = Apollo.MutationFunction; - -/** - * __useCreateOneCompanyPipelineProgressMutation__ - * - * To run a mutation, you first call `useCreateOneCompanyPipelineProgressMutation` within a React component and pass it any options that fit your needs. - * When your component renders, `useCreateOneCompanyPipelineProgressMutation` returns a tuple that includes: - * - A mutate function that you can call at any time to execute the mutation - * - An object with fields that represent the current status of the mutation's execution - * - * @param baseOptions options that will be passed into the mutation, supported options are listed on: https://www.apollographql.com/docs/react/api/react-hooks/#options-2; - * - * @example - * const [createOneCompanyPipelineProgressMutation, { data, loading, error }] = useCreateOneCompanyPipelineProgressMutation({ - * variables: { - * uuid: // value for 'uuid' - * companyId: // value for 'companyId' - * pipelineId: // value for 'pipelineId' - * pipelineStageId: // value for 'pipelineStageId' - * }, - * }); - */ -export function useCreateOneCompanyPipelineProgressMutation(baseOptions?: Apollo.MutationHookOptions) { - const options = {...defaultOptions, ...baseOptions} - return Apollo.useMutation(CreateOneCompanyPipelineProgressDocument, options); - } -export type CreateOneCompanyPipelineProgressMutationHookResult = ReturnType; -export type CreateOneCompanyPipelineProgressMutationResult = Apollo.MutationResult; -export type CreateOneCompanyPipelineProgressMutationOptions = Apollo.BaseMutationOptions; -export const CreatePipelineStageDocument = gql` - mutation CreatePipelineStage($data: PipelineStageCreateInput!) { - pipelineStage: createOnePipelineStage(data: $data) { - id - name - color - } -} - `; -export type CreatePipelineStageMutationFn = Apollo.MutationFunction; - -/** - * __useCreatePipelineStageMutation__ - * - * To run a mutation, you first call `useCreatePipelineStageMutation` within a React component and pass it any options that fit your needs. - * When your component renders, `useCreatePipelineStageMutation` returns a tuple that includes: - * - A mutate function that you can call at any time to execute the mutation - * - An object with fields that represent the current status of the mutation's execution - * - * @param baseOptions options that will be passed into the mutation, supported options are listed on: https://www.apollographql.com/docs/react/api/react-hooks/#options-2; - * - * @example - * const [createPipelineStageMutation, { data, loading, error }] = useCreatePipelineStageMutation({ - * variables: { - * data: // value for 'data' - * }, - * }); - */ -export function useCreatePipelineStageMutation(baseOptions?: Apollo.MutationHookOptions) { - const options = {...defaultOptions, ...baseOptions} - return Apollo.useMutation(CreatePipelineStageDocument, options); - } -export type CreatePipelineStageMutationHookResult = ReturnType; -export type CreatePipelineStageMutationResult = Apollo.MutationResult; -export type CreatePipelineStageMutationOptions = Apollo.BaseMutationOptions; -export const DeleteManyPipelineProgressDocument = gql` - mutation DeleteManyPipelineProgress($ids: [String!]) { - deleteManyPipelineProgress(where: {id: {in: $ids}}) { - count - } -} - `; -export type DeleteManyPipelineProgressMutationFn = Apollo.MutationFunction; - -/** - * __useDeleteManyPipelineProgressMutation__ - * - * To run a mutation, you first call `useDeleteManyPipelineProgressMutation` within a React component and pass it any options that fit your needs. - * When your component renders, `useDeleteManyPipelineProgressMutation` returns a tuple that includes: - * - A mutate function that you can call at any time to execute the mutation - * - An object with fields that represent the current status of the mutation's execution - * - * @param baseOptions options that will be passed into the mutation, supported options are listed on: https://www.apollographql.com/docs/react/api/react-hooks/#options-2; - * - * @example - * const [deleteManyPipelineProgressMutation, { data, loading, error }] = useDeleteManyPipelineProgressMutation({ - * variables: { - * ids: // value for 'ids' - * }, - * }); - */ -export function useDeleteManyPipelineProgressMutation(baseOptions?: Apollo.MutationHookOptions) { - const options = {...defaultOptions, ...baseOptions} - return Apollo.useMutation(DeleteManyPipelineProgressDocument, options); - } -export type DeleteManyPipelineProgressMutationHookResult = ReturnType; -export type DeleteManyPipelineProgressMutationResult = Apollo.MutationResult; -export type DeleteManyPipelineProgressMutationOptions = Apollo.BaseMutationOptions; -export const DeletePipelineStageDocument = gql` - mutation DeletePipelineStage($where: PipelineStageWhereUniqueInput!) { - pipelineStage: deleteOnePipelineStage(where: $where) { - id - name - color - } -} - `; -export type DeletePipelineStageMutationFn = Apollo.MutationFunction; - -/** - * __useDeletePipelineStageMutation__ - * - * To run a mutation, you first call `useDeletePipelineStageMutation` within a React component and pass it any options that fit your needs. - * When your component renders, `useDeletePipelineStageMutation` returns a tuple that includes: - * - A mutate function that you can call at any time to execute the mutation - * - An object with fields that represent the current status of the mutation's execution - * - * @param baseOptions options that will be passed into the mutation, supported options are listed on: https://www.apollographql.com/docs/react/api/react-hooks/#options-2; - * - * @example - * const [deletePipelineStageMutation, { data, loading, error }] = useDeletePipelineStageMutation({ - * variables: { - * where: // value for 'where' - * }, - * }); - */ -export function useDeletePipelineStageMutation(baseOptions?: Apollo.MutationHookOptions) { - const options = {...defaultOptions, ...baseOptions} - return Apollo.useMutation(DeletePipelineStageDocument, options); - } -export type DeletePipelineStageMutationHookResult = ReturnType; -export type DeletePipelineStageMutationResult = Apollo.MutationResult; -export type DeletePipelineStageMutationOptions = Apollo.BaseMutationOptions; -export const UpdateOnePipelineProgressDocument = gql` - mutation UpdateOnePipelineProgress($data: PipelineProgressUpdateInput!, $where: PipelineProgressWhereUniqueInput!) { - updateOnePipelineProgress(where: $where, data: $data) { - id - amount - closeDate - probability - pointOfContact { - id - } - } -} - `; -export type UpdateOnePipelineProgressMutationFn = Apollo.MutationFunction; - -/** - * __useUpdateOnePipelineProgressMutation__ - * - * To run a mutation, you first call `useUpdateOnePipelineProgressMutation` within a React component and pass it any options that fit your needs. - * When your component renders, `useUpdateOnePipelineProgressMutation` returns a tuple that includes: - * - A mutate function that you can call at any time to execute the mutation - * - An object with fields that represent the current status of the mutation's execution - * - * @param baseOptions options that will be passed into the mutation, supported options are listed on: https://www.apollographql.com/docs/react/api/react-hooks/#options-2; - * - * @example - * const [updateOnePipelineProgressMutation, { data, loading, error }] = useUpdateOnePipelineProgressMutation({ - * variables: { - * data: // value for 'data' - * where: // value for 'where' - * }, - * }); - */ -export function useUpdateOnePipelineProgressMutation(baseOptions?: Apollo.MutationHookOptions) { - const options = {...defaultOptions, ...baseOptions} - return Apollo.useMutation(UpdateOnePipelineProgressDocument, options); - } -export type UpdateOnePipelineProgressMutationHookResult = ReturnType; -export type UpdateOnePipelineProgressMutationResult = Apollo.MutationResult; -export type UpdateOnePipelineProgressMutationOptions = Apollo.BaseMutationOptions; -export const UpdateOnePipelineProgressStageDocument = gql` - mutation UpdateOnePipelineProgressStage($id: String, $pipelineStageId: String) { - updateOnePipelineProgress( - where: {id: $id} - data: {pipelineStage: {connect: {id: $pipelineStageId}}} - ) { - id - } -} - `; -export type UpdateOnePipelineProgressStageMutationFn = Apollo.MutationFunction; - -/** - * __useUpdateOnePipelineProgressStageMutation__ - * - * To run a mutation, you first call `useUpdateOnePipelineProgressStageMutation` within a React component and pass it any options that fit your needs. - * When your component renders, `useUpdateOnePipelineProgressStageMutation` returns a tuple that includes: - * - A mutate function that you can call at any time to execute the mutation - * - An object with fields that represent the current status of the mutation's execution - * - * @param baseOptions options that will be passed into the mutation, supported options are listed on: https://www.apollographql.com/docs/react/api/react-hooks/#options-2; - * - * @example - * const [updateOnePipelineProgressStageMutation, { data, loading, error }] = useUpdateOnePipelineProgressStageMutation({ - * variables: { - * id: // value for 'id' - * pipelineStageId: // value for 'pipelineStageId' - * }, - * }); - */ -export function useUpdateOnePipelineProgressStageMutation(baseOptions?: Apollo.MutationHookOptions) { - const options = {...defaultOptions, ...baseOptions} - return Apollo.useMutation(UpdateOnePipelineProgressStageDocument, options); - } -export type UpdateOnePipelineProgressStageMutationHookResult = ReturnType; -export type UpdateOnePipelineProgressStageMutationResult = Apollo.MutationResult; -export type UpdateOnePipelineProgressStageMutationOptions = Apollo.BaseMutationOptions; -export const UpdatePipelineStageDocument = gql` - mutation UpdatePipelineStage($id: String, $data: PipelineStageUpdateInput!) { - updateOnePipelineStage(where: {id: $id}, data: $data) { - id - name - color - } -} - `; -export type UpdatePipelineStageMutationFn = Apollo.MutationFunction; - -/** - * __useUpdatePipelineStageMutation__ - * - * To run a mutation, you first call `useUpdatePipelineStageMutation` within a React component and pass it any options that fit your needs. - * When your component renders, `useUpdatePipelineStageMutation` returns a tuple that includes: - * - A mutate function that you can call at any time to execute the mutation - * - An object with fields that represent the current status of the mutation's execution - * - * @param baseOptions options that will be passed into the mutation, supported options are listed on: https://www.apollographql.com/docs/react/api/react-hooks/#options-2; - * - * @example - * const [updatePipelineStageMutation, { data, loading, error }] = useUpdatePipelineStageMutation({ - * variables: { - * id: // value for 'id' - * data: // value for 'data' - * }, - * }); - */ -export function useUpdatePipelineStageMutation(baseOptions?: Apollo.MutationHookOptions) { - const options = {...defaultOptions, ...baseOptions} - return Apollo.useMutation(UpdatePipelineStageDocument, options); - } -export type UpdatePipelineStageMutationHookResult = ReturnType; -export type UpdatePipelineStageMutationResult = Apollo.MutationResult; -export type UpdatePipelineStageMutationOptions = Apollo.BaseMutationOptions; -export const GetPipelineProgressDocument = gql` - query GetPipelineProgress($where: PipelineProgressWhereInput, $orderBy: [PipelineProgressOrderByWithRelationInput!]) { - findManyPipelineProgress(where: $where, orderBy: $orderBy) { - id - pipelineStageId - companyId - personId - amount - closeDate - pointOfContactId - pointOfContact { - id - firstName - lastName - displayName - avatarUrl - } - probability - } -} - `; - -/** - * __useGetPipelineProgressQuery__ - * - * To run a query within a React component, call `useGetPipelineProgressQuery` and pass it any options that fit your needs. - * When your component renders, `useGetPipelineProgressQuery` returns an object from Apollo Client that contains loading, error, and data properties - * you can use to render your UI. - * - * @param baseOptions options that will be passed into the query, supported options are listed on: https://www.apollographql.com/docs/react/api/react-hooks/#options; - * - * @example - * const { data, loading, error } = useGetPipelineProgressQuery({ - * variables: { - * where: // value for 'where' - * orderBy: // value for 'orderBy' - * }, - * }); - */ -export function useGetPipelineProgressQuery(baseOptions?: Apollo.QueryHookOptions) { - const options = {...defaultOptions, ...baseOptions} - return Apollo.useQuery(GetPipelineProgressDocument, options); - } -export function useGetPipelineProgressLazyQuery(baseOptions?: Apollo.LazyQueryHookOptions) { - const options = {...defaultOptions, ...baseOptions} - return Apollo.useLazyQuery(GetPipelineProgressDocument, options); - } -export type GetPipelineProgressQueryHookResult = ReturnType; -export type GetPipelineProgressLazyQueryHookResult = ReturnType; -export type GetPipelineProgressQueryResult = Apollo.QueryResult; -export const GetPipelinesDocument = gql` - query GetPipelines($where: PipelineWhereInput) { - findManyPipeline(where: $where) { - id - name - pipelineProgressableType - pipelineStages { - id - name - color - position - } - } -} - `; - -/** - * __useGetPipelinesQuery__ - * - * To run a query within a React component, call `useGetPipelinesQuery` and pass it any options that fit your needs. - * When your component renders, `useGetPipelinesQuery` returns an object from Apollo Client that contains loading, error, and data properties - * you can use to render your UI. - * - * @param baseOptions options that will be passed into the query, supported options are listed on: https://www.apollographql.com/docs/react/api/react-hooks/#options; - * - * @example - * const { data, loading, error } = useGetPipelinesQuery({ - * variables: { - * where: // value for 'where' - * }, - * }); - */ -export function useGetPipelinesQuery(baseOptions?: Apollo.QueryHookOptions) { - const options = {...defaultOptions, ...baseOptions} - return Apollo.useQuery(GetPipelinesDocument, options); - } -export function useGetPipelinesLazyQuery(baseOptions?: Apollo.LazyQueryHookOptions) { - const options = {...defaultOptions, ...baseOptions} - return Apollo.useLazyQuery(GetPipelinesDocument, options); - } -export type GetPipelinesQueryHookResult = ReturnType; -export type GetPipelinesLazyQueryHookResult = ReturnType; -export type GetPipelinesQueryResult = Apollo.QueryResult; export const SearchActivityDocument = gql` query SearchActivity($where: ActivityWhereInput, $limit: Int, $orderBy: [ActivityOrderByWithRelationInput!]) { searchResults: findManyActivities( diff --git a/front/src/modules/activities/hooks/useHandleCheckableActivityTargetChange.ts b/front/src/modules/activities/hooks/useHandleCheckableActivityTargetChange.ts index 0929c74f3..5882e3338 100644 --- a/front/src/modules/activities/hooks/useHandleCheckableActivityTargetChange.ts +++ b/front/src/modules/activities/hooks/useHandleCheckableActivityTargetChange.ts @@ -20,7 +20,7 @@ export const useHandleCheckableActivityTargetChange = ({ objectNameSingular: 'activityTargetV2', }); const { deleteOneObject } = useDeleteOneObjectRecord({ - objectNamePlural: 'activityTargetV2', + objectNameSingular: 'activityTargetV2', }); return async ( diff --git a/front/src/modules/activities/right-drawer/components/ActivityActionBar.tsx b/front/src/modules/activities/right-drawer/components/ActivityActionBar.tsx index 679853617..0285a8a5f 100644 --- a/front/src/modules/activities/right-drawer/components/ActivityActionBar.tsx +++ b/front/src/modules/activities/right-drawer/components/ActivityActionBar.tsx @@ -12,7 +12,7 @@ type ActivityActionBarProps = { export const ActivityActionBar = ({ activityId }: ActivityActionBarProps) => { const [, setIsRightDrawerOpen] = useRecoilState(isRightDrawerOpenState); const { deleteOneObject } = useDeleteOneObjectRecord({ - objectNamePlural: 'activitiesV2', + objectNameSingular: 'activityV2', }); const deleteActivity = () => { diff --git a/front/src/modules/companies/components/CompanyBoardCard.tsx b/front/src/modules/companies/components/CompanyBoardCard.tsx index 85aa693db..85b624bb8 100644 --- a/front/src/modules/companies/components/CompanyBoardCard.tsx +++ b/front/src/modules/companies/components/CompanyBoardCard.tsx @@ -2,6 +2,7 @@ import { ReactNode, useContext } from 'react'; import styled from '@emotion/styled'; import { useRecoilState } from 'recoil'; +import { useUpdateOneObjectRecord } from '@/object-record/hooks/useUpdateOneObjectRecord'; import { EntityChipVariant } from '@/ui/display/chip/components/EntityChip'; import { IconEye } from '@/ui/display/icon/index'; import { LightIconButton } from '@/ui/input/button/components/LightIconButton'; @@ -17,7 +18,6 @@ import { RecordInlineCell } from '@/ui/object/record-inline-cell/components/Reco import { InlineCellHotkeyScope } from '@/ui/object/record-inline-cell/types/InlineCellHotkeyScope'; import { AnimatedEaseInOut } from '@/ui/utilities/animation/components/AnimatedEaseInOut'; import { useRecoilScopedValue } from '@/ui/utilities/recoil-scope/hooks/useRecoilScopedValue'; -import { useUpdateOnePipelineProgressMutation } from '~/generated/graphql'; import { getLogoUrlFromDomainName } from '~/utils'; import { companyProgressesFamilyState } from '../states/companyProgressesFamilyState'; @@ -150,6 +150,30 @@ export const CompanyBoardCard = () => { BoardRecoilScopeContext, ); + const useUpdateOneObjectMutation: () => [(params: any) => any, any] = () => { + const { updateOneObject } = useUpdateOneObjectRecord({ + objectNameSingular: 'opportunityV2', + }); + + const updateEntity = ({ + variables, + }: { + variables: { + where: { id: string }; + data: { + [fieldName: string]: any; + }; + }; + }) => { + updateOneObject?.({ + idToUpdate: variables.where.id, + input: variables.data, + }); + }; + + return [updateEntity, { loading: false }]; + }; + // boardCardId check can be moved to a wrapper to avoid unnecessary logic above if (!company || !pipelineProgress || !boardCardId) { return null; @@ -224,8 +248,7 @@ export const CompanyBoardCard = () => { entityChipDisplayMapper: viewField.entityChipDisplayMapper, }, - useUpdateEntityMutation: - useUpdateOnePipelineProgressMutation, + useUpdateEntityMutation: useUpdateOneObjectMutation, hotkeyScope: InlineCellHotkeyScope.InlineCell, }} > diff --git a/front/src/modules/companies/components/HooksCompanyBoardEffect.tsx b/front/src/modules/companies/components/HooksCompanyBoardEffect.tsx index e36bab747..7fb718e17 100644 --- a/front/src/modules/companies/components/HooksCompanyBoardEffect.tsx +++ b/front/src/modules/companies/components/HooksCompanyBoardEffect.tsx @@ -1,8 +1,12 @@ -import { useEffect, useMemo } from 'react'; +import { useCallback, useEffect, useMemo, useState } from 'react'; import { useSearchParams } from 'react-router-dom'; import { useRecoilState, useRecoilValue } from 'recoil'; +import { useFindManyObjectRecords } from '@/object-record/hooks/useFindManyObjectRecords'; +import { PaginatedObjectTypeResults } from '@/object-record/types/PaginatedObjectTypeResults'; import { pipelineAvailableFieldDefinitions } from '@/pipeline/constants/pipelineAvailableFieldDefinitions'; +import { Opportunity } from '@/pipeline/types/Opportunity'; +import { PipelineStep } from '@/pipeline/types/PipelineStep'; import { useBoardActionBarEntries } from '@/ui/layout/board/hooks/useBoardActionBarEntries'; import { useBoardContext } from '@/ui/layout/board/hooks/useBoardContext'; import { useBoardContextMenuEntries } from '@/ui/layout/board/hooks/useBoardContextMenuEntries'; @@ -15,13 +19,7 @@ import { useViewScopedStates } from '@/views/hooks/internal/useViewScopedStates' import { useView } from '@/views/hooks/useView'; import { ViewType } from '@/views/types/ViewType'; import { mapViewFieldsToBoardFieldDefinitions } from '@/views/utils/mapViewFieldsToBoardFieldDefinitions'; -import { - Pipeline, - PipelineProgressableType, - useGetCompaniesQuery, - useGetPipelineProgressQuery, - useGetPipelinesQuery, -} from '~/generated/graphql'; +import { Company } from '~/generated-metadata/graphql'; import { opportunitiesBoardOptions } from '~/pages/opportunities/opportunitiesBoardOptions'; import { useUpdateCompanyBoardCardIds } from '../hooks/useUpdateBoardCardIds'; @@ -40,6 +38,10 @@ export const HooksCompanyBoardEffect = () => { const { currentViewFiltersState, currentViewFieldsState } = useViewScopedStates(); + const [pipelineSteps, setPipelineSteps] = useState([]); + const [opportunities, setOpportunities] = useState([]); + const [companies, setCompanies] = useState([]); + const currentViewFields = useRecoilValue(currentViewFieldsState); const currentViewFilters = useRecoilValue(currentViewFiltersState); @@ -56,21 +58,62 @@ export const HooksCompanyBoardEffect = () => { availableBoardCardFieldsScopedState, BoardRecoilScopeContext, ); - + const updateCompanyBoardCardIds = useUpdateCompanyBoardCardIds(); const updateCompanyBoard = useUpdateCompanyBoard(); - const { data: pipelineData, loading: loadingGetPipelines } = - useGetPipelinesQuery({ - variables: { - where: { - pipelineProgressableType: { - equals: PipelineProgressableType.Company, + useFindManyObjectRecords({ + objectNamePlural: 'pipelineStepsV2', + filter: {}, + onCompleted: useCallback( + (data: PaginatedObjectTypeResults) => { + setPipelineSteps(data.edges.map((edge) => edge.node)); + }, + [], + ), + }); + + const whereFilters = useMemo(() => { + return { + AND: [ + { + pipelineStageId: { + in: pipelineSteps.map((pipelineStep) => pipelineStep.id), }, }, - }, - }); + ...(currentViewFilters?.map(turnFilterIntoWhereClause) || []), + ], + }; + }, [currentViewFilters, pipelineSteps]) as any; - const pipeline = pipelineData?.findManyPipeline[0] as Pipeline | undefined; + useFindManyObjectRecords({ + skip: !pipelineSteps.length, + objectNamePlural: 'opportunitiesV2', + filter: whereFilters, + onCompleted: useCallback( + (_data: PaginatedObjectTypeResults) => { + const pipelineProgresses: Array = []; + + updateCompanyBoardCardIds(pipelineProgresses); + + setOpportunities(pipelineProgresses); + setIsBoardLoaded(true); + }, + [setIsBoardLoaded, updateCompanyBoardCardIds], + ), + }); + + useFindManyObjectRecords({ + skip: !opportunities.length, + objectNamePlural: 'companiesV2', + filter: { + id: { + in: opportunities.map((opportuntiy) => opportuntiy.companyId || ''), + }, + }, + onCompleted: useCallback((data: PaginatedObjectTypeResults) => { + setCompanies(data.edges.map((edge) => edge.node)); + }, []), + }); useEffect(() => { setAvailableFilterDefinitions(opportunitiesBoardOptions.filterDefinitions); @@ -87,77 +130,32 @@ export const HooksCompanyBoardEffect = () => { setViewType?.(ViewType.Kanban); }, [setViewObjectMetadataId, setViewType]); - const pipelineStageIds = pipeline?.pipelineStages - ?.map((pipelineStage) => pipelineStage.id) - .flat(); - - const whereFilters = useMemo(() => { - return { - AND: [ - { pipelineStageId: { in: pipelineStageIds } }, - ...(currentViewFilters?.map(turnFilterIntoWhereClause) || []), - ], - }; - }, [currentViewFilters, pipelineStageIds]) as any; - - const updateCompanyBoardCardIds = useUpdateCompanyBoardCardIds(); - - const { data: pipelineProgressData, loading: loadingGetPipelineProgress } = - useGetPipelineProgressQuery({ - variables: { - where: whereFilters, - }, - onCompleted: (data) => { - const pipelineProgresses = data?.findManyPipelineProgress || []; - - updateCompanyBoardCardIds(pipelineProgresses); - - setIsBoardLoaded(true); - }, - }); - - const pipelineProgresses = useMemo(() => { - return pipelineProgressData?.findManyPipelineProgress || []; - }, [pipelineProgressData]); - - const { data: companiesData, loading: loadingGetCompanies } = - useGetCompaniesQuery({ - variables: { - where: { - id: { - in: pipelineProgresses.map((item) => item.companyId || ''), - }, - }, - }, - }); - const [searchParams] = useSearchParams(); - const loading = - loadingGetPipelines || loadingGetPipelineProgress || loadingGetCompanies; + const loading = !companies; const { setActionBarEntries } = useBoardActionBarEntries(); const { setContextMenuEntries } = useBoardContextMenuEntries(); useEffect(() => { - if (!loading && pipeline && pipelineProgresses && companiesData) { + if (!loading && opportunities && companies) { setActionBarEntries(); setContextMenuEntries(); setAvailableBoardCardFields(pipelineAvailableFieldDefinitions); - updateCompanyBoard(pipeline, pipelineProgresses, companiesData.companies); - setEntityCountInCurrentView(companiesData.companies.length); + updateCompanyBoard(pipelineSteps, opportunities, companies); + setEntityCountInCurrentView(companies.length); } }, [ loading, - pipeline, - pipelineProgresses, - companiesData, updateCompanyBoard, setActionBarEntries, setContextMenuEntries, searchParams, setEntityCountInCurrentView, setAvailableBoardCardFields, + opportunities, + companies, + pipelineSteps, ]); useEffect(() => { diff --git a/front/src/modules/companies/hooks/useCreateCompanyProgress.ts b/front/src/modules/companies/hooks/useCreateCompanyProgress.ts index ff1078b1e..ff7dfc08f 100644 --- a/front/src/modules/companies/hooks/useCreateCompanyProgress.ts +++ b/front/src/modules/companies/hooks/useCreateCompanyProgress.ts @@ -1,20 +1,15 @@ -import { getOperationName } from '@apollo/client/utilities'; import { useRecoilCallback, useRecoilState } from 'recoil'; import { v4 } from 'uuid'; -import { GET_PIPELINE_PROGRESS } from '@/pipeline/graphql/queries/getPipelineProgress'; -import { GET_PIPELINES } from '@/pipeline/graphql/queries/getPipelines'; +import { useCreateOneObjectRecord } from '@/object-record/hooks/useCreateOneObjectRecord'; import { currentPipelineState } from '@/pipeline/states/currentPipelineState'; +import { Opportunity } from '@/pipeline/types/Opportunity'; import { boardCardIdsByColumnIdFamilyState } from '@/ui/layout/board/states/boardCardIdsByColumnIdFamilyState'; -import { useCreateOneCompanyPipelineProgressMutation } from '~/generated/graphql'; export const useCreateCompanyProgress = () => { - const [createOneCompanyPipelineProgress] = - useCreateOneCompanyPipelineProgressMutation({ - refetchQueries: [ - getOperationName(GET_PIPELINE_PROGRESS) ?? '', - getOperationName(GET_PIPELINES) ?? '', - ], + const { createOneObject: createOneOpportunity } = + useCreateOneObjectRecord({ + objectNameSingular: 'opportunityV2', }); const [currentPipeline] = useRecoilState(currentPipelineState); @@ -33,15 +28,11 @@ export const useCreateCompanyProgress = () => { newUuid, ]); - await createOneCompanyPipelineProgress({ - variables: { - uuid: newUuid, - pipelineStageId: pipelineStageId, - pipelineId: currentPipeline?.id ?? '', - companyId: companyId, - }, + await createOneOpportunity?.({ + pipelineStepId: pipelineStageId, + companyId: companyId, }); }, - [createOneCompanyPipelineProgress, currentPipeline], + [createOneOpportunity, currentPipeline?.id], ); }; diff --git a/front/src/modules/companies/hooks/useUpdateBoardCardIds.ts b/front/src/modules/companies/hooks/useUpdateBoardCardIds.ts index c5095ba82..332812581 100644 --- a/front/src/modules/companies/hooks/useUpdateBoardCardIds.ts +++ b/front/src/modules/companies/hooks/useUpdateBoardCardIds.ts @@ -1,15 +1,13 @@ import { useRecoilCallback } from 'recoil'; +import { Opportunity } from '@/pipeline/types/Opportunity'; import { boardCardIdsByColumnIdFamilyState } from '@/ui/layout/board/states/boardCardIdsByColumnIdFamilyState'; import { boardColumnsState } from '@/ui/layout/board/states/boardColumnsState'; -import { GetPipelineProgressQuery } from '~/generated/graphql'; export const useUpdateCompanyBoardCardIds = () => useRecoilCallback( ({ snapshot, set }) => - ( - pipelineProgresses: GetPipelineProgressQuery['findManyPipelineProgress'], - ) => { + (pipelineProgresses: Opportunity[]) => { const boardColumns = snapshot .getLoadable(boardColumnsState) .valueOrThrow(); diff --git a/front/src/modules/companies/hooks/useUpdateCompanyBoardColumns.ts b/front/src/modules/companies/hooks/useUpdateCompanyBoardColumns.ts index 7c7a957fe..9e74ee755 100644 --- a/front/src/modules/companies/hooks/useUpdateCompanyBoardColumns.ts +++ b/front/src/modules/companies/hooks/useUpdateCompanyBoardColumns.ts @@ -1,31 +1,26 @@ import { useRecoilCallback } from 'recoil'; -import { currentPipelineState } from '@/pipeline/states/currentPipelineState'; +import { currentPipelineStepsState } from '@/pipeline/states/currentPipelineStepsState'; +import { Opportunity } from '@/pipeline/types/Opportunity'; +import { PipelineStep } from '@/pipeline/types/PipelineStep'; import { boardCardIdsByColumnIdFamilyState } from '@/ui/layout/board/states/boardCardIdsByColumnIdFamilyState'; import { boardColumnsState } from '@/ui/layout/board/states/boardColumnsState'; import { savedBoardColumnsState } from '@/ui/layout/board/states/savedBoardColumnsState'; import { BoardColumnDefinition } from '@/ui/layout/board/types/BoardColumnDefinition'; import { entityFieldsFamilyState } from '@/ui/object/field/states/entityFieldsFamilyState'; import { isThemeColor } from '@/ui/theme/utils/castStringAsThemeColor'; -import { Pipeline } from '~/generated/graphql'; import { isDeeplyEqual } from '~/utils/isDeeplyEqual'; import { logError } from '~/utils/logError'; import { companyProgressesFamilyState } from '../states/companyProgressesFamilyState'; -import { - CompanyForBoard, - CompanyProgressDict, - PipelineProgressForBoard, -} from '../types/CompanyProgress'; +import { CompanyForBoard, CompanyProgressDict } from '../types/CompanyProgress'; export const useUpdateCompanyBoard = () => useRecoilCallback( ({ set, snapshot }) => ( - pipeline: Pipeline, - pipelineProgresses: (PipelineProgressForBoard & { - pipelineStageId: string; - })[], + pipelineSteps: PipelineStep[], + pipelineProgresses: Opportunity[], companies: CompanyForBoard[], ) => { const indexCompanyByIdReducer = ( @@ -44,7 +39,7 @@ export const useUpdateCompanyBoard = () => const indexPipelineProgressByIdReducer = ( acc: CompanyProgressDict, - pipelineProgress: PipelineProgressForBoard, + pipelineProgress: Opportunity, ) => { const company = pipelineProgress.companyId && @@ -77,21 +72,19 @@ export const useUpdateCompanyBoard = () => } } - const currentPipeline = snapshot - .getLoadable(currentPipelineState) + const currentPipelineSteps = snapshot + .getLoadable(currentPipelineStepsState) .valueOrThrow(); const currentBoardColumns = snapshot .getLoadable(boardColumnsState) .valueOrThrow(); - if (!isDeeplyEqual(pipeline, currentPipeline)) { - set(currentPipelineState, pipeline); + if (!isDeeplyEqual(pipelineSteps, currentPipelineSteps)) { + set(currentPipelineStepsState, currentPipelineSteps); } - const pipelineStages = pipeline?.pipelineStages ?? []; - - const orderedPipelineStages = [...pipelineStages].sort((a, b) => { + const orderedPipelineStages = [...pipelineSteps].sort((a, b) => { if (!a.position || !b.position) return 0; return a.position - b.position; }); diff --git a/front/src/modules/companies/types/CompanyProgress.ts b/front/src/modules/companies/types/CompanyProgress.ts index 250c7711a..ca981fed3 100644 --- a/front/src/modules/companies/types/CompanyProgress.ts +++ b/front/src/modules/companies/types/CompanyProgress.ts @@ -1,17 +1,8 @@ -import { Company, Person, PipelineProgress } from '~/generated/graphql'; +import { Opportunity } from '@/pipeline/types/Opportunity'; +import { Company } from '~/generated/graphql'; export type CompanyForBoard = Pick; -export type PipelineProgressForBoard = Pick< - PipelineProgress, - | 'id' - | 'amount' - | 'closeDate' - | 'companyId' - | 'probability' - | 'pointOfContactId' -> & { - pointOfContact?: Pick | null; -}; +export type PipelineProgressForBoard = Opportunity; export type CompanyProgress = { company: CompanyForBoard; diff --git a/front/src/modules/object-metadata/components/ObjectMetadataNavItems.tsx b/front/src/modules/object-metadata/components/ObjectMetadataNavItems.tsx index 79436d300..eed8e28e2 100644 --- a/front/src/modules/object-metadata/components/ObjectMetadataNavItems.tsx +++ b/front/src/modules/object-metadata/components/ObjectMetadataNavItems.tsx @@ -22,6 +22,7 @@ export const ObjectMetadataNavItems = () => { return ( <> {objectMetadataItems.map((objectMetadataItem) => { + if (objectMetadataItem.nameSingular === 'opportunityV2') return null; return ( ) => { +export const useDeleteOneObjectRecord = ({ + objectNameSingular, +}: Pick) => { const { foundObjectMetadataItem, objectNotFoundInMetadata, findManyQuery, deleteOneMutation, } = useFindOneObjectMetadataItem({ - objectNamePlural, + objectNameSingular, }); // TODO: type this with a minimal type at least with Record const [mutate] = useMutation(deleteOneMutation); - const deleteOneObject = foundObjectMetadataItem - ? (idToDelete: string) => { - return mutate({ - variables: { - idToDelete, - }, - refetchQueries: [getOperationName(findManyQuery) ?? ''], - }); - } - : undefined; + const deleteOneObject = + objectNameSingular && foundObjectMetadataItem + ? async (idToDelete: string) => { + const deletedObject = await mutate({ + variables: { + idToDelete, + }, + refetchQueries: [getOperationName(findManyQuery) ?? ''], + }); + return deletedObject.data[ + `create${capitalize(objectNameSingular)}` + ] as T; + } + : undefined; return { deleteOneObject, diff --git a/front/src/modules/object-record/hooks/useRecordTableContextMenuEntries.tsx b/front/src/modules/object-record/hooks/useRecordTableContextMenuEntries.tsx index 64a17da89..50822c321 100644 --- a/front/src/modules/object-record/hooks/useRecordTableContextMenuEntries.tsx +++ b/front/src/modules/object-record/hooks/useRecordTableContextMenuEntries.tsx @@ -3,6 +3,7 @@ import { isNonEmptyString } from '@sniptt/guards'; import { useRecoilCallback, useRecoilValue, useSetRecoilState } from 'recoil'; import { useFavorites } from '@/favorites/hooks/useFavorites'; +import { useFindOneObjectMetadataItem } from '@/object-metadata/hooks/useFindOneObjectMetadataItem'; import { useDeleteOneObjectRecord } from '@/object-record/hooks/useDeleteOneObjectRecord'; import { IconCheckbox, @@ -28,6 +29,11 @@ export const useRecordTableContextMenuEntries = () => { const { scopeId: objectNamePlural, resetTableRowSelection } = useRecordTable(); + const { data } = useGetFavoritesQuery(); + const { foundObjectMetadataItem } = useFindOneObjectMetadataItem({ + objectNamePlural, + }); + const { createFavorite, deleteFavorite, favorites } = useFavorites({ objectNamePlural, }); @@ -53,7 +59,7 @@ export const useRecordTableContextMenuEntries = () => { }); const { deleteOneObject } = useDeleteOneObjectRecord({ - objectNamePlural, + objectNameSingular: foundObjectMetadataItem?.nameSingular, }); const handleDeleteClick = useRecoilCallback(({ snapshot }) => async () => { diff --git a/front/src/modules/pipeline/graphql/mutations/createCompanyPipelineProgress.ts b/front/src/modules/pipeline/graphql/mutations/createCompanyPipelineProgress.ts deleted file mode 100644 index bcf4801c0..000000000 --- a/front/src/modules/pipeline/graphql/mutations/createCompanyPipelineProgress.ts +++ /dev/null @@ -1,21 +0,0 @@ -import { gql } from '@apollo/client'; - -export const CREATE_COMPANY_PIPELINE_PROGRESS = gql` - mutation CreateOneCompanyPipelineProgress( - $uuid: String! - $companyId: String! - $pipelineId: String! - $pipelineStageId: String! - ) { - createOnePipelineProgress( - data: { - id: $uuid - company: { connect: { id: $companyId } } - pipeline: { connect: { id: $pipelineId } } - pipelineStage: { connect: { id: $pipelineStageId } } - } - ) { - id - } - } -`; diff --git a/front/src/modules/pipeline/graphql/mutations/createPipelineStage.ts b/front/src/modules/pipeline/graphql/mutations/createPipelineStage.ts deleted file mode 100644 index c41adbad4..000000000 --- a/front/src/modules/pipeline/graphql/mutations/createPipelineStage.ts +++ /dev/null @@ -1,11 +0,0 @@ -import { gql } from '@apollo/client'; - -export const CREATE_PIPELINE_STAGE = gql` - mutation CreatePipelineStage($data: PipelineStageCreateInput!) { - pipelineStage: createOnePipelineStage(data: $data) { - id - name - color - } - } -`; diff --git a/front/src/modules/pipeline/graphql/mutations/deletePipelineProgress.ts b/front/src/modules/pipeline/graphql/mutations/deletePipelineProgress.ts deleted file mode 100644 index 6214e00cb..000000000 --- a/front/src/modules/pipeline/graphql/mutations/deletePipelineProgress.ts +++ /dev/null @@ -1,9 +0,0 @@ -import { gql } from '@apollo/client'; - -export const DELETE_PIPELINE_PROGRESS = gql` - mutation DeleteManyPipelineProgress($ids: [String!]) { - deleteManyPipelineProgress(where: { id: { in: $ids } }) { - count - } - } -`; diff --git a/front/src/modules/pipeline/graphql/mutations/deletePipelineStage.ts b/front/src/modules/pipeline/graphql/mutations/deletePipelineStage.ts deleted file mode 100644 index d1c017565..000000000 --- a/front/src/modules/pipeline/graphql/mutations/deletePipelineStage.ts +++ /dev/null @@ -1,11 +0,0 @@ -import { gql } from '@apollo/client'; - -export const DELETE_PIPELINE_STAGE = gql` - mutation DeletePipelineStage($where: PipelineStageWhereUniqueInput!) { - pipelineStage: deleteOnePipelineStage(where: $where) { - id - name - color - } - } -`; diff --git a/front/src/modules/pipeline/graphql/mutations/updatePipelineProgress.ts b/front/src/modules/pipeline/graphql/mutations/updatePipelineProgress.ts deleted file mode 100644 index 2d9b0b766..000000000 --- a/front/src/modules/pipeline/graphql/mutations/updatePipelineProgress.ts +++ /dev/null @@ -1,18 +0,0 @@ -import { gql } from '@apollo/client'; - -export const UPDATE_PIPELINE_PROGRESS = gql` - mutation UpdateOnePipelineProgress( - $data: PipelineProgressUpdateInput! - $where: PipelineProgressWhereUniqueInput! - ) { - updateOnePipelineProgress(where: $where, data: $data) { - id - amount - closeDate - probability - pointOfContact { - id - } - } - } -`; diff --git a/front/src/modules/pipeline/graphql/mutations/updatePipelineProgressStage.ts b/front/src/modules/pipeline/graphql/mutations/updatePipelineProgressStage.ts deleted file mode 100644 index 648aaaadd..000000000 --- a/front/src/modules/pipeline/graphql/mutations/updatePipelineProgressStage.ts +++ /dev/null @@ -1,15 +0,0 @@ -import { gql } from '@apollo/client'; - -export const UPDATE_PIPELINE_PROGRESS_STAGE = gql` - mutation UpdateOnePipelineProgressStage( - $id: String - $pipelineStageId: String - ) { - updateOnePipelineProgress( - where: { id: $id } - data: { pipelineStage: { connect: { id: $pipelineStageId } } } - ) { - id - } - } -`; diff --git a/front/src/modules/pipeline/graphql/mutations/updatePipelineStage.ts b/front/src/modules/pipeline/graphql/mutations/updatePipelineStage.ts deleted file mode 100644 index 34c42c8f8..000000000 --- a/front/src/modules/pipeline/graphql/mutations/updatePipelineStage.ts +++ /dev/null @@ -1,11 +0,0 @@ -import { gql } from '@apollo/client'; - -export const UPDATE_PIPELINE_STAGE = gql` - mutation UpdatePipelineStage($id: String, $data: PipelineStageUpdateInput!) { - updateOnePipelineStage(where: { id: $id }, data: $data) { - id - name - color - } - } -`; diff --git a/front/src/modules/pipeline/graphql/queries/getPipelineProgress.ts b/front/src/modules/pipeline/graphql/queries/getPipelineProgress.ts deleted file mode 100644 index 38684c5b9..000000000 --- a/front/src/modules/pipeline/graphql/queries/getPipelineProgress.ts +++ /dev/null @@ -1,26 +0,0 @@ -import { gql } from '@apollo/client'; - -export const GET_PIPELINE_PROGRESS = gql` - query GetPipelineProgress( - $where: PipelineProgressWhereInput - $orderBy: [PipelineProgressOrderByWithRelationInput!] - ) { - findManyPipelineProgress(where: $where, orderBy: $orderBy) { - id - pipelineStageId - companyId - personId - amount - closeDate - pointOfContactId - pointOfContact { - id - firstName - lastName - displayName - avatarUrl - } - probability - } - } -`; diff --git a/front/src/modules/pipeline/graphql/queries/getPipelines.ts b/front/src/modules/pipeline/graphql/queries/getPipelines.ts deleted file mode 100644 index 617205aac..000000000 --- a/front/src/modules/pipeline/graphql/queries/getPipelines.ts +++ /dev/null @@ -1,17 +0,0 @@ -import { gql } from '@apollo/client'; - -export const GET_PIPELINES = gql` - query GetPipelines($where: PipelineWhereInput) { - findManyPipeline(where: $where) { - id - name - pipelineProgressableType - pipelineStages { - id - name - color - position - } - } - } -`; diff --git a/front/src/modules/pipeline/hooks/usePipelineStages.ts b/front/src/modules/pipeline/hooks/usePipelineStages.ts index 4f87f62ae..e14d2c097 100644 --- a/front/src/modules/pipeline/hooks/usePipelineStages.ts +++ b/front/src/modules/pipeline/hooks/usePipelineStages.ts @@ -1,25 +1,29 @@ -import { getOperationName } from '@apollo/client/utilities'; import { useRecoilValue } from 'recoil'; +import { useCreateOneObjectRecord } from '@/object-record/hooks/useCreateOneObjectRecord'; +import { useDeleteOneObjectRecord } from '@/object-record/hooks/useDeleteOneObjectRecord'; +import { PipelineStep } from '@/pipeline/types/PipelineStep'; import { BoardColumnDefinition } from '@/ui/layout/board/types/BoardColumnDefinition'; -import { - useCreatePipelineStageMutation, - useDeletePipelineStageMutation, -} from '~/generated/graphql'; -import { GET_PIPELINES } from '../graphql/queries/getPipelines'; import { currentPipelineState } from '../states/currentPipelineState'; export const usePipelineStages = () => { const currentPipeline = useRecoilValue(currentPipelineState); - const [createPipelineStageMutation] = useCreatePipelineStageMutation(); - const [deletePipelineStageMutation] = useDeletePipelineStageMutation(); + const { createOneObject: createOnePipelineStep } = + useCreateOneObjectRecord({ + objectNameSingular: 'pipelineStepV2', + }); + + const { deleteOneObject: deleteOnePipelineStep } = + useDeleteOneObjectRecord({ + objectNameSingular: 'pipelineStepV2', + }); const handlePipelineStageAdd = async (boardColumn: BoardColumnDefinition) => { if (!currentPipeline?.id) return; - return createPipelineStageMutation({ + return createOnePipelineStep?.({ variables: { data: { color: boardColumn.colorCode ?? 'gray', @@ -30,17 +34,13 @@ export const usePipelineStages = () => { type: 'ongoing', }, }, - refetchQueries: [getOperationName(GET_PIPELINES) ?? ''], }); }; const handlePipelineStageDelete = async (boardColumnId: string) => { if (!currentPipeline?.id) return; - return deletePipelineStageMutation({ - variables: { where: { id: boardColumnId } }, - refetchQueries: [getOperationName(GET_PIPELINES) ?? ''], - }); + return deleteOnePipelineStep?.(boardColumnId); }; return { handlePipelineStageAdd, handlePipelineStageDelete }; diff --git a/front/src/modules/pipeline/states/currentPipelineStepsState.ts b/front/src/modules/pipeline/states/currentPipelineStepsState.ts new file mode 100644 index 000000000..fce0bc745 --- /dev/null +++ b/front/src/modules/pipeline/states/currentPipelineStepsState.ts @@ -0,0 +1,8 @@ +import { atom } from 'recoil'; + +import { PipelineStep } from '@/pipeline/types/PipelineStep'; + +export const currentPipelineStepsState = atom({ + key: 'currentPipelineStepsState', + default: [], +}); diff --git a/front/src/modules/pipeline/types/Opportunity.ts b/front/src/modules/pipeline/types/Opportunity.ts new file mode 100644 index 000000000..8f215f2f4 --- /dev/null +++ b/front/src/modules/pipeline/types/Opportunity.ts @@ -0,0 +1,17 @@ +import { PipelineStep } from '@/pipeline/types/PipelineStep'; +import { Person } from '~/generated-metadata/graphql'; + +export type Opportunity = { + id: string; + amount: { + amountMicros: number; + currencyCode: string; + }; + closeDate: Date; + probability: number; + pipelineStepId: string; + pipelineStep: PipelineStep; + pointOfContactId: string; + pointOfContact: Pick; + [key: string]: any; +}; diff --git a/front/src/modules/pipeline/types/PipelineStep.ts b/front/src/modules/pipeline/types/PipelineStep.ts new file mode 100644 index 000000000..f5bf63f21 --- /dev/null +++ b/front/src/modules/pipeline/types/PipelineStep.ts @@ -0,0 +1,6 @@ +export type PipelineStep = { + id: string; + name: string; + color: string; + position: number; +}; diff --git a/front/src/modules/ui/layout/board/components/EntityBoard.tsx b/front/src/modules/ui/layout/board/components/EntityBoard.tsx index 4022a69a7..6f10c4f55 100644 --- a/front/src/modules/ui/layout/board/components/EntityBoard.tsx +++ b/front/src/modules/ui/layout/board/components/EntityBoard.tsx @@ -1,10 +1,11 @@ import { useCallback, useRef } from 'react'; -import { getOperationName } from '@apollo/client/utilities'; +import { useApolloClient } from '@apollo/client'; import styled from '@emotion/styled'; import { DragDropContext, OnDragEndResponder } from '@hello-pangea/dnd'; // Atlassian dnd does not support StrictMode from RN 18, so we use a fork @hello-pangea/dnd https://github.com/atlassian/react-beautiful-dnd/issues/2350 import { useRecoilValue } from 'recoil'; -import { GET_PIPELINE_PROGRESS } from '@/pipeline/graphql/queries/getPipelineProgress'; +import { useUpdateOneObjectRecord } from '@/object-record/hooks/useUpdateOneObjectRecord'; +import { Opportunity } from '@/pipeline/types/Opportunity'; import { PageHotkeyScope } from '@/types/PageHotkeyScope'; import { StyledBoard } from '@/ui/layout/board/components/StyledBoard'; import { BoardColumnContext } from '@/ui/layout/board/contexts/BoardColumnContext'; @@ -13,11 +14,7 @@ import { useScopedHotkeys } from '@/ui/utilities/hotkey/hooks/useScopedHotkeys'; import { useListenClickOutsideByClassName } from '@/ui/utilities/pointer-event/hooks/useListenClickOutside'; import { RecoilScope } from '@/ui/utilities/recoil-scope/components/RecoilScope'; import { ScrollWrapper } from '@/ui/utilities/scroll/components/ScrollWrapper'; -import { - PipelineProgress, - PipelineStage, - useUpdateOnePipelineProgressStageMutation, -} from '~/generated/graphql'; +import { PipelineProgress, PipelineStage } from '~/generated/graphql'; import { logError } from '~/utils/logError'; import { useCurrentCardSelected } from '../hooks/useCurrentCardSelected'; @@ -59,8 +56,12 @@ export const EntityBoard = ({ const boardColumns = useRecoilValue(boardColumnsState); const setCardSelected = useSetCardSelected(); - const [updatePipelineProgressStage] = - useUpdateOnePipelineProgressStageMutation(); + const { updateOneObject: updateOneOpportunity } = + useUpdateOneObjectRecord({ + objectNameSingular: 'opportunityV2', + }); + + const apolloClient = useApolloClient(); const { unselectAllActiveCards } = useCurrentCardSelected(); @@ -69,33 +70,25 @@ export const EntityBoard = ({ pipelineProgressId: NonNullable, pipelineStageId: NonNullable, ) => { - updatePipelineProgressStage({ - variables: { + await updateOneOpportunity?.({ + idToUpdate: pipelineProgressId, + input: { + pipelineStepId: pipelineStageId, + }, + }); + + const cache = apolloClient.cache; + cache.modify({ + id: cache.identify({ id: pipelineProgressId, - pipelineStageId, + __typename: 'PipelineProgress', + }), + fields: { + pipelineStageId: () => pipelineStageId, }, - optimisticResponse: { - __typename: 'Mutation', - updateOnePipelineProgress: { - __typename: 'PipelineProgress', - id: pipelineProgressId, - }, - }, - update: (cache) => { - cache.modify({ - id: cache.identify({ - id: pipelineProgressId, - __typename: 'PipelineProgress', - }), - fields: { - pipelineStageId: () => pipelineStageId, - }, - }); - }, - refetchQueries: [getOperationName(GET_PIPELINE_PROGRESS) ?? ''], }); }, - [updatePipelineProgressStage], + [apolloClient.cache, updateOneOpportunity], ); useListenClickOutsideByClassName({ diff --git a/front/src/modules/ui/layout/board/hooks/useBoardActionBarEntries.tsx b/front/src/modules/ui/layout/board/hooks/useBoardActionBarEntries.tsx index 321dc14cf..f3e377aa4 100644 --- a/front/src/modules/ui/layout/board/hooks/useBoardActionBarEntries.tsx +++ b/front/src/modules/ui/layout/board/hooks/useBoardActionBarEntries.tsx @@ -1,10 +1,9 @@ import { useSetRecoilState } from 'recoil'; import { IconTrash } from '@/ui/display/icon'; +import { useDeleteSelectedBoardCards } from '@/ui/layout/board/hooks/useDeleteSelectedBoardCards'; import { actionBarEntriesState } from '@/ui/navigation/action-bar/states/actionBarEntriesState'; -import { useDeleteSelectedBoardCards } from './useDeleteSelectedBoardCards'; - export const useBoardActionBarEntries = () => { const setActionBarEntries = useSetRecoilState(actionBarEntriesState); diff --git a/front/src/modules/ui/layout/board/hooks/useBoardColumns.ts b/front/src/modules/ui/layout/board/hooks/useBoardColumns.ts index d82ba3cb2..dc970fd36 100644 --- a/front/src/modules/ui/layout/board/hooks/useBoardColumns.ts +++ b/front/src/modules/ui/layout/board/hooks/useBoardColumns.ts @@ -1,7 +1,8 @@ import { useRecoilState } from 'recoil'; +import { useUpdateOneObjectRecord } from '@/object-record/hooks/useUpdateOneObjectRecord'; +import { PipelineStep } from '@/pipeline/types/PipelineStep'; import { useMoveViewColumns } from '@/views/hooks/useMoveViewColumns'; -import { useUpdatePipelineStageMutation } from '~/generated/graphql'; import { boardColumnsState } from '../states/boardColumnsState'; import { BoardColumnDefinition } from '../types/BoardColumnDefinition'; @@ -11,19 +12,20 @@ export const useBoardColumns = () => { const { handleColumnMove } = useMoveViewColumns(); - const [updatePipelineStageMutation] = useUpdatePipelineStageMutation(); + const { updateOneObject: updateOnePipelineStep } = + useUpdateOneObjectRecord({ + objectNameSingular: 'pipelineStepV2', + }); const updatedPipelineStages = (stages: BoardColumnDefinition[]) => { if (!stages.length) return; return Promise.all( stages.map((stage) => - updatePipelineStageMutation({ - variables: { - data: { - position: stage.position, - }, - id: stage.id, + updateOnePipelineStep?.({ + idToUpdate: stage.id, + input: { + position: stage.position, }, }), ), diff --git a/front/src/modules/ui/layout/board/hooks/useBoardContextMenuEntries.tsx b/front/src/modules/ui/layout/board/hooks/useBoardContextMenuEntries.tsx index 16b3c11e7..d51437057 100644 --- a/front/src/modules/ui/layout/board/hooks/useBoardContextMenuEntries.tsx +++ b/front/src/modules/ui/layout/board/hooks/useBoardContextMenuEntries.tsx @@ -1,10 +1,9 @@ import { useSetRecoilState } from 'recoil'; import { IconTrash } from '@/ui/display/icon'; +import { useDeleteSelectedBoardCards } from '@/ui/layout/board/hooks/useDeleteSelectedBoardCards'; import { contextMenuEntriesState } from '@/ui/navigation/context-menu/states/contextMenuEntriesState'; -import { useDeleteSelectedBoardCards } from './useDeleteSelectedBoardCards'; - export const useBoardContextMenuEntries = () => { const setContextMenuEntries = useSetRecoilState(contextMenuEntriesState); diff --git a/front/src/modules/ui/layout/board/hooks/useDeleteSelectedBoardCards.ts b/front/src/modules/ui/layout/board/hooks/useDeleteSelectedBoardCards.ts index 31c2121aa..0aaaab23d 100644 --- a/front/src/modules/ui/layout/board/hooks/useDeleteSelectedBoardCards.ts +++ b/front/src/modules/ui/layout/board/hooks/useDeleteSelectedBoardCards.ts @@ -1,40 +1,41 @@ -import { getOperationName } from '@apollo/client/utilities'; -import { useRecoilValue } from 'recoil'; +import { useApolloClient } from '@apollo/client'; +import { useRecoilCallback } from 'recoil'; -import { GET_PIPELINES } from '@/pipeline/graphql/queries/getPipelines'; -import { useDeleteManyPipelineProgressMutation } from '~/generated/graphql'; +import { useDeleteOneObjectRecord } from '@/object-record/hooks/useDeleteOneObjectRecord'; +import { Opportunity } from '@/pipeline/types/Opportunity'; import { selectedCardIdsSelector } from '../states/selectors/selectedCardIdsSelector'; import { useRemoveCardIds } from './useRemoveCardIds'; export const useDeleteSelectedBoardCards = () => { - const selectedCardIds = useRecoilValue(selectedCardIdsSelector); const removeCardIds = useRemoveCardIds(); + const apolloClient = useApolloClient(); - const [deletePipelineProgress] = useDeleteManyPipelineProgressMutation({ - refetchQueries: [getOperationName(GET_PIPELINES) ?? ''], - }); + const { deleteOneObject: deleteOneOpportunity } = + useDeleteOneObjectRecord({ + objectNameSingular: 'opportunityV2', + }); - const deleteSelectedBoardCards = async () => { - await deletePipelineProgress({ - variables: { - ids: selectedCardIds, - }, - optimisticResponse: { - __typename: 'Mutation', - deleteManyPipelineProgress: { - count: selectedCardIds.length, - }, - }, - update: (cache) => { + const deleteSelectedBoardCards = useRecoilCallback( + ({ snapshot }) => + async () => { + const selectedCardIds = snapshot + .getLoadable(selectedCardIdsSelector) + .getValue(); + + await Promise.all( + selectedCardIds.map(async (id) => { + await deleteOneOpportunity?.(id); + }), + ); removeCardIds(selectedCardIds); selectedCardIds.forEach((id) => { - cache.evict({ id: `PipelineProgress:${id}` }); + apolloClient.cache.evict({ id: `Opportunity:${id}` }); }); }, - }); - }; + [apolloClient.cache, deleteOneOpportunity, removeCardIds], + ); return deleteSelectedBoardCards; }; diff --git a/front/src/pages/opportunities/Opportunities.tsx b/front/src/pages/opportunities/Opportunities.tsx index f2c5dd36f..98e6b430d 100644 --- a/front/src/pages/opportunities/Opportunities.tsx +++ b/front/src/pages/opportunities/Opportunities.tsx @@ -1,16 +1,20 @@ +import { useEffect } from 'react'; import styled from '@emotion/styled'; import { CompanyBoard } from '@/companies/board/components/CompanyBoard'; import { CompanyBoardRecoilScopeContext } from '@/companies/states/recoil-scope-contexts/CompanyBoardRecoilScopeContext'; +import { useFindOneObjectMetadataItem } from '@/object-metadata/hooks/useFindOneObjectMetadataItem'; +import { useUpdateOneObjectRecord } from '@/object-record/hooks/useUpdateOneObjectRecord'; import { PipelineAddButton } from '@/pipeline/components/PipelineAddButton'; import { usePipelineStages } from '@/pipeline/hooks/usePipelineStages'; +import { PipelineStep } from '@/pipeline/types/PipelineStep'; import { IconTargetArrow } from '@/ui/display/icon'; import { BoardOptionsContext } from '@/ui/layout/board/contexts/BoardOptionsContext'; import { PageBody } from '@/ui/layout/page/PageBody'; import { PageContainer } from '@/ui/layout/page/PageContainer'; import { PageHeader } from '@/ui/layout/page/PageHeader'; import { RecoilScope } from '@/ui/utilities/recoil-scope/components/RecoilScope'; -import { useUpdatePipelineStageMutation } from '~/generated/graphql'; +import { useView } from '@/views/hooks/useView'; import { opportunitiesBoardOptions } from '~/pages/opportunities/opportunitiesBoardOptions'; const StyledBoardContainer = styled.div` @@ -22,30 +26,37 @@ export const Opportunities = () => { const { handlePipelineStageAdd, handlePipelineStageDelete } = usePipelineStages(); - const [updatePipelineStage] = useUpdatePipelineStageMutation(); + const { updateOneObject: updateOnePipelineStep } = + useUpdateOneObjectRecord({ + objectNameSingular: 'pipelineStepV2', + }); const handleEditColumnTitle = ( boardColumnId: string, newTitle: string, newColor: string, ) => { - updatePipelineStage({ - variables: { - id: boardColumnId, - data: { name: newTitle, color: newColor }, - }, - optimisticResponse: { - __typename: 'Mutation', - updateOnePipelineStage: { - __typename: 'PipelineStage', - id: boardColumnId, - name: newTitle, - color: newColor, - }, + updateOnePipelineStep?.({ + idToUpdate: boardColumnId, + input: { + name: newTitle, + color: newColor, }, }); }; + const opportunitiesV2MetadataId = useFindOneObjectMetadataItem({ + objectNameSingular: 'opportunityV2', + }).foundObjectMetadataItem?.id; + + const { setViewObjectMetadataId } = useView({ + viewScopeId: 'company-board-view', + }); + + useEffect(() => { + setViewObjectMetadataId?.(opportunitiesV2MetadataId); + }, [opportunitiesV2MetadataId, setViewObjectMetadataId]); + return ( diff --git a/front/src/pages/settings/SettingsWorkspaceMembers.tsx b/front/src/pages/settings/SettingsWorkspaceMembers.tsx index 4c6b36b85..24c1bc9ca 100644 --- a/front/src/pages/settings/SettingsWorkspaceMembers.tsx +++ b/front/src/pages/settings/SettingsWorkspaceMembers.tsx @@ -39,8 +39,8 @@ export const SettingsWorkspaceMembers = () => { objectNamePlural: 'workspaceMembersV2', }); const { deleteOneObject: deleteOneWorkspaceMember } = - useDeleteOneObjectRecord({ - objectNamePlural: 'workspaceMembersV2', + useDeleteOneObjectRecord({ + objectNameSingular: 'workspaceMemberV2', }); const currentWorkspace = useRecoilValue(currentWorkspaceState); diff --git a/front/src/testing/graphqlMocks.ts b/front/src/testing/graphqlMocks.ts index fc2a8c6cf..6622e37ca 100644 --- a/front/src/testing/graphqlMocks.ts +++ b/front/src/testing/graphqlMocks.ts @@ -10,8 +10,6 @@ import { INSERT_ONE_PERSON } from '@/people/graphql/mutations/insertOnePerson'; import { UPDATE_ONE_PERSON } from '@/people/graphql/mutations/updateOnePerson'; import { GET_PEOPLE } from '@/people/graphql/queries/getPeople'; import { GET_PERSON } from '@/people/graphql/queries/getPerson'; -import { GET_PIPELINE_PROGRESS } from '@/pipeline/graphql/queries/getPipelineProgress'; -import { GET_PIPELINES } from '@/pipeline/graphql/queries/getPipelines'; import { SEARCH_ACTIVITY_QUERY } from '@/search/graphql/queries/searchActivityQuery'; import { SEARCH_COMPANY_QUERY } from '@/search/graphql/queries/searchCompanyQuery'; import { SEARCH_PEOPLE_QUERY } from '@/search/graphql/queries/searchPeopleQuery'; @@ -37,8 +35,6 @@ import { } from './mock-data/companies'; import { mockedObjectMetadataItems } from './mock-data/metadata'; import { mockedEmptyPersonData, mockedPeopleData } from './mock-data/people'; -import { mockedPipelineProgressData } from './mock-data/pipeline-progress'; -import { mockedPipelinesData } from './mock-data/pipelines'; import { mockedUsersData } from './mock-data/users'; import { mockedViewFieldsData } from './mock-data/view-fields'; import { mockedViewsData } from './mock-data/views'; @@ -47,6 +43,7 @@ import { filterAndSortData, updateOneFromData, } from './mock-data'; +import { createEvent } from '@storybook/testing-library'; const metadataGraphql = graphql.link( `${process.env.REACT_APP_SERVER_BASE_URL}/metadata`, @@ -205,23 +202,7 @@ export const graphqlMocks = [ ); }, ), - graphql.query(getOperationName(GET_PIPELINES) ?? '', (req, res, ctx) => { - return res( - ctx.data({ - findManyPipeline: mockedPipelinesData, - }), - ); - }), - graphql.query( - getOperationName(GET_PIPELINE_PROGRESS) ?? '', - (req, res, ctx) => { - return res( - ctx.data({ - findManyPipelineProgress: mockedPipelineProgressData, - }), - ); - }, - ), + graphql.mutation(getOperationName(CREATE_EVENT) ?? '', (req, res, ctx) => { return res( ctx.data({ diff --git a/server/src/database/commands/data-seed-workspace.command.ts b/server/src/database/commands/data-seed-workspace.command.ts index c7f501f3f..e7bf83a1d 100644 --- a/server/src/database/commands/data-seed-workspace.command.ts +++ b/server/src/database/commands/data-seed-workspace.command.ts @@ -8,6 +8,8 @@ import { seedViewFields } from 'src/database/typeorm-seeds/workspace/view-fields import { seedViews } from 'src/database/typeorm-seeds/workspace/views'; import { TypeORMService } from 'src/database/typeorm/typeorm.service'; import { seedMetadataSchema } from 'src/database/typeorm-seeds/metadata'; +import { seedOpportunity } from 'src/database/typeorm-seeds/workspace/opportunity'; +import { seedPipelineStep } from 'src/database/typeorm-seeds/workspace/pipeline-step'; import { seedWorkspaceMember } from 'src/database/typeorm-seeds/workspace/workspaceMember'; import { seedPeople } from 'src/database/typeorm-seeds/workspace/people'; @@ -55,6 +57,8 @@ export class DataSeedWorkspaceCommand extends CommandRunner { await seedCompanies(workspaceDataSource, dataSourceMetadata.schema); await seedPeople(workspaceDataSource, dataSourceMetadata.schema); + await seedPipelineStep(workspaceDataSource, dataSourceMetadata.schema); + await seedOpportunity(workspaceDataSource, dataSourceMetadata.schema); await seedViews(workspaceDataSource, dataSourceMetadata.schema); await seedViewFields(workspaceDataSource, dataSourceMetadata.schema); diff --git a/server/src/database/typeorm-seeds/metadata/object-metadata.ts b/server/src/database/typeorm-seeds/metadata/object-metadata.ts index df573ceb6..1952fbffe 100644 --- a/server/src/database/typeorm-seeds/metadata/object-metadata.ts +++ b/server/src/database/typeorm-seeds/metadata/object-metadata.ts @@ -86,7 +86,7 @@ export const seedObjectMetadata = async ( dataSourceId: SeedDataSourceId, workspaceId: SeedWorkspaceId, isActive: true, - isSystem: true, + isSystem: false, }, { id: SeedObjectMetadataIds.PipelineStep, diff --git a/server/src/database/typeorm-seeds/workspace/opportunity.ts b/server/src/database/typeorm-seeds/workspace/opportunity.ts new file mode 100644 index 000000000..fc1afaf55 --- /dev/null +++ b/server/src/database/typeorm-seeds/workspace/opportunity.ts @@ -0,0 +1,38 @@ +import { DataSource } from 'typeorm'; + +const tableName = 'opportunity'; + +export const seedOpportunity = async ( + workspaceDataSource: DataSource, + schemaName: string, +) => { + await workspaceDataSource + .createQueryBuilder() + .insert() + .into(`${schemaName}.${tableName}`, [ + 'id', + 'amountAmountMicros', + 'amountCurrencyCode', + 'closeDate', + 'probability', + 'pipelineStepId', + 'pointOfContactId', + 'personId', + 'companyId', + ]) + .orIgnore() + .values([ + { + id: '7c887ee3-be10-412b-a663-16bd3c2228e1', + amountAmountMicros: 100000, + amountCurrencyCode: 'USD', + closeDate: new Date(), + probability: 0.5, + pipelineStepId: '6edf4ead-006a-46e1-9c6d-228f1d0143c9', + pointOfContactId: '86083141-1c0e-494c-a1b6-85b1c6fefaa5', + personId: '86083141-1c0e-494c-a1b6-85b1c6fefaa5', + companyId: 'fe256b39-3ec3-4fe3-8997-b76aa0bfa408', + }, + ]) + .execute(); +}; diff --git a/server/src/database/typeorm-seeds/workspace/pipeline-step.ts b/server/src/database/typeorm-seeds/workspace/pipeline-step.ts new file mode 100644 index 000000000..c99821440 --- /dev/null +++ b/server/src/database/typeorm-seeds/workspace/pipeline-step.ts @@ -0,0 +1,47 @@ +import { DataSource } from 'typeorm'; + +const tableName = 'pipelineStep'; + +export const seedPipelineStep = async ( + workspaceDataSource: DataSource, + schemaName: string, +) => { + await workspaceDataSource + .createQueryBuilder() + .insert() + .into(`${schemaName}.${tableName}`, ['id', 'name', 'color', 'position']) + .orIgnore() + .values([ + { + id: '6edf4ead-006a-46e1-9c6d-228f1d0143c9', + name: 'New', + color: 'red', + position: 0, + }, + { + id: 'd8361722-03fb-4e65-bd4f-ec9e52e5ec0a', + name: 'Screening', + color: 'purple', + position: 1, + }, + { + id: '30b14887-d592-427d-bd97-6e670158db02', + name: 'Meeting', + color: 'sky', + position: 2, + }, + { + id: 'db5a6648-d80d-4020-af64-4817ab4a12e8', + name: 'Proposal', + color: 'turquoise', + position: 3, + }, + { + id: 'bea8bb7b-5467-48a6-9a8a-a8fa500123fe', + name: 'Customer', + color: 'yellow', + position: 4, + }, + ]) + .execute(); +}; diff --git a/server/src/database/typeorm-seeds/workspace/view-fields.ts b/server/src/database/typeorm-seeds/workspace/view-fields.ts index 48943a33e..81ab68e9a 100644 --- a/server/src/database/typeorm-seeds/workspace/view-fields.ts +++ b/server/src/database/typeorm-seeds/workspace/view-fields.ts @@ -1,7 +1,6 @@ import { DataSource } from 'typeorm'; import { SeedViewIds } from 'src/database/typeorm-seeds/workspace/views'; -import { SeedCompanyFieldMetadataIds } from 'src/database/typeorm-seeds/metadata/field-metadata/company'; const tableName = 'viewField'; @@ -23,130 +22,144 @@ export const seedViewFields = async ( .values([ { fieldMetadataId: 'name', - viewId: SeedViewIds.PrismaCompany, + viewId: SeedViewIds.Company, position: 0, isVisible: true, size: 180, }, { fieldMetadataId: 'domainName', - viewId: SeedViewIds.PrismaCompany, + viewId: SeedViewIds.Company, position: 1, isVisible: true, size: 100, }, { fieldMetadataId: 'accountOwner', - viewId: SeedViewIds.PrismaCompany, + viewId: SeedViewIds.Company, position: 2, isVisible: true, size: 150, }, { fieldMetadataId: 'createdAt', - viewId: SeedViewIds.PrismaCompany, + viewId: SeedViewIds.Company, position: 3, isVisible: true, size: 150, }, { fieldMetadataId: 'employees', - viewId: SeedViewIds.PrismaCompany, + viewId: SeedViewIds.Company, position: 4, isVisible: true, size: 150, }, { fieldMetadataId: 'linkedin', - viewId: SeedViewIds.PrismaCompany, + viewId: SeedViewIds.Company, position: 5, isVisible: true, size: 170, }, { fieldMetadataId: 'address', - viewId: SeedViewIds.PrismaCompany, + viewId: SeedViewIds.Company, position: 6, isVisible: true, size: 170, }, { fieldMetadataId: 'displayName', - viewId: SeedViewIds.PrismaPerson, + viewId: SeedViewIds.Person, position: 0, isVisible: true, size: 210, }, { fieldMetadataId: 'email', - viewId: SeedViewIds.PrismaPerson, + viewId: SeedViewIds.Person, position: 1, isVisible: true, size: 150, }, { fieldMetadataId: 'company', - viewId: SeedViewIds.PrismaPerson, + viewId: SeedViewIds.Person, position: 2, isVisible: true, size: 150, }, { fieldMetadataId: 'phone', - viewId: SeedViewIds.PrismaPerson, + viewId: SeedViewIds.Person, position: 3, isVisible: true, size: 150, }, { fieldMetadataId: 'createdAt', - viewId: SeedViewIds.PrismaPerson, + viewId: SeedViewIds.Person, position: 4, isVisible: true, size: 150, }, { fieldMetadataId: 'city', - viewId: SeedViewIds.PrismaPerson, + viewId: SeedViewIds.Person, position: 5, isVisible: true, size: 150, }, { fieldMetadataId: 'jobTitle', - viewId: SeedViewIds.PrismaPerson, + viewId: SeedViewIds.Person, position: 6, isVisible: true, size: 150, }, { fieldMetadataId: 'linkedin', - viewId: SeedViewIds.PrismaPerson, + viewId: SeedViewIds.Person, position: 7, isVisible: true, size: 150, }, { fieldMetadataId: 'x', - viewId: SeedViewIds.PrismaPerson, + viewId: SeedViewIds.Person, position: 8, isVisible: true, size: 150, }, { - fieldMetadataId: SeedCompanyFieldMetadataIds.Name, - viewId: SeedViewIds.Company, + fieldMetadataId: 'amount', + viewId: SeedViewIds.Opportunity, position: 0, isVisible: true, - size: 180, + size: 150, }, { - fieldMetadataId: SeedCompanyFieldMetadataIds.DomainName, - viewId: SeedViewIds.Company, + fieldMetadataId: 'closeDate', + viewId: SeedViewIds.Opportunity, position: 1, isVisible: true, - size: 100, + size: 150, + }, + { + fieldMetadataId: 'probability', + viewId: SeedViewIds.Opportunity, + position: 2, + isVisible: true, + size: 150, + }, + { + fieldMetadataId: 'pointOfContact', + viewId: SeedViewIds.Opportunity, + position: 3, + isVisible: true, + size: 150, }, ]) .execute(); diff --git a/server/src/database/typeorm-seeds/workspace/views.ts b/server/src/database/typeorm-seeds/workspace/views.ts index c9c8a91f0..6fce2ea09 100644 --- a/server/src/database/typeorm-seeds/workspace/views.ts +++ b/server/src/database/typeorm-seeds/workspace/views.ts @@ -5,9 +5,6 @@ import { SeedObjectMetadataIds } from 'src/database/typeorm-seeds/metadata/objec const tableName = 'view'; export const enum SeedViewIds { - PrismaCompany = '20202020-1ad3-4d1b-81f3-d7ecba29f8d3', - PrismaPerson = '20202020-9adf-4768-bd9c-27a82fa141f1', - PrismaOpportunity = '20202020-ffc7-4c81-bb41-d4baed4ed685', Company = '20202020-2441-4424-8163-4002c523d415', Person = '20202020-1979-447d-8115-593744eb4ead', Opportunity = '20202020-b2b3-48a5-96ce-0936d6af21f7', @@ -28,24 +25,6 @@ export const seedViews = async ( ]) .orIgnore() .values([ - { - id: SeedViewIds.PrismaCompany, - name: 'All companies', - objectMetadataId: 'company', - type: 'table', - }, - { - id: SeedViewIds.PrismaPerson, - name: 'All people', - objectMetadataId: 'person', - type: 'table', - }, - { - id: SeedViewIds.PrismaOpportunity, - name: 'All opportunities', - objectMetadataId: 'company', - type: 'kanban', - }, { id: SeedViewIds.Company, name: 'All Companies', diff --git a/server/src/workspace/workspace-manager/standard-objects-prefill-data/opportunity.ts b/server/src/workspace/workspace-manager/standard-objects-prefill-data/opportunity.ts new file mode 100644 index 000000000..74141faea --- /dev/null +++ b/server/src/workspace/workspace-manager/standard-objects-prefill-data/opportunity.ts @@ -0,0 +1,33 @@ +import { EntityManager } from 'typeorm'; + +export const opportunityPrefillData = async ( + entityManager: EntityManager, + schemaName: string, +) => { + await entityManager + .createQueryBuilder() + .insert() + .into(`${schemaName}.opportunity`, [ + 'amount', + 'closeDate', + 'probability', + 'pipelineStepId', + 'pointOfContactId', + 'personId', + 'companyId', + ]) + .orIgnore() + .values([ + { + amount: 100000, + closeDate: new Date(), + probability: 0.5, + pipelineStepId: '73ac09c6-2b90-4874-9e5d-553ea76912ee', + pointOfContactId: 'bb757987-ae38-4d16-96ec-b25b595e7bd8', + personId: 'a4a2b8e9-7a2b-4b6a-8c8b-7e9a0a0a0a0a', + companyId: 'fe256b39-3ec3-4fe3-8997-b76aa0bfa408', + }, + ]) + .returning('*') + .execute(); +}; diff --git a/server/src/workspace/workspace-manager/standard-objects-prefill-data/standard-objects-prefill-data.ts b/server/src/workspace/workspace-manager/standard-objects-prefill-data/standard-objects-prefill-data.ts index 566be4e9a..44840bc86 100644 --- a/server/src/workspace/workspace-manager/standard-objects-prefill-data/standard-objects-prefill-data.ts +++ b/server/src/workspace/workspace-manager/standard-objects-prefill-data/standard-objects-prefill-data.ts @@ -5,6 +5,7 @@ import { viewPrefillData } from 'src/workspace/workspace-manager/standard-object import { companyPrefillData } from 'src/workspace/workspace-manager/standard-objects-prefill-data/company'; import { personPrefillData } from 'src/workspace/workspace-manager/standard-objects-prefill-data/person'; import { pipelineStepPrefillData } from 'src/workspace/workspace-manager/standard-objects-prefill-data/pipeline-step'; +import { opportunityPrefillData } from 'src/workspace/workspace-manager/standard-objects-prefill-data/opportunity'; export const standardObjectsPrefillData = async ( workspaceDataSource: DataSource, @@ -27,5 +28,6 @@ export const standardObjectsPrefillData = async ( await personPrefillData(entityManager, schemaName); await viewPrefillData(entityManager, schemaName, objectMetadataMap); await pipelineStepPrefillData(entityManager, schemaName); + await opportunityPrefillData(entityManager, schemaName); }); }; diff --git a/server/src/workspace/workspace-manager/standard-objects/opportunity.ts b/server/src/workspace/workspace-manager/standard-objects/opportunity.ts index b0a923eb8..1275d0d2d 100644 --- a/server/src/workspace/workspace-manager/standard-objects/opportunity.ts +++ b/server/src/workspace/workspace-manager/standard-objects/opportunity.ts @@ -9,7 +9,7 @@ const opportunityMetadata = { description: 'An opportunity', icon: 'IconTargetArrow', isActive: true, - isSystem: true, + isSystem: false, fields: [ { isCustom: false,