mirror of
https://github.com/twentyhq/twenty.git
synced 2024-12-29 15:25:45 +03:00
282 on opportunities page data pipeline + companies + people is fetched from be (#285)
* feature: get pipelines columns from backend * feature: display item not found instead of crashing * feature: add BoardCard component * feature: display items from the backend * refactor: extract useBoard in a hook * refactor: export only loading and error from useBoard * refactor: create var pipelineStage * feature: implement support for Company boards
This commit is contained in:
parent
eb8fc50ff1
commit
bf6fb0ba70
@ -1159,6 +1159,11 @@ export type DeleteCompaniesMutationVariables = Exact<{
|
|||||||
|
|
||||||
export type DeleteCompaniesMutation = { __typename?: 'Mutation', deleteManyCompany: { __typename?: 'AffectedRows', count: number } };
|
export type DeleteCompaniesMutation = { __typename?: 'Mutation', deleteManyCompany: { __typename?: 'AffectedRows', count: number } };
|
||||||
|
|
||||||
|
export type GetPipelinesQueryVariables = Exact<{ [key: string]: never; }>;
|
||||||
|
|
||||||
|
|
||||||
|
export type GetPipelinesQuery = { __typename?: 'Query', findManyPipeline: Array<{ __typename?: 'Pipeline', id: string, name: string, pipelineStages?: Array<{ __typename?: 'PipelineStage', name: string, color: string, pipelineProgresses?: Array<{ __typename?: 'PipelineProgress', id: string, associableType: PipelineProgressableType, associableId: string }> | null }> | null }> };
|
||||||
|
|
||||||
export type GetPeopleQueryVariables = Exact<{
|
export type GetPeopleQueryVariables = Exact<{
|
||||||
orderBy?: InputMaybe<Array<PersonOrderByWithRelationInput> | PersonOrderByWithRelationInput>;
|
orderBy?: InputMaybe<Array<PersonOrderByWithRelationInput> | PersonOrderByWithRelationInput>;
|
||||||
where?: InputMaybe<PersonWhereInput>;
|
where?: InputMaybe<PersonWhereInput>;
|
||||||
@ -1623,6 +1628,50 @@ export function useDeleteCompaniesMutation(baseOptions?: Apollo.MutationHookOpti
|
|||||||
export type DeleteCompaniesMutationHookResult = ReturnType<typeof useDeleteCompaniesMutation>;
|
export type DeleteCompaniesMutationHookResult = ReturnType<typeof useDeleteCompaniesMutation>;
|
||||||
export type DeleteCompaniesMutationResult = Apollo.MutationResult<DeleteCompaniesMutation>;
|
export type DeleteCompaniesMutationResult = Apollo.MutationResult<DeleteCompaniesMutation>;
|
||||||
export type DeleteCompaniesMutationOptions = Apollo.BaseMutationOptions<DeleteCompaniesMutation, DeleteCompaniesMutationVariables>;
|
export type DeleteCompaniesMutationOptions = Apollo.BaseMutationOptions<DeleteCompaniesMutation, DeleteCompaniesMutationVariables>;
|
||||||
|
export const GetPipelinesDocument = gql`
|
||||||
|
query GetPipelines {
|
||||||
|
findManyPipeline(skip: 1) {
|
||||||
|
id
|
||||||
|
name
|
||||||
|
pipelineStages {
|
||||||
|
name
|
||||||
|
color
|
||||||
|
pipelineProgresses {
|
||||||
|
id
|
||||||
|
associableType
|
||||||
|
associableId
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
`;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* __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: {
|
||||||
|
* },
|
||||||
|
* });
|
||||||
|
*/
|
||||||
|
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 GetPeopleDocument = gql`
|
export const GetPeopleDocument = gql`
|
||||||
query GetPeople($orderBy: [PersonOrderByWithRelationInput!], $where: PersonWhereInput, $limit: Int) {
|
query GetPeople($orderBy: [PersonOrderByWithRelationInput!], $where: PersonWhereInput, $limit: Int) {
|
||||||
people: findManyPerson(orderBy: $orderBy, where: $where, take: $limit) {
|
people: findManyPerson(orderBy: $orderBy, where: $where, take: $limit) {
|
||||||
|
@ -22,6 +22,8 @@ import {
|
|||||||
import { BoardItem } from '../../ui/components/board/BoardItem';
|
import { BoardItem } from '../../ui/components/board/BoardItem';
|
||||||
import { NewButton } from '../../ui/components/board/BoardNewButton';
|
import { NewButton } from '../../ui/components/board/BoardNewButton';
|
||||||
|
|
||||||
|
import { BoardCard } from './BoardCard';
|
||||||
|
|
||||||
type BoardProps = {
|
type BoardProps = {
|
||||||
initialBoard: Column[];
|
initialBoard: Column[];
|
||||||
items: Items;
|
items: Items;
|
||||||
@ -41,8 +43,8 @@ export const Board = ({ initialBoard, items }: BoardProps) => {
|
|||||||
);
|
);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<DragDropContext onDragEnd={onDragEnd}>
|
<StyledBoard>
|
||||||
<StyledBoard>
|
<DragDropContext onDragEnd={onDragEnd}>
|
||||||
{board.map((column) => (
|
{board.map((column) => (
|
||||||
<Droppable key={column.id} droppableId={column.id}>
|
<Droppable key={column.id} droppableId={column.id}>
|
||||||
{(droppableProvided) => (
|
{(droppableProvided) => (
|
||||||
@ -59,7 +61,9 @@ export const Board = ({ initialBoard, items }: BoardProps) => {
|
|||||||
>
|
>
|
||||||
{(draggableProvided) => (
|
{(draggableProvided) => (
|
||||||
<BoardItem draggableProvided={draggableProvided}>
|
<BoardItem draggableProvided={draggableProvided}>
|
||||||
<p>{items[itemKey].content}</p>
|
<BoardCard>
|
||||||
|
{items[itemKey]?.id || 'Item not found'}
|
||||||
|
</BoardCard>
|
||||||
</BoardItem>
|
</BoardItem>
|
||||||
)}
|
)}
|
||||||
</Draggable>
|
</Draggable>
|
||||||
@ -70,7 +74,7 @@ export const Board = ({ initialBoard, items }: BoardProps) => {
|
|||||||
)}
|
)}
|
||||||
</Droppable>
|
</Droppable>
|
||||||
))}
|
))}
|
||||||
</StyledBoard>
|
</DragDropContext>
|
||||||
</DragDropContext>
|
</StyledBoard>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
5
front/src/modules/opportunities/components/BoardCard.tsx
Normal file
5
front/src/modules/opportunities/components/BoardCard.tsx
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
import styled from '@emotion/styled';
|
||||||
|
|
||||||
|
export const BoardCard = styled.p`
|
||||||
|
color: ${(props) => props.theme.text80};
|
||||||
|
`;
|
75
front/src/modules/opportunities/hooks/useBoard.ts
Normal file
75
front/src/modules/opportunities/hooks/useBoard.ts
Normal file
@ -0,0 +1,75 @@
|
|||||||
|
import {
|
||||||
|
GetCompaniesQuery,
|
||||||
|
GetPeopleQuery,
|
||||||
|
useGetCompaniesQuery,
|
||||||
|
useGetPeopleQuery,
|
||||||
|
useGetPipelinesQuery,
|
||||||
|
} from '../../../generated/graphql';
|
||||||
|
import { BoardItemKey, Column, Items } from '../../ui/components/board/Board';
|
||||||
|
|
||||||
|
type Entities = GetCompaniesQuery | GetPeopleQuery;
|
||||||
|
|
||||||
|
function isGetCompaniesQuery(
|
||||||
|
entities: Entities,
|
||||||
|
): entities is GetCompaniesQuery {
|
||||||
|
return (entities as GetCompaniesQuery).companies !== undefined;
|
||||||
|
}
|
||||||
|
|
||||||
|
function isGetPeopleQuery(entities: Entities): entities is GetPeopleQuery {
|
||||||
|
return (entities as GetPeopleQuery).people !== undefined;
|
||||||
|
}
|
||||||
|
|
||||||
|
export const useBoard = () => {
|
||||||
|
const pipelines = useGetPipelinesQuery();
|
||||||
|
const pipelineStages = pipelines.data?.findManyPipeline[0].pipelineStages;
|
||||||
|
const initialBoard: Column[] =
|
||||||
|
pipelineStages?.map((pipelineStage) => ({
|
||||||
|
id: pipelineStage.name,
|
||||||
|
title: pipelineStage.name,
|
||||||
|
colorCode: pipelineStage.color,
|
||||||
|
itemKeys:
|
||||||
|
pipelineStage.pipelineProgresses?.map(
|
||||||
|
(item) => `item-${item.associableId}` as BoardItemKey,
|
||||||
|
) || [],
|
||||||
|
})) || [];
|
||||||
|
|
||||||
|
const pipelineEntityIds = pipelineStages?.reduce(
|
||||||
|
(acc, pipelineStage) => [
|
||||||
|
...acc,
|
||||||
|
...(pipelineStage.pipelineProgresses?.map((item) => item.associableId) ||
|
||||||
|
[]),
|
||||||
|
],
|
||||||
|
[] as string[],
|
||||||
|
);
|
||||||
|
|
||||||
|
const pipelineEntityType: 'Person' | 'Company' | undefined =
|
||||||
|
pipelineStages?.[0].pipelineProgresses?.[0].associableType;
|
||||||
|
console.log(pipelineEntityType);
|
||||||
|
|
||||||
|
const query =
|
||||||
|
pipelineEntityType === 'Person' ? useGetPeopleQuery : useGetCompaniesQuery;
|
||||||
|
|
||||||
|
const entitiesQueryResult = query({
|
||||||
|
variables: { where: { id: { in: pipelineEntityIds } } },
|
||||||
|
});
|
||||||
|
|
||||||
|
const indexByIdReducer = (acc: Items, entity: { id: string }) => ({
|
||||||
|
...acc,
|
||||||
|
[`item-${entity.id}`]: entity,
|
||||||
|
});
|
||||||
|
|
||||||
|
const items: Items | undefined = entitiesQueryResult.data
|
||||||
|
? isGetCompaniesQuery(entitiesQueryResult.data)
|
||||||
|
? entitiesQueryResult.data.companies.reduce(indexByIdReducer, {} as Items)
|
||||||
|
: isGetPeopleQuery(entitiesQueryResult.data)
|
||||||
|
? entitiesQueryResult.data.people.reduce(indexByIdReducer, {} as Items)
|
||||||
|
: undefined
|
||||||
|
: undefined;
|
||||||
|
|
||||||
|
return {
|
||||||
|
initialBoard,
|
||||||
|
items,
|
||||||
|
loading: pipelines.loading || entitiesQueryResult.loading,
|
||||||
|
error: pipelines.error || entitiesQueryResult.error,
|
||||||
|
};
|
||||||
|
};
|
19
front/src/modules/opportunities/queries/index.ts
Normal file
19
front/src/modules/opportunities/queries/index.ts
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
import { gql } from '@apollo/client';
|
||||||
|
|
||||||
|
export const GET_PIPELINES = gql`
|
||||||
|
query GetPipelines {
|
||||||
|
findManyPipeline(skip: 1) {
|
||||||
|
id
|
||||||
|
name
|
||||||
|
pipelineStages {
|
||||||
|
name
|
||||||
|
color
|
||||||
|
pipelineProgresses {
|
||||||
|
id
|
||||||
|
associableType
|
||||||
|
associableId
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
`;
|
@ -7,10 +7,10 @@ export const StyledBoard = styled.div`
|
|||||||
height: 100%;
|
height: 100%;
|
||||||
`;
|
`;
|
||||||
|
|
||||||
export type BoardItemKey = `item-${number}`;
|
export type BoardItemKey = `item-${number | string}`;
|
||||||
export interface Item {
|
export interface Item {
|
||||||
id: string;
|
id: string;
|
||||||
content: string;
|
content?: string;
|
||||||
}
|
}
|
||||||
export interface Items {
|
export interface Items {
|
||||||
[key: string]: Item;
|
[key: string]: Item;
|
||||||
|
@ -2,13 +2,16 @@ import { IconTarget } from '@/ui/icons/index';
|
|||||||
import { WithTopBarContainer } from '@/ui/layout/containers/WithTopBarContainer';
|
import { WithTopBarContainer } from '@/ui/layout/containers/WithTopBarContainer';
|
||||||
import { AppPage } from '~/AppPage';
|
import { AppPage } from '~/AppPage';
|
||||||
|
|
||||||
import {
|
|
||||||
initialBoard,
|
|
||||||
items,
|
|
||||||
} from '../../modules/opportunities/components/__stories__/mock-data';
|
|
||||||
import { Board } from '../../modules/opportunities/components/Board';
|
import { Board } from '../../modules/opportunities/components/Board';
|
||||||
|
import { useBoard } from '../../modules/opportunities/hooks/useBoard';
|
||||||
|
|
||||||
export function Opportunities() {
|
export function Opportunities() {
|
||||||
|
const { initialBoard, items, loading, error } = useBoard();
|
||||||
|
|
||||||
|
if (loading) return <div>Loading...</div>;
|
||||||
|
if (error) return <div>Error...</div>;
|
||||||
|
if (!initialBoard || !items)
|
||||||
|
return <div>Initial board or items not found</div>;
|
||||||
return (
|
return (
|
||||||
<AppPage>
|
<AppPage>
|
||||||
<WithTopBarContainer title="Opportunities" icon={<IconTarget />}>
|
<WithTopBarContainer title="Opportunities" icon={<IconTarget />}>
|
||||||
|
Loading…
Reference in New Issue
Block a user