Enable column edition, and fix ordering (#683)
* Enable column edition, and fix ordering * Move queries to services * Add total amounts for board columns * Refactor totals selector as a family * Fix 0-index issue * Lint * Rename selector * Remove useless header * Address PR comments * Optimistically update board column names
This commit is contained in:
@ -1168,6 +1168,7 @@ export type Mutation = {
|
|||||||
updateOneCompany?: Maybe<Company>;
|
updateOneCompany?: Maybe<Company>;
|
||||||
updateOnePerson?: Maybe<Person>;
|
updateOnePerson?: Maybe<Person>;
|
||||||
updateOnePipelineProgress?: Maybe<PipelineProgress>;
|
updateOnePipelineProgress?: Maybe<PipelineProgress>;
|
||||||
|
updateOnePipelineStage?: Maybe<PipelineStage>;
|
||||||
updateUser: User;
|
updateUser: User;
|
||||||
updateWorkspace: Workspace;
|
updateWorkspace: Workspace;
|
||||||
uploadFile: Scalars['String'];
|
uploadFile: Scalars['String'];
|
||||||
@ -1276,6 +1277,12 @@ export type MutationUpdateOnePipelineProgressArgs = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
export type MutationUpdateOnePipelineStageArgs = {
|
||||||
|
data: PipelineStageUpdateInput;
|
||||||
|
where: PipelineStageWhereUniqueInput;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
export type MutationUpdateUserArgs = {
|
export type MutationUpdateUserArgs = {
|
||||||
data: UserUpdateInput;
|
data: UserUpdateInput;
|
||||||
where: UserWhereUniqueInput;
|
where: UserWhereUniqueInput;
|
||||||
@ -2232,6 +2239,18 @@ export type PipelineStageScalarWhereInput = {
|
|||||||
updatedAt?: InputMaybe<DateTimeFilter>;
|
updatedAt?: InputMaybe<DateTimeFilter>;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export type PipelineStageUpdateInput = {
|
||||||
|
color?: InputMaybe<StringFieldUpdateOperationsInput>;
|
||||||
|
createdAt?: InputMaybe<DateTimeFieldUpdateOperationsInput>;
|
||||||
|
id?: InputMaybe<StringFieldUpdateOperationsInput>;
|
||||||
|
index?: InputMaybe<NullableIntFieldUpdateOperationsInput>;
|
||||||
|
name?: InputMaybe<StringFieldUpdateOperationsInput>;
|
||||||
|
pipeline?: InputMaybe<PipelineUpdateOneRequiredWithoutPipelineStagesNestedInput>;
|
||||||
|
pipelineProgresses?: InputMaybe<PipelineProgressUpdateManyWithoutPipelineStageNestedInput>;
|
||||||
|
type?: InputMaybe<StringFieldUpdateOperationsInput>;
|
||||||
|
updatedAt?: InputMaybe<DateTimeFieldUpdateOperationsInput>;
|
||||||
|
};
|
||||||
|
|
||||||
export type PipelineStageUpdateManyMutationInput = {
|
export type PipelineStageUpdateManyMutationInput = {
|
||||||
color?: InputMaybe<StringFieldUpdateOperationsInput>;
|
color?: InputMaybe<StringFieldUpdateOperationsInput>;
|
||||||
createdAt?: InputMaybe<DateTimeFieldUpdateOperationsInput>;
|
createdAt?: InputMaybe<DateTimeFieldUpdateOperationsInput>;
|
||||||
@ -3410,6 +3429,14 @@ export type DeleteManyPipelineProgressMutationVariables = Exact<{
|
|||||||
|
|
||||||
export type DeleteManyPipelineProgressMutation = { __typename?: 'Mutation', deleteManyPipelineProgress: { __typename?: 'AffectedRows', count: number } };
|
export type DeleteManyPipelineProgressMutation = { __typename?: 'Mutation', deleteManyPipelineProgress: { __typename?: 'AffectedRows', count: number } };
|
||||||
|
|
||||||
|
export type UpdatePipelineStageMutationVariables = Exact<{
|
||||||
|
id?: InputMaybe<Scalars['String']>;
|
||||||
|
name?: InputMaybe<Scalars['String']>;
|
||||||
|
}>;
|
||||||
|
|
||||||
|
|
||||||
|
export type UpdatePipelineStageMutation = { __typename?: 'Mutation', updateOnePipelineStage?: { __typename?: 'PipelineStage', id: string, name: string } | null };
|
||||||
|
|
||||||
export type SearchPeopleQueryVariables = Exact<{
|
export type SearchPeopleQueryVariables = Exact<{
|
||||||
where?: InputMaybe<PersonWhereInput>;
|
where?: InputMaybe<PersonWhereInput>;
|
||||||
limit?: InputMaybe<Scalars['Int']>;
|
limit?: InputMaybe<Scalars['Int']>;
|
||||||
@ -5187,6 +5214,41 @@ export function useDeleteManyPipelineProgressMutation(baseOptions?: Apollo.Mutat
|
|||||||
export type DeleteManyPipelineProgressMutationHookResult = ReturnType<typeof useDeleteManyPipelineProgressMutation>;
|
export type DeleteManyPipelineProgressMutationHookResult = ReturnType<typeof useDeleteManyPipelineProgressMutation>;
|
||||||
export type DeleteManyPipelineProgressMutationResult = Apollo.MutationResult<DeleteManyPipelineProgressMutation>;
|
export type DeleteManyPipelineProgressMutationResult = Apollo.MutationResult<DeleteManyPipelineProgressMutation>;
|
||||||
export type DeleteManyPipelineProgressMutationOptions = Apollo.BaseMutationOptions<DeleteManyPipelineProgressMutation, DeleteManyPipelineProgressMutationVariables>;
|
export type DeleteManyPipelineProgressMutationOptions = Apollo.BaseMutationOptions<DeleteManyPipelineProgressMutation, DeleteManyPipelineProgressMutationVariables>;
|
||||||
|
export const UpdatePipelineStageDocument = gql`
|
||||||
|
mutation UpdatePipelineStage($id: String, $name: String) {
|
||||||
|
updateOnePipelineStage(where: {id: $id}, data: {name: {set: $name}}) {
|
||||||
|
id
|
||||||
|
name
|
||||||
|
}
|
||||||
|
}
|
||||||
|
`;
|
||||||
|
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'
|
||||||
|
* name: // value for 'name'
|
||||||
|
* },
|
||||||
|
* });
|
||||||
|
*/
|
||||||
|
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 SearchPeopleDocument = gql`
|
export const SearchPeopleDocument = gql`
|
||||||
query SearchPeople($where: PersonWhereInput, $limit: Int, $orderBy: [PersonOrderByWithRelationInput!]) {
|
query SearchPeople($where: PersonWhereInput, $limit: Int, $orderBy: [PersonOrderByWithRelationInput!]) {
|
||||||
searchResults: findManyPerson(where: $where, take: $limit, orderBy: $orderBy) {
|
searchResults: findManyPerson(where: $where, take: $limit, orderBy: $orderBy) {
|
||||||
|
|||||||
@ -2,7 +2,7 @@ import { useState } from 'react';
|
|||||||
import { useTheme } from '@emotion/react';
|
import { useTheme } from '@emotion/react';
|
||||||
import { useRecoilValue } from 'recoil';
|
import { useRecoilValue } from 'recoil';
|
||||||
|
|
||||||
import { useFilteredSearchCompanyQuery } from '@/companies/services';
|
import { useFilteredSearchCompanyQuery } from '@/companies/queries';
|
||||||
import { useScopedHotkeys } from '@/lib/hotkeys/hooks/useScopedHotkeys';
|
import { useScopedHotkeys } from '@/lib/hotkeys/hooks/useScopedHotkeys';
|
||||||
import { AppHotkeyScope } from '@/lib/hotkeys/types/AppHotkeyScope';
|
import { AppHotkeyScope } from '@/lib/hotkeys/types/AppHotkeyScope';
|
||||||
import { useFilteredSearchPeopleQuery } from '@/people/services';
|
import { useFilteredSearchPeopleQuery } from '@/people/services';
|
||||||
|
|||||||
@ -10,7 +10,7 @@ import {
|
|||||||
|
|
||||||
import { useHandleCheckableCommentThreadTargetChange } from '@/comments/hooks/useHandleCheckableCommentThreadTargetChange';
|
import { useHandleCheckableCommentThreadTargetChange } from '@/comments/hooks/useHandleCheckableCommentThreadTargetChange';
|
||||||
import { CompanyChip } from '@/companies/components/CompanyChip';
|
import { CompanyChip } from '@/companies/components/CompanyChip';
|
||||||
import { useFilteredSearchCompanyQuery } from '@/companies/services';
|
import { useFilteredSearchCompanyQuery } from '@/companies/queries';
|
||||||
import { usePreviousHotkeyScope } from '@/lib/hotkeys/hooks/usePreviousHotkeyScope';
|
import { usePreviousHotkeyScope } from '@/lib/hotkeys/hooks/usePreviousHotkeyScope';
|
||||||
import { useScopedHotkeys } from '@/lib/hotkeys/hooks/useScopedHotkeys';
|
import { useScopedHotkeys } from '@/lib/hotkeys/hooks/useScopedHotkeys';
|
||||||
import { PersonChip } from '@/people/components/PersonChip';
|
import { PersonChip } from '@/people/components/PersonChip';
|
||||||
|
|||||||
@ -4,7 +4,7 @@ import styled from '@emotion/styled';
|
|||||||
import { useRecoilState } from 'recoil';
|
import { useRecoilState } from 'recoil';
|
||||||
|
|
||||||
import { GET_COMMENT_THREADS_BY_TARGETS } from '@/comments/services';
|
import { GET_COMMENT_THREADS_BY_TARGETS } from '@/comments/services';
|
||||||
import { GET_COMPANIES } from '@/companies/services';
|
import { GET_COMPANIES } from '@/companies/queries';
|
||||||
import { GET_PEOPLE } from '@/people/services';
|
import { GET_PEOPLE } from '@/people/services';
|
||||||
import { Button } from '@/ui/components/buttons/Button';
|
import { Button } from '@/ui/components/buttons/Button';
|
||||||
import { IconTrash } from '@/ui/icons';
|
import { IconTrash } from '@/ui/icons';
|
||||||
|
|||||||
@ -1,7 +1,7 @@
|
|||||||
import { getOperationName } from '@apollo/client/utilities';
|
import { getOperationName } from '@apollo/client/utilities';
|
||||||
import { v4 } from 'uuid';
|
import { v4 } from 'uuid';
|
||||||
|
|
||||||
import { GET_COMPANIES } from '@/companies/services';
|
import { GET_COMPANIES } from '@/companies/queries';
|
||||||
import { GET_PEOPLE } from '@/people/services';
|
import { GET_PEOPLE } from '@/people/services';
|
||||||
import {
|
import {
|
||||||
CommentThread,
|
CommentThread,
|
||||||
|
|||||||
@ -3,7 +3,7 @@ import { useRecoilState, useRecoilValue } from 'recoil';
|
|||||||
import { v4 } from 'uuid';
|
import { v4 } from 'uuid';
|
||||||
|
|
||||||
import { currentUserState } from '@/auth/states/currentUserState';
|
import { currentUserState } from '@/auth/states/currentUserState';
|
||||||
import { GET_COMPANIES } from '@/companies/services';
|
import { GET_COMPANIES } from '@/companies/queries';
|
||||||
import { useSetHotkeyScope } from '@/lib/hotkeys/hooks/useSetHotkeyScope';
|
import { useSetHotkeyScope } from '@/lib/hotkeys/hooks/useSetHotkeyScope';
|
||||||
import { GET_PEOPLE } from '@/people/services';
|
import { GET_PEOPLE } from '@/people/services';
|
||||||
import { RightDrawerHotkeyScope } from '@/ui/layout/right-drawer/types/RightDrawerHotkeyScope';
|
import { RightDrawerHotkeyScope } from '@/ui/layout/right-drawer/types/RightDrawerHotkeyScope';
|
||||||
|
|||||||
@ -3,7 +3,7 @@ import { useRecoilState, useRecoilValue } from 'recoil';
|
|||||||
import { v4 } from 'uuid';
|
import { v4 } from 'uuid';
|
||||||
|
|
||||||
import { currentUserState } from '@/auth/states/currentUserState';
|
import { currentUserState } from '@/auth/states/currentUserState';
|
||||||
import { GET_COMPANIES } from '@/companies/services';
|
import { GET_COMPANIES } from '@/companies/queries';
|
||||||
import { useSetHotkeyScope } from '@/lib/hotkeys/hooks/useSetHotkeyScope';
|
import { useSetHotkeyScope } from '@/lib/hotkeys/hooks/useSetHotkeyScope';
|
||||||
import { GET_PEOPLE } from '@/people/services';
|
import { GET_PEOPLE } from '@/people/services';
|
||||||
import { RightDrawerHotkeyScope } from '@/ui/layout/right-drawer/types/RightDrawerHotkeyScope';
|
import { RightDrawerHotkeyScope } from '@/ui/layout/right-drawer/types/RightDrawerHotkeyScope';
|
||||||
|
|||||||
@ -5,7 +5,8 @@ import styled from '@emotion/styled';
|
|||||||
import { IconCurrencyDollar } from '@tabler/icons-react';
|
import { IconCurrencyDollar } from '@tabler/icons-react';
|
||||||
import { useRecoilState } from 'recoil';
|
import { useRecoilState } from 'recoil';
|
||||||
|
|
||||||
import { GET_PIPELINES } from '@/pipeline-progress/queries';
|
import { companyProgressesFamilyState } from '@/companies/states/companyProgressesFamilyState';
|
||||||
|
import { GET_PIPELINES } from '@/pipeline-progress/services';
|
||||||
import { BoardCardContext } from '@/pipeline-progress/states/BoardCardContext';
|
import { BoardCardContext } from '@/pipeline-progress/states/BoardCardContext';
|
||||||
import { pipelineProgressIdScopedState } from '@/pipeline-progress/states/pipelineProgressIdScopedState';
|
import { pipelineProgressIdScopedState } from '@/pipeline-progress/states/pipelineProgressIdScopedState';
|
||||||
import { selectedBoardCardsState } from '@/pipeline-progress/states/selectedBoardCardsState';
|
import { selectedBoardCardsState } from '@/pipeline-progress/states/selectedBoardCardsState';
|
||||||
@ -19,7 +20,6 @@ import {
|
|||||||
PipelineProgress,
|
PipelineProgress,
|
||||||
useUpdateOnePipelineProgressMutation,
|
useUpdateOnePipelineProgressMutation,
|
||||||
} from '~/generated/graphql';
|
} from '~/generated/graphql';
|
||||||
import { companyProgressesFamilyState } from '~/pages/opportunities/companyProgressesFamilyState';
|
|
||||||
|
|
||||||
const StyledBoardCard = styled.div<{ selected: boolean }>`
|
const StyledBoardCard = styled.div<{ selected: boolean }>`
|
||||||
background-color: ${({ theme, selected }) =>
|
background-color: ${({ theme, selected }) =>
|
||||||
|
|||||||
@ -5,7 +5,7 @@ import { useRecoilScopedState } from '@/recoil-scope/hooks/useRecoilScopedState'
|
|||||||
import { useRecoilScopedValue } from '@/recoil-scope/hooks/useRecoilScopedValue';
|
import { useRecoilScopedValue } from '@/recoil-scope/hooks/useRecoilScopedValue';
|
||||||
import { TableContext } from '@/ui/tables/states/TableContext';
|
import { TableContext } from '@/ui/tables/states/TableContext';
|
||||||
|
|
||||||
import { useFilteredSearchCompanyQuery } from '../services';
|
import { useFilteredSearchCompanyQuery } from '../queries';
|
||||||
|
|
||||||
export function FilterDropdownCompanySearchSelect() {
|
export function FilterDropdownCompanySearchSelect() {
|
||||||
const filterDropdownSearchInput = useRecoilScopedValue(
|
const filterDropdownSearchInput = useRecoilScopedValue(
|
||||||
|
|||||||
@ -4,7 +4,7 @@ import { useRecoilScopedState } from '@/recoil-scope/hooks/useRecoilScopedState'
|
|||||||
import { SingleEntitySelect } from '@/relation-picker/components/SingleEntitySelect';
|
import { SingleEntitySelect } from '@/relation-picker/components/SingleEntitySelect';
|
||||||
import { relationPickerSearchFilterScopedState } from '@/relation-picker/states/relationPickerSearchFilterScopedState';
|
import { relationPickerSearchFilterScopedState } from '@/relation-picker/states/relationPickerSearchFilterScopedState';
|
||||||
|
|
||||||
import { useFilteredSearchCompanyQuery } from '../services';
|
import { useFilteredSearchCompanyQuery } from '../queries';
|
||||||
|
|
||||||
export function NewCompanyBoardCard() {
|
export function NewCompanyBoardCard() {
|
||||||
const [searchFilter] = useRecoilScopedState(
|
const [searchFilter] = useRecoilScopedState(
|
||||||
|
|||||||
@ -4,9 +4,10 @@ import { useRecoilState } from 'recoil';
|
|||||||
import { v4 as uuidv4 } from 'uuid';
|
import { v4 as uuidv4 } from 'uuid';
|
||||||
|
|
||||||
import { usePreviousHotkeyScope } from '@/lib/hotkeys/hooks/usePreviousHotkeyScope';
|
import { usePreviousHotkeyScope } from '@/lib/hotkeys/hooks/usePreviousHotkeyScope';
|
||||||
import { GET_PIPELINES } from '@/pipeline-progress/queries';
|
import { GET_PIPELINES } from '@/pipeline-progress/services';
|
||||||
import { BoardColumnContext } from '@/pipeline-progress/states/BoardColumnContext';
|
import { BoardColumnContext } from '@/pipeline-progress/states/BoardColumnContext';
|
||||||
import { boardState } from '@/pipeline-progress/states/boardState';
|
import { boardState } from '@/pipeline-progress/states/boardState';
|
||||||
|
import { currentPipelineState } from '@/pipeline-progress/states/currentPipelineState';
|
||||||
import { pipelineStageIdScopedState } from '@/pipeline-progress/states/pipelineStageIdScopedState';
|
import { pipelineStageIdScopedState } from '@/pipeline-progress/states/pipelineStageIdScopedState';
|
||||||
import { RecoilScope } from '@/recoil-scope/components/RecoilScope';
|
import { RecoilScope } from '@/recoil-scope/components/RecoilScope';
|
||||||
import { useRecoilScopedState } from '@/recoil-scope/hooks/useRecoilScopedState';
|
import { useRecoilScopedState } from '@/recoil-scope/hooks/useRecoilScopedState';
|
||||||
@ -19,9 +20,8 @@ import {
|
|||||||
PipelineProgressableType,
|
PipelineProgressableType,
|
||||||
useCreateOnePipelineProgressMutation,
|
useCreateOnePipelineProgressMutation,
|
||||||
} from '~/generated/graphql';
|
} from '~/generated/graphql';
|
||||||
import { currentPipelineState } from '~/pages/opportunities/currentPipelineState';
|
|
||||||
|
|
||||||
import { useFilteredSearchCompanyQuery } from '../services';
|
import { useFilteredSearchCompanyQuery } from '../queries';
|
||||||
|
|
||||||
export function NewCompanyProgressButton() {
|
export function NewCompanyProgressButton() {
|
||||||
const [isCreatingCard, setIsCreatingCard] = useState(false);
|
const [isCreatingCard, setIsCreatingCard] = useState(false);
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
import { useRecoilState } from 'recoil';
|
import { useRecoilState } from 'recoil';
|
||||||
|
|
||||||
import { defaultOrderBy } from '@/companies/services';
|
import { defaultOrderBy } from '@/companies/queries';
|
||||||
import { isFetchingEntityTableDataState } from '@/ui/tables/states/isFetchingEntityTableDataState';
|
import { isFetchingEntityTableDataState } from '@/ui/tables/states/isFetchingEntityTableDataState';
|
||||||
import { tableRowIdsState } from '@/ui/tables/states/tableRowIdsState';
|
import { tableRowIdsState } from '@/ui/tables/states/tableRowIdsState';
|
||||||
import {
|
import {
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
import { Key } from 'ts-key-enum';
|
import { Key } from 'ts-key-enum';
|
||||||
|
|
||||||
import { useFilteredSearchCompanyQuery } from '@/companies/services';
|
import { useFilteredSearchCompanyQuery } from '@/companies/queries';
|
||||||
import { useScopedHotkeys } from '@/lib/hotkeys/hooks/useScopedHotkeys';
|
import { useScopedHotkeys } from '@/lib/hotkeys/hooks/useScopedHotkeys';
|
||||||
import { useSetHotkeyScope } from '@/lib/hotkeys/hooks/useSetHotkeyScope';
|
import { useSetHotkeyScope } from '@/lib/hotkeys/hooks/useSetHotkeyScope';
|
||||||
import { useRecoilScopedState } from '@/recoil-scope/hooks/useRecoilScopedState';
|
import { useRecoilScopedState } from '@/recoil-scope/hooks/useRecoilScopedState';
|
||||||
|
|||||||
@ -6,7 +6,7 @@ import { EntityTableActionBarButton } from '@/ui/components/table/action-bar/Ent
|
|||||||
import { IconTrash } from '@/ui/icons/index';
|
import { IconTrash } from '@/ui/icons/index';
|
||||||
import { useDeleteManyPipelineProgressMutation } from '~/generated/graphql';
|
import { useDeleteManyPipelineProgressMutation } from '~/generated/graphql';
|
||||||
|
|
||||||
import { GET_PIPELINES } from '../queries';
|
import { GET_PIPELINES } from '../services';
|
||||||
import { selectedBoardCardsState } from '../states/selectedBoardCardsState';
|
import { selectedBoardCardsState } from '../states/selectedBoardCardsState';
|
||||||
|
|
||||||
export function BoardActionBarButtonDeletePipelineProgress() {
|
export function BoardActionBarButtonDeletePipelineProgress() {
|
||||||
|
|||||||
@ -62,10 +62,16 @@ export function EntityBoard({ boardOptions }: { boardOptions: BoardOptions }) {
|
|||||||
[board, updatePipelineProgressStageInDB, setBoard],
|
[board, updatePipelineProgressStageInDB, setBoard],
|
||||||
);
|
);
|
||||||
|
|
||||||
|
const sortedBoard = board
|
||||||
|
? [...board].sort((a, b) => {
|
||||||
|
return a.index - b.index;
|
||||||
|
})
|
||||||
|
: [];
|
||||||
|
|
||||||
return (board?.length ?? 0) > 0 ? (
|
return (board?.length ?? 0) > 0 ? (
|
||||||
<StyledBoard>
|
<StyledBoard>
|
||||||
<DragDropContext onDragEnd={onDragEnd}>
|
<DragDropContext onDragEnd={onDragEnd}>
|
||||||
{board?.map((column) => (
|
{sortedBoard.map((column) => (
|
||||||
<RecoilScope
|
<RecoilScope
|
||||||
SpecificContext={BoardColumnContext}
|
SpecificContext={BoardColumnContext}
|
||||||
key={column.pipelineStageId}
|
key={column.pipelineStageId}
|
||||||
|
|||||||
@ -1,14 +1,18 @@
|
|||||||
import { useEffect } from 'react';
|
import { useEffect } from 'react';
|
||||||
import styled from '@emotion/styled';
|
import styled from '@emotion/styled';
|
||||||
import { Droppable, DroppableProvided } from '@hello-pangea/dnd';
|
import { Droppable, DroppableProvided } from '@hello-pangea/dnd';
|
||||||
|
import { useRecoilState, useRecoilValue } from 'recoil';
|
||||||
|
|
||||||
import { BoardCardContext } from '@/pipeline-progress/states/BoardCardContext';
|
import { BoardCardContext } from '@/pipeline-progress/states/BoardCardContext';
|
||||||
import { RecoilScope } from '@/recoil-scope/components/RecoilScope';
|
import { RecoilScope } from '@/recoil-scope/components/RecoilScope';
|
||||||
import { useRecoilScopedState } from '@/recoil-scope/hooks/useRecoilScopedState';
|
import { useRecoilScopedState } from '@/recoil-scope/hooks/useRecoilScopedState';
|
||||||
import { BoardPipelineStageColumn } from '@/ui/board/components/Board';
|
import { BoardPipelineStageColumn } from '@/ui/board/components/Board';
|
||||||
import { BoardColumn } from '@/ui/board/components/BoardColumn';
|
import { BoardColumn } from '@/ui/board/components/BoardColumn';
|
||||||
|
import { useUpdatePipelineStageMutation } from '~/generated/graphql';
|
||||||
|
|
||||||
import { BoardColumnContext } from '../states/BoardColumnContext';
|
import { BoardColumnContext } from '../states/BoardColumnContext';
|
||||||
|
import { boardColumnTotalsFamilySelector } from '../states/boardColumnTotalsFamilySelector';
|
||||||
|
import { boardState } from '../states/boardState';
|
||||||
import { pipelineStageIdScopedState } from '../states/pipelineStageIdScopedState';
|
import { pipelineStageIdScopedState } from '../states/pipelineStageIdScopedState';
|
||||||
import { BoardOptions } from '../types/BoardOptions';
|
import { BoardOptions } from '../types/BoardOptions';
|
||||||
|
|
||||||
@ -47,10 +51,14 @@ export function EntityBoardColumn({
|
|||||||
column: BoardPipelineStageColumn;
|
column: BoardPipelineStageColumn;
|
||||||
boardOptions: BoardOptions;
|
boardOptions: BoardOptions;
|
||||||
}) {
|
}) {
|
||||||
|
const [board, setBoard] = useRecoilState(boardState);
|
||||||
const [pipelineStageId, setPipelineStageId] = useRecoilScopedState(
|
const [pipelineStageId, setPipelineStageId] = useRecoilScopedState(
|
||||||
pipelineStageIdScopedState,
|
pipelineStageIdScopedState,
|
||||||
BoardColumnContext,
|
BoardColumnContext,
|
||||||
);
|
);
|
||||||
|
const boardColumnTotal = useRecoilValue(
|
||||||
|
boardColumnTotalsFamilySelector(column.pipelineStageId),
|
||||||
|
);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (pipelineStageId !== column.pipelineStageId) {
|
if (pipelineStageId !== column.pipelineStageId) {
|
||||||
@ -58,10 +66,37 @@ export function EntityBoardColumn({
|
|||||||
}
|
}
|
||||||
}, [column, setPipelineStageId, pipelineStageId]);
|
}, [column, setPipelineStageId, pipelineStageId]);
|
||||||
|
|
||||||
|
const [updatePipelineStage] = useUpdatePipelineStageMutation();
|
||||||
|
function handleEditColumnTitle(value: string) {
|
||||||
|
updatePipelineStage({
|
||||||
|
variables: {
|
||||||
|
id: pipelineStageId,
|
||||||
|
name: value,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
setBoard([
|
||||||
|
...(board || []).map((pipelineStage) => {
|
||||||
|
if (pipelineStage.pipelineStageId === pipelineStageId) {
|
||||||
|
return {
|
||||||
|
...pipelineStage,
|
||||||
|
name: value,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
return pipelineStage;
|
||||||
|
}),
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Droppable droppableId={column.pipelineStageId}>
|
<Droppable droppableId={column.pipelineStageId}>
|
||||||
{(droppableProvided) => (
|
{(droppableProvided) => (
|
||||||
<BoardColumn title={`${column.title} `} colorCode={column.colorCode}>
|
<BoardColumn
|
||||||
|
onTitleEdit={handleEditColumnTitle}
|
||||||
|
title={column.title}
|
||||||
|
colorCode={column.colorCode}
|
||||||
|
pipelineStageId={column.pipelineStageId}
|
||||||
|
totalAmount={boardColumnTotal}
|
||||||
|
>
|
||||||
<BoardColumnCardsContainer droppableProvided={droppableProvided}>
|
<BoardColumnCardsContainer droppableProvided={droppableProvided}>
|
||||||
{column.pipelineProgressIds.map((pipelineProgressId, index) => (
|
{column.pipelineProgressIds.map((pipelineProgressId, index) => (
|
||||||
<RecoilScope
|
<RecoilScope
|
||||||
|
|||||||
@ -1 +1,2 @@
|
|||||||
|
export * from './select';
|
||||||
export * from './update';
|
export * from './update';
|
||||||
|
|||||||
@ -0,0 +1,31 @@
|
|||||||
|
import { selectorFamily } from 'recoil';
|
||||||
|
|
||||||
|
import { companyProgressesFamilyState } from '@/companies/states/companyProgressesFamilyState';
|
||||||
|
import { BoardPipelineStageColumn } from '@/ui/board/components/Board';
|
||||||
|
|
||||||
|
import { boardState } from './boardState';
|
||||||
|
|
||||||
|
export const boardColumnTotalsFamilySelector = selectorFamily({
|
||||||
|
key: 'BoardColumnTotalsFamily',
|
||||||
|
get:
|
||||||
|
(pipelineStageId: string) =>
|
||||||
|
({ get }) => {
|
||||||
|
const board = get(boardState);
|
||||||
|
const pipelineStage = board?.find(
|
||||||
|
(pipelineStage: BoardPipelineStageColumn) =>
|
||||||
|
pipelineStage.pipelineStageId === pipelineStageId,
|
||||||
|
);
|
||||||
|
|
||||||
|
const pipelineProgresses = pipelineStage?.pipelineProgressIds.map(
|
||||||
|
(pipelineProgressId: string) =>
|
||||||
|
get(companyProgressesFamilyState(pipelineProgressId)),
|
||||||
|
);
|
||||||
|
const pipelineStageTotal: number =
|
||||||
|
pipelineProgresses?.reduce(
|
||||||
|
(acc: number, curr: any) => acc + curr?.pipelineProgress.amount,
|
||||||
|
0,
|
||||||
|
) || 0;
|
||||||
|
|
||||||
|
return pipelineStageTotal;
|
||||||
|
},
|
||||||
|
});
|
||||||
1
front/src/modules/pipeline-stages/services/index.ts
Normal file
1
front/src/modules/pipeline-stages/services/index.ts
Normal file
@ -0,0 +1 @@
|
|||||||
|
export * from './update';
|
||||||
10
front/src/modules/pipeline-stages/services/update.ts
Normal file
10
front/src/modules/pipeline-stages/services/update.ts
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
import { gql } from '@apollo/client';
|
||||||
|
|
||||||
|
export const UPDATE_PIPELINE_STAGE = gql`
|
||||||
|
mutation UpdatePipelineStage($id: String, $name: String) {
|
||||||
|
updateOnePipelineStage(where: { id: $id }, data: { name: { set: $name } }) {
|
||||||
|
id
|
||||||
|
name
|
||||||
|
}
|
||||||
|
}
|
||||||
|
`;
|
||||||
@ -1,33 +0,0 @@
|
|||||||
import * as React from 'react';
|
|
||||||
import styled from '@emotion/styled';
|
|
||||||
|
|
||||||
import { Pipeline } from '~/generated/graphql';
|
|
||||||
|
|
||||||
type OwnProps = {
|
|
||||||
opportunity: Pipeline;
|
|
||||||
};
|
|
||||||
|
|
||||||
const StyledContainer = styled.span`
|
|
||||||
align-items: center;
|
|
||||||
background-color: ${({ theme }) => theme.background.tertiary};
|
|
||||||
border-radius: ${({ theme }) => theme.spacing(1)};
|
|
||||||
color: ${({ theme }) => theme.font.color.primary};
|
|
||||||
display: inline-flex;
|
|
||||||
gap: ${({ theme }) => theme.spacing(1)};
|
|
||||||
padding: ${({ theme }) => theme.spacing(1)};
|
|
||||||
|
|
||||||
:hover {
|
|
||||||
filter: brightness(95%);
|
|
||||||
}
|
|
||||||
`;
|
|
||||||
|
|
||||||
function PipelineChip({ opportunity }: OwnProps) {
|
|
||||||
return (
|
|
||||||
<StyledContainer data-testid="company-chip" key={opportunity.id}>
|
|
||||||
{opportunity.icon && <span>{opportunity.icon}</span>}
|
|
||||||
<span>{opportunity.name}</span>
|
|
||||||
</StyledContainer>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
export default PipelineChip;
|
|
||||||
@ -12,6 +12,7 @@ export const StyledBoard = styled.div`
|
|||||||
export type BoardPipelineStageColumn = {
|
export type BoardPipelineStageColumn = {
|
||||||
pipelineStageId: string;
|
pipelineStageId: string;
|
||||||
title: string;
|
title: string;
|
||||||
|
index: number;
|
||||||
colorCode?: string;
|
colorCode?: string;
|
||||||
pipelineProgressIds: string[];
|
pipelineProgressIds: string[];
|
||||||
};
|
};
|
||||||
|
|||||||
@ -1,6 +1,10 @@
|
|||||||
import React from 'react';
|
import React, { ChangeEvent } from 'react';
|
||||||
import styled from '@emotion/styled';
|
import styled from '@emotion/styled';
|
||||||
|
|
||||||
|
import { debounce } from '@/utils/debounce';
|
||||||
|
|
||||||
|
import { EditColumnTitleInput } from './EditColumnTitleInput';
|
||||||
|
|
||||||
export const StyledColumn = styled.div`
|
export const StyledColumn = styled.div`
|
||||||
background-color: ${({ theme }) => theme.background.primary};
|
background-color: ${({ theme }) => theme.background.primary};
|
||||||
display: flex;
|
display: flex;
|
||||||
@ -26,21 +30,53 @@ export const StyledColumnTitle = styled.h3`
|
|||||||
margin-bottom: ${({ theme }) => theme.spacing(2)};
|
margin-bottom: ${({ theme }) => theme.spacing(2)};
|
||||||
`;
|
`;
|
||||||
|
|
||||||
export const StyledAmount = styled.div`
|
const StyledAmount = styled.div`
|
||||||
color: ${({ theme }) => theme.font.color.light};
|
color: ${({ theme }) => theme.font.color.light};
|
||||||
`;
|
`;
|
||||||
|
|
||||||
type OwnProps = {
|
type OwnProps = {
|
||||||
colorCode?: string;
|
colorCode?: string;
|
||||||
title: string;
|
title: string;
|
||||||
|
pipelineStageId?: string;
|
||||||
|
onTitleEdit: (title: string) => void;
|
||||||
|
totalAmount?: number;
|
||||||
children: React.ReactNode;
|
children: React.ReactNode;
|
||||||
};
|
};
|
||||||
|
|
||||||
export function BoardColumn({ colorCode, title, children }: OwnProps) {
|
export function BoardColumn({
|
||||||
|
colorCode,
|
||||||
|
title,
|
||||||
|
onTitleEdit,
|
||||||
|
totalAmount,
|
||||||
|
children,
|
||||||
|
}: OwnProps) {
|
||||||
|
const [isEditing, setIsEditing] = React.useState(false);
|
||||||
|
const [internalValue, setInternalValue] = React.useState(title);
|
||||||
|
|
||||||
|
function toggleEditMode() {
|
||||||
|
setIsEditing(!isEditing);
|
||||||
|
}
|
||||||
|
|
||||||
|
const debouncedOnUpdate = debounce(onTitleEdit, 200);
|
||||||
|
const handleChange = (event: ChangeEvent<HTMLInputElement>) => {
|
||||||
|
setInternalValue(event.target.value);
|
||||||
|
debouncedOnUpdate(event.target.value);
|
||||||
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<StyledColumn>
|
<StyledColumn>
|
||||||
<StyledHeader>
|
<StyledHeader onClick={toggleEditMode}>
|
||||||
<StyledColumnTitle color={colorCode}>• {title}</StyledColumnTitle>
|
{isEditing ? (
|
||||||
|
<EditColumnTitleInput
|
||||||
|
color={colorCode}
|
||||||
|
toggleEditMode={toggleEditMode}
|
||||||
|
value={internalValue}
|
||||||
|
onChange={handleChange}
|
||||||
|
/>
|
||||||
|
) : (
|
||||||
|
<StyledColumnTitle color={colorCode}>• {title}</StyledColumnTitle>
|
||||||
|
)}
|
||||||
|
{!!totalAmount && <StyledAmount>${totalAmount}</StyledAmount>}
|
||||||
</StyledHeader>
|
</StyledHeader>
|
||||||
{children}
|
{children}
|
||||||
</StyledColumn>
|
</StyledColumn>
|
||||||
|
|||||||
@ -0,0 +1,3 @@
|
|||||||
|
export enum ColumnHotkeyScope {
|
||||||
|
EditColumnName = 'EditColumnNameHotkeyScope',
|
||||||
|
}
|
||||||
@ -0,0 +1,53 @@
|
|||||||
|
import styled from '@emotion/styled';
|
||||||
|
|
||||||
|
import { useScopedHotkeys } from '@/lib/hotkeys/hooks/useScopedHotkeys';
|
||||||
|
import { useSetHotkeyScope } from '@/lib/hotkeys/hooks/useSetHotkeyScope';
|
||||||
|
|
||||||
|
import { ColumnHotkeyScope } from './ColumnHotkeyScope';
|
||||||
|
|
||||||
|
const StyledEditTitleInput = styled.input`
|
||||||
|
background-color: transparent;
|
||||||
|
border: none;
|
||||||
|
&::placeholder,
|
||||||
|
&::-webkit-input-placeholder {
|
||||||
|
color: ${({ theme }) => theme.font.color.light};
|
||||||
|
font-family: ${({ theme }) => theme.font.family};
|
||||||
|
font-weight: ${({ theme }) => theme.font.weight.medium};
|
||||||
|
}
|
||||||
|
color: ${({ color }) => color};
|
||||||
|
&:focus {
|
||||||
|
color: ${({ color }) => color};
|
||||||
|
font-weight: ${({ theme }) => theme.font.weight.medium};
|
||||||
|
line-height: ${({ theme }) => theme.text.lineHeight};
|
||||||
|
}
|
||||||
|
margin: 0;
|
||||||
|
margin-bottom: ${({ theme }) => theme.spacing(2)};
|
||||||
|
outline: none;
|
||||||
|
`;
|
||||||
|
|
||||||
|
export function EditColumnTitleInput({
|
||||||
|
color,
|
||||||
|
value,
|
||||||
|
onChange,
|
||||||
|
toggleEditMode,
|
||||||
|
}: {
|
||||||
|
color?: string;
|
||||||
|
value: string;
|
||||||
|
onChange: (event: React.ChangeEvent<HTMLInputElement>) => void;
|
||||||
|
toggleEditMode: () => void;
|
||||||
|
}) {
|
||||||
|
const setHotkeyScope = useSetHotkeyScope();
|
||||||
|
setHotkeyScope(ColumnHotkeyScope.EditColumnName, { goto: false });
|
||||||
|
|
||||||
|
useScopedHotkeys('enter', toggleEditMode, ColumnHotkeyScope.EditColumnName);
|
||||||
|
useScopedHotkeys('esc', toggleEditMode, ColumnHotkeyScope.EditColumnName);
|
||||||
|
return (
|
||||||
|
<StyledEditTitleInput
|
||||||
|
placeholder={'Enter column name'}
|
||||||
|
color={color}
|
||||||
|
autoFocus
|
||||||
|
value={value}
|
||||||
|
onChange={onChange}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
}
|
||||||
@ -3,7 +3,7 @@ import { useTheme } from '@emotion/react';
|
|||||||
import styled from '@emotion/styled';
|
import styled from '@emotion/styled';
|
||||||
import { v4 as uuidv4 } from 'uuid';
|
import { v4 as uuidv4 } from 'uuid';
|
||||||
|
|
||||||
import { GET_COMPANIES } from '@/companies/services';
|
import { GET_COMPANIES } from '@/companies/queries';
|
||||||
import { RecoilScope } from '@/recoil-scope/components/RecoilScope';
|
import { RecoilScope } from '@/recoil-scope/components/RecoilScope';
|
||||||
import { EntityTableActionBar } from '@/ui/components/table/action-bar/EntityTableActionBar';
|
import { EntityTableActionBar } from '@/ui/components/table/action-bar/EntityTableActionBar';
|
||||||
import { IconBuildingSkyscraper } from '@/ui/icons/index';
|
import { IconBuildingSkyscraper } from '@/ui/icons/index';
|
||||||
|
|||||||
@ -7,7 +7,7 @@ import { CompanyAddressEditableField } from '@/companies/fields/components/Compa
|
|||||||
import { CompanyCreatedAtEditableField } from '@/companies/fields/components/CompanyCreatedAtEditableField';
|
import { CompanyCreatedAtEditableField } from '@/companies/fields/components/CompanyCreatedAtEditableField';
|
||||||
import { CompanyDomainNameEditableField } from '@/companies/fields/components/CompanyDomainNameEditableField';
|
import { CompanyDomainNameEditableField } from '@/companies/fields/components/CompanyDomainNameEditableField';
|
||||||
import { CompanyEmployeesEditableField } from '@/companies/fields/components/CompanyEmployeesEditableField';
|
import { CompanyEmployeesEditableField } from '@/companies/fields/components/CompanyEmployeesEditableField';
|
||||||
import { useCompanyQuery } from '@/companies/services';
|
import { useCompanyQuery } from '@/companies/queries';
|
||||||
import { PropertyBox } from '@/ui/components/property-box/PropertyBox';
|
import { PropertyBox } from '@/ui/components/property-box/PropertyBox';
|
||||||
import { IconBuildingSkyscraper } from '@/ui/icons/index';
|
import { IconBuildingSkyscraper } from '@/ui/icons/index';
|
||||||
import { WithTopBarContainer } from '@/ui/layout/containers/WithTopBarContainer';
|
import { WithTopBarContainer } from '@/ui/layout/containers/WithTopBarContainer';
|
||||||
|
|||||||
@ -1,10 +1,7 @@
|
|||||||
import { useCallback, useMemo, useState } from 'react';
|
import { useCallback, useMemo, useState } from 'react';
|
||||||
import { IconList } from '@tabler/icons-react';
|
import { IconList } from '@tabler/icons-react';
|
||||||
|
|
||||||
import {
|
import { CompaniesSelectedSortType, defaultOrderBy } from '@/companies/queries';
|
||||||
CompaniesSelectedSortType,
|
|
||||||
defaultOrderBy,
|
|
||||||
} from '@/companies/services';
|
|
||||||
import { companyColumns } from '@/companies/table/components/companyColumns';
|
import { companyColumns } from '@/companies/table/components/companyColumns';
|
||||||
import { CompanyEntityTableData } from '@/companies/table/components/CompanyEntityTableData';
|
import { CompanyEntityTableData } from '@/companies/table/components/CompanyEntityTableData';
|
||||||
import { reduceSortsToOrderBy } from '@/lib/filters-and-sorts/helpers';
|
import { reduceSortsToOrderBy } from '@/lib/filters-and-sorts/helpers';
|
||||||
|
|||||||
@ -8,7 +8,7 @@ import {
|
|||||||
GET_COMMENT_THREADS_BY_TARGETS,
|
GET_COMMENT_THREADS_BY_TARGETS,
|
||||||
} from '@/comments/services';
|
} from '@/comments/services';
|
||||||
import { CREATE_COMMENT_THREAD_WITH_COMMENT } from '@/comments/services/create';
|
import { CREATE_COMMENT_THREAD_WITH_COMMENT } from '@/comments/services/create';
|
||||||
import { GET_COMPANY } from '@/companies/services';
|
import { GET_COMPANY } from '@/companies/queries';
|
||||||
import { graphqlMocks } from '~/testing/graphqlMocks';
|
import { graphqlMocks } from '~/testing/graphqlMocks';
|
||||||
import { mockedCommentThreads } from '~/testing/mock-data/comment-threads';
|
import { mockedCommentThreads } from '~/testing/mock-data/comment-threads';
|
||||||
import { mockedCompaniesData } from '~/testing/mock-data/companies';
|
import { mockedCompaniesData } from '~/testing/mock-data/companies';
|
||||||
|
|||||||
@ -1,7 +1,7 @@
|
|||||||
import { getOperationName } from '@apollo/client/utilities';
|
import { getOperationName } from '@apollo/client/utilities';
|
||||||
import { useRecoilValue } from 'recoil';
|
import { useRecoilValue } from 'recoil';
|
||||||
|
|
||||||
import { GET_COMPANIES } from '@/companies/services';
|
import { GET_COMPANIES } from '@/companies/queries';
|
||||||
import { EntityTableActionBarButton } from '@/ui/components/table/action-bar/EntityTableActionBarButton';
|
import { EntityTableActionBarButton } from '@/ui/components/table/action-bar/EntityTableActionBarButton';
|
||||||
import { IconTrash } from '@/ui/icons/index';
|
import { IconTrash } from '@/ui/icons/index';
|
||||||
import { useResetTableRowSelection } from '@/ui/tables/hooks/useResetTableRowSelection';
|
import { useResetTableRowSelection } from '@/ui/tables/hooks/useResetTableRowSelection';
|
||||||
|
|||||||
@ -1,11 +1,15 @@
|
|||||||
import { useEffect } from 'react';
|
import { useEffect } from 'react';
|
||||||
import { useRecoilCallback, useRecoilState } from 'recoil';
|
import { useRecoilCallback, useRecoilState } from 'recoil';
|
||||||
|
|
||||||
|
import { companyProgressesFamilyState } from '@/companies/states/companyProgressesFamilyState';
|
||||||
import {
|
import {
|
||||||
CompanyForBoard,
|
CompanyForBoard,
|
||||||
CompanyProgress,
|
CompanyProgress,
|
||||||
PipelineProgressForBoard,
|
PipelineProgressForBoard,
|
||||||
} from '@/companies/types/CompanyProgress';
|
} from '@/companies/types/CompanyProgress';
|
||||||
|
import { boardState } from '@/pipeline-progress/states/boardState';
|
||||||
|
import { currentPipelineState } from '@/pipeline-progress/states/currentPipelineState';
|
||||||
|
import { isBoardLoadedState } from '@/pipeline-progress/states/isBoardLoadedState';
|
||||||
import { BoardPipelineStageColumn } from '@/ui/board/components/Board';
|
import { BoardPipelineStageColumn } from '@/ui/board/components/Board';
|
||||||
import {
|
import {
|
||||||
Pipeline,
|
Pipeline,
|
||||||
@ -15,11 +19,6 @@ import {
|
|||||||
useGetPipelinesQuery,
|
useGetPipelinesQuery,
|
||||||
} from '~/generated/graphql';
|
} from '~/generated/graphql';
|
||||||
|
|
||||||
import { boardState } from '../../modules/pipeline-progress/states/boardState';
|
|
||||||
|
|
||||||
import { companyProgressesFamilyState } from './companyProgressesFamilyState';
|
|
||||||
import { currentPipelineState } from './currentPipelineState';
|
|
||||||
import { isBoardLoadedState } from './isBoardLoadedState';
|
|
||||||
export function HookCompanyBoard() {
|
export function HookCompanyBoard() {
|
||||||
const [currentPipeline, setCurrentPipeline] =
|
const [currentPipeline, setCurrentPipeline] =
|
||||||
useRecoilState(currentPipelineState);
|
useRecoilState(currentPipelineState);
|
||||||
@ -44,6 +43,7 @@ export function HookCompanyBoard() {
|
|||||||
pipelineStageId: pipelineStage.id,
|
pipelineStageId: pipelineStage.id,
|
||||||
title: pipelineStage.name,
|
title: pipelineStage.name,
|
||||||
colorCode: pipelineStage.color,
|
colorCode: pipelineStage.color,
|
||||||
|
index: pipelineStage.index || 0,
|
||||||
pipelineProgressIds:
|
pipelineProgressIds:
|
||||||
pipelineStage.pipelineProgresses?.map(
|
pipelineStage.pipelineProgresses?.map(
|
||||||
(item) => item.id as string,
|
(item) => item.id as string,
|
||||||
|
|||||||
@ -1,8 +0,0 @@
|
|||||||
import { atom } from 'recoil';
|
|
||||||
|
|
||||||
import { Pipeline } from '~/generated/graphql';
|
|
||||||
|
|
||||||
export const currentPipelineState = atom<Pipeline | undefined>({
|
|
||||||
key: 'currentPipelineState',
|
|
||||||
default: undefined,
|
|
||||||
});
|
|
||||||
@ -1,6 +0,0 @@
|
|||||||
import { atom } from 'recoil';
|
|
||||||
|
|
||||||
export const isBoardLoadedState = atom<boolean>({
|
|
||||||
key: 'isBoardLoadedState',
|
|
||||||
default: false,
|
|
||||||
});
|
|
||||||
@ -1,7 +1,7 @@
|
|||||||
import { useCallback, useMemo, useState } from 'react';
|
import { useCallback, useMemo, useState } from 'react';
|
||||||
import { IconList } from '@tabler/icons-react';
|
import { IconList } from '@tabler/icons-react';
|
||||||
|
|
||||||
import { defaultOrderBy } from '@/companies/services';
|
import { defaultOrderBy } from '@/companies/queries';
|
||||||
import { reduceSortsToOrderBy } from '@/lib/filters-and-sorts/helpers';
|
import { reduceSortsToOrderBy } from '@/lib/filters-and-sorts/helpers';
|
||||||
import { filtersScopedState } from '@/lib/filters-and-sorts/states/filtersScopedState';
|
import { filtersScopedState } from '@/lib/filters-and-sorts/states/filtersScopedState';
|
||||||
import { turnFilterIntoWhereClause } from '@/lib/filters-and-sorts/utils/turnFilterIntoWhereClause';
|
import { turnFilterIntoWhereClause } from '@/lib/filters-and-sorts/utils/turnFilterIntoWhereClause';
|
||||||
|
|||||||
@ -3,12 +3,12 @@ import { graphql } from 'msw';
|
|||||||
|
|
||||||
import { CREATE_EVENT } from '@/analytics/services';
|
import { CREATE_EVENT } from '@/analytics/services';
|
||||||
import { GET_CLIENT_CONFIG } from '@/client-config/queries';
|
import { GET_CLIENT_CONFIG } from '@/client-config/queries';
|
||||||
import { GET_COMPANIES } from '@/companies/services';
|
import { GET_COMPANIES } from '@/companies/queries';
|
||||||
import { GET_PEOPLE, UPDATE_PERSON } from '@/people/services';
|
import { GET_PEOPLE, UPDATE_PERSON } from '@/people/services';
|
||||||
import {
|
import {
|
||||||
GET_PIPELINE_PROGRESS,
|
GET_PIPELINE_PROGRESS,
|
||||||
GET_PIPELINES,
|
GET_PIPELINES,
|
||||||
} from '@/pipeline-progress/queries';
|
} from '@/pipeline-progress/services';
|
||||||
import {
|
import {
|
||||||
SEARCH_COMPANY_QUERY,
|
SEARCH_COMPANY_QUERY,
|
||||||
SEARCH_USER_QUERY,
|
SEARCH_USER_QUERY,
|
||||||
|
|||||||
@ -1,4 +1,4 @@
|
|||||||
import { Resolver, Args, Query } from '@nestjs/graphql';
|
import { Resolver, Args, Query, Mutation } from '@nestjs/graphql';
|
||||||
import { UseGuards } from '@nestjs/common';
|
import { UseGuards } from '@nestjs/common';
|
||||||
import { accessibleBy } from '@casl/prisma';
|
import { accessibleBy } from '@casl/prisma';
|
||||||
import { JwtAuthGuard } from 'src/guards/jwt.auth.guard';
|
import { JwtAuthGuard } from 'src/guards/jwt.auth.guard';
|
||||||
@ -7,13 +7,18 @@ import { FindManyPipelineStageArgs } from '../../../core/@generated/pipeline-sta
|
|||||||
import { PipelineStageService } from '../services/pipeline-stage.service';
|
import { PipelineStageService } from '../services/pipeline-stage.service';
|
||||||
import { AbilityGuard } from 'src/guards/ability.guard';
|
import { AbilityGuard } from 'src/guards/ability.guard';
|
||||||
import { CheckAbilities } from 'src/decorators/check-abilities.decorator';
|
import { CheckAbilities } from 'src/decorators/check-abilities.decorator';
|
||||||
import { ReadPipelineStageAbilityHandler } from 'src/ability/handlers/pipeline-stage.ability-handler';
|
import {
|
||||||
|
ReadPipelineStageAbilityHandler,
|
||||||
|
UpdatePipelineStageAbilityHandler,
|
||||||
|
} from 'src/ability/handlers/pipeline-stage.ability-handler';
|
||||||
import { UserAbility } from 'src/decorators/user-ability.decorator';
|
import { UserAbility } from 'src/decorators/user-ability.decorator';
|
||||||
import { AppAbility } from 'src/ability/ability.factory';
|
import { AppAbility } from 'src/ability/ability.factory';
|
||||||
import {
|
import {
|
||||||
PrismaSelector,
|
PrismaSelector,
|
||||||
PrismaSelect,
|
PrismaSelect,
|
||||||
} from 'src/decorators/prisma-select.decorator';
|
} from 'src/decorators/prisma-select.decorator';
|
||||||
|
import { UpdateOnePipelineStageArgs } from 'src/core/@generated/pipeline-stage/update-one-pipeline-stage.args';
|
||||||
|
import { Prisma } from '@prisma/client';
|
||||||
|
|
||||||
@UseGuards(JwtAuthGuard)
|
@UseGuards(JwtAuthGuard)
|
||||||
@Resolver(() => PipelineStage)
|
@Resolver(() => PipelineStage)
|
||||||
@ -43,4 +48,21 @@ export class PipelineStageResolver {
|
|||||||
select: prismaSelect.value,
|
select: prismaSelect.value,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Mutation(() => PipelineStage, {
|
||||||
|
nullable: true,
|
||||||
|
})
|
||||||
|
@UseGuards(AbilityGuard)
|
||||||
|
@CheckAbilities(UpdatePipelineStageAbilityHandler)
|
||||||
|
async updateOnePipelineStage(
|
||||||
|
@Args() args: UpdateOnePipelineStageArgs,
|
||||||
|
@PrismaSelector({ modelName: 'PipelineProgress' })
|
||||||
|
prismaSelect: PrismaSelect<'PipelineProgress'>,
|
||||||
|
): Promise<Partial<PipelineStage> | null> {
|
||||||
|
return this.pipelineStageService.update({
|
||||||
|
where: args.where,
|
||||||
|
data: args.data,
|
||||||
|
select: prismaSelect.value,
|
||||||
|
} as Prisma.PipelineProgressUpdateArgs);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user