fix: fix table columns resize glitches on slow network (#1707)

Fixes #1580
This commit is contained in:
Thaïs
2023-09-22 19:45:29 +02:00
committed by GitHub
parent 20267f081a
commit 1c3897848f
8 changed files with 137 additions and 45 deletions

View File

@ -565,6 +565,7 @@ export type ClientConfig = {
__typename?: 'ClientConfig'; __typename?: 'ClientConfig';
authProviders: AuthProviders; authProviders: AuthProviders;
debugMode: Scalars['Boolean']; debugMode: Scalars['Boolean'];
flexibleBackendEnabled: Scalars['Boolean'];
signInPrefilled: Scalars['Boolean']; signInPrefilled: Scalars['Boolean'];
support: Support; support: Support;
telemetry: Telemetry; telemetry: Telemetry;
@ -1064,6 +1065,7 @@ export type Mutation = {
UpdateOneWorkspaceMember: WorkspaceMember; UpdateOneWorkspaceMember: WorkspaceMember;
allowImpersonation: WorkspaceMember; allowImpersonation: WorkspaceMember;
challenge: LoginToken; challenge: LoginToken;
createCustomField: Scalars['String'];
createEvent: Analytics; createEvent: Analytics;
createFavoriteForCompany: Favorite; createFavoriteForCompany: Favorite;
createFavoriteForPerson: Favorite; createFavoriteForPerson: Favorite;
@ -1135,6 +1137,13 @@ export type MutationChallengeArgs = {
}; };
export type MutationCreateCustomFieldArgs = {
name: Scalars['String'];
objectId: Scalars['String'];
type: Scalars['String'];
};
export type MutationCreateEventArgs = { export type MutationCreateEventArgs = {
data: Scalars['JSON']; data: Scalars['JSON'];
type: Scalars['String']; type: Scalars['String'];
@ -1528,6 +1537,21 @@ export type NestedStringNullableFilter = {
startsWith?: InputMaybe<Scalars['String']>; startsWith?: InputMaybe<Scalars['String']>;
}; };
export type PageInfo = {
__typename?: 'PageInfo';
endCursor?: Maybe<Scalars['String']>;
hasNextPage: Scalars['Boolean'];
hasPreviousPage: Scalars['Boolean'];
startCursor?: Maybe<Scalars['String']>;
};
export type PaginatedUniversalEntity = {
__typename?: 'PaginatedUniversalEntity';
edges?: Maybe<Array<UniversalEntityEdge>>;
pageInfo?: Maybe<PageInfo>;
totalCount: Scalars['Float'];
};
export type Person = { export type Person = {
__typename?: 'Person'; __typename?: 'Person';
ActivityTarget?: Maybe<Array<ActivityTarget>>; ActivityTarget?: Maybe<Array<ActivityTarget>>;
@ -2099,7 +2123,9 @@ export type Query = {
clientConfig: ClientConfig; clientConfig: ClientConfig;
currentUser: User; currentUser: User;
currentWorkspace: Workspace; currentWorkspace: Workspace;
deleteOneCustom: UniversalEntity;
findFavorites: Array<Favorite>; findFavorites: Array<Favorite>;
findMany: PaginatedUniversalEntity;
findManyActivities: Array<Activity>; findManyActivities: Array<Activity>;
findManyCompany: Array<Company>; findManyCompany: Array<Company>;
findManyPerson: Array<Person>; findManyPerson: Array<Person>;
@ -2112,9 +2138,11 @@ export type Query = {
findManyViewFilter: Array<ViewFilter>; findManyViewFilter: Array<ViewFilter>;
findManyViewSort: Array<ViewSort>; findManyViewSort: Array<ViewSort>;
findManyWorkspaceMember: Array<WorkspaceMember>; findManyWorkspaceMember: Array<WorkspaceMember>;
findUnique: UniversalEntity;
findUniqueCompany: Company; findUniqueCompany: Company;
findUniquePerson: Person; findUniquePerson: Person;
findWorkspaceFromInviteHash: Workspace; findWorkspaceFromInviteHash: Workspace;
updateOneCustom: UniversalEntity;
}; };
@ -2128,6 +2156,21 @@ export type QueryCheckWorkspaceInviteHashIsValidArgs = {
}; };
export type QueryFindManyArgs = {
after?: InputMaybe<Scalars['String']>;
before?: InputMaybe<Scalars['String']>;
cursor?: InputMaybe<Scalars['JSON']>;
distinct?: InputMaybe<Array<Scalars['String']>>;
entity: Scalars['String'];
first?: InputMaybe<Scalars['Float']>;
last?: InputMaybe<Scalars['Float']>;
orderBy?: InputMaybe<UniversalEntityOrderByRelationInput>;
skip?: InputMaybe<Scalars['Int']>;
take?: InputMaybe<Scalars['Int']>;
where?: InputMaybe<UniversalEntityInput>;
};
export type QueryFindManyActivitiesArgs = { export type QueryFindManyActivitiesArgs = {
cursor?: InputMaybe<ActivityWhereUniqueInput>; cursor?: InputMaybe<ActivityWhereUniqueInput>;
distinct?: InputMaybe<Array<ActivityScalarFieldEnum>>; distinct?: InputMaybe<Array<ActivityScalarFieldEnum>>;
@ -2248,6 +2291,12 @@ export type QueryFindManyWorkspaceMemberArgs = {
}; };
export type QueryFindUniqueArgs = {
entity: Scalars['String'];
where?: InputMaybe<UniversalEntityInput>;
};
export type QueryFindUniqueCompanyArgs = { export type QueryFindUniqueCompanyArgs = {
where: CompanyWhereUniqueInput; where: CompanyWhereUniqueInput;
}; };
@ -2314,6 +2363,39 @@ export type Telemetry = {
enabled: Scalars['Boolean']; enabled: Scalars['Boolean'];
}; };
export enum TypeOrmSortOrder {
Asc = 'ASC',
Desc = 'DESC'
}
export type UniversalEntity = {
__typename?: 'UniversalEntity';
createdAt: Scalars['DateTime'];
data: Scalars['JSON'];
id: Scalars['ID'];
updatedAt: Scalars['DateTime'];
};
export type UniversalEntityEdge = {
__typename?: 'UniversalEntityEdge';
cursor?: Maybe<Scalars['String']>;
node?: Maybe<UniversalEntity>;
};
export type UniversalEntityInput = {
createdAt?: InputMaybe<Scalars['DateTime']>;
data?: InputMaybe<Scalars['JSON']>;
id?: InputMaybe<Scalars['ID']>;
updatedAt?: InputMaybe<Scalars['DateTime']>;
};
export type UniversalEntityOrderByRelationInput = {
createdAt?: InputMaybe<TypeOrmSortOrder>;
data?: InputMaybe<Scalars['JSON']>;
id?: InputMaybe<TypeOrmSortOrder>;
updatedAt?: InputMaybe<TypeOrmSortOrder>;
};
export type User = { export type User = {
__typename?: 'User'; __typename?: 'User';
assignedActivities?: Maybe<Array<Activity>>; assignedActivities?: Maybe<Array<Activity>>;
@ -3657,6 +3739,8 @@ export type GetUsersQueryVariables = Exact<{ [key: string]: never; }>;
export type GetUsersQuery = { __typename?: 'Query', findManyUser: Array<{ __typename?: 'User', id: string, email: string, displayName: string, firstName?: string | null, lastName?: string | null }> }; export type GetUsersQuery = { __typename?: 'Query', findManyUser: Array<{ __typename?: 'User', id: string, email: string, displayName: string, firstName?: string | null, lastName?: string | null }> };
export type ViewFieldFragmentFragment = { __typename?: 'ViewField', index: number, isVisible: boolean, key: string, name: string, size?: number | null, viewId: string };
export type CreateViewMutationVariables = Exact<{ export type CreateViewMutationVariables = Exact<{
data: ViewCreateInput; data: ViewCreateInput;
}>; }>;
@ -3720,7 +3804,7 @@ export type UpdateViewFieldMutationVariables = Exact<{
}>; }>;
export type UpdateViewFieldMutation = { __typename?: 'Mutation', updateOneViewField: { __typename?: 'ViewField', index: number, isVisible: boolean, key: string, name: string, size?: number | null } }; export type UpdateViewFieldMutation = { __typename?: 'Mutation', updateOneViewField: { __typename?: 'ViewField', index: number, isVisible: boolean, key: string, name: string, size?: number | null, viewId: string } };
export type UpdateViewFilterMutationVariables = Exact<{ export type UpdateViewFilterMutationVariables = Exact<{
data: ViewFilterUpdateInput; data: ViewFilterUpdateInput;
@ -3744,7 +3828,7 @@ export type GetViewFieldsQueryVariables = Exact<{
}>; }>;
export type GetViewFieldsQuery = { __typename?: 'Query', viewFields: Array<{ __typename?: 'ViewField', index: number, isVisible: boolean, key: string, name: string, size?: number | null }> }; export type GetViewFieldsQuery = { __typename?: 'Query', viewFields: Array<{ __typename?: 'ViewField', index: number, isVisible: boolean, key: string, name: string, size?: number | null, viewId: string }> };
export type GetViewFiltersQueryVariables = Exact<{ export type GetViewFiltersQueryVariables = Exact<{
where?: InputMaybe<ViewFilterWhereInput>; where?: InputMaybe<ViewFilterWhereInput>;
@ -4045,6 +4129,16 @@ export const UserFieldsFragmentFragmentDoc = gql`
lastName lastName
} }
`; `;
export const ViewFieldFragmentFragmentDoc = gql`
fragment ViewFieldFragment on ViewField {
index
isVisible
key
name
size
viewId
}
`;
export const WorkspaceMemberFieldsFragmentFragmentDoc = gql` export const WorkspaceMemberFieldsFragmentFragmentDoc = gql`
fragment workspaceMemberFieldsFragment on WorkspaceMember { fragment workspaceMemberFieldsFragment on WorkspaceMember {
id id
@ -6754,14 +6848,10 @@ export type UpdateViewMutationOptions = Apollo.BaseMutationOptions<UpdateViewMut
export const UpdateViewFieldDocument = gql` export const UpdateViewFieldDocument = gql`
mutation UpdateViewField($data: ViewFieldUpdateInput!, $where: ViewFieldWhereUniqueInput!) { mutation UpdateViewField($data: ViewFieldUpdateInput!, $where: ViewFieldWhereUniqueInput!) {
updateOneViewField(data: $data, where: $where) { updateOneViewField(data: $data, where: $where) {
index ...ViewFieldFragment
isVisible
key
name
size
} }
} }
`; ${ViewFieldFragmentFragmentDoc}`;
export type UpdateViewFieldMutationFn = Apollo.MutationFunction<UpdateViewFieldMutation, UpdateViewFieldMutationVariables>; export type UpdateViewFieldMutationFn = Apollo.MutationFunction<UpdateViewFieldMutation, UpdateViewFieldMutationVariables>;
/** /**
@ -6866,14 +6956,10 @@ export type UpdateViewSortMutationOptions = Apollo.BaseMutationOptions<UpdateVie
export const GetViewFieldsDocument = gql` export const GetViewFieldsDocument = gql`
query GetViewFields($where: ViewFieldWhereInput, $orderBy: [ViewFieldOrderByWithRelationInput!]) { query GetViewFields($where: ViewFieldWhereInput, $orderBy: [ViewFieldOrderByWithRelationInput!]) {
viewFields: findManyViewField(where: $where, orderBy: $orderBy) { viewFields: findManyViewField(where: $where, orderBy: $orderBy) {
index ...ViewFieldFragment
isVisible
key
name
size
} }
} }
`; ${ViewFieldFragmentFragmentDoc}`;
/** /**
* __useGetViewFieldsQuery__ * __useGetViewFieldsQuery__

View File

@ -37,6 +37,7 @@ export const useApolloFactory = () => {
}, },
}, },
}, },
ViewField: { keyFields: ['viewId', 'key'] },
}, },
}), }),
defaultOptions: { defaultOptions: {

View File

@ -126,6 +126,10 @@ export const EntityTableHeader = () => {
), ),
); );
set(resizeFieldOffsetState, 0);
setInitialPointerPositionX(null);
setResizedFieldKey(null);
if (nextWidth !== tableColumnsByKey[resizedFieldKey].size) { if (nextWidth !== tableColumnsByKey[resizedFieldKey].size) {
const nextColumns = tableColumns.map((column) => const nextColumns = tableColumns.map((column) =>
column.key === resizedFieldKey column.key === resizedFieldKey
@ -135,10 +139,6 @@ export const EntityTableHeader = () => {
await handleColumnsChange(nextColumns); await handleColumnsChange(nextColumns);
} }
set(resizeFieldOffsetState, 0);
setInitialPointerPositionX(null);
setResizedFieldKey(null);
}, },
[resizedFieldKey, tableColumnsByKey, tableColumns, handleColumnsChange], [resizedFieldKey, tableColumnsByKey, tableColumns, handleColumnsChange],
); );

View File

@ -34,10 +34,10 @@ export const useTableColumns = () => {
const handleColumnsChange = useCallback( const handleColumnsChange = useCallback(
async (columns: ColumnDefinition<ViewFieldMetadata>[]) => { async (columns: ColumnDefinition<ViewFieldMetadata>[]) => {
await onColumnsChange?.(columns);
setSavedTableColumns(columns); setSavedTableColumns(columns);
setTableColumns(columns); setTableColumns(columns);
await onColumnsChange?.(columns);
}, },
[onColumnsChange, setSavedTableColumns, setTableColumns], [onColumnsChange, setSavedTableColumns, setTableColumns],
); );

View File

@ -0,0 +1,12 @@
import { gql } from '@apollo/client';
export const VIEW_FIELD_FRAGMENT = gql`
fragment ViewFieldFragment on ViewField {
index
isVisible
key
name
size
viewId
}
`;

View File

@ -6,11 +6,7 @@ export const UPDATE_VIEW_FIELD = gql`
$where: ViewFieldWhereUniqueInput! $where: ViewFieldWhereUniqueInput!
) { ) {
updateOneViewField(data: $data, where: $where) { updateOneViewField(data: $data, where: $where) {
index ...ViewFieldFragment
isVisible
key
name
size
} }
} }
`; `;

View File

@ -6,11 +6,7 @@ export const GET_VIEW_FIELDS = gql`
$orderBy: [ViewFieldOrderByWithRelationInput!] $orderBy: [ViewFieldOrderByWithRelationInput!]
) { ) {
viewFields: findManyViewField(where: $where, orderBy: $orderBy) { viewFields: findManyViewField(where: $where, orderBy: $orderBy) {
index ...ViewFieldFragment
isVisible
key
name
size
} }
} }
`; `;

View File

@ -1,4 +1,5 @@
import { useCallback } from 'react'; import { useCallback, useState } from 'react';
import { getOperationName } from '@apollo/client/utilities';
import { useRecoilValue, useSetRecoilState } from 'recoil'; import { useRecoilValue, useSetRecoilState } from 'recoil';
import type { ViewFieldMetadata } from '@/ui/editable-field/types/ViewField'; import type { ViewFieldMetadata } from '@/ui/editable-field/types/ViewField';
@ -20,6 +21,8 @@ import {
import { assertNotNull } from '~/utils/assert'; import { assertNotNull } from '~/utils/assert';
import { isDeeplyEqual } from '~/utils/isDeeplyEqual'; import { isDeeplyEqual } from '~/utils/isDeeplyEqual';
import { GET_VIEW_FIELDS } from '../graphql/queries/getViewFields';
const toViewFieldInput = ( const toViewFieldInput = (
objectId: 'company' | 'person', objectId: 'company' | 'person',
fieldDefinition: ColumnDefinition<ViewFieldMetadata>, fieldDefinition: ColumnDefinition<ViewFieldMetadata>,
@ -45,6 +48,7 @@ export const useTableViewFields = ({
currentViewIdScopedState, currentViewIdScopedState,
TableRecoilScopeContext, TableRecoilScopeContext,
); );
const [previousViewId, setPreviousViewId] = useState<string | undefined>();
const [availableTableColumns, setAvailableTableColumns] = const [availableTableColumns, setAvailableTableColumns] =
useRecoilScopedState( useRecoilScopedState(
availableTableColumnsScopedState, availableTableColumnsScopedState,
@ -78,6 +82,7 @@ export const useTableViewFields = ({
viewId, viewId,
})), })),
}, },
refetchQueries: [getOperationName(GET_VIEW_FIELDS) ?? ''],
}); });
}, },
[createViewFieldsMutation, currentViewId, objectId], [createViewFieldsMutation, currentViewId, objectId],
@ -107,7 +112,7 @@ export const useTableViewFields = ({
[currentViewId, updateViewFieldMutation], [currentViewId, updateViewFieldMutation],
); );
const { refetch } = useGetViewFieldsQuery({ useGetViewFieldsQuery({
skip: !currentViewId || skipFetch, skip: !currentViewId || skipFetch,
variables: { variables: {
orderBy: { index: SortOrder.Asc }, orderBy: { index: SortOrder.Asc },
@ -118,8 +123,7 @@ export const useTableViewFields = ({
onCompleted: async (data) => { onCompleted: async (data) => {
if (!data.viewFields.length) { if (!data.viewFields.length) {
// Populate if empty // Populate if empty
await createViewFields(columnDefinitions); return createViewFields(columnDefinitions);
return refetch();
} }
const nextColumns = data.viewFields const nextColumns = data.viewFields
@ -141,9 +145,14 @@ export const useTableViewFields = ({
}) })
.filter<ColumnDefinition<ViewFieldMetadata>>(assertNotNull); .filter<ColumnDefinition<ViewFieldMetadata>>(assertNotNull);
if (!isDeeplyEqual(tableColumns, nextColumns)) { setSavedTableColumns(nextColumns);
setSavedTableColumns(nextColumns);
if (
previousViewId !== currentViewId &&
!isDeeplyEqual(tableColumns, nextColumns)
) {
setTableColumns(nextColumns); setTableColumns(nextColumns);
setPreviousViewId(currentViewId);
} }
if (!availableTableColumns.length) { if (!availableTableColumns.length) {
@ -169,16 +178,8 @@ export const useTableViewFields = ({
savedTableColumnsByKey[column.key].isVisible !== column.isVisible), savedTableColumnsByKey[column.key].isVisible !== column.isVisible),
); );
await updateViewFields(viewFieldsToUpdate); await updateViewFields(viewFieldsToUpdate);
await refetch();
}, },
[ [createViewFields, currentViewId, savedTableColumnsByKey, updateViewFields],
createViewFields,
currentViewId,
refetch,
savedTableColumnsByKey,
updateViewFields,
],
); );
return { createViewFields, persistColumns }; return { createViewFields, persistColumns };