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 <charles@twenty.com> Co-authored-by: Charles Bochet <charlesBochet@users.noreply.github.com>
This commit is contained in:
@ -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 = () => {
|
||||
<Favorites />
|
||||
<NavTitle label="Workspace" />
|
||||
<ObjectMetadataNavItems />
|
||||
<NavItem
|
||||
label="Opportunities"
|
||||
to="/opportunities"
|
||||
active={currentPath === '/opportunities'}
|
||||
Icon={IconTargetArrow}
|
||||
/>
|
||||
</MainNavbar>
|
||||
) : (
|
||||
<SettingsNavbar />
|
||||
|
||||
@ -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<Array<Scalars['String']> | 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<Scalars['String']>;
|
||||
pipelineStageId?: InputMaybe<Scalars['String']>;
|
||||
}>;
|
||||
|
||||
|
||||
export type UpdateOnePipelineProgressStageMutation = { __typename?: 'Mutation', updateOnePipelineProgress?: { __typename?: 'PipelineProgress', id: string } | null };
|
||||
|
||||
export type UpdatePipelineStageMutationVariables = Exact<{
|
||||
id?: InputMaybe<Scalars['String']>;
|
||||
data: PipelineStageUpdateInput;
|
||||
}>;
|
||||
|
||||
|
||||
export type UpdatePipelineStageMutation = { __typename?: 'Mutation', updateOnePipelineStage?: { __typename?: 'PipelineStage', id: string, name: string, color: string } | null };
|
||||
|
||||
export type GetPipelineProgressQueryVariables = Exact<{
|
||||
where?: InputMaybe<PipelineProgressWhereInput>;
|
||||
orderBy?: InputMaybe<Array<PipelineProgressOrderByWithRelationInput> | 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<PipelineWhereInput>;
|
||||
}>;
|
||||
|
||||
|
||||
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<ActivityWhereInput>;
|
||||
limit?: InputMaybe<Scalars['Int']>;
|
||||
@ -5128,353 +5058,6 @@ export function useGetPersonPhoneByIdLazyQuery(baseOptions?: Apollo.LazyQueryHoo
|
||||
export type GetPersonPhoneByIdQueryHookResult = ReturnType<typeof useGetPersonPhoneByIdQuery>;
|
||||
export type GetPersonPhoneByIdLazyQueryHookResult = ReturnType<typeof useGetPersonPhoneByIdLazyQuery>;
|
||||
export type GetPersonPhoneByIdQueryResult = Apollo.QueryResult<GetPersonPhoneByIdQuery, GetPersonPhoneByIdQueryVariables>;
|
||||
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<CreateOneCompanyPipelineProgressMutation, CreateOneCompanyPipelineProgressMutationVariables>;
|
||||
|
||||
/**
|
||||
* __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<CreateOneCompanyPipelineProgressMutation, CreateOneCompanyPipelineProgressMutationVariables>) {
|
||||
const options = {...defaultOptions, ...baseOptions}
|
||||
return Apollo.useMutation<CreateOneCompanyPipelineProgressMutation, CreateOneCompanyPipelineProgressMutationVariables>(CreateOneCompanyPipelineProgressDocument, options);
|
||||
}
|
||||
export type CreateOneCompanyPipelineProgressMutationHookResult = ReturnType<typeof useCreateOneCompanyPipelineProgressMutation>;
|
||||
export type CreateOneCompanyPipelineProgressMutationResult = Apollo.MutationResult<CreateOneCompanyPipelineProgressMutation>;
|
||||
export type CreateOneCompanyPipelineProgressMutationOptions = Apollo.BaseMutationOptions<CreateOneCompanyPipelineProgressMutation, CreateOneCompanyPipelineProgressMutationVariables>;
|
||||
export const CreatePipelineStageDocument = gql`
|
||||
mutation CreatePipelineStage($data: PipelineStageCreateInput!) {
|
||||
pipelineStage: createOnePipelineStage(data: $data) {
|
||||
id
|
||||
name
|
||||
color
|
||||
}
|
||||
}
|
||||
`;
|
||||
export type CreatePipelineStageMutationFn = Apollo.MutationFunction<CreatePipelineStageMutation, CreatePipelineStageMutationVariables>;
|
||||
|
||||
/**
|
||||
* __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<CreatePipelineStageMutation, CreatePipelineStageMutationVariables>) {
|
||||
const options = {...defaultOptions, ...baseOptions}
|
||||
return Apollo.useMutation<CreatePipelineStageMutation, CreatePipelineStageMutationVariables>(CreatePipelineStageDocument, options);
|
||||
}
|
||||
export type CreatePipelineStageMutationHookResult = ReturnType<typeof useCreatePipelineStageMutation>;
|
||||
export type CreatePipelineStageMutationResult = Apollo.MutationResult<CreatePipelineStageMutation>;
|
||||
export type CreatePipelineStageMutationOptions = Apollo.BaseMutationOptions<CreatePipelineStageMutation, CreatePipelineStageMutationVariables>;
|
||||
export const DeleteManyPipelineProgressDocument = gql`
|
||||
mutation DeleteManyPipelineProgress($ids: [String!]) {
|
||||
deleteManyPipelineProgress(where: {id: {in: $ids}}) {
|
||||
count
|
||||
}
|
||||
}
|
||||
`;
|
||||
export type DeleteManyPipelineProgressMutationFn = Apollo.MutationFunction<DeleteManyPipelineProgressMutation, DeleteManyPipelineProgressMutationVariables>;
|
||||
|
||||
/**
|
||||
* __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<DeleteManyPipelineProgressMutation, DeleteManyPipelineProgressMutationVariables>) {
|
||||
const options = {...defaultOptions, ...baseOptions}
|
||||
return Apollo.useMutation<DeleteManyPipelineProgressMutation, DeleteManyPipelineProgressMutationVariables>(DeleteManyPipelineProgressDocument, options);
|
||||
}
|
||||
export type DeleteManyPipelineProgressMutationHookResult = ReturnType<typeof useDeleteManyPipelineProgressMutation>;
|
||||
export type DeleteManyPipelineProgressMutationResult = Apollo.MutationResult<DeleteManyPipelineProgressMutation>;
|
||||
export type DeleteManyPipelineProgressMutationOptions = Apollo.BaseMutationOptions<DeleteManyPipelineProgressMutation, DeleteManyPipelineProgressMutationVariables>;
|
||||
export const DeletePipelineStageDocument = gql`
|
||||
mutation DeletePipelineStage($where: PipelineStageWhereUniqueInput!) {
|
||||
pipelineStage: deleteOnePipelineStage(where: $where) {
|
||||
id
|
||||
name
|
||||
color
|
||||
}
|
||||
}
|
||||
`;
|
||||
export type DeletePipelineStageMutationFn = Apollo.MutationFunction<DeletePipelineStageMutation, DeletePipelineStageMutationVariables>;
|
||||
|
||||
/**
|
||||
* __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<DeletePipelineStageMutation, DeletePipelineStageMutationVariables>) {
|
||||
const options = {...defaultOptions, ...baseOptions}
|
||||
return Apollo.useMutation<DeletePipelineStageMutation, DeletePipelineStageMutationVariables>(DeletePipelineStageDocument, options);
|
||||
}
|
||||
export type DeletePipelineStageMutationHookResult = ReturnType<typeof useDeletePipelineStageMutation>;
|
||||
export type DeletePipelineStageMutationResult = Apollo.MutationResult<DeletePipelineStageMutation>;
|
||||
export type DeletePipelineStageMutationOptions = Apollo.BaseMutationOptions<DeletePipelineStageMutation, DeletePipelineStageMutationVariables>;
|
||||
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<UpdateOnePipelineProgressMutation, UpdateOnePipelineProgressMutationVariables>;
|
||||
|
||||
/**
|
||||
* __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<UpdateOnePipelineProgressMutation, UpdateOnePipelineProgressMutationVariables>) {
|
||||
const options = {...defaultOptions, ...baseOptions}
|
||||
return Apollo.useMutation<UpdateOnePipelineProgressMutation, UpdateOnePipelineProgressMutationVariables>(UpdateOnePipelineProgressDocument, options);
|
||||
}
|
||||
export type UpdateOnePipelineProgressMutationHookResult = ReturnType<typeof useUpdateOnePipelineProgressMutation>;
|
||||
export type UpdateOnePipelineProgressMutationResult = Apollo.MutationResult<UpdateOnePipelineProgressMutation>;
|
||||
export type UpdateOnePipelineProgressMutationOptions = Apollo.BaseMutationOptions<UpdateOnePipelineProgressMutation, UpdateOnePipelineProgressMutationVariables>;
|
||||
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<UpdateOnePipelineProgressStageMutation, UpdateOnePipelineProgressStageMutationVariables>;
|
||||
|
||||
/**
|
||||
* __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<UpdateOnePipelineProgressStageMutation, UpdateOnePipelineProgressStageMutationVariables>) {
|
||||
const options = {...defaultOptions, ...baseOptions}
|
||||
return Apollo.useMutation<UpdateOnePipelineProgressStageMutation, UpdateOnePipelineProgressStageMutationVariables>(UpdateOnePipelineProgressStageDocument, options);
|
||||
}
|
||||
export type UpdateOnePipelineProgressStageMutationHookResult = ReturnType<typeof useUpdateOnePipelineProgressStageMutation>;
|
||||
export type UpdateOnePipelineProgressStageMutationResult = Apollo.MutationResult<UpdateOnePipelineProgressStageMutation>;
|
||||
export type UpdateOnePipelineProgressStageMutationOptions = Apollo.BaseMutationOptions<UpdateOnePipelineProgressStageMutation, UpdateOnePipelineProgressStageMutationVariables>;
|
||||
export const UpdatePipelineStageDocument = gql`
|
||||
mutation UpdatePipelineStage($id: String, $data: PipelineStageUpdateInput!) {
|
||||
updateOnePipelineStage(where: {id: $id}, data: $data) {
|
||||
id
|
||||
name
|
||||
color
|
||||
}
|
||||
}
|
||||
`;
|
||||
export type UpdatePipelineStageMutationFn = Apollo.MutationFunction<UpdatePipelineStageMutation, UpdatePipelineStageMutationVariables>;
|
||||
|
||||
/**
|
||||
* __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<UpdatePipelineStageMutation, UpdatePipelineStageMutationVariables>) {
|
||||
const options = {...defaultOptions, ...baseOptions}
|
||||
return Apollo.useMutation<UpdatePipelineStageMutation, UpdatePipelineStageMutationVariables>(UpdatePipelineStageDocument, options);
|
||||
}
|
||||
export type UpdatePipelineStageMutationHookResult = ReturnType<typeof useUpdatePipelineStageMutation>;
|
||||
export type UpdatePipelineStageMutationResult = Apollo.MutationResult<UpdatePipelineStageMutation>;
|
||||
export type UpdatePipelineStageMutationOptions = Apollo.BaseMutationOptions<UpdatePipelineStageMutation, UpdatePipelineStageMutationVariables>;
|
||||
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<GetPipelineProgressQuery, GetPipelineProgressQueryVariables>) {
|
||||
const options = {...defaultOptions, ...baseOptions}
|
||||
return Apollo.useQuery<GetPipelineProgressQuery, GetPipelineProgressQueryVariables>(GetPipelineProgressDocument, options);
|
||||
}
|
||||
export function useGetPipelineProgressLazyQuery(baseOptions?: Apollo.LazyQueryHookOptions<GetPipelineProgressQuery, GetPipelineProgressQueryVariables>) {
|
||||
const options = {...defaultOptions, ...baseOptions}
|
||||
return Apollo.useLazyQuery<GetPipelineProgressQuery, GetPipelineProgressQueryVariables>(GetPipelineProgressDocument, options);
|
||||
}
|
||||
export type GetPipelineProgressQueryHookResult = ReturnType<typeof useGetPipelineProgressQuery>;
|
||||
export type GetPipelineProgressLazyQueryHookResult = ReturnType<typeof useGetPipelineProgressLazyQuery>;
|
||||
export type GetPipelineProgressQueryResult = Apollo.QueryResult<GetPipelineProgressQuery, GetPipelineProgressQueryVariables>;
|
||||
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<GetPipelinesQuery, GetPipelinesQueryVariables>) {
|
||||
const options = {...defaultOptions, ...baseOptions}
|
||||
return Apollo.useQuery<GetPipelinesQuery, GetPipelinesQueryVariables>(GetPipelinesDocument, options);
|
||||
}
|
||||
export function useGetPipelinesLazyQuery(baseOptions?: Apollo.LazyQueryHookOptions<GetPipelinesQuery, GetPipelinesQueryVariables>) {
|
||||
const options = {...defaultOptions, ...baseOptions}
|
||||
return Apollo.useLazyQuery<GetPipelinesQuery, GetPipelinesQueryVariables>(GetPipelinesDocument, options);
|
||||
}
|
||||
export type GetPipelinesQueryHookResult = ReturnType<typeof useGetPipelinesQuery>;
|
||||
export type GetPipelinesLazyQueryHookResult = ReturnType<typeof useGetPipelinesLazyQuery>;
|
||||
export type GetPipelinesQueryResult = Apollo.QueryResult<GetPipelinesQuery, GetPipelinesQueryVariables>;
|
||||
export const SearchActivityDocument = gql`
|
||||
query SearchActivity($where: ActivityWhereInput, $limit: Int, $orderBy: [ActivityOrderByWithRelationInput!]) {
|
||||
searchResults: findManyActivities(
|
||||
|
||||
@ -20,7 +20,7 @@ export const useHandleCheckableActivityTargetChange = ({
|
||||
objectNameSingular: 'activityTargetV2',
|
||||
});
|
||||
const { deleteOneObject } = useDeleteOneObjectRecord({
|
||||
objectNamePlural: 'activityTargetV2',
|
||||
objectNameSingular: 'activityTargetV2',
|
||||
});
|
||||
|
||||
return async (
|
||||
|
||||
@ -12,7 +12,7 @@ type ActivityActionBarProps = {
|
||||
export const ActivityActionBar = ({ activityId }: ActivityActionBarProps) => {
|
||||
const [, setIsRightDrawerOpen] = useRecoilState(isRightDrawerOpenState);
|
||||
const { deleteOneObject } = useDeleteOneObjectRecord({
|
||||
objectNamePlural: 'activitiesV2',
|
||||
objectNameSingular: 'activityV2',
|
||||
});
|
||||
|
||||
const deleteActivity = () => {
|
||||
|
||||
@ -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,
|
||||
}}
|
||||
>
|
||||
|
||||
@ -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<PipelineStep[]>([]);
|
||||
const [opportunities, setOpportunities] = useState<Opportunity[]>([]);
|
||||
const [companies, setCompanies] = useState<Company[]>([]);
|
||||
|
||||
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<PipelineStep>) => {
|
||||
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<Opportunity>) => {
|
||||
const pipelineProgresses: Array<Opportunity> = [];
|
||||
|
||||
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<Company>) => {
|
||||
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(() => {
|
||||
|
||||
@ -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<Opportunity>({
|
||||
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],
|
||||
);
|
||||
};
|
||||
|
||||
@ -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();
|
||||
|
||||
@ -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;
|
||||
});
|
||||
|
||||
@ -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<Company, 'id' | 'name' | 'domainName'>;
|
||||
export type PipelineProgressForBoard = Pick<
|
||||
PipelineProgress,
|
||||
| 'id'
|
||||
| 'amount'
|
||||
| 'closeDate'
|
||||
| 'companyId'
|
||||
| 'probability'
|
||||
| 'pointOfContactId'
|
||||
> & {
|
||||
pointOfContact?: Pick<Person, 'id' | 'displayName'> | null;
|
||||
};
|
||||
export type PipelineProgressForBoard = Opportunity;
|
||||
|
||||
export type CompanyProgress = {
|
||||
company: CompanyForBoard;
|
||||
|
||||
@ -22,6 +22,7 @@ export const ObjectMetadataNavItems = () => {
|
||||
return (
|
||||
<>
|
||||
{objectMetadataItems.map((objectMetadataItem) => {
|
||||
if (objectMetadataItem.nameSingular === 'opportunityV2') return null;
|
||||
return (
|
||||
<NavItem
|
||||
key={objectMetadataItem.id}
|
||||
|
||||
@ -3,32 +3,37 @@ import { getOperationName } from '@apollo/client/utilities';
|
||||
|
||||
import { useFindOneObjectMetadataItem } from '@/object-metadata/hooks/useFindOneObjectMetadataItem';
|
||||
import { ObjectMetadataItemIdentifier } from '@/object-metadata/types/ObjectMetadataItemIdentifier';
|
||||
import { capitalize } from '~/utils/string/capitalize';
|
||||
|
||||
export const useDeleteOneObjectRecord = ({
|
||||
objectNamePlural,
|
||||
}: Pick<ObjectMetadataItemIdentifier, 'objectNamePlural'>) => {
|
||||
export const useDeleteOneObjectRecord = <T>({
|
||||
objectNameSingular,
|
||||
}: Pick<ObjectMetadataItemIdentifier, 'objectNameSingular'>) => {
|
||||
const {
|
||||
foundObjectMetadataItem,
|
||||
objectNotFoundInMetadata,
|
||||
findManyQuery,
|
||||
deleteOneMutation,
|
||||
} = useFindOneObjectMetadataItem({
|
||||
objectNamePlural,
|
||||
objectNameSingular,
|
||||
});
|
||||
|
||||
// TODO: type this with a minimal type at least with Record<string, any>
|
||||
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,
|
||||
|
||||
@ -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 () => {
|
||||
|
||||
@ -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
|
||||
}
|
||||
}
|
||||
`;
|
||||
@ -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
|
||||
}
|
||||
}
|
||||
`;
|
||||
@ -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
|
||||
}
|
||||
}
|
||||
`;
|
||||
@ -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
|
||||
}
|
||||
}
|
||||
`;
|
||||
@ -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
|
||||
}
|
||||
}
|
||||
}
|
||||
`;
|
||||
@ -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
|
||||
}
|
||||
}
|
||||
`;
|
||||
@ -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
|
||||
}
|
||||
}
|
||||
`;
|
||||
@ -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
|
||||
}
|
||||
}
|
||||
`;
|
||||
@ -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
|
||||
}
|
||||
}
|
||||
}
|
||||
`;
|
||||
@ -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<PipelineStep>({
|
||||
objectNameSingular: 'pipelineStepV2',
|
||||
});
|
||||
|
||||
const { deleteOneObject: deleteOnePipelineStep } =
|
||||
useDeleteOneObjectRecord<PipelineStep>({
|
||||
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 };
|
||||
|
||||
@ -0,0 +1,8 @@
|
||||
import { atom } from 'recoil';
|
||||
|
||||
import { PipelineStep } from '@/pipeline/types/PipelineStep';
|
||||
|
||||
export const currentPipelineStepsState = atom<PipelineStep[]>({
|
||||
key: 'currentPipelineStepsState',
|
||||
default: [],
|
||||
});
|
||||
17
front/src/modules/pipeline/types/Opportunity.ts
Normal file
17
front/src/modules/pipeline/types/Opportunity.ts
Normal file
@ -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<Person, 'id' | 'firstName' | 'lastName' | 'avatarUrl'>;
|
||||
[key: string]: any;
|
||||
};
|
||||
6
front/src/modules/pipeline/types/PipelineStep.ts
Normal file
6
front/src/modules/pipeline/types/PipelineStep.ts
Normal file
@ -0,0 +1,6 @@
|
||||
export type PipelineStep = {
|
||||
id: string;
|
||||
name: string;
|
||||
color: string;
|
||||
position: number;
|
||||
};
|
||||
@ -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<Opportunity>({
|
||||
objectNameSingular: 'opportunityV2',
|
||||
});
|
||||
|
||||
const apolloClient = useApolloClient();
|
||||
|
||||
const { unselectAllActiveCards } = useCurrentCardSelected();
|
||||
|
||||
@ -69,33 +70,25 @@ export const EntityBoard = ({
|
||||
pipelineProgressId: NonNullable<PipelineProgress['id']>,
|
||||
pipelineStageId: NonNullable<PipelineStage['id']>,
|
||||
) => {
|
||||
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({
|
||||
|
||||
@ -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);
|
||||
|
||||
|
||||
@ -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<PipelineStep>({
|
||||
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,
|
||||
},
|
||||
}),
|
||||
),
|
||||
|
||||
@ -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);
|
||||
|
||||
|
||||
@ -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<Opportunity>({
|
||||
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;
|
||||
};
|
||||
|
||||
@ -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<PipelineStep>({
|
||||
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 (
|
||||
<PageContainer>
|
||||
<RecoilScope>
|
||||
|
||||
@ -39,8 +39,8 @@ export const SettingsWorkspaceMembers = () => {
|
||||
objectNamePlural: 'workspaceMembersV2',
|
||||
});
|
||||
const { deleteOneObject: deleteOneWorkspaceMember } =
|
||||
useDeleteOneObjectRecord({
|
||||
objectNamePlural: 'workspaceMembersV2',
|
||||
useDeleteOneObjectRecord<WorkspaceMember>({
|
||||
objectNameSingular: 'workspaceMemberV2',
|
||||
});
|
||||
const currentWorkspace = useRecoilValue(currentWorkspaceState);
|
||||
|
||||
|
||||
@ -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({
|
||||
|
||||
@ -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);
|
||||
|
||||
@ -86,7 +86,7 @@ export const seedObjectMetadata = async (
|
||||
dataSourceId: SeedDataSourceId,
|
||||
workspaceId: SeedWorkspaceId,
|
||||
isActive: true,
|
||||
isSystem: true,
|
||||
isSystem: false,
|
||||
},
|
||||
{
|
||||
id: SeedObjectMetadataIds.PipelineStep,
|
||||
|
||||
38
server/src/database/typeorm-seeds/workspace/opportunity.ts
Normal file
38
server/src/database/typeorm-seeds/workspace/opportunity.ts
Normal file
@ -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();
|
||||
};
|
||||
47
server/src/database/typeorm-seeds/workspace/pipeline-step.ts
Normal file
47
server/src/database/typeorm-seeds/workspace/pipeline-step.ts
Normal file
@ -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();
|
||||
};
|
||||
@ -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();
|
||||
|
||||
@ -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',
|
||||
|
||||
@ -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();
|
||||
};
|
||||
@ -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);
|
||||
});
|
||||
};
|
||||
|
||||
@ -9,7 +9,7 @@ const opportunityMetadata = {
|
||||
description: 'An opportunity',
|
||||
icon: 'IconTargetArrow',
|
||||
isActive: true,
|
||||
isSystem: true,
|
||||
isSystem: false,
|
||||
fields: [
|
||||
{
|
||||
isCustom: false,
|
||||
|
||||
Reference in New Issue
Block a user