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:
Lucas Bordeau 2023-09-11 08:02:51 +02:00 committed by GitHub
parent 08727aafe5
commit 9be069bedc
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
37 changed files with 363 additions and 243 deletions

View File

@ -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}`;

View File

@ -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) ?? ''],
});
}

View File

@ -119,6 +119,7 @@ export function ActivityEditor({
title: newTitle,
},
},
refetchQueries: [getOperationName(GET_ACTIVITIES) ?? ''],
});
},
[activity.id, cachedActivity, updateActivityMutation],

View File

@ -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);
},
});

View File

@ -24,6 +24,9 @@ export function useOpenCreateActivityDrawerForSelectedRowIds() {
type: entityType,
id,
}));
openCreateActivityDrawer(type, activityTargetableEntityArray);
openCreateActivityDrawer({
type,
targetableEntities: activityTargetableEntityArray,
});
};
}

View File

@ -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>
}
/>

View File

@ -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>
);
}

View File

@ -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>
);
}

View File

@ -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} />
)
}
/>
</>

View File

@ -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>
);

View File

@ -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,
});
}

View File

@ -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: {},

View File

@ -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>;
};

View File

@ -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>;
};

View File

@ -0,0 +1,11 @@
import { OperationVariables } from '@apollo/client';
export type OptimisticEffectResolver<T> = ({
currentData,
newData,
variables,
}: {
currentData: T[];
newData: T[];
variables: OperationVariables;
}) => void;

View File

@ -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>;
};

View File

@ -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
}
`;

View File

@ -3,7 +3,7 @@ import { gql } from '@apollo/client';
export const INSERT_ONE_COMPANY = gql`
mutation InsertOneCompany($data: CompanyCreateInput!) {
createOneCompany(data: $data) {
...CompanyFieldsFragment
...companyFieldsFragment
}
}
`;

View File

@ -6,7 +6,7 @@ export const UPDATE_ONE_COMPANY = gql`
$data: CompanyUpdateInput!
) {
updateOneCompany(data: $data, where: $where) {
...CompanyFieldsFragment
...companyFieldsFragment
}
}
`;

View File

@ -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];
},
};

View File

@ -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,
};
}

View File

@ -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}

View File

@ -1,11 +0,0 @@
import { gql } from '@apollo/client';
export const INSERT_PERSON_FRAGMENT = gql`
fragment InsertPersonFragment on Person {
id
firstName
lastName
displayName
createdAt
}
`;

View File

@ -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
}
}
`;

View File

@ -3,7 +3,7 @@ import { gql } from '@apollo/client';
export const INSERT_ONE_PERSON = gql`
mutation InsertOnePerson($data: PersonCreateInput!) {
createOnePerson(data: $data) {
...InsertPersonFragment
...personFieldsFragment
}
}
`;

View File

@ -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,
};
}

View File

@ -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];
},
};

View File

@ -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}

View File

@ -11,7 +11,7 @@ export const SEARCH_COMPANY_QUERY = gql`
take: $limit
orderBy: $orderBy
) {
...CompanyFieldsFragment
...companyFieldsFragment
}
}
`;

View File

@ -98,8 +98,6 @@ export function useFilteredSearchEntityQuery<
};
});
console.log(searchFilter);
const {
loading: filteredSelectedEntitiesLoading,
data: filteredSelectedEntitiesData,

View File

@ -27,7 +27,7 @@ export function ShowPageAddButton({
const openCreateActivity = useOpenCreateActivityDrawer();
function handleSelect(type: ActivityType) {
openCreateActivity(type, [entity]);
openCreateActivity({ type, targetableEntities: [entity] });
closeDropdownButton();
}

View File

@ -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;

View File

@ -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,
});
},
});

View File

@ -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);

View File

@ -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);

View File

@ -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>
);
}

View File

@ -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;