mirror of
https://github.com/twentyhq/twenty.git
synced 2025-01-04 18:21:59 +03:00
Fixed bug for refectch activities and create activity on the currently filtered user. (#1493)
* Fixed bug for refectch activities and create activity on the currently filtered user. * Refactor optimistif effect --------- Co-authored-by: Charles Bochet <charles@twenty.com>
This commit is contained in:
parent
08727aafe5
commit
9be069bedc
@ -3196,7 +3196,7 @@ export type GetFavoritesQueryVariables = Exact<{ [key: string]: never; }>;
|
||||
|
||||
export type GetFavoritesQuery = { __typename?: 'Query', findFavorites: Array<{ __typename?: 'Favorite', id: string, person?: { __typename?: 'Person', id: string, firstName?: string | null, lastName?: string | null, avatarUrl?: string | null } | null, company?: { __typename?: 'Company', id: string, name: string, domainName: string, accountOwner?: { __typename?: 'User', id: string, displayName: string, avatarUrl?: string | null } | null } | null }> };
|
||||
|
||||
export type InsertPersonFragmentFragment = { __typename?: 'Person', id: string, firstName?: string | null, lastName?: string | null, displayName: string, createdAt: string };
|
||||
export type PersonFieldsFragmentFragment = { __typename?: 'Person', id: string, phone?: string | null, email?: string | null, city?: string | null, firstName?: string | null, lastName?: string | null, displayName: string, jobTitle?: string | null, linkedinUrl?: string | null, xUrl?: string | null, avatarUrl?: string | null, createdAt: string, _activityCount: number, company?: { __typename?: 'Company', id: string, name: string, domainName: string } | null };
|
||||
|
||||
export type DeleteManyPersonMutationVariables = Exact<{
|
||||
ids?: InputMaybe<Array<Scalars['String']> | Scalars['String']>;
|
||||
@ -3217,7 +3217,7 @@ export type InsertOnePersonMutationVariables = Exact<{
|
||||
}>;
|
||||
|
||||
|
||||
export type InsertOnePersonMutation = { __typename?: 'Mutation', createOnePerson: { __typename?: 'Person', id: string, firstName?: string | null, lastName?: string | null, displayName: string, createdAt: string } };
|
||||
export type InsertOnePersonMutation = { __typename?: 'Mutation', createOnePerson: { __typename?: 'Person', id: string, phone?: string | null, email?: string | null, city?: string | null, firstName?: string | null, lastName?: string | null, displayName: string, jobTitle?: string | null, linkedinUrl?: string | null, xUrl?: string | null, avatarUrl?: string | null, createdAt: string, _activityCount: number, company?: { __typename?: 'Company', id: string, name: string, domainName: string } | null } };
|
||||
|
||||
export type RemovePersonPictureMutationVariables = Exact<{
|
||||
where: PersonWhereUniqueInput;
|
||||
@ -3707,7 +3707,7 @@ export const UserQueryFragmentFragmentDoc = gql`
|
||||
}
|
||||
`;
|
||||
export const CompanyFieldsFragmentFragmentDoc = gql`
|
||||
fragment CompanyFieldsFragment on Company {
|
||||
fragment companyFieldsFragment on Company {
|
||||
accountOwner {
|
||||
id
|
||||
email
|
||||
@ -3726,13 +3726,26 @@ export const CompanyFieldsFragmentFragmentDoc = gql`
|
||||
name
|
||||
}
|
||||
`;
|
||||
export const InsertPersonFragmentFragmentDoc = gql`
|
||||
fragment InsertPersonFragment on Person {
|
||||
export const PersonFieldsFragmentFragmentDoc = gql`
|
||||
fragment personFieldsFragment on Person {
|
||||
id
|
||||
phone
|
||||
email
|
||||
city
|
||||
firstName
|
||||
lastName
|
||||
displayName
|
||||
jobTitle
|
||||
linkedinUrl
|
||||
xUrl
|
||||
avatarUrl
|
||||
createdAt
|
||||
_activityCount
|
||||
company {
|
||||
id
|
||||
name
|
||||
domainName
|
||||
}
|
||||
}
|
||||
`;
|
||||
export const AddActivityTargetsOnActivityDocument = gql`
|
||||
@ -4535,7 +4548,7 @@ export type InsertManyCompanyMutationOptions = Apollo.BaseMutationOptions<Insert
|
||||
export const InsertOneCompanyDocument = gql`
|
||||
mutation InsertOneCompany($data: CompanyCreateInput!) {
|
||||
createOneCompany(data: $data) {
|
||||
...CompanyFieldsFragment
|
||||
...companyFieldsFragment
|
||||
}
|
||||
}
|
||||
${CompanyFieldsFragmentFragmentDoc}`;
|
||||
@ -4568,7 +4581,7 @@ export type InsertOneCompanyMutationOptions = Apollo.BaseMutationOptions<InsertO
|
||||
export const UpdateOneCompanyDocument = gql`
|
||||
mutation UpdateOneCompany($where: CompanyWhereUniqueInput!, $data: CompanyUpdateInput!) {
|
||||
updateOneCompany(data: $data, where: $where) {
|
||||
...CompanyFieldsFragment
|
||||
...companyFieldsFragment
|
||||
}
|
||||
}
|
||||
${CompanyFieldsFragmentFragmentDoc}`;
|
||||
@ -4942,10 +4955,10 @@ export type InsertManyPersonMutationOptions = Apollo.BaseMutationOptions<InsertM
|
||||
export const InsertOnePersonDocument = gql`
|
||||
mutation InsertOnePerson($data: PersonCreateInput!) {
|
||||
createOnePerson(data: $data) {
|
||||
...InsertPersonFragment
|
||||
...personFieldsFragment
|
||||
}
|
||||
}
|
||||
${InsertPersonFragmentFragmentDoc}`;
|
||||
${PersonFieldsFragmentFragmentDoc}`;
|
||||
export type InsertOnePersonMutationFn = Apollo.MutationFunction<InsertOnePersonMutation, InsertOnePersonMutationVariables>;
|
||||
|
||||
/**
|
||||
@ -5855,7 +5868,7 @@ export type SearchActivityQueryResult = Apollo.QueryResult<SearchActivityQuery,
|
||||
export const SearchCompanyDocument = gql`
|
||||
query SearchCompany($where: CompanyWhereInput, $limit: Int, $orderBy: [CompanyOrderByWithRelationInput!]) {
|
||||
searchResults: findManyCompany(where: $where, take: $limit, orderBy: $orderBy) {
|
||||
...CompanyFieldsFragment
|
||||
...companyFieldsFragment
|
||||
}
|
||||
}
|
||||
${CompanyFieldsFragmentFragmentDoc}`;
|
||||
|
@ -1,4 +1,5 @@
|
||||
import { useApolloClient } from '@apollo/client';
|
||||
import { getOperationName } from '@apollo/client/utilities';
|
||||
|
||||
import { useFilteredSearchEntityQuery } from '@/search/hooks/useFilteredSearchEntityQuery';
|
||||
import { SingleEntitySelect } from '@/ui/input/relation-picker/components/SingleEntitySelect';
|
||||
@ -14,6 +15,7 @@ import {
|
||||
} from '~/generated/graphql';
|
||||
|
||||
import { ACTIVITY_UPDATE_FRAGMENT } from '../graphql/fragments/activityUpdateFragment';
|
||||
import { GET_ACTIVITIES } from '../graphql/queries/getActivities';
|
||||
|
||||
export type OwnProps = {
|
||||
activity: Pick<Activity, 'id'> & {
|
||||
@ -86,6 +88,7 @@ export function ActivityAssigneePicker({
|
||||
},
|
||||
},
|
||||
},
|
||||
refetchQueries: [getOperationName(GET_ACTIVITIES) ?? ''],
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -119,6 +119,7 @@ export function ActivityEditor({
|
||||
title: newTitle,
|
||||
},
|
||||
},
|
||||
refetchQueries: [getOperationName(GET_ACTIVITIES) ?? ''],
|
||||
});
|
||||
},
|
||||
[activity.id, cachedActivity, updateActivityMutation],
|
||||
|
@ -30,10 +30,15 @@ export function useOpenCreateActivityDrawer() {
|
||||
);
|
||||
const [, setViewableActivityId] = useRecoilState(viewableActivityIdState);
|
||||
|
||||
return function openCreateActivityDrawer(
|
||||
type: ActivityType,
|
||||
entities?: ActivityTargetableEntity[],
|
||||
) {
|
||||
return function openCreateActivityDrawer({
|
||||
type,
|
||||
targetableEntities,
|
||||
assigneeId,
|
||||
}: {
|
||||
type: ActivityType;
|
||||
targetableEntities?: ActivityTargetableEntity[];
|
||||
assigneeId?: string;
|
||||
}) {
|
||||
const now = new Date().toISOString();
|
||||
|
||||
return createActivityMutation({
|
||||
@ -43,11 +48,13 @@ export function useOpenCreateActivityDrawer() {
|
||||
createdAt: now,
|
||||
updatedAt: now,
|
||||
author: { connect: { id: currentUser?.id ?? '' } },
|
||||
assignee: { connect: { id: currentUser?.id ?? '' } },
|
||||
assignee: { connect: { id: assigneeId ?? currentUser?.id ?? '' } },
|
||||
type: type,
|
||||
activityTargets: {
|
||||
createMany: {
|
||||
data: entities ? getRelationData(entities) : [],
|
||||
data: targetableEntities
|
||||
? getRelationData(targetableEntities)
|
||||
: [],
|
||||
skipDuplicates: true,
|
||||
},
|
||||
},
|
||||
@ -63,7 +70,7 @@ export function useOpenCreateActivityDrawer() {
|
||||
onCompleted(data) {
|
||||
setHotkeyScope(RightDrawerHotkeyScope.RightDrawer, { goto: false });
|
||||
setViewableActivityId(data.createOneActivity.id);
|
||||
setActivityTargetableEntityArray(entities ?? []);
|
||||
setActivityTargetableEntityArray(targetableEntities ?? []);
|
||||
openRightDrawer(RightDrawerPages.CreateActivity);
|
||||
},
|
||||
});
|
||||
|
@ -24,6 +24,9 @@ export function useOpenCreateActivityDrawerForSelectedRowIds() {
|
||||
type: entityType,
|
||||
id,
|
||||
}));
|
||||
openCreateActivityDrawer(type, activityTargetableEntityArray);
|
||||
openCreateActivityDrawer({
|
||||
type,
|
||||
targetableEntities: activityTargetableEntityArray,
|
||||
});
|
||||
};
|
||||
}
|
||||
|
@ -59,7 +59,12 @@ export function Notes({ entity }: { entity: ActivityTargetableEntity }) {
|
||||
Icon={IconNotes}
|
||||
title="New note"
|
||||
variant="secondary"
|
||||
onClick={() => openCreateActivity(ActivityType.Note, [entity])}
|
||||
onClick={() =>
|
||||
openCreateActivity({
|
||||
type: ActivityType.Note,
|
||||
targetableEntities: [entity],
|
||||
})
|
||||
}
|
||||
/>
|
||||
</StyledTaskGroupEmptyContainer>
|
||||
);
|
||||
@ -76,7 +81,12 @@ export function Notes({ entity }: { entity: ActivityTargetableEntity }) {
|
||||
size="small"
|
||||
variant="secondary"
|
||||
title="Add note"
|
||||
onClick={() => openCreateActivity(ActivityType.Note, [entity])}
|
||||
onClick={() =>
|
||||
openCreateActivity({
|
||||
type: ActivityType.Note,
|
||||
targetableEntities: [entity],
|
||||
})
|
||||
}
|
||||
></Button>
|
||||
}
|
||||
/>
|
||||
|
@ -5,13 +5,13 @@ import { IconPlus } from '@/ui/icon';
|
||||
import { ActivityType } from '~/generated/graphql';
|
||||
|
||||
export function AddTaskButton({
|
||||
entity,
|
||||
activityTargetEntity,
|
||||
}: {
|
||||
entity?: ActivityTargetableEntity;
|
||||
activityTargetEntity?: ActivityTargetableEntity;
|
||||
}) {
|
||||
const openCreateActivity = useOpenCreateActivityDrawer();
|
||||
|
||||
if (!entity) {
|
||||
if (!activityTargetEntity) {
|
||||
return <></>;
|
||||
}
|
||||
|
||||
@ -21,7 +21,12 @@ export function AddTaskButton({
|
||||
size="small"
|
||||
variant="secondary"
|
||||
title="Add task"
|
||||
onClick={() => openCreateActivity(ActivityType.Task, [entity])}
|
||||
onClick={() =>
|
||||
openCreateActivity({
|
||||
type: ActivityType.Task,
|
||||
targetableEntities: [activityTargetEntity],
|
||||
})
|
||||
}
|
||||
></Button>
|
||||
);
|
||||
}
|
||||
|
@ -0,0 +1,34 @@
|
||||
import { useOpenCreateActivityDrawer } from '@/activities/hooks/useOpenCreateActivityDrawer';
|
||||
import { TasksRecoilScopeContext } from '@/activities/states/recoil-scope-contexts/TasksRecoilScopeContext';
|
||||
import { DropdownRecoilScopeContext } from '@/ui/dropdown/states/recoil-scope-contexts/DropdownRecoilScopeContext';
|
||||
import { PageAddButton } from '@/ui/layout/components/PageAddButton';
|
||||
import { RecoilScope } from '@/ui/utilities/recoil-scope/components/RecoilScope';
|
||||
import { useRecoilScopedValue } from '@/ui/utilities/recoil-scope/hooks/useRecoilScopedValue';
|
||||
import { filtersScopedState } from '@/ui/view-bar/states/filtersScopedState';
|
||||
import { ActivityType } from '~/generated/graphql';
|
||||
|
||||
export function PageAddTaskButton() {
|
||||
const openCreateActivity = useOpenCreateActivityDrawer();
|
||||
|
||||
const filters = useRecoilScopedValue(
|
||||
filtersScopedState,
|
||||
TasksRecoilScopeContext,
|
||||
);
|
||||
|
||||
const assigneeIdFilter = filters.find(
|
||||
(filter) => filter.key === 'assigneeId',
|
||||
);
|
||||
|
||||
function handleClick() {
|
||||
openCreateActivity({
|
||||
type: ActivityType.Task,
|
||||
assigneeId: assigneeIdFilter?.value,
|
||||
});
|
||||
}
|
||||
|
||||
return (
|
||||
<RecoilScope SpecificContext={DropdownRecoilScopeContext}>
|
||||
<PageAddButton onClick={handleClick} />
|
||||
</RecoilScope>
|
||||
);
|
||||
}
|
@ -83,7 +83,10 @@ export function TaskGroups({ entity, showAddButton }: OwnProps) {
|
||||
title="New task"
|
||||
variant={'secondary'}
|
||||
onClick={() =>
|
||||
openCreateActivity(ActivityType.Task, entity ? [entity] : undefined)
|
||||
openCreateActivity({
|
||||
type: ActivityType.Task,
|
||||
targetableEntities: entity ? [entity] : undefined,
|
||||
})
|
||||
}
|
||||
/>
|
||||
</StyledTaskGroupEmptyContainer>
|
||||
@ -95,21 +98,27 @@ export function TaskGroups({ entity, showAddButton }: OwnProps) {
|
||||
{activeTabId === 'done' ? (
|
||||
<TaskList
|
||||
tasks={completedTasks ?? []}
|
||||
button={showAddButton && <AddTaskButton entity={entity} />}
|
||||
button={
|
||||
showAddButton && <AddTaskButton activityTargetEntity={entity} />
|
||||
}
|
||||
/>
|
||||
) : (
|
||||
<>
|
||||
<TaskList
|
||||
title="Today"
|
||||
tasks={todayOrPreviousTasks ?? []}
|
||||
button={showAddButton && <AddTaskButton entity={entity} />}
|
||||
button={
|
||||
showAddButton && <AddTaskButton activityTargetEntity={entity} />
|
||||
}
|
||||
/>
|
||||
<TaskList
|
||||
title="Upcoming"
|
||||
tasks={upcomingTasks ?? []}
|
||||
button={
|
||||
showAddButton &&
|
||||
!todayOrPreviousTasks?.length && <AddTaskButton entity={entity} />
|
||||
!todayOrPreviousTasks?.length && (
|
||||
<AddTaskButton activityTargetEntity={entity} />
|
||||
)
|
||||
}
|
||||
/>
|
||||
<TaskList
|
||||
@ -118,7 +127,9 @@ export function TaskGroups({ entity, showAddButton }: OwnProps) {
|
||||
button={
|
||||
showAddButton &&
|
||||
!todayOrPreviousTasks?.length &&
|
||||
!upcomingTasks?.length && <AddTaskButton entity={entity} />
|
||||
!upcomingTasks?.length && (
|
||||
<AddTaskButton activityTargetEntity={entity} />
|
||||
)
|
||||
}
|
||||
/>
|
||||
</>
|
||||
|
@ -77,8 +77,18 @@ export function Timeline({ entity }: { entity: ActivityTargetableEntity }) {
|
||||
<StyledEmptyTimelineTitle>No activity yet</StyledEmptyTimelineTitle>
|
||||
<StyledEmptyTimelineSubTitle>Create one:</StyledEmptyTimelineSubTitle>
|
||||
<ActivityCreateButton
|
||||
onNoteClick={() => openCreateActivity(ActivityType.Note, [entity])}
|
||||
onTaskClick={() => openCreateActivity(ActivityType.Task, [entity])}
|
||||
onNoteClick={() =>
|
||||
openCreateActivity({
|
||||
type: ActivityType.Note,
|
||||
targetableEntities: [entity],
|
||||
})
|
||||
}
|
||||
onTaskClick={() =>
|
||||
openCreateActivity({
|
||||
type: ActivityType.Task,
|
||||
targetableEntities: [entity],
|
||||
})
|
||||
}
|
||||
/>
|
||||
</StyledTimelineEmptyContainer>
|
||||
);
|
||||
|
@ -1,39 +1,111 @@
|
||||
import { useApolloClient } from '@apollo/client';
|
||||
import {
|
||||
ApolloCache,
|
||||
DocumentNode,
|
||||
OperationVariables,
|
||||
useApolloClient,
|
||||
} from '@apollo/client';
|
||||
import { useRecoilCallback } from 'recoil';
|
||||
|
||||
import { GET_COMPANIES } from '@/companies/graphql/queries/getCompanies';
|
||||
import { GET_PEOPLE } from '@/people/graphql/queries/getPeople';
|
||||
import { GetCompaniesQuery, GetPeopleQuery } from '~/generated/graphql';
|
||||
|
||||
import { optimisticEffectState } from '../states/optimisticEffectState';
|
||||
import { OptimisticEffect } from '../types/OptimisticEffect';
|
||||
import { OptimisticEffectDefinition } from '../types/OptimisticEffectDefinition';
|
||||
|
||||
export function useOptimisticEffect() {
|
||||
const apolloClient = useApolloClient();
|
||||
|
||||
const registerOptimisticEffect = useRecoilCallback(
|
||||
({ snapshot, set }) =>
|
||||
(optimisticEffect: OptimisticEffect<unknown, unknown>) => {
|
||||
const { key } = optimisticEffect;
|
||||
({
|
||||
variables,
|
||||
definition,
|
||||
}: {
|
||||
variables: OperationVariables;
|
||||
definition: OptimisticEffectDefinition<unknown>;
|
||||
}) => {
|
||||
const optimisticEffects = snapshot
|
||||
.getLoadable(optimisticEffectState)
|
||||
.getValue();
|
||||
|
||||
function optimisticEffectWriter({
|
||||
cache,
|
||||
newData,
|
||||
query,
|
||||
variables,
|
||||
}: {
|
||||
cache: ApolloCache<unknown>;
|
||||
newData: unknown[];
|
||||
variables: OperationVariables;
|
||||
query: DocumentNode;
|
||||
}) {
|
||||
const existingData = cache.readQuery({
|
||||
query,
|
||||
variables,
|
||||
});
|
||||
|
||||
if (!existingData) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (query === GET_PEOPLE) {
|
||||
cache.writeQuery({
|
||||
query,
|
||||
variables,
|
||||
data: {
|
||||
people: definition.resolver({
|
||||
currentData: (existingData as GetPeopleQuery).people,
|
||||
newData,
|
||||
variables,
|
||||
}),
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
if (query === GET_COMPANIES) {
|
||||
cache.writeQuery({
|
||||
query,
|
||||
variables,
|
||||
data: {
|
||||
companies: definition.resolver({
|
||||
currentData: (existingData as GetCompaniesQuery).companies,
|
||||
newData,
|
||||
variables,
|
||||
}),
|
||||
},
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
const optimisticEffect = {
|
||||
key: definition.key,
|
||||
variables,
|
||||
typename: definition.typename,
|
||||
query: definition.query,
|
||||
writer: optimisticEffectWriter,
|
||||
};
|
||||
|
||||
set(optimisticEffectState, {
|
||||
...optimisticEffects,
|
||||
[key]: optimisticEffect,
|
||||
[definition.key]: optimisticEffect,
|
||||
});
|
||||
},
|
||||
);
|
||||
|
||||
const triggerOptimisticEffects = useRecoilCallback(
|
||||
({ snapshot }) =>
|
||||
(typename: string, entities: any[]) => {
|
||||
(typename: string, newData: any[]) => {
|
||||
const optimisticEffects = snapshot
|
||||
.getLoadable(optimisticEffectState)
|
||||
.getValue();
|
||||
|
||||
Object.values(optimisticEffects).forEach((optimisticEffect) => {
|
||||
if (optimisticEffect.typename === typename) {
|
||||
optimisticEffect.resolver({
|
||||
optimisticEffect.writer({
|
||||
cache: apolloClient.cache,
|
||||
entities,
|
||||
query: optimisticEffect.query,
|
||||
newData,
|
||||
variables: optimisticEffect.variables,
|
||||
});
|
||||
}
|
||||
|
@ -1,9 +1,9 @@
|
||||
import { atom } from 'recoil';
|
||||
|
||||
import { OptimisticEffect } from '../types/OptimisticEffect';
|
||||
import { OptimisticEffect } from '../types/internal/OptimisticEffect';
|
||||
|
||||
export const optimisticEffectState = atom<
|
||||
Record<string, OptimisticEffect<unknown, unknown>>
|
||||
Record<string, OptimisticEffect<unknown>>
|
||||
>({
|
||||
key: 'optimisticEffectState',
|
||||
default: {},
|
||||
|
@ -1,18 +0,0 @@
|
||||
import { ApolloCache } from '@apollo/client';
|
||||
|
||||
type OptimisticEffectResolver<T, QueryVariables> = ({
|
||||
cache,
|
||||
entities,
|
||||
variables,
|
||||
}: {
|
||||
cache: ApolloCache<T>;
|
||||
entities: T[];
|
||||
variables: QueryVariables;
|
||||
}) => void;
|
||||
|
||||
export type OptimisticEffect<T, QueryVariables> = {
|
||||
key: string;
|
||||
typename: string;
|
||||
variables: QueryVariables;
|
||||
resolver: OptimisticEffectResolver<T, QueryVariables>;
|
||||
};
|
@ -0,0 +1,10 @@
|
||||
import { DocumentNode } from 'graphql';
|
||||
|
||||
import { OptimisticEffectResolver } from './OptimisticEffectResolver';
|
||||
|
||||
export type OptimisticEffectDefinition<T> = {
|
||||
key: string;
|
||||
query: DocumentNode;
|
||||
typename: string;
|
||||
resolver: OptimisticEffectResolver<T>;
|
||||
};
|
@ -0,0 +1,11 @@
|
||||
import { OperationVariables } from '@apollo/client';
|
||||
|
||||
export type OptimisticEffectResolver<T> = ({
|
||||
currentData,
|
||||
newData,
|
||||
variables,
|
||||
}: {
|
||||
currentData: T[];
|
||||
newData: T[];
|
||||
variables: OperationVariables;
|
||||
}) => void;
|
@ -0,0 +1,21 @@
|
||||
import { ApolloCache, DocumentNode, OperationVariables } from '@apollo/client';
|
||||
|
||||
type OptimisticEffectWriter<T> = ({
|
||||
cache,
|
||||
newData,
|
||||
variables,
|
||||
query,
|
||||
}: {
|
||||
cache: ApolloCache<T>;
|
||||
query: DocumentNode;
|
||||
newData: T[];
|
||||
variables: OperationVariables;
|
||||
}) => void;
|
||||
|
||||
export type OptimisticEffect<T> = {
|
||||
key: string;
|
||||
query: DocumentNode;
|
||||
typename: string;
|
||||
variables: OperationVariables;
|
||||
writer: OptimisticEffectWriter<T>;
|
||||
};
|
@ -1,7 +1,7 @@
|
||||
import { gql } from '@apollo/client';
|
||||
|
||||
export const COMPANY_FIELDS_FRAGMENT = gql`
|
||||
fragment CompanyFieldsFragment on Company {
|
||||
fragment companyFieldsFragment on Company {
|
||||
accountOwner {
|
||||
id
|
||||
email
|
||||
@ -18,5 +18,6 @@ export const COMPANY_FIELDS_FRAGMENT = gql`
|
||||
idealCustomerProfile
|
||||
id
|
||||
name
|
||||
_activityCount
|
||||
}
|
||||
`;
|
||||
|
@ -3,7 +3,7 @@ import { gql } from '@apollo/client';
|
||||
export const INSERT_ONE_COMPANY = gql`
|
||||
mutation InsertOneCompany($data: CompanyCreateInput!) {
|
||||
createOneCompany(data: $data) {
|
||||
...CompanyFieldsFragment
|
||||
...companyFieldsFragment
|
||||
}
|
||||
}
|
||||
`;
|
||||
|
@ -6,7 +6,7 @@ export const UPDATE_ONE_COMPANY = gql`
|
||||
$data: CompanyUpdateInput!
|
||||
) {
|
||||
updateOneCompany(data: $data, where: $where) {
|
||||
...CompanyFieldsFragment
|
||||
...companyFieldsFragment
|
||||
}
|
||||
}
|
||||
`;
|
||||
|
@ -0,0 +1,18 @@
|
||||
import { Company } from '~/generated/graphql';
|
||||
|
||||
import { GET_COMPANIES } from '../queries/getCompanies';
|
||||
|
||||
export const getCompaniesOptimisticEffectDefinition = {
|
||||
key: 'generic-entity-table-data-companies',
|
||||
typename: 'Company',
|
||||
query: GET_COMPANIES,
|
||||
resolver: ({
|
||||
currentData,
|
||||
newData,
|
||||
}: {
|
||||
currentData: Company[];
|
||||
newData: Company[];
|
||||
}) => {
|
||||
return [...newData, ...currentData];
|
||||
},
|
||||
};
|
@ -1,47 +0,0 @@
|
||||
import { ApolloCache } from '@apollo/client';
|
||||
|
||||
import {
|
||||
Company,
|
||||
GetCompaniesQuery,
|
||||
GetCompaniesQueryVariables,
|
||||
} from '~/generated/graphql';
|
||||
|
||||
import { GET_COMPANIES } from '../queries/getCompanies';
|
||||
|
||||
function optimisticEffectResolver({
|
||||
cache,
|
||||
entities,
|
||||
variables,
|
||||
}: {
|
||||
cache: ApolloCache<Company>;
|
||||
entities: Company[];
|
||||
variables: GetCompaniesQueryVariables;
|
||||
}) {
|
||||
const existingData = cache.readQuery<GetCompaniesQuery>({
|
||||
query: GET_COMPANIES,
|
||||
variables: { orderBy: variables.orderBy, where: variables.where },
|
||||
});
|
||||
|
||||
if (!existingData) {
|
||||
return;
|
||||
}
|
||||
|
||||
cache.writeQuery({
|
||||
query: GET_COMPANIES,
|
||||
variables: { orderBy: variables.orderBy, where: variables.where },
|
||||
data: {
|
||||
companies: [...entities, ...existingData.companies],
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
export function getCompaniesOptimisticEffect(
|
||||
variables: GetCompaniesQueryVariables,
|
||||
) {
|
||||
return {
|
||||
key: 'generic-entity-table-data-companies',
|
||||
variables: variables,
|
||||
typename: 'Company',
|
||||
resolver: optimisticEffectResolver,
|
||||
};
|
||||
}
|
@ -1,5 +1,5 @@
|
||||
import { companiesAvailableColumnDefinitions } from '@/companies/constants/companiesAvailableColumnDefinitions';
|
||||
import { getCompaniesOptimisticEffect } from '@/companies/graphql/optimistic-effects/getCompaniesOptimisticEffect';
|
||||
import { getCompaniesOptimisticEffectDefinition } from '@/companies/graphql/optimistic-effect-definitions/getCompaniesOptimisticEffectDefinition';
|
||||
import { useCompanyTableActionBarEntries } from '@/companies/hooks/useCompanyTableActionBarEntries';
|
||||
import { useCompanyTableContextMenuEntries } from '@/companies/hooks/useCompanyTableContextMenuEntries';
|
||||
import { useSpreadsheetCompanyImport } from '@/companies/hooks/useSpreadsheetCompanyImport';
|
||||
@ -53,7 +53,9 @@ export function CompanyTable() {
|
||||
<GenericEntityTableData
|
||||
getRequestResultKey="companies"
|
||||
useGetRequest={useGetCompaniesQuery}
|
||||
getRequestOptimisticEffect={getCompaniesOptimisticEffect}
|
||||
getRequestOptimisticEffectDefinition={
|
||||
getCompaniesOptimisticEffectDefinition
|
||||
}
|
||||
orderBy={sortsOrderBy}
|
||||
whereFilters={filtersWhere}
|
||||
filterDefinitionArray={companiesFilters}
|
||||
|
@ -1,11 +0,0 @@
|
||||
import { gql } from '@apollo/client';
|
||||
|
||||
export const INSERT_PERSON_FRAGMENT = gql`
|
||||
fragment InsertPersonFragment on Person {
|
||||
id
|
||||
firstName
|
||||
lastName
|
||||
displayName
|
||||
createdAt
|
||||
}
|
||||
`;
|
@ -0,0 +1,24 @@
|
||||
import { gql } from '@apollo/client';
|
||||
|
||||
export const PERSON_FIELDS_FRAGMENT = gql`
|
||||
fragment personFieldsFragment on Person {
|
||||
id
|
||||
phone
|
||||
email
|
||||
city
|
||||
firstName
|
||||
lastName
|
||||
displayName
|
||||
jobTitle
|
||||
linkedinUrl
|
||||
xUrl
|
||||
avatarUrl
|
||||
createdAt
|
||||
_activityCount
|
||||
company {
|
||||
id
|
||||
name
|
||||
domainName
|
||||
}
|
||||
}
|
||||
`;
|
@ -3,7 +3,7 @@ import { gql } from '@apollo/client';
|
||||
export const INSERT_ONE_PERSON = gql`
|
||||
mutation InsertOnePerson($data: PersonCreateInput!) {
|
||||
createOnePerson(data: $data) {
|
||||
...InsertPersonFragment
|
||||
...personFieldsFragment
|
||||
}
|
||||
}
|
||||
`;
|
||||
|
@ -1,45 +0,0 @@
|
||||
import { ApolloCache } from '@apollo/client';
|
||||
|
||||
import {
|
||||
GetPeopleQuery,
|
||||
GetPeopleQueryVariables,
|
||||
Person,
|
||||
} from '~/generated/graphql';
|
||||
|
||||
import { GET_PEOPLE } from '../queries/getPeople';
|
||||
|
||||
function optimisticEffectResolver({
|
||||
cache,
|
||||
entities,
|
||||
variables,
|
||||
}: {
|
||||
cache: ApolloCache<Person>;
|
||||
entities: Person[];
|
||||
variables: GetPeopleQueryVariables;
|
||||
}) {
|
||||
const existingData = cache.readQuery<GetPeopleQuery>({
|
||||
query: GET_PEOPLE,
|
||||
variables: { orderBy: variables.orderBy, where: variables.where },
|
||||
});
|
||||
|
||||
if (!existingData) {
|
||||
return;
|
||||
}
|
||||
|
||||
cache.writeQuery({
|
||||
query: GET_PEOPLE,
|
||||
variables: { orderBy: variables.orderBy, where: variables.where },
|
||||
data: {
|
||||
people: [...entities, ...existingData.people],
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
export function getPeopleOptimisticEffect(variables: GetPeopleQueryVariables) {
|
||||
return {
|
||||
key: 'generic-entity-table-data-person',
|
||||
variables: variables,
|
||||
typename: 'Person',
|
||||
resolver: optimisticEffectResolver,
|
||||
};
|
||||
}
|
@ -0,0 +1,18 @@
|
||||
import { Person } from '~/generated/graphql';
|
||||
|
||||
import { GET_PEOPLE } from '../queries/getPeople';
|
||||
|
||||
export const getPeopleOptimisticEffectDefinition = {
|
||||
key: 'generic-entity-table-data-people',
|
||||
typename: 'Person',
|
||||
query: GET_PEOPLE,
|
||||
resolver: ({
|
||||
currentData,
|
||||
newData,
|
||||
}: {
|
||||
currentData: Person[];
|
||||
newData: Person[];
|
||||
}) => {
|
||||
return [...newData, ...currentData];
|
||||
},
|
||||
};
|
@ -1,5 +1,5 @@
|
||||
import { peopleAvailableColumnDefinitions } from '@/people/constants/peopleAvailableColumnDefinitions';
|
||||
import { getPeopleOptimisticEffect } from '@/people/graphql/optimistic-effect-callback/getPeopleOptimisticEffect';
|
||||
import { getPeopleOptimisticEffectDefinition } from '@/people/graphql/optimistic-effect-definitions/getPeopleOptimisticEffectDefinition';
|
||||
import { usePersonTableContextMenuEntries } from '@/people/hooks/usePeopleTableContextMenuEntries';
|
||||
import { usePersonTableActionBarEntries } from '@/people/hooks/usePersonTableActionBarEntries';
|
||||
import { useSpreadsheetPersonImport } from '@/people/hooks/useSpreadsheetPersonImport';
|
||||
@ -52,7 +52,9 @@ export function PeopleTable() {
|
||||
<GenericEntityTableData
|
||||
getRequestResultKey="people"
|
||||
useGetRequest={useGetPeopleQuery}
|
||||
getRequestOptimisticEffect={getPeopleOptimisticEffect}
|
||||
getRequestOptimisticEffectDefinition={
|
||||
getPeopleOptimisticEffectDefinition
|
||||
}
|
||||
orderBy={sortsOrderBy}
|
||||
whereFilters={filtersWhere}
|
||||
filterDefinitionArray={peopleFilters}
|
||||
|
@ -11,7 +11,7 @@ export const SEARCH_COMPANY_QUERY = gql`
|
||||
take: $limit
|
||||
orderBy: $orderBy
|
||||
) {
|
||||
...CompanyFieldsFragment
|
||||
...companyFieldsFragment
|
||||
}
|
||||
}
|
||||
`;
|
||||
|
@ -98,8 +98,6 @@ export function useFilteredSearchEntityQuery<
|
||||
};
|
||||
});
|
||||
|
||||
console.log(searchFilter);
|
||||
|
||||
const {
|
||||
loading: filteredSelectedEntitiesLoading,
|
||||
data: filteredSelectedEntitiesData,
|
||||
|
@ -27,7 +27,7 @@ export function ShowPageAddButton({
|
||||
const openCreateActivity = useOpenCreateActivityDrawer();
|
||||
|
||||
function handleSelect(type: ActivityType) {
|
||||
openCreateActivity(type, [entity]);
|
||||
openCreateActivity({ type, targetableEntities: [entity] });
|
||||
closeDropdownButton();
|
||||
}
|
||||
|
||||
|
@ -9,7 +9,7 @@ import {
|
||||
import { isNavbarOpenedState } from '@/ui/layout/states/isNavbarOpenedState';
|
||||
import { useIsMobile } from '@/ui/utilities/responsive/hooks/useIsMobile';
|
||||
|
||||
const StyledCollapseButton = styled.button<{
|
||||
const StyledCollapseButton = styled.div<{
|
||||
hide: boolean;
|
||||
}>`
|
||||
align-items: center;
|
||||
|
@ -1,7 +1,7 @@
|
||||
import { useEffect } from 'react';
|
||||
|
||||
import { useOptimisticEffect } from '@/apollo/optimistic-effect/hooks/useOptimisticEffect';
|
||||
import { OptimisticEffect } from '@/apollo/optimistic-effect/types/OptimisticEffect';
|
||||
import { OptimisticEffectDefinition } from '@/apollo/optimistic-effect/types/OptimisticEffectDefinition';
|
||||
import { useSetEntityTableData } from '@/ui/table/hooks/useSetEntityTableData';
|
||||
import { FilterDefinition } from '@/ui/view-bar/types/FilterDefinition';
|
||||
import { SortOrder } from '~/generated/graphql';
|
||||
@ -9,7 +9,7 @@ import { SortOrder } from '~/generated/graphql';
|
||||
export function GenericEntityTableData({
|
||||
useGetRequest,
|
||||
getRequestResultKey,
|
||||
getRequestOptimisticEffect,
|
||||
getRequestOptimisticEffectDefinition,
|
||||
orderBy = [
|
||||
{
|
||||
createdAt: SortOrder.Desc,
|
||||
@ -22,7 +22,7 @@ export function GenericEntityTableData({
|
||||
}: {
|
||||
useGetRequest: any;
|
||||
getRequestResultKey: string;
|
||||
getRequestOptimisticEffect: (variables: any) => OptimisticEffect<any, any>;
|
||||
getRequestOptimisticEffectDefinition: OptimisticEffectDefinition<any>;
|
||||
orderBy?: any;
|
||||
whereFilters?: any;
|
||||
filterDefinitionArray: FilterDefinition[];
|
||||
@ -37,9 +37,10 @@ export function GenericEntityTableData({
|
||||
onCompleted: (data: any) => {
|
||||
const entities = data[getRequestResultKey] ?? [];
|
||||
setEntityTableData(entities, filterDefinitionArray);
|
||||
registerOptimisticEffect(
|
||||
getRequestOptimisticEffect({ orderBy, where: whereFilters }),
|
||||
);
|
||||
registerOptimisticEffect({
|
||||
variables: { orderBy, where: whereFilters },
|
||||
definition: getRequestOptimisticEffectDefinition,
|
||||
});
|
||||
},
|
||||
});
|
||||
|
||||
|
@ -43,21 +43,6 @@ export function Companies() {
|
||||
address: '',
|
||||
},
|
||||
},
|
||||
optimisticResponse: {
|
||||
__typename: 'Mutation',
|
||||
createOneCompany: {
|
||||
__typename: 'Company',
|
||||
id: newCompanyId,
|
||||
name: '',
|
||||
domainName: '',
|
||||
address: '',
|
||||
createdAt: new Date().toISOString(),
|
||||
accountOwner: null,
|
||||
linkedinUrl: '',
|
||||
idealCustomerProfile: false,
|
||||
employees: null,
|
||||
},
|
||||
},
|
||||
update: (_cache, { data }) => {
|
||||
if (data?.createOneCompany) {
|
||||
upsertTableRowIds(data?.createOneCompany.id);
|
||||
|
@ -40,17 +40,6 @@ export function People() {
|
||||
lastName: '',
|
||||
},
|
||||
},
|
||||
optimisticResponse: {
|
||||
__typename: 'Mutation',
|
||||
createOnePerson: {
|
||||
__typename: 'Person',
|
||||
id: newPersonId,
|
||||
firstName: '',
|
||||
lastName: '',
|
||||
displayName: '',
|
||||
createdAt: '',
|
||||
},
|
||||
},
|
||||
update: (_cache, { data }) => {
|
||||
if (data?.createOnePerson) {
|
||||
upsertTableRowIds(data?.createOnePerson.id);
|
||||
|
@ -1,12 +1,10 @@
|
||||
import styled from '@emotion/styled';
|
||||
|
||||
import { useOpenCreateActivityDrawer } from '@/activities/hooks/useOpenCreateActivityDrawer';
|
||||
import { TasksRecoilScopeContext } from '@/activities/states/recoil-scope-contexts/TasksRecoilScopeContext';
|
||||
import { PageAddTaskButton } from '@/activities/tasks/components/PageAddTaskButton';
|
||||
import { TaskGroups } from '@/activities/tasks/components/TaskGroups';
|
||||
import { DropdownRecoilScopeContext } from '@/ui/dropdown/states/recoil-scope-contexts/DropdownRecoilScopeContext';
|
||||
import { IconArchive, IconCheck, IconCheckbox } from '@/ui/icon/index';
|
||||
import { RelationPickerHotkeyScope } from '@/ui/input/relation-picker/types/RelationPickerHotkeyScope';
|
||||
import { PageAddButton } from '@/ui/layout/components/PageAddButton';
|
||||
import { PageBody } from '@/ui/layout/components/PageBody';
|
||||
import { PageContainer } from '@/ui/layout/components/PageContainer';
|
||||
import { PageHeader } from '@/ui/layout/components/PageHeader';
|
||||
@ -14,7 +12,6 @@ import { TabList } from '@/ui/tab/components/TabList';
|
||||
import { TopBar } from '@/ui/top-bar/TopBar';
|
||||
import { RecoilScope } from '@/ui/utilities/recoil-scope/components/RecoilScope';
|
||||
import { FilterDropdownButton } from '@/ui/view-bar/components/FilterDropdownButton';
|
||||
import { ActivityType } from '~/generated/graphql';
|
||||
|
||||
const StyledTasksContainer = styled.div`
|
||||
display: flex;
|
||||
@ -32,8 +29,6 @@ const StyledTabListContainer = styled.div`
|
||||
`;
|
||||
|
||||
export function Tasks() {
|
||||
const openCreateActivity = useOpenCreateActivityDrawer();
|
||||
|
||||
const TASK_TABS = [
|
||||
{
|
||||
id: 'to-do',
|
||||
@ -49,16 +44,12 @@ export function Tasks() {
|
||||
|
||||
return (
|
||||
<PageContainer>
|
||||
<PageHeader title="Tasks" Icon={IconCheckbox}>
|
||||
<RecoilScope SpecificContext={DropdownRecoilScopeContext}>
|
||||
<PageAddButton
|
||||
onClick={() => openCreateActivity(ActivityType.Task)}
|
||||
/>
|
||||
</RecoilScope>
|
||||
</PageHeader>
|
||||
<PageBody>
|
||||
<StyledTasksContainer>
|
||||
<RecoilScope SpecificContext={TasksRecoilScopeContext}>
|
||||
<RecoilScope SpecificContext={TasksRecoilScopeContext}>
|
||||
<PageHeader title="Tasks" Icon={IconCheckbox}>
|
||||
<PageAddTaskButton />
|
||||
</PageHeader>
|
||||
<PageBody>
|
||||
<StyledTasksContainer>
|
||||
<TopBar
|
||||
leftComponent={
|
||||
<StyledTabListContainer>
|
||||
@ -74,9 +65,9 @@ export function Tasks() {
|
||||
}
|
||||
/>
|
||||
<TaskGroups />
|
||||
</RecoilScope>
|
||||
</StyledTasksContainer>
|
||||
</PageBody>
|
||||
</StyledTasksContainer>
|
||||
</PageBody>
|
||||
</RecoilScope>
|
||||
</PageContainer>
|
||||
);
|
||||
}
|
||||
|
@ -191,10 +191,10 @@ export function PageChangeEffect() {
|
||||
type: CommandType.Create,
|
||||
Icon: IconCheckbox,
|
||||
onCommandClick: () =>
|
||||
openCreateActivity(
|
||||
ActivityType.Task,
|
||||
entity ? [entity] : undefined,
|
||||
),
|
||||
openCreateActivity({
|
||||
type: ActivityType.Task,
|
||||
targetableEntities: entity ? [entity] : undefined,
|
||||
}),
|
||||
},
|
||||
{
|
||||
to: '',
|
||||
@ -202,10 +202,10 @@ export function PageChangeEffect() {
|
||||
type: CommandType.Create,
|
||||
Icon: IconNotes,
|
||||
onCommandClick: () =>
|
||||
openCreateActivity(
|
||||
ActivityType.Note,
|
||||
entity ? [entity] : undefined,
|
||||
),
|
||||
openCreateActivity({
|
||||
type: ActivityType.Note,
|
||||
targetableEntities: entity ? [entity] : undefined,
|
||||
}),
|
||||
},
|
||||
]);
|
||||
break;
|
||||
@ -225,10 +225,10 @@ export function PageChangeEffect() {
|
||||
type: CommandType.Create,
|
||||
Icon: IconCheckbox,
|
||||
onCommandClick: () =>
|
||||
openCreateActivity(
|
||||
ActivityType.Task,
|
||||
entity ? [entity] : undefined,
|
||||
),
|
||||
openCreateActivity({
|
||||
type: ActivityType.Task,
|
||||
targetableEntities: entity ? [entity] : undefined,
|
||||
}),
|
||||
},
|
||||
{
|
||||
to: '',
|
||||
@ -236,10 +236,10 @@ export function PageChangeEffect() {
|
||||
type: CommandType.Create,
|
||||
Icon: IconNotes,
|
||||
onCommandClick: () =>
|
||||
openCreateActivity(
|
||||
ActivityType.Note,
|
||||
entity ? [entity] : undefined,
|
||||
),
|
||||
openCreateActivity({
|
||||
type: ActivityType.Note,
|
||||
targetableEntities: entity ? [entity] : undefined,
|
||||
}),
|
||||
},
|
||||
]);
|
||||
break;
|
||||
@ -251,7 +251,8 @@ export function PageChangeEffect() {
|
||||
label: 'Create Task',
|
||||
type: CommandType.Create,
|
||||
Icon: IconCheckbox,
|
||||
onCommandClick: () => openCreateActivity(ActivityType.Task),
|
||||
onCommandClick: () =>
|
||||
openCreateActivity({ type: ActivityType.Task }),
|
||||
},
|
||||
]);
|
||||
break;
|
||||
|
Loading…
Reference in New Issue
Block a user