Improve Performances of FE by reducing first print queries (#2623)
This commit is contained in:
@ -1,10 +1,8 @@
|
|||||||
import { useState } from 'react';
|
|
||||||
import { useApolloClient } from '@apollo/client';
|
import { useApolloClient } from '@apollo/client';
|
||||||
import { OnDragEndResponder } from '@hello-pangea/dnd';
|
import { OnDragEndResponder } from '@hello-pangea/dnd';
|
||||||
import { useRecoilCallback, useRecoilState, useRecoilValue } from 'recoil';
|
import { useRecoilCallback, useRecoilState, useRecoilValue } from 'recoil';
|
||||||
|
|
||||||
import { currentWorkspaceMemberState } from '@/auth/states/currentWorkspaceMemberState';
|
import { currentWorkspaceMemberState } from '@/auth/states/currentWorkspaceMemberState';
|
||||||
import { Company } from '@/companies/types/Company';
|
|
||||||
import { Favorite } from '@/favorites/types/Favorite';
|
import { Favorite } from '@/favorites/types/Favorite';
|
||||||
import { mapFavorites } from '@/favorites/utils/mapFavorites';
|
import { mapFavorites } from '@/favorites/utils/mapFavorites';
|
||||||
import { useObjectMetadataItem } from '@/object-metadata/hooks/useObjectMetadataItem';
|
import { useObjectMetadataItem } from '@/object-metadata/hooks/useObjectMetadataItem';
|
||||||
@ -35,55 +33,7 @@ export const useFavorites = ({
|
|||||||
|
|
||||||
const apolloClient = useApolloClient();
|
const apolloClient = useApolloClient();
|
||||||
|
|
||||||
const [allCompanies, setAllCompanies] = useState<
|
|
||||||
Record<string, { name: string; domainName?: string }>
|
|
||||||
>({});
|
|
||||||
const [allPeople, setAllPeople] = useState<
|
|
||||||
Record<string, { firstName: string; lastName: string; avatarUrl?: string }>
|
|
||||||
>({});
|
|
||||||
|
|
||||||
// This is only temporary and will be refactored once we have main identifiers
|
|
||||||
const { loading: companiesLoading } = useFindManyObjectRecords({
|
|
||||||
objectNamePlural: 'companies',
|
|
||||||
onCompleted: async (
|
|
||||||
data: PaginatedObjectTypeResults<Required<Company>>,
|
|
||||||
) => {
|
|
||||||
setAllCompanies(
|
|
||||||
data.edges.reduce(
|
|
||||||
(acc, { node: company }) => ({
|
|
||||||
...acc,
|
|
||||||
[company.id]: {
|
|
||||||
name: company.name,
|
|
||||||
domainName: company.domainName,
|
|
||||||
},
|
|
||||||
}),
|
|
||||||
{},
|
|
||||||
),
|
|
||||||
);
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
const { loading: peopleLoading } = useFindManyObjectRecords({
|
|
||||||
objectNamePlural: 'people',
|
|
||||||
onCompleted: async (data) => {
|
|
||||||
setAllPeople(
|
|
||||||
data.edges.reduce(
|
|
||||||
(acc, { node: person }) => ({
|
|
||||||
...acc,
|
|
||||||
[person.id]: {
|
|
||||||
firstName: person.firstName,
|
|
||||||
lastName: person.lastName,
|
|
||||||
avatarUrl: person.avatarUrl,
|
|
||||||
},
|
|
||||||
}),
|
|
||||||
{},
|
|
||||||
),
|
|
||||||
);
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
useFindManyObjectRecords({
|
useFindManyObjectRecords({
|
||||||
skip: companiesLoading || peopleLoading,
|
|
||||||
objectNamePlural: 'favorites',
|
objectNamePlural: 'favorites',
|
||||||
onCompleted: useRecoilCallback(
|
onCompleted: useRecoilCallback(
|
||||||
({ snapshot, set }) =>
|
({ snapshot, set }) =>
|
||||||
@ -92,17 +42,13 @@ export const useFavorites = ({
|
|||||||
|
|
||||||
const queriedFavorites = mapFavorites(
|
const queriedFavorites = mapFavorites(
|
||||||
data.edges.map((edge) => edge.node),
|
data.edges.map((edge) => edge.node),
|
||||||
{
|
|
||||||
...allCompanies,
|
|
||||||
...allPeople,
|
|
||||||
},
|
|
||||||
);
|
);
|
||||||
|
|
||||||
if (!isDeeplyEqual(favorites, queriedFavorites)) {
|
if (!isDeeplyEqual(favorites, queriedFavorites)) {
|
||||||
set(favoritesState, queriedFavorites);
|
set(favoritesState, queriedFavorites);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
[allCompanies, allPeople],
|
[],
|
||||||
),
|
),
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -125,25 +71,20 @@ export const useFavorites = ({
|
|||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
const createdFavorite = result?.data?.createFavoriteV2;
|
const createdFavorite = result?.data?.createFavorite;
|
||||||
|
|
||||||
const newFavorite = {
|
const newFavorite = {
|
||||||
...additionalData,
|
...additionalData,
|
||||||
...createdFavorite,
|
...createdFavorite,
|
||||||
};
|
};
|
||||||
|
|
||||||
const newFavoritesMapped = mapFavorites([newFavorite], {
|
const newFavoritesMapped = mapFavorites([newFavorite]);
|
||||||
...allCompanies,
|
|
||||||
...allPeople,
|
|
||||||
});
|
|
||||||
|
|
||||||
if (createdFavorite) {
|
if (createdFavorite) {
|
||||||
set(favoritesState, [...favorites, ...newFavoritesMapped]);
|
set(favoritesState, [...favorites, ...newFavoritesMapped]);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
[
|
[
|
||||||
allCompanies,
|
|
||||||
allPeople,
|
|
||||||
apolloClient,
|
apolloClient,
|
||||||
createOneMutation,
|
createOneMutation,
|
||||||
currentWorkspaceMember,
|
currentWorkspaceMember,
|
||||||
|
|||||||
@ -1,48 +1,30 @@
|
|||||||
import { Company } from '@/companies/types/Company';
|
|
||||||
import { Person } from '@/people/types/Person';
|
|
||||||
import { getLogoUrlFromDomainName } from '~/utils';
|
import { getLogoUrlFromDomainName } from '~/utils';
|
||||||
import { assertNotNull } from '~/utils/assert';
|
import { assertNotNull } from '~/utils/assert';
|
||||||
import { isDefined } from '~/utils/isDefined';
|
import { isDefined } from '~/utils/isDefined';
|
||||||
|
|
||||||
export const mapFavorites = (
|
export const mapFavorites = (favorites: any) => {
|
||||||
favorites: any,
|
|
||||||
recordsDict: {
|
|
||||||
[key: string]: {
|
|
||||||
firstName?: Person['name']['firstName'];
|
|
||||||
lastName?: Person['name']['lastName'];
|
|
||||||
avatarUrl?: Person['avatarUrl'];
|
|
||||||
name?: Company['name'];
|
|
||||||
domainName?: Company['domainName'];
|
|
||||||
};
|
|
||||||
},
|
|
||||||
) => {
|
|
||||||
return favorites
|
return favorites
|
||||||
.map((favorite: any) => {
|
.map((favorite: any) => {
|
||||||
const recordInformation =
|
const recordInformation = isDefined(favorite?.person)
|
||||||
isDefined(favorite?.person) &&
|
? {
|
||||||
isDefined(recordsDict[favorite.person.id])
|
id: favorite.person.id,
|
||||||
? {
|
labelIdentifier:
|
||||||
id: favorite.person.id,
|
favorite.person.name.firstName +
|
||||||
labelIdentifier:
|
' ' +
|
||||||
recordsDict[favorite.person.id].firstName +
|
favorite.person.name.lastName,
|
||||||
' ' +
|
avatarUrl: favorite.person.avatarUrl,
|
||||||
recordsDict[favorite.person.id].lastName,
|
avatarType: 'rounded',
|
||||||
avatarUrl: recordsDict[favorite.person.id].avatarUrl,
|
link: `/object/person/${favorite.person.id}`,
|
||||||
avatarType: 'rounded',
|
}
|
||||||
link: `/object/personV2/${favorite.person.id}`,
|
: isDefined(favorite?.company)
|
||||||
}
|
? {
|
||||||
: isDefined(favorite?.company) &&
|
id: favorite.company.id,
|
||||||
isDefined(recordsDict[favorite.company.id])
|
labelIdentifier: favorite.company.name,
|
||||||
? {
|
avatarUrl: getLogoUrlFromDomainName(favorite.company.domainName),
|
||||||
id: favorite.company.id,
|
avatarType: 'squared',
|
||||||
labelIdentifier: recordsDict[favorite.company.id].name,
|
link: `/object/company/${favorite.company.id}`,
|
||||||
avatarUrl: getLogoUrlFromDomainName(
|
}
|
||||||
recordsDict[favorite.company.id].domainName ?? '',
|
: undefined;
|
||||||
),
|
|
||||||
avatarType: 'squared',
|
|
||||||
link: `/object/companyV2/${favorite.company.id}`,
|
|
||||||
}
|
|
||||||
: undefined;
|
|
||||||
|
|
||||||
return {
|
return {
|
||||||
...recordInformation,
|
...recordInformation,
|
||||||
|
|||||||
@ -42,7 +42,8 @@ export const ObjectMetadataItemsRelationPickerEffect = () => {
|
|||||||
) {
|
) {
|
||||||
return {
|
return {
|
||||||
id: record.id,
|
id: record.id,
|
||||||
name: record.name.firstName + ' ' + record.name.lastName,
|
name:
|
||||||
|
(record.name?.firstName ?? '') + ' ' + (record.name?.lastName ?? ''),
|
||||||
avatarUrl: record.avatarUrl,
|
avatarUrl: record.avatarUrl,
|
||||||
avatarType: 'rounded',
|
avatarType: 'rounded',
|
||||||
record: record,
|
record: record,
|
||||||
@ -52,7 +53,7 @@ export const ObjectMetadataItemsRelationPickerEffect = () => {
|
|||||||
if (['opportunity'].includes(objectMetadataItemSingularName)) {
|
if (['opportunity'].includes(objectMetadataItemSingularName)) {
|
||||||
return {
|
return {
|
||||||
id: record.id,
|
id: record.id,
|
||||||
name: record.company.name,
|
name: record?.company?.name,
|
||||||
avatarUrl: record.avatarUrl,
|
avatarUrl: record.avatarUrl,
|
||||||
avatarType: 'rounded',
|
avatarType: 'rounded',
|
||||||
record: record,
|
record: record,
|
||||||
|
|||||||
@ -20,10 +20,15 @@ export const useRelationFieldPreview = ({
|
|||||||
skip: skipDefaultValue || !relationObjectMetadataItem,
|
skip: skipDefaultValue || !relationObjectMetadataItem,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
const mockValueName = capitalize(
|
||||||
|
relationObjectMetadataItem?.nameSingular ?? '',
|
||||||
|
);
|
||||||
|
|
||||||
return {
|
return {
|
||||||
relationObjectMetadataItem,
|
relationObjectMetadataItem,
|
||||||
defaultValue: relationObjects?.[0] ?? {
|
defaultValue: relationObjects?.[0] ?? {
|
||||||
name: capitalize(relationObjectMetadataItem?.nameSingular ?? ''),
|
company: { name: mockValueName }, // Temporary mock for opportunities, this needs to be replaced once labelIdentifiers are implemented
|
||||||
|
name: mockValueName,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|||||||
@ -1,17 +1,12 @@
|
|||||||
import { useRef } from 'react';
|
import { useRef } from 'react';
|
||||||
import styled from '@emotion/styled';
|
import styled from '@emotion/styled';
|
||||||
|
|
||||||
|
import { RecordTableInternalEffect } from '@/ui/object/record-table/components/RecordTableInternalEffect';
|
||||||
|
import { useRecordTable } from '@/ui/object/record-table/hooks/useRecordTable';
|
||||||
import { DragSelect } from '@/ui/utilities/drag-select/components/DragSelect';
|
import { DragSelect } from '@/ui/utilities/drag-select/components/DragSelect';
|
||||||
import { useScopedHotkeys } from '@/ui/utilities/hotkey/hooks/useScopedHotkeys';
|
|
||||||
import {
|
|
||||||
useListenClickOutside,
|
|
||||||
useListenClickOutsideByClassName,
|
|
||||||
} from '@/ui/utilities/pointer-event/hooks/useListenClickOutside';
|
|
||||||
import { ScrollWrapper } from '@/ui/utilities/scroll/components/ScrollWrapper';
|
import { ScrollWrapper } from '@/ui/utilities/scroll/components/ScrollWrapper';
|
||||||
|
|
||||||
import { EntityUpdateMutationContext } from '../contexts/EntityUpdateMutationHookContext';
|
import { EntityUpdateMutationContext } from '../contexts/EntityUpdateMutationHookContext';
|
||||||
import { useRecordTable } from '../hooks/useRecordTable';
|
|
||||||
import { TableHotkeyScope } from '../types/TableHotkeyScope';
|
|
||||||
|
|
||||||
import { RecordTableBody } from './RecordTableBody';
|
import { RecordTableBody } from './RecordTableBody';
|
||||||
import { RecordTableHeader } from './RecordTableHeader';
|
import { RecordTableHeader } from './RecordTableHeader';
|
||||||
@ -82,37 +77,7 @@ type RecordTableProps = {
|
|||||||
export const RecordTable = ({ updateEntityMutation }: RecordTableProps) => {
|
export const RecordTable = ({ updateEntityMutation }: RecordTableProps) => {
|
||||||
const tableBodyRef = useRef<HTMLDivElement>(null);
|
const tableBodyRef = useRef<HTMLDivElement>(null);
|
||||||
|
|
||||||
const {
|
const { resetTableRowSelection, setRowSelectedState } = useRecordTable();
|
||||||
leaveTableFocus,
|
|
||||||
setRowSelectedState,
|
|
||||||
resetTableRowSelection,
|
|
||||||
useMapKeyboardToSoftFocus,
|
|
||||||
} = useRecordTable();
|
|
||||||
|
|
||||||
useMapKeyboardToSoftFocus();
|
|
||||||
|
|
||||||
useListenClickOutside({
|
|
||||||
refs: [tableBodyRef],
|
|
||||||
callback: () => {
|
|
||||||
leaveTableFocus();
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
useScopedHotkeys(
|
|
||||||
'escape',
|
|
||||||
() => {
|
|
||||||
resetTableRowSelection();
|
|
||||||
},
|
|
||||||
TableHotkeyScope.Table,
|
|
||||||
);
|
|
||||||
|
|
||||||
useListenClickOutsideByClassName({
|
|
||||||
classNames: ['entity-table-cell'],
|
|
||||||
excludeClassNames: ['action-bar', 'context-menu'],
|
|
||||||
callback: () => {
|
|
||||||
resetTableRowSelection();
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<ScrollWrapper>
|
<ScrollWrapper>
|
||||||
@ -130,6 +95,7 @@ export const RecordTable = ({ updateEntityMutation }: RecordTableProps) => {
|
|||||||
onDragSelectionChange={setRowSelectedState}
|
onDragSelectionChange={setRowSelectedState}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
<RecordTableInternalEffect tableBodyRef={tableBodyRef} />
|
||||||
</StyledTableContainer>
|
</StyledTableContainer>
|
||||||
</StyledTableWithHeader>
|
</StyledTableWithHeader>
|
||||||
</EntityUpdateMutationContext.Provider>
|
</EntityUpdateMutationContext.Provider>
|
||||||
|
|||||||
@ -0,0 +1,45 @@
|
|||||||
|
import { useRecordTable } from '@/ui/object/record-table/hooks/useRecordTable';
|
||||||
|
import { TableHotkeyScope } from '@/ui/object/record-table/types/TableHotkeyScope';
|
||||||
|
import { useScopedHotkeys } from '@/ui/utilities/hotkey/hooks/useScopedHotkeys';
|
||||||
|
import {
|
||||||
|
useListenClickOutside,
|
||||||
|
useListenClickOutsideByClassName,
|
||||||
|
} from '@/ui/utilities/pointer-event/hooks/useListenClickOutside';
|
||||||
|
|
||||||
|
type RecordTableInternalEffectProps = {
|
||||||
|
tableBodyRef: React.RefObject<HTMLDivElement>;
|
||||||
|
};
|
||||||
|
|
||||||
|
export const RecordTableInternalEffect = ({
|
||||||
|
tableBodyRef,
|
||||||
|
}: RecordTableInternalEffectProps) => {
|
||||||
|
const { leaveTableFocus, resetTableRowSelection, useMapKeyboardToSoftFocus } =
|
||||||
|
useRecordTable();
|
||||||
|
|
||||||
|
useMapKeyboardToSoftFocus();
|
||||||
|
|
||||||
|
useListenClickOutside({
|
||||||
|
refs: [tableBodyRef],
|
||||||
|
callback: () => {
|
||||||
|
leaveTableFocus();
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
useScopedHotkeys(
|
||||||
|
'escape',
|
||||||
|
() => {
|
||||||
|
resetTableRowSelection();
|
||||||
|
},
|
||||||
|
TableHotkeyScope.Table,
|
||||||
|
);
|
||||||
|
|
||||||
|
useListenClickOutsideByClassName({
|
||||||
|
classNames: ['entity-table-cell'],
|
||||||
|
excludeClassNames: ['action-bar', 'context-menu'],
|
||||||
|
callback: () => {
|
||||||
|
resetTableRowSelection();
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
return <></>;
|
||||||
|
};
|
||||||
@ -18,7 +18,6 @@ import { ColumnDefinition } from '../types/ColumnDefinition';
|
|||||||
import { TableHotkeyScope } from '../types/TableHotkeyScope';
|
import { TableHotkeyScope } from '../types/TableHotkeyScope';
|
||||||
|
|
||||||
import { useDisableSoftFocus } from './internal/useDisableSoftFocus';
|
import { useDisableSoftFocus } from './internal/useDisableSoftFocus';
|
||||||
import { useGetIsSomeCellInEditMode } from './internal/useGetIsSomeCellInEditMode';
|
|
||||||
import { useLeaveTableFocus } from './internal/useLeaveTableFocus';
|
import { useLeaveTableFocus } from './internal/useLeaveTableFocus';
|
||||||
import { useRecordTableScopedStates } from './internal/useRecordTableScopedStates';
|
import { useRecordTableScopedStates } from './internal/useRecordTableScopedStates';
|
||||||
import { useResetTableRowSelection } from './internal/useResetTableRowSelection';
|
import { useResetTableRowSelection } from './internal/useResetTableRowSelection';
|
||||||
@ -99,8 +98,6 @@ export const useRecordTable = (props?: useRecordTableProps) => {
|
|||||||
|
|
||||||
const leaveTableFocus = useLeaveTableFocus();
|
const leaveTableFocus = useLeaveTableFocus();
|
||||||
|
|
||||||
const getIsSomeCellInEditMode = useGetIsSomeCellInEditMode();
|
|
||||||
|
|
||||||
const setRowSelectedState = useSetRowSelectedState();
|
const setRowSelectedState = useSetRowSelectedState();
|
||||||
|
|
||||||
const resetTableRowSelection = useResetTableRowSelection();
|
const resetTableRowSelection = useResetTableRowSelection();
|
||||||
@ -308,7 +305,6 @@ export const useRecordTable = (props?: useRecordTableProps) => {
|
|||||||
setRecordTableData,
|
setRecordTableData,
|
||||||
setTableColumns,
|
setTableColumns,
|
||||||
leaveTableFocus,
|
leaveTableFocus,
|
||||||
getIsSomeCellInEditMode,
|
|
||||||
setRowSelectedState,
|
setRowSelectedState,
|
||||||
resetTableRowSelection,
|
resetTableRowSelection,
|
||||||
upsertRecordTableItem,
|
upsertRecordTableItem,
|
||||||
|
|||||||
@ -5,11 +5,11 @@ import { IconArrowUpRight } from '@/ui/display/icon';
|
|||||||
import { useGetButtonIcon } from '@/ui/object/field/hooks/useGetButtonIcon';
|
import { useGetButtonIcon } from '@/ui/object/field/hooks/useGetButtonIcon';
|
||||||
import { useIsFieldEmpty } from '@/ui/object/field/hooks/useIsFieldEmpty';
|
import { useIsFieldEmpty } from '@/ui/object/field/hooks/useIsFieldEmpty';
|
||||||
import { useIsFieldInputOnly } from '@/ui/object/field/hooks/useIsFieldInputOnly';
|
import { useIsFieldInputOnly } from '@/ui/object/field/hooks/useIsFieldInputOnly';
|
||||||
|
import { useGetIsSomeCellInEditMode } from '@/ui/object/record-table/hooks/internal/useGetIsSomeCellInEditMode';
|
||||||
import { HotkeyScope } from '@/ui/utilities/hotkey/types/HotkeyScope';
|
import { HotkeyScope } from '@/ui/utilities/hotkey/types/HotkeyScope';
|
||||||
|
|
||||||
import { CellHotkeyScopeContext } from '../../contexts/CellHotkeyScopeContext';
|
import { CellHotkeyScopeContext } from '../../contexts/CellHotkeyScopeContext';
|
||||||
import { ColumnIndexContext } from '../../contexts/ColumnIndexContext';
|
import { ColumnIndexContext } from '../../contexts/ColumnIndexContext';
|
||||||
import { useRecordTable } from '../../hooks/useRecordTable';
|
|
||||||
import { TableHotkeyScope } from '../../types/TableHotkeyScope';
|
import { TableHotkeyScope } from '../../types/TableHotkeyScope';
|
||||||
import { useCurrentTableCellEditMode } from '../hooks/useCurrentTableCellEditMode';
|
import { useCurrentTableCellEditMode } from '../hooks/useCurrentTableCellEditMode';
|
||||||
import { useIsSoftFocusOnCurrentTableCell } from '../hooks/useIsSoftFocusOnCurrentTableCell';
|
import { useIsSoftFocusOnCurrentTableCell } from '../hooks/useIsSoftFocusOnCurrentTableCell';
|
||||||
@ -57,7 +57,7 @@ export const TableCellContainer = ({
|
|||||||
}: TableCellContainerProps) => {
|
}: TableCellContainerProps) => {
|
||||||
const { isCurrentTableCellInEditMode } = useCurrentTableCellEditMode();
|
const { isCurrentTableCellInEditMode } = useCurrentTableCellEditMode();
|
||||||
|
|
||||||
const { getIsSomeCellInEditMode } = useRecordTable();
|
const getIsSomeCellInEditMode = useGetIsSomeCellInEditMode();
|
||||||
|
|
||||||
const [isHovered, setIsHovered] = useState(false);
|
const [isHovered, setIsHovered] = useState(false);
|
||||||
|
|
||||||
|
|||||||
@ -5,12 +5,12 @@ import { useRecoilCallback, useRecoilValue } from 'recoil';
|
|||||||
import { useFindManyObjectRecords } from '@/object-record/hooks/useFindManyObjectRecords';
|
import { useFindManyObjectRecords } from '@/object-record/hooks/useFindManyObjectRecords';
|
||||||
import { PaginatedObjectTypeResults } from '@/object-record/types/PaginatedObjectTypeResults';
|
import { PaginatedObjectTypeResults } from '@/object-record/types/PaginatedObjectTypeResults';
|
||||||
import { getSnapshotValue } from '@/ui/utilities/recoil-scope/utils/getSnapshotValue';
|
import { getSnapshotValue } from '@/ui/utilities/recoil-scope/utils/getSnapshotValue';
|
||||||
|
import { GraphQLView } from '@/views/types/GraphQLView';
|
||||||
import { assertNotNull } from '~/utils/assert';
|
import { assertNotNull } from '~/utils/assert';
|
||||||
import { isDeeplyEqual } from '~/utils/isDeeplyEqual';
|
import { isDeeplyEqual } from '~/utils/isDeeplyEqual';
|
||||||
|
|
||||||
import { useViewScopedStates } from '../hooks/internal/useViewScopedStates';
|
import { useViewScopedStates } from '../hooks/internal/useViewScopedStates';
|
||||||
import { useView } from '../hooks/useView';
|
import { useView } from '../hooks/useView';
|
||||||
import { View } from '../types/View';
|
|
||||||
import { ViewField } from '../types/ViewField';
|
import { ViewField } from '../types/ViewField';
|
||||||
import { ViewFilter } from '../types/ViewFilter';
|
import { ViewFilter } from '../types/ViewFilter';
|
||||||
import { ViewSort } from '../types/ViewSort';
|
import { ViewSort } from '../types/ViewSort';
|
||||||
@ -18,12 +18,7 @@ import { getViewScopedStatesFromSnapshot } from '../utils/getViewScopedStatesFro
|
|||||||
import { getViewScopedStateValuesFromSnapshot } from '../utils/getViewScopedStateValuesFromSnapshot';
|
import { getViewScopedStateValuesFromSnapshot } from '../utils/getViewScopedStateValuesFromSnapshot';
|
||||||
|
|
||||||
export const ViewBarEffect = () => {
|
export const ViewBarEffect = () => {
|
||||||
const {
|
const { scopeId: viewScopeId, loadView, changeViewInUrl } = useView();
|
||||||
scopeId: viewScopeId,
|
|
||||||
currentViewId,
|
|
||||||
loadView,
|
|
||||||
changeViewInUrl,
|
|
||||||
} = useView();
|
|
||||||
|
|
||||||
const [searchParams] = useSearchParams();
|
const [searchParams] = useSearchParams();
|
||||||
const currentViewIdFromUrl = searchParams.get('view');
|
const currentViewIdFromUrl = searchParams.get('view');
|
||||||
@ -34,6 +29,7 @@ export const ViewBarEffect = () => {
|
|||||||
const viewObjectMetadataId = useRecoilValue(viewObjectMetadataIdState);
|
const viewObjectMetadataId = useRecoilValue(viewObjectMetadataIdState);
|
||||||
|
|
||||||
useFindManyObjectRecords({
|
useFindManyObjectRecords({
|
||||||
|
skip: !viewObjectMetadataId,
|
||||||
objectNamePlural: 'views',
|
objectNamePlural: 'views',
|
||||||
filter: {
|
filter: {
|
||||||
type: { eq: viewType },
|
type: { eq: viewType },
|
||||||
@ -41,177 +37,190 @@ export const ViewBarEffect = () => {
|
|||||||
},
|
},
|
||||||
onCompleted: useRecoilCallback(
|
onCompleted: useRecoilCallback(
|
||||||
({ snapshot, set }) =>
|
({ snapshot, set }) =>
|
||||||
async (data: PaginatedObjectTypeResults<View>) => {
|
async (data: PaginatedObjectTypeResults<GraphQLView>) => {
|
||||||
const nextViews = data.edges.map((view) => ({
|
const nextViews = data.edges.map((view) => ({
|
||||||
id: view.node.id,
|
id: view.node.id,
|
||||||
name: view.node.name,
|
name: view.node.name,
|
||||||
objectMetadataId: view.node.objectMetadataId,
|
objectMetadataId: view.node.objectMetadataId,
|
||||||
}));
|
}));
|
||||||
|
|
||||||
const { viewsState } = getViewScopedStatesFromSnapshot({
|
const { viewsState, currentViewIdState } =
|
||||||
snapshot,
|
getViewScopedStatesFromSnapshot({
|
||||||
viewScopeId,
|
snapshot,
|
||||||
});
|
viewScopeId,
|
||||||
|
});
|
||||||
|
|
||||||
const views = getSnapshotValue(snapshot, viewsState);
|
const views = getSnapshotValue(snapshot, viewsState);
|
||||||
|
|
||||||
if (!isDeeplyEqual(views, nextViews)) set(viewsState, nextViews);
|
if (!isDeeplyEqual(views, nextViews)) set(viewsState, nextViews);
|
||||||
|
|
||||||
if (!nextViews.length) return;
|
const currentView =
|
||||||
|
data.edges
|
||||||
|
.map((view) => view.node)
|
||||||
|
.find((view) => view.id === currentViewIdFromUrl) ??
|
||||||
|
data.edges[0].node;
|
||||||
|
|
||||||
|
set(currentViewIdState, currentView.id);
|
||||||
|
|
||||||
|
if (currentView?.viewFields) {
|
||||||
|
updateViewFields(currentView.viewFields, currentView.id);
|
||||||
|
updateViewFilters(currentView.viewFilters, currentView.id);
|
||||||
|
updateViewSorts(currentView.viewSorts, currentView.id);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!nextViews.length) return;
|
||||||
if (!currentViewIdFromUrl) return changeViewInUrl(nextViews[0].id);
|
if (!currentViewIdFromUrl) return changeViewInUrl(nextViews[0].id);
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
});
|
});
|
||||||
|
|
||||||
useFindManyObjectRecords({
|
const updateViewFields = useRecoilCallback(
|
||||||
skip: !currentViewId,
|
({ snapshot, set }) =>
|
||||||
objectNamePlural: 'viewFields',
|
async (
|
||||||
filter: { viewId: { eq: currentViewId } },
|
data: PaginatedObjectTypeResults<ViewField>,
|
||||||
onCompleted: useRecoilCallback(
|
currentViewId: string,
|
||||||
({ snapshot, set }) =>
|
) => {
|
||||||
async (data: PaginatedObjectTypeResults<ViewField>) => {
|
const {
|
||||||
const {
|
availableFieldDefinitions,
|
||||||
availableFieldDefinitions,
|
onViewFieldsChange,
|
||||||
onViewFieldsChange,
|
savedViewFields,
|
||||||
savedViewFields,
|
isPersistingView,
|
||||||
currentViewId,
|
} = getViewScopedStateValuesFromSnapshot({
|
||||||
} = getViewScopedStateValuesFromSnapshot({
|
snapshot,
|
||||||
|
viewScopeId,
|
||||||
|
viewId: currentViewId,
|
||||||
|
});
|
||||||
|
|
||||||
|
const { savedViewFieldsState, currentViewFieldsState } =
|
||||||
|
getViewScopedStatesFromSnapshot({
|
||||||
snapshot,
|
snapshot,
|
||||||
viewScopeId,
|
viewScopeId,
|
||||||
|
viewId: currentViewId,
|
||||||
});
|
});
|
||||||
|
|
||||||
const { savedViewFieldsState, currentViewFieldsState } =
|
if (!availableFieldDefinitions) {
|
||||||
getViewScopedStatesFromSnapshot({
|
return;
|
||||||
snapshot,
|
}
|
||||||
viewScopeId,
|
|
||||||
});
|
|
||||||
|
|
||||||
if (!availableFieldDefinitions || !currentViewId) {
|
const queriedViewFields = data.edges
|
||||||
return;
|
.map((viewField) => viewField.node)
|
||||||
}
|
.filter(assertNotNull);
|
||||||
|
|
||||||
const queriedViewFields = data.edges
|
if (isPersistingView) {
|
||||||
.map((viewField) => viewField.node)
|
return;
|
||||||
.filter(assertNotNull);
|
}
|
||||||
|
|
||||||
if (!isDeeplyEqual(savedViewFields, queriedViewFields)) {
|
if (!isDeeplyEqual(savedViewFields, queriedViewFields)) {
|
||||||
set(currentViewFieldsState, queriedViewFields);
|
set(currentViewFieldsState, queriedViewFields);
|
||||||
set(savedViewFieldsState, queriedViewFields);
|
set(savedViewFieldsState, queriedViewFields);
|
||||||
onViewFieldsChange?.(queriedViewFields);
|
onViewFieldsChange?.(queriedViewFields);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
[viewScopeId],
|
[viewScopeId],
|
||||||
),
|
);
|
||||||
});
|
|
||||||
|
|
||||||
useFindManyObjectRecords({
|
const updateViewFilters = useRecoilCallback(
|
||||||
skip: !currentViewId,
|
({ snapshot, set }) =>
|
||||||
objectNamePlural: 'viewFilters',
|
async (
|
||||||
filter: { viewId: { eq: currentViewId } },
|
data: PaginatedObjectTypeResults<Required<ViewFilter>>,
|
||||||
onCompleted: useRecoilCallback(
|
currentViewId: string,
|
||||||
({ snapshot, set }) =>
|
) => {
|
||||||
async (data: PaginatedObjectTypeResults<Required<ViewFilter>>) => {
|
const {
|
||||||
const {
|
availableFilterDefinitions,
|
||||||
availableFilterDefinitions,
|
savedViewFilters,
|
||||||
savedViewFilters,
|
onViewFiltersChange,
|
||||||
onViewFiltersChange,
|
} = getViewScopedStateValuesFromSnapshot({
|
||||||
currentViewId,
|
snapshot,
|
||||||
} = getViewScopedStateValuesFromSnapshot({
|
viewScopeId,
|
||||||
|
viewId: currentViewId,
|
||||||
|
});
|
||||||
|
|
||||||
|
const { savedViewFiltersState, currentViewFiltersState } =
|
||||||
|
getViewScopedStatesFromSnapshot({
|
||||||
snapshot,
|
snapshot,
|
||||||
viewScopeId,
|
viewScopeId,
|
||||||
|
viewId: currentViewId,
|
||||||
});
|
});
|
||||||
|
|
||||||
const { savedViewFiltersState, currentViewFiltersState } =
|
if (!availableFilterDefinitions) {
|
||||||
getViewScopedStatesFromSnapshot({
|
return;
|
||||||
snapshot,
|
}
|
||||||
viewScopeId,
|
|
||||||
});
|
|
||||||
|
|
||||||
if (!availableFilterDefinitions || !currentViewId) {
|
const queriedViewFilters = data.edges
|
||||||
return;
|
.map(({ node }) => {
|
||||||
}
|
const availableFilterDefinition = availableFilterDefinitions.find(
|
||||||
|
(filterDefinition) =>
|
||||||
|
filterDefinition.fieldMetadataId === node.fieldMetadataId,
|
||||||
|
);
|
||||||
|
|
||||||
const queriedViewFilters = data.edges
|
if (!availableFilterDefinition) return null;
|
||||||
.map(({ node }) => {
|
|
||||||
const availableFilterDefinition = availableFilterDefinitions.find(
|
|
||||||
(filterDefinition) =>
|
|
||||||
filterDefinition.fieldMetadataId === node.fieldMetadataId,
|
|
||||||
);
|
|
||||||
|
|
||||||
if (!availableFilterDefinition) return null;
|
return {
|
||||||
|
...node,
|
||||||
|
displayValue: node.displayValue ?? node.value,
|
||||||
|
definition: availableFilterDefinition,
|
||||||
|
};
|
||||||
|
})
|
||||||
|
.filter(assertNotNull);
|
||||||
|
|
||||||
return {
|
if (!isDeeplyEqual(savedViewFilters, queriedViewFilters)) {
|
||||||
...node,
|
set(savedViewFiltersState, queriedViewFilters);
|
||||||
displayValue: node.displayValue ?? node.value,
|
set(currentViewFiltersState, queriedViewFilters);
|
||||||
definition: availableFilterDefinition,
|
onViewFiltersChange?.(queriedViewFilters);
|
||||||
};
|
}
|
||||||
})
|
},
|
||||||
.filter(assertNotNull);
|
[viewScopeId],
|
||||||
|
);
|
||||||
|
|
||||||
if (!isDeeplyEqual(savedViewFilters, queriedViewFilters)) {
|
const updateViewSorts = useRecoilCallback(
|
||||||
set(savedViewFiltersState, queriedViewFilters);
|
({ snapshot, set }) =>
|
||||||
set(currentViewFiltersState, queriedViewFilters);
|
async (
|
||||||
onViewFiltersChange?.(queriedViewFilters);
|
data: PaginatedObjectTypeResults<Required<ViewSort>>,
|
||||||
}
|
currentViewId: string,
|
||||||
},
|
) => {
|
||||||
[viewScopeId],
|
const { availableSortDefinitions, savedViewSorts, onViewSortsChange } =
|
||||||
),
|
getViewScopedStateValuesFromSnapshot({
|
||||||
});
|
|
||||||
|
|
||||||
useFindManyObjectRecords({
|
|
||||||
skip: !currentViewId,
|
|
||||||
objectNamePlural: 'viewSorts',
|
|
||||||
filter: { viewId: { eq: currentViewId } },
|
|
||||||
onCompleted: useRecoilCallback(
|
|
||||||
({ snapshot, set }) =>
|
|
||||||
async (data: PaginatedObjectTypeResults<Required<ViewSort>>) => {
|
|
||||||
const {
|
|
||||||
availableSortDefinitions,
|
|
||||||
savedViewSorts,
|
|
||||||
onViewSortsChange,
|
|
||||||
currentViewId,
|
|
||||||
} = getViewScopedStateValuesFromSnapshot({
|
|
||||||
snapshot,
|
snapshot,
|
||||||
viewScopeId,
|
viewScopeId,
|
||||||
|
viewId: currentViewId,
|
||||||
});
|
});
|
||||||
|
|
||||||
const { savedViewSortsState, currentViewSortsState } =
|
const { savedViewSortsState, currentViewSortsState } =
|
||||||
getViewScopedStatesFromSnapshot({
|
getViewScopedStatesFromSnapshot({
|
||||||
snapshot,
|
snapshot,
|
||||||
viewScopeId,
|
viewScopeId,
|
||||||
});
|
viewId: currentViewId,
|
||||||
|
});
|
||||||
|
|
||||||
if (!availableSortDefinitions || !currentViewId) {
|
if (!availableSortDefinitions || !currentViewId) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const queriedViewSorts = data.edges
|
const queriedViewSorts = data.edges
|
||||||
.map(({ node }) => {
|
.map(({ node }) => {
|
||||||
const availableSortDefinition = availableSortDefinitions.find(
|
const availableSortDefinition = availableSortDefinitions.find(
|
||||||
(sort) => sort.fieldMetadataId === node.fieldMetadataId,
|
(sort) => sort.fieldMetadataId === node.fieldMetadataId,
|
||||||
);
|
);
|
||||||
|
|
||||||
if (!availableSortDefinition) return null;
|
if (!availableSortDefinition) return null;
|
||||||
|
|
||||||
return {
|
return {
|
||||||
id: node.id,
|
id: node.id,
|
||||||
fieldMetadataId: node.fieldMetadataId,
|
fieldMetadataId: node.fieldMetadataId,
|
||||||
direction: node.direction,
|
direction: node.direction,
|
||||||
definition: availableSortDefinition,
|
definition: availableSortDefinition,
|
||||||
};
|
};
|
||||||
})
|
})
|
||||||
.filter(assertNotNull);
|
.filter(assertNotNull);
|
||||||
|
|
||||||
if (!isDeeplyEqual(savedViewSorts, queriedViewSorts)) {
|
if (!isDeeplyEqual(savedViewSorts, queriedViewSorts)) {
|
||||||
set(savedViewSortsState, queriedViewSorts);
|
set(savedViewSortsState, queriedViewSorts);
|
||||||
set(currentViewSortsState, queriedViewSorts);
|
set(currentViewSortsState, queriedViewSorts);
|
||||||
onViewSortsChange?.(queriedViewSorts);
|
onViewSortsChange?.(queriedViewSorts);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
[viewScopeId],
|
[viewScopeId],
|
||||||
),
|
);
|
||||||
});
|
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (!currentViewIdFromUrl) return;
|
if (!currentViewIdFromUrl) return;
|
||||||
|
|||||||
@ -3,18 +3,18 @@ import { useRecoilCallback } from 'recoil';
|
|||||||
|
|
||||||
import { useObjectMetadataItem } from '@/object-metadata/hooks/useObjectMetadataItem';
|
import { useObjectMetadataItem } from '@/object-metadata/hooks/useObjectMetadataItem';
|
||||||
import { ViewField } from '@/views/types/ViewField';
|
import { ViewField } from '@/views/types/ViewField';
|
||||||
|
import { getViewScopedStatesFromSnapshot } from '@/views/utils/getViewScopedStatesFromSnapshot';
|
||||||
import { getViewScopedStateValuesFromSnapshot } from '@/views/utils/getViewScopedStateValuesFromSnapshot';
|
import { getViewScopedStateValuesFromSnapshot } from '@/views/utils/getViewScopedStateValuesFromSnapshot';
|
||||||
|
|
||||||
export const useViewFields = (viewScopeId: string) => {
|
export const useViewFields = (viewScopeId: string) => {
|
||||||
const { updateOneMutation, createOneMutation, findManyQuery } =
|
const { updateOneMutation, createOneMutation } = useObjectMetadataItem({
|
||||||
useObjectMetadataItem({
|
objectNameSingular: 'viewField',
|
||||||
objectNameSingular: 'viewField',
|
});
|
||||||
});
|
|
||||||
|
|
||||||
const apolloClient = useApolloClient();
|
const apolloClient = useApolloClient();
|
||||||
|
|
||||||
const persistViewFields = useRecoilCallback(
|
const persistViewFields = useRecoilCallback(
|
||||||
({ snapshot }) =>
|
({ snapshot, set }) =>
|
||||||
async (viewFieldsToPersist: ViewField[], viewId?: string) => {
|
async (viewFieldsToPersist: ViewField[], viewId?: string) => {
|
||||||
const { viewObjectMetadataId, currentViewId, savedViewFieldsByKey } =
|
const { viewObjectMetadataId, currentViewId, savedViewFieldsByKey } =
|
||||||
getViewScopedStateValuesFromSnapshot({
|
getViewScopedStateValuesFromSnapshot({
|
||||||
@ -23,6 +23,12 @@ export const useViewFields = (viewScopeId: string) => {
|
|||||||
viewId,
|
viewId,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
const { isPersistingViewState } = getViewScopedStatesFromSnapshot({
|
||||||
|
snapshot,
|
||||||
|
viewScopeId,
|
||||||
|
viewId,
|
||||||
|
});
|
||||||
|
|
||||||
const viewIdToPersist = viewId ?? currentViewId;
|
const viewIdToPersist = viewId ?? currentViewId;
|
||||||
|
|
||||||
if (!currentViewId || !savedViewFieldsByKey || !viewObjectMetadataId) {
|
if (!currentViewId || !savedViewFieldsByKey || !viewObjectMetadataId) {
|
||||||
@ -47,7 +53,6 @@ export const useViewFields = (viewScopeId: string) => {
|
|||||||
position: viewField.position,
|
position: viewField.position,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
refetchQueries: [findManyQuery],
|
|
||||||
}),
|
}),
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
@ -90,17 +95,13 @@ export const useViewFields = (viewScopeId: string) => {
|
|||||||
.isVisible !== viewFieldToPersit.isVisible),
|
.isVisible !== viewFieldToPersit.isVisible),
|
||||||
);
|
);
|
||||||
|
|
||||||
|
set(isPersistingViewState, true);
|
||||||
await _createViewFields(viewFieldsToCreate);
|
await _createViewFields(viewFieldsToCreate);
|
||||||
|
|
||||||
await _updateViewFields(viewFieldsToUpdate);
|
await _updateViewFields(viewFieldsToUpdate);
|
||||||
|
set(isPersistingViewState, false);
|
||||||
},
|
},
|
||||||
[
|
[apolloClient, createOneMutation, updateOneMutation, viewScopeId],
|
||||||
apolloClient,
|
|
||||||
createOneMutation,
|
|
||||||
findManyQuery,
|
|
||||||
updateOneMutation,
|
|
||||||
viewScopeId,
|
|
||||||
],
|
|
||||||
);
|
);
|
||||||
|
|
||||||
return { persistViewFields };
|
return { persistViewFields };
|
||||||
|
|||||||
@ -11,14 +11,10 @@ import { getViewScopedStateValuesFromSnapshot } from '@/views/utils/getViewScope
|
|||||||
import { useViewScopedStates } from './useViewScopedStates';
|
import { useViewScopedStates } from './useViewScopedStates';
|
||||||
|
|
||||||
export const useViewFilters = (viewScopeId: string) => {
|
export const useViewFilters = (viewScopeId: string) => {
|
||||||
const {
|
const { updateOneMutation, createOneMutation, deleteOneMutation } =
|
||||||
updateOneMutation,
|
useObjectMetadataItem({
|
||||||
createOneMutation,
|
objectNameSingular: 'viewFilter',
|
||||||
deleteOneMutation,
|
});
|
||||||
findManyQuery,
|
|
||||||
} = useObjectMetadataItem({
|
|
||||||
objectNameSingular: 'viewFilter',
|
|
||||||
});
|
|
||||||
const apolloClient = useApolloClient();
|
const apolloClient = useApolloClient();
|
||||||
|
|
||||||
const { currentViewFiltersState } = useViewScopedStates({
|
const { currentViewFiltersState } = useViewScopedStates({
|
||||||
@ -60,7 +56,6 @@ export const useViewFilters = (viewScopeId: string) => {
|
|||||||
operand: viewFilter.operand,
|
operand: viewFilter.operand,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
refetchQueries: [findManyQuery],
|
|
||||||
}),
|
}),
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
@ -139,7 +134,6 @@ export const useViewFilters = (viewScopeId: string) => {
|
|||||||
apolloClient,
|
apolloClient,
|
||||||
createOneMutation,
|
createOneMutation,
|
||||||
deleteOneMutation,
|
deleteOneMutation,
|
||||||
findManyQuery,
|
|
||||||
updateOneMutation,
|
updateOneMutation,
|
||||||
viewScopeId,
|
viewScopeId,
|
||||||
],
|
],
|
||||||
|
|||||||
@ -36,6 +36,7 @@ export const useViewScopedStates = (args?: { customViewScopeId?: string }) => {
|
|||||||
currentViewSortsState,
|
currentViewSortsState,
|
||||||
entityCountInCurrentViewState,
|
entityCountInCurrentViewState,
|
||||||
isViewBarExpandedState,
|
isViewBarExpandedState,
|
||||||
|
isPersistingViewState,
|
||||||
onViewFieldsChangeState,
|
onViewFieldsChangeState,
|
||||||
onViewFiltersChangeState,
|
onViewFiltersChangeState,
|
||||||
onViewSortsChangeState,
|
onViewSortsChangeState,
|
||||||
@ -67,6 +68,7 @@ export const useViewScopedStates = (args?: { customViewScopeId?: string }) => {
|
|||||||
currentViewSortsState,
|
currentViewSortsState,
|
||||||
entityCountInCurrentViewState,
|
entityCountInCurrentViewState,
|
||||||
isViewBarExpandedState,
|
isViewBarExpandedState,
|
||||||
|
isPersistingViewState,
|
||||||
onViewFieldsChangeState,
|
onViewFieldsChangeState,
|
||||||
onViewFiltersChangeState,
|
onViewFiltersChangeState,
|
||||||
onViewSortsChangeState,
|
onViewSortsChangeState,
|
||||||
|
|||||||
@ -11,14 +11,10 @@ import { getViewScopedStateValuesFromSnapshot } from '@/views/utils/getViewScope
|
|||||||
import { useViewScopedStates } from './useViewScopedStates';
|
import { useViewScopedStates } from './useViewScopedStates';
|
||||||
|
|
||||||
export const useViewSorts = (viewScopeId: string) => {
|
export const useViewSorts = (viewScopeId: string) => {
|
||||||
const {
|
const { updateOneMutation, createOneMutation, deleteOneMutation } =
|
||||||
updateOneMutation,
|
useObjectMetadataItem({
|
||||||
createOneMutation,
|
objectNameSingular: 'viewSort',
|
||||||
deleteOneMutation,
|
});
|
||||||
findManyQuery,
|
|
||||||
} = useObjectMetadataItem({
|
|
||||||
objectNameSingular: 'viewSort',
|
|
||||||
});
|
|
||||||
const apolloClient = useApolloClient();
|
const apolloClient = useApolloClient();
|
||||||
|
|
||||||
const { currentViewSortsState } = useViewScopedStates({
|
const { currentViewSortsState } = useViewScopedStates({
|
||||||
@ -59,7 +55,6 @@ export const useViewSorts = (viewScopeId: string) => {
|
|||||||
direction: viewSort.direction,
|
direction: viewSort.direction,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
refetchQueries: [findManyQuery],
|
|
||||||
}),
|
}),
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
@ -132,7 +127,6 @@ export const useViewSorts = (viewScopeId: string) => {
|
|||||||
apolloClient,
|
apolloClient,
|
||||||
createOneMutation,
|
createOneMutation,
|
||||||
deleteOneMutation,
|
deleteOneMutation,
|
||||||
findManyQuery,
|
|
||||||
updateOneMutation,
|
updateOneMutation,
|
||||||
viewScopeId,
|
viewScopeId,
|
||||||
],
|
],
|
||||||
|
|||||||
@ -1,7 +1,7 @@
|
|||||||
import { ReactNode } from 'react';
|
import { ReactNode } from 'react';
|
||||||
|
|
||||||
import { Filter } from '@/ui/object/object-filter-dropdown/types/Filter';
|
import { ViewFilter } from '@/views/types/ViewFilter';
|
||||||
import { Sort } from '@/ui/object/object-sort-dropdown/types/Sort';
|
import { ViewSort } from '@/views/types/ViewSort';
|
||||||
|
|
||||||
import { ViewField } from '../types/ViewField';
|
import { ViewField } from '../types/ViewField';
|
||||||
|
|
||||||
@ -11,8 +11,8 @@ import { ViewScopeInternalContext } from './scope-internal-context/ViewScopeInte
|
|||||||
type ViewScopeProps = {
|
type ViewScopeProps = {
|
||||||
children: ReactNode;
|
children: ReactNode;
|
||||||
viewScopeId: string;
|
viewScopeId: string;
|
||||||
onViewSortsChange?: (sorts: Sort[]) => void | Promise<void>;
|
onViewSortsChange?: (sorts: ViewSort[]) => void | Promise<void>;
|
||||||
onViewFiltersChange?: (filters: Filter[]) => void | Promise<void>;
|
onViewFiltersChange?: (filters: ViewFilter[]) => void | Promise<void>;
|
||||||
onViewFieldsChange?: (fields: ViewField[]) => void | Promise<void>;
|
onViewFieldsChange?: (fields: ViewField[]) => void | Promise<void>;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@ -1,15 +1,15 @@
|
|||||||
import { useEffect } from 'react';
|
import { useEffect } from 'react';
|
||||||
import { useSetRecoilState } from 'recoil';
|
import { useSetRecoilState } from 'recoil';
|
||||||
|
|
||||||
import { Filter } from '@/ui/object/object-filter-dropdown/types/Filter';
|
|
||||||
import { Sort } from '@/ui/object/object-sort-dropdown/types/Sort';
|
|
||||||
import { useViewScopedStates } from '@/views/hooks/internal/useViewScopedStates';
|
import { useViewScopedStates } from '@/views/hooks/internal/useViewScopedStates';
|
||||||
import { ViewField } from '@/views/types/ViewField';
|
import { ViewField } from '@/views/types/ViewField';
|
||||||
|
import { ViewFilter } from '@/views/types/ViewFilter';
|
||||||
|
import { ViewSort } from '@/views/types/ViewSort';
|
||||||
|
|
||||||
type ViewScopeInitEffectProps = {
|
type ViewScopeInitEffectProps = {
|
||||||
viewScopeId: string;
|
viewScopeId: string;
|
||||||
onViewSortsChange?: (sorts: Sort[]) => void | Promise<void>;
|
onViewSortsChange?: (sorts: ViewSort[]) => void | Promise<void>;
|
||||||
onViewFiltersChange?: (filters: Filter[]) => void | Promise<void>;
|
onViewFiltersChange?: (filters: ViewFilter[]) => void | Promise<void>;
|
||||||
onViewFieldsChange?: (fields: ViewField[]) => void | Promise<void>;
|
onViewFieldsChange?: (fields: ViewField[]) => void | Promise<void>;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@ -0,0 +1,6 @@
|
|||||||
|
import { createScopedState } from '@/ui/utilities/recoil-scope/utils/createScopedState';
|
||||||
|
|
||||||
|
export const isPersistingViewScopedState = createScopedState<boolean>({
|
||||||
|
key: 'isPersistingViewScopedState',
|
||||||
|
defaultValue: false,
|
||||||
|
});
|
||||||
@ -1,8 +1,8 @@
|
|||||||
import { Filter } from '@/ui/object/object-filter-dropdown/types/Filter';
|
|
||||||
import { createScopedState } from '@/ui/utilities/recoil-scope/utils/createScopedState';
|
import { createScopedState } from '@/ui/utilities/recoil-scope/utils/createScopedState';
|
||||||
|
import { ViewFilter } from '@/views/types/ViewFilter';
|
||||||
|
|
||||||
export const onViewFiltersChangeScopedState = createScopedState<
|
export const onViewFiltersChangeScopedState = createScopedState<
|
||||||
((filters: Filter[]) => void | Promise<void>) | undefined
|
((filters: ViewFilter[]) => void | Promise<void>) | undefined
|
||||||
>({
|
>({
|
||||||
key: 'onViewFiltersChangeScopedState',
|
key: 'onViewFiltersChangeScopedState',
|
||||||
defaultValue: undefined,
|
defaultValue: undefined,
|
||||||
|
|||||||
@ -1,8 +1,8 @@
|
|||||||
import { Sort } from '@/ui/object/object-sort-dropdown/types/Sort';
|
|
||||||
import { createScopedState } from '@/ui/utilities/recoil-scope/utils/createScopedState';
|
import { createScopedState } from '@/ui/utilities/recoil-scope/utils/createScopedState';
|
||||||
|
import { ViewSort } from '@/views/types/ViewSort';
|
||||||
|
|
||||||
export const onViewSortsChangeScopedState = createScopedState<
|
export const onViewSortsChangeScopedState = createScopedState<
|
||||||
((sorts: Sort[]) => void | Promise<void>) | undefined
|
((sorts: ViewSort[]) => void | Promise<void>) | undefined
|
||||||
>({
|
>({
|
||||||
key: 'onViewSortsChangeScopedState',
|
key: 'onViewSortsChangeScopedState',
|
||||||
defaultValue: undefined,
|
defaultValue: undefined,
|
||||||
|
|||||||
13
front/src/modules/views/types/GraphQLView.ts
Normal file
13
front/src/modules/views/types/GraphQLView.ts
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
import { PaginatedObjectTypeResults } from '@/object-record/types/PaginatedObjectTypeResults';
|
||||||
|
import { ViewField } from '@/views/types/ViewField';
|
||||||
|
import { ViewFilter } from '@/views/types/ViewFilter';
|
||||||
|
import { ViewSort } from '@/views/types/ViewSort';
|
||||||
|
|
||||||
|
export type GraphQLView = {
|
||||||
|
id: string;
|
||||||
|
name: string;
|
||||||
|
objectMetadataId: string;
|
||||||
|
viewFields: PaginatedObjectTypeResults<ViewField>;
|
||||||
|
viewFilters: PaginatedObjectTypeResults<ViewFilter>;
|
||||||
|
viewSorts: PaginatedObjectTypeResults<ViewSort>;
|
||||||
|
};
|
||||||
@ -1 +1,5 @@
|
|||||||
export type View = { id: string; name: string; objectMetadataId: string };
|
export type View = {
|
||||||
|
id: string;
|
||||||
|
name: string;
|
||||||
|
objectMetadataId: string;
|
||||||
|
};
|
||||||
|
|||||||
@ -3,7 +3,7 @@ import { FilterDefinition } from '@/ui/object/object-filter-dropdown/types/Filte
|
|||||||
import { ViewFilterOperand } from './ViewFilterOperand';
|
import { ViewFilterOperand } from './ViewFilterOperand';
|
||||||
|
|
||||||
export type ViewFilter = {
|
export type ViewFilter = {
|
||||||
id?: string;
|
id: string;
|
||||||
fieldMetadataId: string;
|
fieldMetadataId: string;
|
||||||
operand: ViewFilterOperand;
|
operand: ViewFilterOperand;
|
||||||
value: string;
|
value: string;
|
||||||
|
|||||||
@ -2,7 +2,7 @@ import { SortDefinition } from '@/ui/object/object-sort-dropdown/types/SortDefin
|
|||||||
import { SortDirection } from '@/ui/object/object-sort-dropdown/types/SortDirection';
|
import { SortDirection } from '@/ui/object/object-sort-dropdown/types/SortDirection';
|
||||||
|
|
||||||
export type ViewSort = {
|
export type ViewSort = {
|
||||||
id?: string;
|
id: string;
|
||||||
fieldMetadataId: string;
|
fieldMetadataId: string;
|
||||||
direction: SortDirection;
|
direction: SortDirection;
|
||||||
definition: SortDefinition;
|
definition: SortDefinition;
|
||||||
|
|||||||
@ -37,6 +37,7 @@ export const getViewScopedStateValuesFromSnapshot = ({
|
|||||||
currentViewSortsState,
|
currentViewSortsState,
|
||||||
entityCountInCurrentViewState,
|
entityCountInCurrentViewState,
|
||||||
isViewBarExpandedState,
|
isViewBarExpandedState,
|
||||||
|
isPersistingViewState,
|
||||||
onViewFieldsChangeState,
|
onViewFieldsChangeState,
|
||||||
onViewFiltersChangeState,
|
onViewFiltersChangeState,
|
||||||
onViewSortsChangeState,
|
onViewSortsChangeState,
|
||||||
@ -80,6 +81,7 @@ export const getViewScopedStateValuesFromSnapshot = ({
|
|||||||
entityCountInCurrentViewState,
|
entityCountInCurrentViewState,
|
||||||
),
|
),
|
||||||
isViewBarExpanded: getSnapshotValue(snapshot, isViewBarExpandedState),
|
isViewBarExpanded: getSnapshotValue(snapshot, isViewBarExpandedState),
|
||||||
|
isPersistingView: getSnapshotValue(snapshot, isPersistingViewState),
|
||||||
onViewFieldsChange: getSnapshotValue(snapshot, onViewFieldsChangeState),
|
onViewFieldsChange: getSnapshotValue(snapshot, onViewFieldsChangeState),
|
||||||
onViewFiltersChange: getSnapshotValue(snapshot, onViewFiltersChangeState),
|
onViewFiltersChange: getSnapshotValue(snapshot, onViewFiltersChangeState),
|
||||||
onViewSortsChange: getSnapshotValue(snapshot, onViewSortsChangeState),
|
onViewSortsChange: getSnapshotValue(snapshot, onViewSortsChangeState),
|
||||||
|
|||||||
@ -37,6 +37,7 @@ export const getViewScopedStatesFromSnapshot = ({
|
|||||||
currentViewSortsState,
|
currentViewSortsState,
|
||||||
entityCountInCurrentViewState,
|
entityCountInCurrentViewState,
|
||||||
isViewBarExpandedState,
|
isViewBarExpandedState,
|
||||||
|
isPersistingViewState,
|
||||||
onViewFieldsChangeState,
|
onViewFieldsChangeState,
|
||||||
onViewFiltersChangeState,
|
onViewFiltersChangeState,
|
||||||
onViewSortsChangeState,
|
onViewSortsChangeState,
|
||||||
@ -68,6 +69,7 @@ export const getViewScopedStatesFromSnapshot = ({
|
|||||||
currentViewSortsState,
|
currentViewSortsState,
|
||||||
entityCountInCurrentViewState,
|
entityCountInCurrentViewState,
|
||||||
isViewBarExpandedState,
|
isViewBarExpandedState,
|
||||||
|
isPersistingViewState,
|
||||||
onViewFieldsChangeState,
|
onViewFieldsChangeState,
|
||||||
onViewFiltersChangeState,
|
onViewFiltersChangeState,
|
||||||
onViewSortsChangeState,
|
onViewSortsChangeState,
|
||||||
|
|||||||
@ -2,6 +2,7 @@ import { getScopedFamilyState } from '@/ui/utilities/recoil-scope/utils/getScope
|
|||||||
import { getScopedSelector } from '@/ui/utilities/recoil-scope/utils/getScopedSelector';
|
import { getScopedSelector } from '@/ui/utilities/recoil-scope/utils/getScopedSelector';
|
||||||
import { getScopedState } from '@/ui/utilities/recoil-scope/utils/getScopedState';
|
import { getScopedState } from '@/ui/utilities/recoil-scope/utils/getScopedState';
|
||||||
import { currentViewIdScopedState } from '@/views/states/currentViewIdScopedState';
|
import { currentViewIdScopedState } from '@/views/states/currentViewIdScopedState';
|
||||||
|
import { isPersistingViewScopedState } from '@/views/states/isPersistingViewScopedState';
|
||||||
import { currentViewScopedSelector } from '@/views/states/selectors/currentViewScopedSelector';
|
import { currentViewScopedSelector } from '@/views/states/selectors/currentViewScopedSelector';
|
||||||
|
|
||||||
import { availableFieldDefinitionsScopedState } from '../../states/availableFieldDefinitionsScopedState';
|
import { availableFieldDefinitionsScopedState } from '../../states/availableFieldDefinitionsScopedState';
|
||||||
@ -59,6 +60,11 @@ export const getViewScopedStates = ({
|
|||||||
viewScopeId,
|
viewScopeId,
|
||||||
);
|
);
|
||||||
|
|
||||||
|
const isPersistingViewState = getScopedState(
|
||||||
|
isPersistingViewScopedState,
|
||||||
|
viewScopeId,
|
||||||
|
);
|
||||||
|
|
||||||
// ViewSorts
|
// ViewSorts
|
||||||
const currentViewSortsState = getScopedFamilyState(
|
const currentViewSortsState = getScopedFamilyState(
|
||||||
currentViewSortsScopedFamilyState,
|
currentViewSortsScopedFamilyState,
|
||||||
@ -170,6 +176,7 @@ export const getViewScopedStates = ({
|
|||||||
currentViewSelector,
|
currentViewSelector,
|
||||||
|
|
||||||
isViewBarExpandedState,
|
isViewBarExpandedState,
|
||||||
|
isPersistingViewState,
|
||||||
|
|
||||||
viewsState,
|
viewsState,
|
||||||
viewEditModeState,
|
viewEditModeState,
|
||||||
|
|||||||
@ -1,3 +1,6 @@
|
|||||||
|
import { isNonEmptyString } from '@sniptt/guards';
|
||||||
|
|
||||||
export const capitalize = (stringToCapitalize: string) => {
|
export const capitalize = (stringToCapitalize: string) => {
|
||||||
|
if (!isNonEmptyString(stringToCapitalize)) return '';
|
||||||
return stringToCapitalize[0].toUpperCase() + stringToCapitalize.slice(1);
|
return stringToCapitalize[0].toUpperCase() + stringToCapitalize.slice(1);
|
||||||
};
|
};
|
||||||
|
|||||||
Reference in New Issue
Block a user