test: improve utils coverage (#4230)
* test: improve utils coverage * refactor: review - rename isDefined to isNonNullable, update tests and return statement
This commit is contained in:
@ -22,7 +22,7 @@ import {
|
|||||||
} from '@/ui/input/components/Checkbox';
|
} from '@/ui/input/components/Checkbox';
|
||||||
import { usePreviousHotkeyScope } from '@/ui/utilities/hotkey/hooks/usePreviousHotkeyScope';
|
import { usePreviousHotkeyScope } from '@/ui/utilities/hotkey/hooks/usePreviousHotkeyScope';
|
||||||
import { useScopedHotkeys } from '@/ui/utilities/hotkey/hooks/useScopedHotkeys';
|
import { useScopedHotkeys } from '@/ui/utilities/hotkey/hooks/useScopedHotkeys';
|
||||||
import { isDefined } from '~/utils/isDefined';
|
import { isNonNullable } from '~/utils/isNonNullable';
|
||||||
|
|
||||||
const StyledEditableTitleInput = styled.input<{
|
const StyledEditableTitleInput = styled.input<{
|
||||||
completed: boolean;
|
completed: boolean;
|
||||||
@ -166,7 +166,7 @@ export const ActivityTitle = ({ activityId }: ActivityTitleProps) => {
|
|||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
const completed = isDefined(activity.completedAt);
|
const completed = isNonNullable(activity.completedAt);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<StyledContainer>
|
<StyledContainer>
|
||||||
|
|||||||
@ -8,7 +8,7 @@ import { CoreObjectNameSingular } from '@/object-metadata/types/CoreObjectNameSi
|
|||||||
import { getEmptyPageInfo } from '@/object-record/cache/utils/getEmptyPageInfo';
|
import { getEmptyPageInfo } from '@/object-record/cache/utils/getEmptyPageInfo';
|
||||||
import { useMapConnectionToRecords } from '@/object-record/hooks/useMapConnectionToRecords';
|
import { useMapConnectionToRecords } from '@/object-record/hooks/useMapConnectionToRecords';
|
||||||
import { ObjectRecordConnection } from '@/object-record/types/ObjectRecordConnection';
|
import { ObjectRecordConnection } from '@/object-record/types/ObjectRecordConnection';
|
||||||
import { isDefined } from '~/utils/isDefined';
|
import { isNonNullable } from '~/utils/isNonNullable';
|
||||||
|
|
||||||
export const useActivityConnectionUtils = () => {
|
export const useActivityConnectionUtils = () => {
|
||||||
const mapConnectionToRecords = useMapConnectionToRecords();
|
const mapConnectionToRecords = useMapConnectionToRecords();
|
||||||
@ -19,7 +19,7 @@ export const useActivityConnectionUtils = () => {
|
|||||||
comments: ObjectRecordConnection<Comment>;
|
comments: ObjectRecordConnection<Comment>;
|
||||||
},
|
},
|
||||||
) => {
|
) => {
|
||||||
if (!isDefined(activityWithConnections)) {
|
if (!isNonNullable(activityWithConnections)) {
|
||||||
throw new Error('Activity with connections is not defined');
|
throw new Error('Activity with connections is not defined');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -7,7 +7,7 @@ import { objectMetadataItemsState } from '@/object-metadata/states/objectMetadat
|
|||||||
import { CoreObjectNameSingular } from '@/object-metadata/types/CoreObjectNameSingular';
|
import { CoreObjectNameSingular } from '@/object-metadata/types/CoreObjectNameSingular';
|
||||||
import { useFindManyRecords } from '@/object-record/hooks/useFindManyRecords';
|
import { useFindManyRecords } from '@/object-record/hooks/useFindManyRecords';
|
||||||
import { Nullable } from '~/types/Nullable';
|
import { Nullable } from '~/types/Nullable';
|
||||||
import { isDefined } from '~/utils/isDefined';
|
import { isNonNullable } from '~/utils/isNonNullable';
|
||||||
|
|
||||||
export const useActivityTargetObjectRecords = ({
|
export const useActivityTargetObjectRecords = ({
|
||||||
activityId,
|
activityId,
|
||||||
@ -31,7 +31,7 @@ export const useActivityTargetObjectRecords = ({
|
|||||||
.map<Nullable<ActivityTargetWithTargetRecord>>((activityTarget) => {
|
.map<Nullable<ActivityTargetWithTargetRecord>>((activityTarget) => {
|
||||||
const correspondingObjectMetadataItem = objectMetadataItems.find(
|
const correspondingObjectMetadataItem = objectMetadataItems.find(
|
||||||
(objectMetadataItem) =>
|
(objectMetadataItem) =>
|
||||||
isDefined(activityTarget[objectMetadataItem.nameSingular]) &&
|
isNonNullable(activityTarget[objectMetadataItem.nameSingular]) &&
|
||||||
!objectMetadataItem.isSystem,
|
!objectMetadataItem.isSystem,
|
||||||
);
|
);
|
||||||
|
|
||||||
@ -47,7 +47,7 @@ export const useActivityTargetObjectRecords = ({
|
|||||||
targetObjectNameSingular: correspondingObjectMetadataItem.nameSingular,
|
targetObjectNameSingular: correspondingObjectMetadataItem.nameSingular,
|
||||||
};
|
};
|
||||||
})
|
})
|
||||||
.filter(isDefined);
|
.filter(isNonNullable);
|
||||||
|
|
||||||
return {
|
return {
|
||||||
activityTargetObjectRecords,
|
activityTargetObjectRecords,
|
||||||
|
|||||||
@ -6,7 +6,7 @@ import { triggerAttachRelationOptimisticEffect } from '@/apollo/optimistic-effec
|
|||||||
import { useObjectMetadataItems } from '@/object-metadata/hooks/useObjectMetadataItems';
|
import { useObjectMetadataItems } from '@/object-metadata/hooks/useObjectMetadataItems';
|
||||||
import { getObjectMetadataItemByNameSingular } from '@/object-metadata/utils/getObjectMetadataItemBySingularName';
|
import { getObjectMetadataItemByNameSingular } from '@/object-metadata/utils/getObjectMetadataItemBySingularName';
|
||||||
import { ObjectRecord } from '@/object-record/types/ObjectRecord';
|
import { ObjectRecord } from '@/object-record/types/ObjectRecord';
|
||||||
import { isDefined } from '~/utils/isDefined';
|
import { isNonNullable } from '~/utils/isNonNullable';
|
||||||
|
|
||||||
export const useAttachRelationInBothDirections = () => {
|
export const useAttachRelationInBothDirections = () => {
|
||||||
const { objectMetadataItems } = useObjectMetadataItems();
|
const { objectMetadataItems } = useObjectMetadataItems();
|
||||||
@ -46,7 +46,7 @@ export const useAttachRelationInBothDirections = () => {
|
|||||||
(field) => field.name === fieldNameOnSourceRecord,
|
(field) => field.name === fieldNameOnSourceRecord,
|
||||||
);
|
);
|
||||||
|
|
||||||
if (!isDefined(fieldMetadataItemOnSourceRecord)) {
|
if (!isNonNullable(fieldMetadataItemOnSourceRecord)) {
|
||||||
throw new Error(
|
throw new Error(
|
||||||
`Field ${fieldNameOnSourceRecord} not found on object ${sourceObjectNameSingular}`,
|
`Field ${fieldNameOnSourceRecord} not found on object ${sourceObjectNameSingular}`,
|
||||||
);
|
);
|
||||||
@ -57,7 +57,7 @@ export const useAttachRelationInBothDirections = () => {
|
|||||||
objectMetadataItems,
|
objectMetadataItems,
|
||||||
});
|
});
|
||||||
|
|
||||||
if (!isDefined(relationDefinition)) {
|
if (!isNonNullable(relationDefinition)) {
|
||||||
throw new Error(
|
throw new Error(
|
||||||
`Relation metadata not found for field ${fieldNameOnSourceRecord} on object ${sourceObjectNameSingular}`,
|
`Relation metadata not found for field ${fieldNameOnSourceRecord} on object ${sourceObjectNameSingular}`,
|
||||||
);
|
);
|
||||||
|
|||||||
@ -14,7 +14,7 @@ import { useCreateOneRecordInCache } from '@/object-record/hooks/useCreateOneRec
|
|||||||
import { useFindOneRecord } from '@/object-record/hooks/useFindOneRecord';
|
import { useFindOneRecord } from '@/object-record/hooks/useFindOneRecord';
|
||||||
import { recordStoreFamilyState } from '@/object-record/record-store/states/recordStoreFamilyState';
|
import { recordStoreFamilyState } from '@/object-record/record-store/states/recordStoreFamilyState';
|
||||||
import { WorkspaceMember } from '@/workspace-member/types/WorkspaceMember';
|
import { WorkspaceMember } from '@/workspace-member/types/WorkspaceMember';
|
||||||
import { isDefined } from '~/utils/isDefined';
|
import { isNonNullable } from '~/utils/isNonNullable';
|
||||||
|
|
||||||
export const useCreateActivityInCache = () => {
|
export const useCreateActivityInCache = () => {
|
||||||
const { createManyRecordsInCache: createManyActivityTargetsInCache } =
|
const { createManyRecordsInCache: createManyActivityTargetsInCache } =
|
||||||
@ -71,7 +71,7 @@ export const useCreateActivityInCache = () => {
|
|||||||
|
|
||||||
return targetObject;
|
return targetObject;
|
||||||
})
|
})
|
||||||
.filter(isDefined);
|
.filter(isNonNullable);
|
||||||
|
|
||||||
const activityTargetsToCreate =
|
const activityTargetsToCreate =
|
||||||
makeActivityTargetsToCreateFromTargetableObjects({
|
makeActivityTargetsToCreateFromTargetableObjects({
|
||||||
|
|||||||
@ -5,7 +5,7 @@ import { ActivityType } from '@/activities/types/Activity';
|
|||||||
import { recordStoreFamilyState } from '@/object-record/record-store/states/recordStoreFamilyState';
|
import { recordStoreFamilyState } from '@/object-record/record-store/states/recordStoreFamilyState';
|
||||||
import { useRecordTableStates } from '@/object-record/record-table/hooks/internal/useRecordTableStates';
|
import { useRecordTableStates } from '@/object-record/record-table/hooks/internal/useRecordTableStates';
|
||||||
import { getSnapshotValue } from '@/ui/utilities/recoil-scope/utils/getSnapshotValue';
|
import { getSnapshotValue } from '@/ui/utilities/recoil-scope/utils/getSnapshotValue';
|
||||||
import { isDefined } from '~/utils/isDefined';
|
import { isNonNullable } from '~/utils/isNonNullable';
|
||||||
|
|
||||||
import { ActivityTargetableObject } from '../types/ActivityTargetableEntity';
|
import { ActivityTargetableObject } from '../types/ActivityTargetableEntity';
|
||||||
|
|
||||||
@ -47,7 +47,7 @@ export const useOpenCreateActivityDrawerForSelectedRowIds = (
|
|||||||
targetObjectRecord,
|
targetObjectRecord,
|
||||||
};
|
};
|
||||||
})
|
})
|
||||||
.filter(isDefined);
|
.filter(isNonNullable);
|
||||||
|
|
||||||
if (relatedEntities) {
|
if (relatedEntities) {
|
||||||
activityTargetableObjectArray =
|
activityTargetableObjectArray =
|
||||||
|
|||||||
@ -16,7 +16,7 @@ import { objectShowPageTargetableObjectState } from '@/activities/timeline/state
|
|||||||
import { Activity } from '@/activities/types/Activity';
|
import { Activity } from '@/activities/types/Activity';
|
||||||
import { CoreObjectNameSingular } from '@/object-metadata/types/CoreObjectNameSingular';
|
import { CoreObjectNameSingular } from '@/object-metadata/types/CoreObjectNameSingular';
|
||||||
import { useUpdateOneRecord } from '@/object-record/hooks/useUpdateOneRecord';
|
import { useUpdateOneRecord } from '@/object-record/hooks/useUpdateOneRecord';
|
||||||
import { isDefined } from '~/utils/isDefined';
|
import { isNonNullable } from '~/utils/isNonNullable';
|
||||||
|
|
||||||
// TODO: create a generic way to have records only in cache for create mode and delete them afterwards ?
|
// TODO: create a generic way to have records only in cache for create mode and delete them afterwards ?
|
||||||
export const useUpsertActivity = () => {
|
export const useUpsertActivity = () => {
|
||||||
@ -85,7 +85,7 @@ export const useUpsertActivity = () => {
|
|||||||
makeActivityWithConnection(activityToCreate);
|
makeActivityWithConnection(activityToCreate);
|
||||||
|
|
||||||
if (weAreOnTaskPage) {
|
if (weAreOnTaskPage) {
|
||||||
if (isDefined(activityWithConnection.completedAt)) {
|
if (isNonNullable(activityWithConnection.completedAt)) {
|
||||||
injectActivitiesQueries({
|
injectActivitiesQueries({
|
||||||
activitiesFilters: currentCompletedTaskQueryVariables?.filter,
|
activitiesFilters: currentCompletedTaskQueryVariables?.filter,
|
||||||
activitiesOrderByVariables:
|
activitiesOrderByVariables:
|
||||||
@ -125,7 +125,7 @@ export const useUpsertActivity = () => {
|
|||||||
const injectOnlyInIdFilterForNotesQueries =
|
const injectOnlyInIdFilterForNotesQueries =
|
||||||
activityWithConnection.type !== 'Note';
|
activityWithConnection.type !== 'Note';
|
||||||
|
|
||||||
if (isDefined(currentCompletedTaskQueryVariables)) {
|
if (isNonNullable(currentCompletedTaskQueryVariables)) {
|
||||||
injectActivitiesQueries({
|
injectActivitiesQueries({
|
||||||
activitiesFilters: currentCompletedTaskQueryVariables?.filter,
|
activitiesFilters: currentCompletedTaskQueryVariables?.filter,
|
||||||
activitiesOrderByVariables:
|
activitiesOrderByVariables:
|
||||||
@ -137,7 +137,7 @@ export const useUpsertActivity = () => {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
if (isDefined(currentIncompleteTaskQueryVariables)) {
|
if (isNonNullable(currentIncompleteTaskQueryVariables)) {
|
||||||
injectActivitiesQueries({
|
injectActivitiesQueries({
|
||||||
activitiesFilters:
|
activitiesFilters:
|
||||||
currentIncompleteTaskQueryVariables?.filter ?? {},
|
currentIncompleteTaskQueryVariables?.filter ?? {},
|
||||||
@ -150,7 +150,7 @@ export const useUpsertActivity = () => {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
if (isDefined(currentNotesQueryVariables)) {
|
if (isNonNullable(currentNotesQueryVariables)) {
|
||||||
injectActivitiesQueries({
|
injectActivitiesQueries({
|
||||||
activitiesFilters: currentNotesQueryVariables?.filter,
|
activitiesFilters: currentNotesQueryVariables?.filter,
|
||||||
activitiesOrderByVariables: currentNotesQueryVariables?.orderBy,
|
activitiesOrderByVariables: currentNotesQueryVariables?.orderBy,
|
||||||
|
|||||||
@ -28,7 +28,7 @@ import { mapToRecordId } from '@/object-record/utils/mapToObjectId';
|
|||||||
import { IconPlus, IconTrash } from '@/ui/display/icon';
|
import { IconPlus, IconTrash } from '@/ui/display/icon';
|
||||||
import { IconButton } from '@/ui/input/button/components/IconButton';
|
import { IconButton } from '@/ui/input/button/components/IconButton';
|
||||||
import { isRightDrawerOpenState } from '@/ui/layout/right-drawer/states/isRightDrawerOpenState';
|
import { isRightDrawerOpenState } from '@/ui/layout/right-drawer/states/isRightDrawerOpenState';
|
||||||
import { isDefined } from '~/utils/isDefined';
|
import { isNonNullable } from '~/utils/isNonNullable';
|
||||||
|
|
||||||
const StyledButtonContainer = styled.div`
|
const StyledButtonContainer = styled.div`
|
||||||
display: inline-flex;
|
display: inline-flex;
|
||||||
@ -109,7 +109,10 @@ export const ActivityActionBar = () => {
|
|||||||
setIsRightDrawerOpen(false);
|
setIsRightDrawerOpen(false);
|
||||||
|
|
||||||
if (viewableActivityId) {
|
if (viewableActivityId) {
|
||||||
if (isActivityInCreateMode && isDefined(temporaryActivityForEditor)) {
|
if (
|
||||||
|
isActivityInCreateMode &&
|
||||||
|
isNonNullable(temporaryActivityForEditor)
|
||||||
|
) {
|
||||||
deleteActivityFromCache(temporaryActivityForEditor);
|
deleteActivityFromCache(temporaryActivityForEditor);
|
||||||
setTemporaryActivityForEditor(null);
|
setTemporaryActivityForEditor(null);
|
||||||
} else {
|
} else {
|
||||||
@ -136,7 +139,7 @@ export const ActivityActionBar = () => {
|
|||||||
});
|
});
|
||||||
} else if (
|
} else if (
|
||||||
weAreOnObjectShowPage &&
|
weAreOnObjectShowPage &&
|
||||||
isDefined(objectShowPageTargetableObject)
|
isNonNullable(objectShowPageTargetableObject)
|
||||||
) {
|
) {
|
||||||
removeFromActivitiesQueries({
|
removeFromActivitiesQueries({
|
||||||
activityIdToRemove: viewableActivityId,
|
activityIdToRemove: viewableActivityId,
|
||||||
@ -146,7 +149,7 @@ export const ActivityActionBar = () => {
|
|||||||
FIND_MANY_TIMELINE_ACTIVITIES_ORDER_BY,
|
FIND_MANY_TIMELINE_ACTIVITIES_ORDER_BY,
|
||||||
});
|
});
|
||||||
|
|
||||||
if (isDefined(currentCompletedTaskQueryVariables)) {
|
if (isNonNullable(currentCompletedTaskQueryVariables)) {
|
||||||
removeFromActivitiesQueries({
|
removeFromActivitiesQueries({
|
||||||
activityIdToRemove: viewableActivityId,
|
activityIdToRemove: viewableActivityId,
|
||||||
targetableObjects: [objectShowPageTargetableObject],
|
targetableObjects: [objectShowPageTargetableObject],
|
||||||
@ -157,7 +160,7 @@ export const ActivityActionBar = () => {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
if (isDefined(currentIncompleteTaskQueryVariables)) {
|
if (isNonNullable(currentIncompleteTaskQueryVariables)) {
|
||||||
removeFromActivitiesQueries({
|
removeFromActivitiesQueries({
|
||||||
activityIdToRemove: viewableActivityId,
|
activityIdToRemove: viewableActivityId,
|
||||||
targetableObjects: [objectShowPageTargetableObject],
|
targetableObjects: [objectShowPageTargetableObject],
|
||||||
@ -168,7 +171,7 @@ export const ActivityActionBar = () => {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
if (isDefined(currentNotesQueryVariables)) {
|
if (isNonNullable(currentNotesQueryVariables)) {
|
||||||
removeFromActivitiesQueries({
|
removeFromActivitiesQueries({
|
||||||
activityIdToRemove: viewableActivityId,
|
activityIdToRemove: viewableActivityId,
|
||||||
targetableObjects: [objectShowPageTargetableObject],
|
targetableObjects: [objectShowPageTargetableObject],
|
||||||
|
|||||||
@ -12,7 +12,7 @@ import { Activity } from '@/activities/types/Activity';
|
|||||||
import { ActivityTargetableObject } from '@/activities/types/ActivityTargetableEntity';
|
import { ActivityTargetableObject } from '@/activities/types/ActivityTargetableEntity';
|
||||||
import { sortObjectRecordByDateField } from '@/object-record/utils/sortObjectRecordByDateField';
|
import { sortObjectRecordByDateField } from '@/object-record/utils/sortObjectRecordByDateField';
|
||||||
import { isDeeplyEqual } from '~/utils/isDeeplyEqual';
|
import { isDeeplyEqual } from '~/utils/isDeeplyEqual';
|
||||||
import { isDefined } from '~/utils/isDefined';
|
import { isNonNullable } from '~/utils/isNonNullable';
|
||||||
|
|
||||||
export const TimelineQueryEffect = ({
|
export const TimelineQueryEffect = ({
|
||||||
targetableObject,
|
targetableObject,
|
||||||
@ -31,7 +31,7 @@ export const TimelineQueryEffect = ({
|
|||||||
targetableObjects: [targetableObject],
|
targetableObjects: [targetableObject],
|
||||||
activitiesFilters: {},
|
activitiesFilters: {},
|
||||||
activitiesOrderByVariables: FIND_MANY_TIMELINE_ACTIVITIES_ORDER_BY,
|
activitiesOrderByVariables: FIND_MANY_TIMELINE_ACTIVITIES_ORDER_BY,
|
||||||
skip: !isDefined(targetableObject),
|
skip: !isNonNullable(targetableObject),
|
||||||
});
|
});
|
||||||
|
|
||||||
const [timelineActivitiesNetworking, setTimelineActivitiesNetworking] =
|
const [timelineActivitiesNetworking, setTimelineActivitiesNetworking] =
|
||||||
@ -41,7 +41,7 @@ export const TimelineQueryEffect = ({
|
|||||||
useRecoilState(timelineActivitiesForGroupState);
|
useRecoilState(timelineActivitiesForGroupState);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (!isDefined(targetableObject)) {
|
if (!isNonNullable(targetableObject)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -13,7 +13,7 @@ import { getRecordsFromRecordConnection } from '@/object-record/cache/utils/getR
|
|||||||
import { useFindManyRecords } from '@/object-record/hooks/useFindManyRecords';
|
import { useFindManyRecords } from '@/object-record/hooks/useFindManyRecords';
|
||||||
import { recordStoreFamilyState } from '@/object-record/record-store/states/recordStoreFamilyState';
|
import { recordStoreFamilyState } from '@/object-record/record-store/states/recordStoreFamilyState';
|
||||||
import { sortByAscString } from '~/utils/array/sortByAscString';
|
import { sortByAscString } from '~/utils/array/sortByAscString';
|
||||||
import { isDefined } from '~/utils/isDefined';
|
import { isNonNullable } from '~/utils/isNonNullable';
|
||||||
|
|
||||||
export const useTimelineActivities = ({
|
export const useTimelineActivities = ({
|
||||||
targetableObject,
|
targetableObject,
|
||||||
@ -27,7 +27,7 @@ export const useTimelineActivities = ({
|
|||||||
);
|
);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (isDefined(targetableObject)) {
|
if (isNonNullable(targetableObject)) {
|
||||||
setObjectShowPageTargetableObject(targetableObject);
|
setObjectShowPageTargetableObject(targetableObject);
|
||||||
}
|
}
|
||||||
}, [targetableObject, setObjectShowPageTargetableObject]);
|
}, [targetableObject, setObjectShowPageTargetableObject]);
|
||||||
@ -100,7 +100,7 @@ export const useTimelineActivities = ({
|
|||||||
const activities = activitiesWithConnection
|
const activities = activitiesWithConnection
|
||||||
?.map(makeActivityWithoutConnection as any)
|
?.map(makeActivityWithoutConnection as any)
|
||||||
.map(({ activity }: any) => activity as any)
|
.map(({ activity }: any) => activity as any)
|
||||||
.filter(isDefined);
|
.filter(isNonNullable);
|
||||||
|
|
||||||
return {
|
return {
|
||||||
activities,
|
activities,
|
||||||
|
|||||||
@ -4,7 +4,7 @@ import { ReadFieldFunction } from '@apollo/client/cache/core/types/common';
|
|||||||
import { CachedObjectRecordEdge } from '@/apollo/types/CachedObjectRecordEdge';
|
import { CachedObjectRecordEdge } from '@/apollo/types/CachedObjectRecordEdge';
|
||||||
import { OrderBy } from '@/object-metadata/types/OrderBy';
|
import { OrderBy } from '@/object-metadata/types/OrderBy';
|
||||||
import { OrderByField } from '@/object-metadata/types/OrderByField';
|
import { OrderByField } from '@/object-metadata/types/OrderByField';
|
||||||
import { isDefined } from '~/utils/isDefined';
|
import { isNonNullable } from '~/utils/isNonNullable';
|
||||||
import { sortAsc, sortDesc, sortNullsFirst, sortNullsLast } from '~/utils/sort';
|
import { sortAsc, sortDesc, sortNullsFirst, sortNullsLast } from '~/utils/sort';
|
||||||
|
|
||||||
export const sortCachedObjectEdges = ({
|
export const sortCachedObjectEdges = ({
|
||||||
@ -31,7 +31,7 @@ export const sortCachedObjectEdges = ({
|
|||||||
orderByFieldName,
|
orderByFieldName,
|
||||||
recordFromCache,
|
recordFromCache,
|
||||||
) ?? null;
|
) ?? null;
|
||||||
const isSubFieldFilter = isDefined(fieldValue) && !!orderBySubFieldName;
|
const isSubFieldFilter = isNonNullable(fieldValue) && !!orderBySubFieldName;
|
||||||
|
|
||||||
if (!isSubFieldFilter) return fieldValue as string | number | null;
|
if (!isSubFieldFilter) return fieldValue as string | number | null;
|
||||||
|
|
||||||
|
|||||||
@ -2,7 +2,7 @@ import { ApolloCache, StoreObject } from '@apollo/client';
|
|||||||
|
|
||||||
import { isCachedObjectRecordConnection } from '@/apollo/optimistic-effect/utils/isCachedObjectRecordConnection';
|
import { isCachedObjectRecordConnection } from '@/apollo/optimistic-effect/utils/isCachedObjectRecordConnection';
|
||||||
import { CachedObjectRecordEdge } from '@/apollo/types/CachedObjectRecordEdge';
|
import { CachedObjectRecordEdge } from '@/apollo/types/CachedObjectRecordEdge';
|
||||||
import { isDefined } from '~/utils/isDefined';
|
import { isNonNullable } from '~/utils/isNonNullable';
|
||||||
import { capitalize } from '~/utils/string/capitalize';
|
import { capitalize } from '~/utils/string/capitalize';
|
||||||
|
|
||||||
export const triggerAttachRelationOptimisticEffect = ({
|
export const triggerAttachRelationOptimisticEffect = ({
|
||||||
@ -43,7 +43,7 @@ export const triggerAttachRelationOptimisticEffect = ({
|
|||||||
__typename: sourceRecordTypeName,
|
__typename: sourceRecordTypeName,
|
||||||
});
|
});
|
||||||
|
|
||||||
if (!isDefined(sourceRecordReference)) {
|
if (!isNonNullable(sourceRecordReference)) {
|
||||||
return targetRecordFieldValue;
|
return targetRecordFieldValue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -6,7 +6,7 @@ import { CachedObjectRecord } from '@/apollo/types/CachedObjectRecord';
|
|||||||
import { CachedObjectRecordEdge } from '@/apollo/types/CachedObjectRecordEdge';
|
import { CachedObjectRecordEdge } from '@/apollo/types/CachedObjectRecordEdge';
|
||||||
import { CachedObjectRecordQueryVariables } from '@/apollo/types/CachedObjectRecordQueryVariables';
|
import { CachedObjectRecordQueryVariables } from '@/apollo/types/CachedObjectRecordQueryVariables';
|
||||||
import { ObjectMetadataItem } from '@/object-metadata/types/ObjectMetadataItem';
|
import { ObjectMetadataItem } from '@/object-metadata/types/ObjectMetadataItem';
|
||||||
import { isDefined } from '~/utils/isDefined';
|
import { isNonNullable } from '~/utils/isNonNullable';
|
||||||
import { parseApolloStoreFieldName } from '~/utils/parseApolloStoreFieldName';
|
import { parseApolloStoreFieldName } from '~/utils/parseApolloStoreFieldName';
|
||||||
|
|
||||||
export const triggerDeleteRecordsOptimisticEffect = ({
|
export const triggerDeleteRecordsOptimisticEffect = ({
|
||||||
@ -38,7 +38,7 @@ export const triggerDeleteRecordsOptimisticEffect = ({
|
|||||||
|
|
||||||
const rootQueryCachedObjectRecordConnection = rootQueryCachedResponse;
|
const rootQueryCachedObjectRecordConnection = rootQueryCachedResponse;
|
||||||
|
|
||||||
const { fieldArguments: rootQueryVariables } =
|
const { fieldVariables: rootQueryVariables } =
|
||||||
parseApolloStoreFieldName<CachedObjectRecordQueryVariables>(
|
parseApolloStoreFieldName<CachedObjectRecordQueryVariables>(
|
||||||
storeFieldName,
|
storeFieldName,
|
||||||
);
|
);
|
||||||
@ -68,7 +68,7 @@ export const triggerDeleteRecordsOptimisticEffect = ({
|
|||||||
|
|
||||||
// TODO: same as in update, should we trigger DELETE ?
|
// TODO: same as in update, should we trigger DELETE ?
|
||||||
if (
|
if (
|
||||||
isDefined(rootQueryVariables?.first) &&
|
isNonNullable(rootQueryVariables?.first) &&
|
||||||
cachedEdges?.length === rootQueryVariables.first
|
cachedEdges?.length === rootQueryVariables.first
|
||||||
) {
|
) {
|
||||||
return DELETE;
|
return DELETE;
|
||||||
|
|||||||
@ -9,7 +9,7 @@ import { CachedObjectRecordQueryVariables } from '@/apollo/types/CachedObjectRec
|
|||||||
import { ObjectMetadataItem } from '@/object-metadata/types/ObjectMetadataItem';
|
import { ObjectMetadataItem } from '@/object-metadata/types/ObjectMetadataItem';
|
||||||
import { getEdgeTypename } from '@/object-record/cache/utils/getEdgeTypename';
|
import { getEdgeTypename } from '@/object-record/cache/utils/getEdgeTypename';
|
||||||
import { isRecordMatchingFilter } from '@/object-record/record-filter/utils/isRecordMatchingFilter';
|
import { isRecordMatchingFilter } from '@/object-record/record-filter/utils/isRecordMatchingFilter';
|
||||||
import { isDefined } from '~/utils/isDefined';
|
import { isNonNullable } from '~/utils/isNonNullable';
|
||||||
import { parseApolloStoreFieldName } from '~/utils/parseApolloStoreFieldName';
|
import { parseApolloStoreFieldName } from '~/utils/parseApolloStoreFieldName';
|
||||||
|
|
||||||
// TODO: add extensive unit tests for this function
|
// TODO: add extensive unit tests for this function
|
||||||
@ -56,7 +56,7 @@ export const triggerUpdateRecordOptimisticEffect = ({
|
|||||||
|
|
||||||
const rootQueryConnection = rootQueryCachedResponse;
|
const rootQueryConnection = rootQueryCachedResponse;
|
||||||
|
|
||||||
const { fieldArguments: rootQueryVariables } =
|
const { fieldVariables: rootQueryVariables } =
|
||||||
parseApolloStoreFieldName<CachedObjectRecordQueryVariables>(
|
parseApolloStoreFieldName<CachedObjectRecordQueryVariables>(
|
||||||
storeFieldName,
|
storeFieldName,
|
||||||
);
|
);
|
||||||
@ -71,7 +71,7 @@ export const triggerUpdateRecordOptimisticEffect = ({
|
|||||||
const rootQueryOrderBy = rootQueryVariables?.orderBy;
|
const rootQueryOrderBy = rootQueryVariables?.orderBy;
|
||||||
const rootQueryLimit = rootQueryVariables?.first;
|
const rootQueryLimit = rootQueryVariables?.first;
|
||||||
|
|
||||||
const shouldTryToMatchFilter = isDefined(rootQueryFilter);
|
const shouldTryToMatchFilter = isNonNullable(rootQueryFilter);
|
||||||
|
|
||||||
if (shouldTryToMatchFilter) {
|
if (shouldTryToMatchFilter) {
|
||||||
const updatedRecordMatchesThisRootQueryFilter =
|
const updatedRecordMatchesThisRootQueryFilter =
|
||||||
@ -101,7 +101,7 @@ export const triggerUpdateRecordOptimisticEffect = ({
|
|||||||
if (updatedRecordShouldBeAddedToRootQueryEdges) {
|
if (updatedRecordShouldBeAddedToRootQueryEdges) {
|
||||||
const updatedRecordNodeReference = toReference(updatedRecord);
|
const updatedRecordNodeReference = toReference(updatedRecord);
|
||||||
|
|
||||||
if (isDefined(updatedRecordNodeReference)) {
|
if (isNonNullable(updatedRecordNodeReference)) {
|
||||||
rootQueryNextEdges.push({
|
rootQueryNextEdges.push({
|
||||||
__typename: objectEdgeTypeName,
|
__typename: objectEdgeTypeName,
|
||||||
node: updatedRecordNodeReference,
|
node: updatedRecordNodeReference,
|
||||||
@ -115,7 +115,8 @@ export const triggerUpdateRecordOptimisticEffect = ({
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const rootQueryNextEdgesShouldBeSorted = isDefined(rootQueryOrderBy);
|
const rootQueryNextEdgesShouldBeSorted =
|
||||||
|
isNonNullable(rootQueryOrderBy);
|
||||||
|
|
||||||
if (
|
if (
|
||||||
rootQueryNextEdgesShouldBeSorted &&
|
rootQueryNextEdgesShouldBeSorted &&
|
||||||
@ -128,7 +129,7 @@ export const triggerUpdateRecordOptimisticEffect = ({
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
const shouldLimitNextRootQueryEdges = isDefined(rootQueryLimit);
|
const shouldLimitNextRootQueryEdges = isNonNullable(rootQueryLimit);
|
||||||
|
|
||||||
// TODO: not sure that we should trigger a DELETE here, as it will trigger a network request
|
// TODO: not sure that we should trigger a DELETE here, as it will trigger a network request
|
||||||
// Is it the responsibility of this optimistic effect function to delete a root query that will trigger a network request ?
|
// Is it the responsibility of this optimistic effect function to delete a root query that will trigger a network request ?
|
||||||
|
|||||||
@ -12,7 +12,7 @@ import { ObjectMetadataItem } from '@/object-metadata/types/ObjectMetadataItem';
|
|||||||
import { ObjectRecordConnection } from '@/object-record/types/ObjectRecordConnection';
|
import { ObjectRecordConnection } from '@/object-record/types/ObjectRecordConnection';
|
||||||
import { FieldMetadataType } from '~/generated-metadata/graphql';
|
import { FieldMetadataType } from '~/generated-metadata/graphql';
|
||||||
import { isDeeplyEqual } from '~/utils/isDeeplyEqual';
|
import { isDeeplyEqual } from '~/utils/isDeeplyEqual';
|
||||||
import { isDefined } from '~/utils/isDefined';
|
import { isNonNullable } from '~/utils/isNonNullable';
|
||||||
|
|
||||||
export const triggerUpdateRelationsOptimisticEffect = ({
|
export const triggerUpdateRelationsOptimisticEffect = ({
|
||||||
cache,
|
cache,
|
||||||
@ -36,7 +36,7 @@ export const triggerUpdateRelationsOptimisticEffect = ({
|
|||||||
}
|
}
|
||||||
|
|
||||||
const fieldDoesNotExist =
|
const fieldDoesNotExist =
|
||||||
isDefined(updatedSourceRecord) &&
|
isNonNullable(updatedSourceRecord) &&
|
||||||
!(fieldMetadataItemOnSourceRecord.name in updatedSourceRecord);
|
!(fieldMetadataItemOnSourceRecord.name in updatedSourceRecord);
|
||||||
|
|
||||||
if (fieldDoesNotExist) {
|
if (fieldDoesNotExist) {
|
||||||
@ -87,7 +87,7 @@ export const triggerUpdateRelationsOptimisticEffect = ({
|
|||||||
? currentFieldValueOnSourceRecord.edges.map(
|
? currentFieldValueOnSourceRecord.edges.map(
|
||||||
({ node }) => node as CachedObjectRecord,
|
({ node }) => node as CachedObjectRecord,
|
||||||
)
|
)
|
||||||
: [currentFieldValueOnSourceRecord].filter(isDefined);
|
: [currentFieldValueOnSourceRecord].filter(isNonNullable);
|
||||||
|
|
||||||
const updatedFieldValueOnSourceRecordIsARecordConnection =
|
const updatedFieldValueOnSourceRecordIsARecordConnection =
|
||||||
isObjectRecordConnection(
|
isObjectRecordConnection(
|
||||||
@ -100,10 +100,11 @@ export const triggerUpdateRelationsOptimisticEffect = ({
|
|||||||
? updatedFieldValueOnSourceRecord.edges.map(
|
? updatedFieldValueOnSourceRecord.edges.map(
|
||||||
({ node }) => node as CachedObjectRecord,
|
({ node }) => node as CachedObjectRecord,
|
||||||
)
|
)
|
||||||
: [updatedFieldValueOnSourceRecord].filter(isDefined);
|
: [updatedFieldValueOnSourceRecord].filter(isNonNullable);
|
||||||
|
|
||||||
const shouldDetachSourceFromAllTargets =
|
const shouldDetachSourceFromAllTargets =
|
||||||
isDefined(currentSourceRecord) && targetRecordsToDetachFrom.length > 0;
|
isNonNullable(currentSourceRecord) &&
|
||||||
|
targetRecordsToDetachFrom.length > 0;
|
||||||
|
|
||||||
if (shouldDetachSourceFromAllTargets) {
|
if (shouldDetachSourceFromAllTargets) {
|
||||||
// TODO: see if we can de-hardcode this, put cascade delete in relation metadata item
|
// TODO: see if we can de-hardcode this, put cascade delete in relation metadata item
|
||||||
|
|||||||
@ -14,7 +14,7 @@ import { createUploadLink } from 'apollo-upload-client';
|
|||||||
|
|
||||||
import { renewToken } from '@/auth/services/AuthService';
|
import { renewToken } from '@/auth/services/AuthService';
|
||||||
import { AuthTokenPair } from '~/generated/graphql';
|
import { AuthTokenPair } from '~/generated/graphql';
|
||||||
import { assertNotNull } from '~/utils/assert';
|
import { isNonNullable } from '~/utils/isNonNullable';
|
||||||
import { logDebug } from '~/utils/logDebug';
|
import { logDebug } from '~/utils/logDebug';
|
||||||
|
|
||||||
import { ApolloManager } from '../types/apolloManager.interface';
|
import { ApolloManager } from '../types/apolloManager.interface';
|
||||||
@ -139,7 +139,7 @@ export class ApolloFactory<TCacheShape> implements ApolloManager<TCacheShape> {
|
|||||||
isDebugMode ? logger : null,
|
isDebugMode ? logger : null,
|
||||||
retryLink,
|
retryLink,
|
||||||
httpLink,
|
httpLink,
|
||||||
].filter(assertNotNull),
|
].filter(isNonNullable),
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@ -11,7 +11,7 @@ import { useDeleteOneRecord } from '@/object-record/hooks/useDeleteOneRecord';
|
|||||||
import { useFindManyRecords } from '@/object-record/hooks/useFindManyRecords';
|
import { useFindManyRecords } from '@/object-record/hooks/useFindManyRecords';
|
||||||
import { useUpdateOneRecord } from '@/object-record/hooks/useUpdateOneRecord';
|
import { useUpdateOneRecord } from '@/object-record/hooks/useUpdateOneRecord';
|
||||||
import { FieldMetadataType } from '~/generated-metadata/graphql';
|
import { FieldMetadataType } from '~/generated-metadata/graphql';
|
||||||
import { isDefined } from '~/utils/isDefined';
|
import { isNonNullable } from '~/utils/isNonNullable';
|
||||||
|
|
||||||
export const useFavorites = () => {
|
export const useFavorites = () => {
|
||||||
const currentWorkspaceMember = useRecoilValue(currentWorkspaceMemberState);
|
const currentWorkspaceMember = useRecoilValue(currentWorkspaceMemberState);
|
||||||
@ -56,7 +56,7 @@ export const useFavorites = () => {
|
|||||||
return favorites
|
return favorites
|
||||||
.map((favorite) => {
|
.map((favorite) => {
|
||||||
for (const relationField of favoriteRelationFieldMetadataItems) {
|
for (const relationField of favoriteRelationFieldMetadataItems) {
|
||||||
if (isDefined(favorite[relationField.name])) {
|
if (isNonNullable(favorite[relationField.name])) {
|
||||||
const relationObject = favorite[relationField.name];
|
const relationObject = favorite[relationField.name];
|
||||||
|
|
||||||
const relationObjectNameSingular =
|
const relationObjectNameSingular =
|
||||||
|
|||||||
@ -1,11 +1,10 @@
|
|||||||
import { getLogoUrlFromDomainName } from '~/utils';
|
import { getLogoUrlFromDomainName } from '~/utils';
|
||||||
import { assertNotNull } from '~/utils/assert';
|
import { isNonNullable } from '~/utils/isNonNullable';
|
||||||
import { isDefined } from '~/utils/isDefined';
|
|
||||||
|
|
||||||
export const mapFavorites = (favorites: any) => {
|
export const mapFavorites = (favorites: any) => {
|
||||||
return favorites
|
return favorites
|
||||||
.map((favorite: any) => {
|
.map((favorite: any) => {
|
||||||
const recordInformation = isDefined(favorite?.person)
|
const recordInformation = isNonNullable(favorite?.person)
|
||||||
? {
|
? {
|
||||||
id: favorite.person.id,
|
id: favorite.person.id,
|
||||||
labelIdentifier:
|
labelIdentifier:
|
||||||
@ -16,7 +15,7 @@ export const mapFavorites = (favorites: any) => {
|
|||||||
avatarType: 'rounded',
|
avatarType: 'rounded',
|
||||||
link: `/object/person/${favorite.person.id}`,
|
link: `/object/person/${favorite.person.id}`,
|
||||||
}
|
}
|
||||||
: isDefined(favorite?.company)
|
: isNonNullable(favorite?.company)
|
||||||
? {
|
? {
|
||||||
id: favorite.company.id,
|
id: favorite.company.id,
|
||||||
labelIdentifier: favorite.company.name,
|
labelIdentifier: favorite.company.name,
|
||||||
@ -33,6 +32,6 @@ export const mapFavorites = (favorites: any) => {
|
|||||||
position: favorite?.position,
|
position: favorite?.position,
|
||||||
};
|
};
|
||||||
})
|
})
|
||||||
.filter(assertNotNull)
|
.filter(isNonNullable)
|
||||||
.sort((a: any, b: any) => a.position - b.position);
|
.sort((a: any, b: any) => a.position - b.position);
|
||||||
};
|
};
|
||||||
|
|||||||
@ -2,7 +2,7 @@ import { useRecoilValue } from 'recoil';
|
|||||||
|
|
||||||
import { objectMetadataItemsByNameSingularMapSelector } from '@/object-metadata/states/objectMetadataItemsByNameSingularMapSelector';
|
import { objectMetadataItemsByNameSingularMapSelector } from '@/object-metadata/states/objectMetadataItemsByNameSingularMapSelector';
|
||||||
import { ObjectMetadataItem } from '@/object-metadata/types/ObjectMetadataItem';
|
import { ObjectMetadataItem } from '@/object-metadata/types/ObjectMetadataItem';
|
||||||
import { isDefined } from '~/utils/isDefined';
|
import { isNonNullable } from '~/utils/isNonNullable';
|
||||||
|
|
||||||
export const useFilterOutUnexistingObjectMetadataItems = () => {
|
export const useFilterOutUnexistingObjectMetadataItems = () => {
|
||||||
const objectMetadataItemsByNameSingularMap = useRecoilValue(
|
const objectMetadataItemsByNameSingularMap = useRecoilValue(
|
||||||
@ -12,7 +12,7 @@ export const useFilterOutUnexistingObjectMetadataItems = () => {
|
|||||||
const filterOutUnexistingObjectMetadataItems = (
|
const filterOutUnexistingObjectMetadataItems = (
|
||||||
objectMetadatItem: ObjectMetadataItem,
|
objectMetadatItem: ObjectMetadataItem,
|
||||||
) =>
|
) =>
|
||||||
isDefined(
|
isNonNullable(
|
||||||
objectMetadataItemsByNameSingularMap.get(objectMetadatItem.nameSingular),
|
objectMetadataItemsByNameSingularMap.get(objectMetadatItem.nameSingular),
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|||||||
@ -21,7 +21,7 @@ import { useGenerateFindManyRecordsQuery } from '@/object-record/hooks/useGenera
|
|||||||
import { useGenerateFindOneRecordQuery } from '@/object-record/hooks/useGenerateFindOneRecordQuery';
|
import { useGenerateFindOneRecordQuery } from '@/object-record/hooks/useGenerateFindOneRecordQuery';
|
||||||
import { useGenerateUpdateOneRecordMutation } from '@/object-record/hooks/useGenerateUpdateOneRecordMutation';
|
import { useGenerateUpdateOneRecordMutation } from '@/object-record/hooks/useGenerateUpdateOneRecordMutation';
|
||||||
import { generateDeleteOneRecordMutation } from '@/object-record/utils/generateDeleteOneRecordMutation';
|
import { generateDeleteOneRecordMutation } from '@/object-record/utils/generateDeleteOneRecordMutation';
|
||||||
import { isDefined } from '~/utils/isDefined';
|
import { isNonNullable } from '~/utils/isNonNullable';
|
||||||
|
|
||||||
import { ObjectMetadataItemIdentifier } from '../types/ObjectMetadataItemIdentifier';
|
import { ObjectMetadataItemIdentifier } from '../types/ObjectMetadataItemIdentifier';
|
||||||
|
|
||||||
@ -63,7 +63,7 @@ export const useObjectMetadataItem = (
|
|||||||
objectMetadataItems = mockObjectMetadataItems;
|
objectMetadataItems = mockObjectMetadataItems;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!isDefined(objectMetadataItem)) {
|
if (!isNonNullable(objectMetadataItem)) {
|
||||||
throw new ObjectMetadataItemNotFoundError(
|
throw new ObjectMetadataItemNotFoundError(
|
||||||
objectNameSingular,
|
objectNameSingular,
|
||||||
objectMetadataItems,
|
objectMetadataItems,
|
||||||
|
|||||||
@ -5,7 +5,7 @@ import { ObjectMetadataItemNotFoundError } from '@/object-metadata/errors/Object
|
|||||||
import { objectMetadataItemFamilySelector } from '@/object-metadata/states/objectMetadataItemFamilySelector';
|
import { objectMetadataItemFamilySelector } from '@/object-metadata/states/objectMetadataItemFamilySelector';
|
||||||
import { objectMetadataItemsState } from '@/object-metadata/states/objectMetadataItemsState';
|
import { objectMetadataItemsState } from '@/object-metadata/states/objectMetadataItemsState';
|
||||||
import { getObjectMetadataItemsMock } from '@/object-metadata/utils/getObjectMetadataItemsMock';
|
import { getObjectMetadataItemsMock } from '@/object-metadata/utils/getObjectMetadataItemsMock';
|
||||||
import { isDefined } from '~/utils/isDefined';
|
import { isNonNullable } from '~/utils/isNonNullable';
|
||||||
|
|
||||||
import { ObjectMetadataItemIdentifier } from '../types/ObjectMetadataItemIdentifier';
|
import { ObjectMetadataItemIdentifier } from '../types/ObjectMetadataItemIdentifier';
|
||||||
|
|
||||||
@ -34,7 +34,7 @@ export const useObjectMetadataItemOnly = ({
|
|||||||
objectMetadataItems = mockObjectMetadataItems;
|
objectMetadataItems = mockObjectMetadataItems;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!isDefined(objectMetadataItem)) {
|
if (!isNonNullable(objectMetadataItem)) {
|
||||||
throw new ObjectMetadataItemNotFoundError(
|
throw new ObjectMetadataItemNotFoundError(
|
||||||
objectNameSingular,
|
objectNameSingular,
|
||||||
objectMetadataItems,
|
objectMetadataItems,
|
||||||
|
|||||||
@ -3,7 +3,7 @@ import { useRecoilValue } from 'recoil';
|
|||||||
import { currentWorkspaceState } from '@/auth/states/currentWorkspaceState.ts';
|
import { currentWorkspaceState } from '@/auth/states/currentWorkspaceState.ts';
|
||||||
import { objectMetadataItemFamilySelector } from '@/object-metadata/states/objectMetadataItemFamilySelector';
|
import { objectMetadataItemFamilySelector } from '@/object-metadata/states/objectMetadataItemFamilySelector';
|
||||||
import { getObjectMetadataItemsMock } from '@/object-metadata/utils/getObjectMetadataItemsMock';
|
import { getObjectMetadataItemsMock } from '@/object-metadata/utils/getObjectMetadataItemsMock';
|
||||||
import { isDefined } from '~/utils/isDefined';
|
import { isNonNullable } from '~/utils/isNonNullable';
|
||||||
|
|
||||||
export const useObjectNamePluralFromSingular = ({
|
export const useObjectNamePluralFromSingular = ({
|
||||||
objectNameSingular,
|
objectNameSingular,
|
||||||
@ -28,7 +28,7 @@ export const useObjectNamePluralFromSingular = ({
|
|||||||
) ?? null;
|
) ?? null;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!isDefined(objectMetadataItem)) {
|
if (!isNonNullable(objectMetadataItem)) {
|
||||||
throw new Error(
|
throw new Error(
|
||||||
`Object metadata item not found for ${objectNameSingular} object`,
|
`Object metadata item not found for ${objectNameSingular} object`,
|
||||||
);
|
);
|
||||||
|
|||||||
@ -3,7 +3,7 @@ import { useRecoilValue } from 'recoil';
|
|||||||
import { currentWorkspaceState } from '@/auth/states/currentWorkspaceState.ts';
|
import { currentWorkspaceState } from '@/auth/states/currentWorkspaceState.ts';
|
||||||
import { objectMetadataItemFamilySelector } from '@/object-metadata/states/objectMetadataItemFamilySelector';
|
import { objectMetadataItemFamilySelector } from '@/object-metadata/states/objectMetadataItemFamilySelector';
|
||||||
import { getObjectMetadataItemsMock } from '@/object-metadata/utils/getObjectMetadataItemsMock';
|
import { getObjectMetadataItemsMock } from '@/object-metadata/utils/getObjectMetadataItemsMock';
|
||||||
import { isDefined } from '~/utils/isDefined';
|
import { isNonNullable } from '~/utils/isNonNullable';
|
||||||
|
|
||||||
export const useObjectNameSingularFromPlural = ({
|
export const useObjectNameSingularFromPlural = ({
|
||||||
objectNamePlural,
|
objectNamePlural,
|
||||||
@ -29,7 +29,7 @@ export const useObjectNameSingularFromPlural = ({
|
|||||||
) ?? null;
|
) ?? null;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!isDefined(objectMetadataItem)) {
|
if (!isNonNullable(objectMetadataItem)) {
|
||||||
throw new Error(
|
throw new Error(
|
||||||
`Object metadata item not found for ${objectNamePlural} object`,
|
`Object metadata item not found for ${objectNamePlural} object`,
|
||||||
);
|
);
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
import { FieldMetadataItem } from '@/object-metadata/types/FieldMetadataItem';
|
import { FieldMetadataItem } from '@/object-metadata/types/FieldMetadataItem';
|
||||||
import { ObjectMetadataItem } from '@/object-metadata/types/ObjectMetadataItem';
|
import { ObjectMetadataItem } from '@/object-metadata/types/ObjectMetadataItem';
|
||||||
import { isDefined } from '~/utils/isDefined';
|
import { isNonNullable } from '~/utils/isNonNullable';
|
||||||
|
|
||||||
export const DEFAULT_LABEL_IDENTIFIER_FIELD_NAME = 'name';
|
export const DEFAULT_LABEL_IDENTIFIER_FIELD_NAME = 'name';
|
||||||
|
|
||||||
@ -14,6 +14,6 @@ export const isLabelIdentifierField = ({
|
|||||||
'labelIdentifierFieldMetadataId'
|
'labelIdentifierFieldMetadataId'
|
||||||
>;
|
>;
|
||||||
}) =>
|
}) =>
|
||||||
isDefined(objectMetadataItem.labelIdentifierFieldMetadataId)
|
isNonNullable(objectMetadataItem.labelIdentifierFieldMetadataId)
|
||||||
? fieldMetadataItem.id === objectMetadataItem.labelIdentifierFieldMetadataId
|
? fieldMetadataItem.id === objectMetadataItem.labelIdentifierFieldMetadataId
|
||||||
: fieldMetadataItem.name === DEFAULT_LABEL_IDENTIFIER_FIELD_NAME;
|
: fieldMetadataItem.name === DEFAULT_LABEL_IDENTIFIER_FIELD_NAME;
|
||||||
|
|||||||
@ -4,7 +4,7 @@ import {
|
|||||||
FieldMetadataType,
|
FieldMetadataType,
|
||||||
RelationMetadataType,
|
RelationMetadataType,
|
||||||
} from '~/generated-metadata/graphql';
|
} from '~/generated-metadata/graphql';
|
||||||
import { isDefined } from '~/utils/isDefined';
|
import { isNonNullable } from '~/utils/isNonNullable';
|
||||||
|
|
||||||
export const parseFieldRelationType = (
|
export const parseFieldRelationType = (
|
||||||
field: FieldMetadataItem | undefined,
|
field: FieldMetadataItem | undefined,
|
||||||
@ -30,14 +30,14 @@ export const parseFieldRelationType = (
|
|||||||
};
|
};
|
||||||
|
|
||||||
if (
|
if (
|
||||||
isDefined(field.fromRelationMetadata) &&
|
isNonNullable(field.fromRelationMetadata) &&
|
||||||
field.fromRelationMetadata.relationType in config
|
field.fromRelationMetadata.relationType in config
|
||||||
) {
|
) {
|
||||||
return config[field.fromRelationMetadata.relationType].from;
|
return config[field.fromRelationMetadata.relationType].from;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (
|
if (
|
||||||
isDefined(field.toRelationMetadata) &&
|
isNonNullable(field.toRelationMetadata) &&
|
||||||
field.toRelationMetadata.relationType in config
|
field.toRelationMetadata.relationType in config
|
||||||
) {
|
) {
|
||||||
return config[field.toRelationMetadata.relationType].to;
|
return config[field.toRelationMetadata.relationType].to;
|
||||||
|
|||||||
@ -6,7 +6,7 @@ import { useGenerateFindManyRecordsQuery } from '@/object-record/hooks/useGenera
|
|||||||
import { ObjectRecord } from '@/object-record/types/ObjectRecord';
|
import { ObjectRecord } from '@/object-record/types/ObjectRecord';
|
||||||
import { ObjectRecordQueryResult } from '@/object-record/types/ObjectRecordQueryResult';
|
import { ObjectRecordQueryResult } from '@/object-record/types/ObjectRecordQueryResult';
|
||||||
import { ObjectRecordQueryVariables } from '@/object-record/types/ObjectRecordQueryVariables';
|
import { ObjectRecordQueryVariables } from '@/object-record/types/ObjectRecordQueryVariables';
|
||||||
import { isDefined } from '~/utils/isDefined';
|
import { isNonNullable } from '~/utils/isNonNullable';
|
||||||
|
|
||||||
export const useReadFindManyRecordsQueryInCache = ({
|
export const useReadFindManyRecordsQueryInCache = ({
|
||||||
objectMetadataItem,
|
objectMetadataItem,
|
||||||
@ -38,7 +38,7 @@ export const useReadFindManyRecordsQueryInCache = ({
|
|||||||
const existingRecordConnection =
|
const existingRecordConnection =
|
||||||
existingRecordsQueryResult?.[objectMetadataItem.namePlural];
|
existingRecordsQueryResult?.[objectMetadataItem.namePlural];
|
||||||
|
|
||||||
const existingObjectRecords = isDefined(existingRecordConnection)
|
const existingObjectRecords = isNonNullable(existingRecordConnection)
|
||||||
? getRecordsFromRecordConnection({
|
? getRecordsFromRecordConnection({
|
||||||
recordConnection: existingRecordConnection,
|
recordConnection: existingRecordConnection,
|
||||||
})
|
})
|
||||||
|
|||||||
@ -13,7 +13,7 @@ import {
|
|||||||
import { useMapConnectionToRecords } from '@/object-record/hooks/useMapConnectionToRecords';
|
import { useMapConnectionToRecords } from '@/object-record/hooks/useMapConnectionToRecords';
|
||||||
import { Person } from '@/people/types/Person';
|
import { Person } from '@/people/types/Person';
|
||||||
import { getJestHookWrapper } from '~/testing/jest/getJestHookWrapper';
|
import { getJestHookWrapper } from '~/testing/jest/getJestHookWrapper';
|
||||||
import { isDefined } from '~/utils/isDefined';
|
import { isNonNullable } from '~/utils/isNonNullable';
|
||||||
|
|
||||||
const Wrapper = getJestHookWrapper({
|
const Wrapper = getJestHookWrapper({
|
||||||
apolloMocks: [],
|
apolloMocks: [],
|
||||||
@ -184,7 +184,7 @@ describe('useMapConnectionToRecords', () => {
|
|||||||
expect(isNonEmptyArray(peopleResult)).toBe(true);
|
expect(isNonEmptyArray(peopleResult)).toBe(true);
|
||||||
expect(firstPersonResult.id).toBe(firstPersonMock.id);
|
expect(firstPersonResult.id).toBe(firstPersonMock.id);
|
||||||
|
|
||||||
expect(isDefined(firstPersonsCompanyresult)).toBe(true);
|
expect(isNonNullable(firstPersonsCompanyresult)).toBe(true);
|
||||||
expect(firstPersonsCompanyresult.id).toEqual(firstPersonsCompanyMock.id);
|
expect(firstPersonsCompanyresult.id).toEqual(firstPersonsCompanyMock.id);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
@ -4,7 +4,7 @@ import { triggerDeleteRecordsOptimisticEffect } from '@/apollo/optimistic-effect
|
|||||||
import { useObjectMetadataItem } from '@/object-metadata/hooks/useObjectMetadataItem';
|
import { useObjectMetadataItem } from '@/object-metadata/hooks/useObjectMetadataItem';
|
||||||
import { useObjectMetadataItems } from '@/object-metadata/hooks/useObjectMetadataItems';
|
import { useObjectMetadataItems } from '@/object-metadata/hooks/useObjectMetadataItems';
|
||||||
import { getDeleteManyRecordsMutationResponseField } from '@/object-record/hooks/useGenerateDeleteManyRecordMutation';
|
import { getDeleteManyRecordsMutationResponseField } from '@/object-record/hooks/useGenerateDeleteManyRecordMutation';
|
||||||
import { isDefined } from '~/utils/isDefined';
|
import { isNonNullable } from '~/utils/isNonNullable';
|
||||||
import { capitalize } from '~/utils/string/capitalize';
|
import { capitalize } from '~/utils/string/capitalize';
|
||||||
|
|
||||||
type useDeleteOneRecordProps = {
|
type useDeleteOneRecordProps = {
|
||||||
@ -56,7 +56,7 @@ export const useDeleteManyRecords = ({
|
|||||||
|
|
||||||
const cachedRecords = records
|
const cachedRecords = records
|
||||||
.map((record) => getRecordFromCache(record.id, cache))
|
.map((record) => getRecordFromCache(record.id, cache))
|
||||||
.filter(isDefined);
|
.filter(isNonNullable);
|
||||||
|
|
||||||
triggerDeleteRecordsOptimisticEffect({
|
triggerDeleteRecordsOptimisticEffect({
|
||||||
cache,
|
cache,
|
||||||
|
|||||||
@ -8,7 +8,7 @@ import { parseFieldRelationType } from '@/object-metadata/utils/parseFieldRelati
|
|||||||
import { ObjectRecord } from '@/object-record/types/ObjectRecord';
|
import { ObjectRecord } from '@/object-record/types/ObjectRecord';
|
||||||
import { ObjectRecordConnection } from '@/object-record/types/ObjectRecordConnection';
|
import { ObjectRecordConnection } from '@/object-record/types/ObjectRecordConnection';
|
||||||
import { FieldMetadataType } from '~/generated/graphql';
|
import { FieldMetadataType } from '~/generated/graphql';
|
||||||
import { isDefined } from '~/utils/isDefined';
|
import { isNonNullable } from '~/utils/isNonNullable';
|
||||||
|
|
||||||
export const useMapConnectionToRecords = () => {
|
export const useMapConnectionToRecords = () => {
|
||||||
const objectMetadataItems = useRecoilValue(objectMetadataItemsState);
|
const objectMetadataItems = useRecoilValue(objectMetadataItemsState);
|
||||||
@ -26,7 +26,7 @@ export const useMapConnectionToRecords = () => {
|
|||||||
depth: number;
|
depth: number;
|
||||||
}): ObjectRecord[] => {
|
}): ObjectRecord[] => {
|
||||||
if (
|
if (
|
||||||
!isDefined(objectRecordConnection) ||
|
!isNonNullable(objectRecordConnection) ||
|
||||||
!isNonEmptyArray(objectMetadataItems)
|
!isNonEmptyArray(objectMetadataItems)
|
||||||
) {
|
) {
|
||||||
return [];
|
return [];
|
||||||
@ -79,7 +79,7 @@ export const useMapConnectionToRecords = () => {
|
|||||||
|
|
||||||
if (
|
if (
|
||||||
!relationFieldMetadataItem ||
|
!relationFieldMetadataItem ||
|
||||||
!isDefined(relatedObjectMetadataSingularName)
|
!isNonNullable(relatedObjectMetadataSingularName)
|
||||||
) {
|
) {
|
||||||
throw new Error(
|
throw new Error(
|
||||||
`Could not find relation object metadata item for object name plural ${relationField.name} in mapConnectionToRecords`,
|
`Could not find relation object metadata item for object name plural ${relationField.name} in mapConnectionToRecords`,
|
||||||
@ -90,7 +90,7 @@ export const useMapConnectionToRecords = () => {
|
|||||||
relationField.name
|
relationField.name
|
||||||
] as ObjectRecordConnection | undefined | null;
|
] as ObjectRecordConnection | undefined | null;
|
||||||
|
|
||||||
if (!isDefined(relationConnection)) {
|
if (!isNonNullable(relationConnection)) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
import { useFilterDropdown } from '@/object-record/object-filter-dropdown/hooks/useFilterDropdown';
|
import { useFilterDropdown } from '@/object-record/object-filter-dropdown/hooks/useFilterDropdown';
|
||||||
import { InternalDatePicker } from '@/ui/input/components/internal/date/components/InternalDatePicker';
|
import { InternalDatePicker } from '@/ui/input/components/internal/date/components/InternalDatePicker';
|
||||||
import { isDefined } from '~/utils/isDefined';
|
import { isNonNullable } from '~/utils/isNonNullable';
|
||||||
|
|
||||||
export const ObjectFilterDropdownDateSearchInput = () => {
|
export const ObjectFilterDropdownDateSearchInput = () => {
|
||||||
const {
|
const {
|
||||||
@ -15,9 +15,9 @@ export const ObjectFilterDropdownDateSearchInput = () => {
|
|||||||
|
|
||||||
selectFilter?.({
|
selectFilter?.({
|
||||||
fieldMetadataId: filterDefinitionUsedInDropdown.fieldMetadataId,
|
fieldMetadataId: filterDefinitionUsedInDropdown.fieldMetadataId,
|
||||||
value: isDefined(date) ? date.toISOString() : '',
|
value: isNonNullable(date) ? date.toISOString() : '',
|
||||||
operand: selectedOperandInDropdown,
|
operand: selectedOperandInDropdown,
|
||||||
displayValue: isDefined(date) ? date.toLocaleString() : '',
|
displayValue: isNonNullable(date) ? date.toLocaleString() : '',
|
||||||
definition: filterDefinitionUsedInDropdown,
|
definition: filterDefinitionUsedInDropdown,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
@ -6,7 +6,7 @@ import { useRecordBoardDeprecatedActionBarEntriesInternal } from '@/object-recor
|
|||||||
import { useRecordBoardDeprecatedContextMenuEntriesInternal } from '@/object-record/record-board-deprecated/hooks/internal/useRecordBoardDeprecatedContextMenuEntriesInternal';
|
import { useRecordBoardDeprecatedContextMenuEntriesInternal } from '@/object-record/record-board-deprecated/hooks/internal/useRecordBoardDeprecatedContextMenuEntriesInternal';
|
||||||
import { useRecordBoardDeprecatedScopedStates } from '@/object-record/record-board-deprecated/hooks/internal/useRecordBoardDeprecatedScopedStates';
|
import { useRecordBoardDeprecatedScopedStates } from '@/object-record/record-board-deprecated/hooks/internal/useRecordBoardDeprecatedScopedStates';
|
||||||
import { useUpdateCompanyBoardColumnsInternal } from '@/object-record/record-board-deprecated/hooks/internal/useUpdateCompanyBoardColumnsInternal';
|
import { useUpdateCompanyBoardColumnsInternal } from '@/object-record/record-board-deprecated/hooks/internal/useUpdateCompanyBoardColumnsInternal';
|
||||||
import { isDefined } from '~/utils/isDefined';
|
import { isNonNullable } from '~/utils/isNonNullable';
|
||||||
|
|
||||||
export type RecordBoardDeprecatedInternalEffectProps = {
|
export type RecordBoardDeprecatedInternalEffectProps = {
|
||||||
onFieldsChange: (fields: any) => void;
|
onFieldsChange: (fields: any) => void;
|
||||||
@ -40,13 +40,13 @@ export const RecordBoardDeprecatedInternalEffect = () => {
|
|||||||
}, [opportunities, setSavedOpportunities]);
|
}, [opportunities, setSavedOpportunities]);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (isDefined(fetchMoreOpportunities)) {
|
if (isNonNullable(fetchMoreOpportunities)) {
|
||||||
fetchMoreOpportunities();
|
fetchMoreOpportunities();
|
||||||
}
|
}
|
||||||
}, [fetchMoreOpportunities]);
|
}, [fetchMoreOpportunities]);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (isDefined(fetchMoreCompanies)) {
|
if (isNonNullable(fetchMoreCompanies)) {
|
||||||
fetchMoreCompanies();
|
fetchMoreCompanies();
|
||||||
}
|
}
|
||||||
}, [fetchMoreCompanies]);
|
}, [fetchMoreCompanies]);
|
||||||
|
|||||||
@ -5,7 +5,7 @@ import { recordBoardColumnsFamilyStateScopeMap } from '@/object-record/record-bo
|
|||||||
import { RecordBoardColumnDefinition } from '@/object-record/record-board/types/RecordBoardColumnDefinition';
|
import { RecordBoardColumnDefinition } from '@/object-record/record-board/types/RecordBoardColumnDefinition';
|
||||||
import { createFamilySelectorScopeMap } from '@/ui/utilities/recoil-scope/utils/createFamilySelectorScopeMap';
|
import { createFamilySelectorScopeMap } from '@/ui/utilities/recoil-scope/utils/createFamilySelectorScopeMap';
|
||||||
import { guardRecoilDefaultValue } from '@/ui/utilities/recoil-scope/utils/guardRecoilDefaultValue';
|
import { guardRecoilDefaultValue } from '@/ui/utilities/recoil-scope/utils/guardRecoilDefaultValue';
|
||||||
import { assertNotNull } from '~/utils/assert';
|
import { isNonNullable } from '~/utils/isNonNullable';
|
||||||
|
|
||||||
export const recordBoardColumnsFamilySelectorScopeMap =
|
export const recordBoardColumnsFamilySelectorScopeMap =
|
||||||
createFamilySelectorScopeMap<RecordBoardColumnDefinition | undefined, string>(
|
createFamilySelectorScopeMap<RecordBoardColumnDefinition | undefined, string>(
|
||||||
@ -57,7 +57,7 @@ export const recordBoardColumnsFamilySelectorScopeMap =
|
|||||||
}),
|
}),
|
||||||
);
|
);
|
||||||
})
|
})
|
||||||
.filter(assertNotNull);
|
.filter(isNonNullable);
|
||||||
|
|
||||||
const lastColumn = [...columns].sort(
|
const lastColumn = [...columns].sort(
|
||||||
(a, b) => b.position - a.position,
|
(a, b) => b.position - a.position,
|
||||||
|
|||||||
@ -2,7 +2,7 @@ import { Key } from 'ts-key-enum';
|
|||||||
|
|
||||||
import { useScopedHotkeys } from '@/ui/utilities/hotkey/hooks/useScopedHotkeys';
|
import { useScopedHotkeys } from '@/ui/utilities/hotkey/hooks/useScopedHotkeys';
|
||||||
import { useListenClickOutside } from '@/ui/utilities/pointer-event/hooks/useListenClickOutside';
|
import { useListenClickOutside } from '@/ui/utilities/pointer-event/hooks/useListenClickOutside';
|
||||||
import { isDefined } from '~/utils/isDefined';
|
import { isNonNullable } from '~/utils/isNonNullable';
|
||||||
|
|
||||||
export const useRegisterInputEvents = <T>({
|
export const useRegisterInputEvents = <T>({
|
||||||
inputRef,
|
inputRef,
|
||||||
@ -30,7 +30,7 @@ export const useRegisterInputEvents = <T>({
|
|||||||
|
|
||||||
onClickOutside?.(event, inputValue);
|
onClickOutside?.(event, inputValue);
|
||||||
},
|
},
|
||||||
enabled: isDefined(onClickOutside),
|
enabled: isNonNullable(onClickOutside),
|
||||||
});
|
});
|
||||||
|
|
||||||
useScopedHotkeys(
|
useScopedHotkeys(
|
||||||
|
|||||||
@ -17,9 +17,9 @@ import { isFieldSelect } from '@/object-record/record-field/types/guards/isField
|
|||||||
import { isFieldSelectValue } from '@/object-record/record-field/types/guards/isFieldSelectValue';
|
import { isFieldSelectValue } from '@/object-record/record-field/types/guards/isFieldSelectValue';
|
||||||
import { isFieldText } from '@/object-record/record-field/types/guards/isFieldText';
|
import { isFieldText } from '@/object-record/record-field/types/guards/isFieldText';
|
||||||
import { isFieldUuid } from '@/object-record/record-field/types/guards/isFieldUuid';
|
import { isFieldUuid } from '@/object-record/record-field/types/guards/isFieldUuid';
|
||||||
import { assertNotNull } from '~/utils/assert';
|
import { isNonNullable } from '~/utils/isNonNullable';
|
||||||
|
|
||||||
const isValueEmpty = (value: unknown) => !assertNotNull(value) || value === '';
|
const isValueEmpty = (value: unknown) => !isNonNullable(value) || value === '';
|
||||||
|
|
||||||
export const isFieldValueEmpty = ({
|
export const isFieldValueEmpty = ({
|
||||||
fieldDefinition,
|
fieldDefinition,
|
||||||
@ -46,7 +46,7 @@ export const isFieldValueEmpty = ({
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (isFieldSelect(fieldDefinition)) {
|
if (isFieldSelect(fieldDefinition)) {
|
||||||
return isFieldSelectValue(fieldValue) && !assertNotNull(fieldValue);
|
return isFieldSelectValue(fieldValue) && !isNonNullable(fieldValue);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (isFieldCurrency(fieldDefinition)) {
|
if (isFieldCurrency(fieldDefinition)) {
|
||||||
|
|||||||
@ -22,8 +22,8 @@ import { isMatchingFloatFilter } from '@/object-record/record-filter/utils/isMat
|
|||||||
import { isMatchingStringFilter } from '@/object-record/record-filter/utils/isMatchingStringFilter';
|
import { isMatchingStringFilter } from '@/object-record/record-filter/utils/isMatchingStringFilter';
|
||||||
import { isMatchingUUIDFilter } from '@/object-record/record-filter/utils/isMatchingUUIDFilter';
|
import { isMatchingUUIDFilter } from '@/object-record/record-filter/utils/isMatchingUUIDFilter';
|
||||||
import { FieldMetadataType } from '~/generated-metadata/graphql';
|
import { FieldMetadataType } from '~/generated-metadata/graphql';
|
||||||
import { isDefined } from '~/utils/isDefined';
|
|
||||||
import { isEmptyObject } from '~/utils/isEmptyObject';
|
import { isEmptyObject } from '~/utils/isEmptyObject';
|
||||||
|
import { isNonNullable } from '~/utils/isNonNullable';
|
||||||
|
|
||||||
const isAndFilter = (
|
const isAndFilter = (
|
||||||
filter: ObjectRecordQueryFilter,
|
filter: ObjectRecordQueryFilter,
|
||||||
@ -102,7 +102,7 @@ export const isRecordMatchingFilter = ({
|
|||||||
if (isNotFilter(filter)) {
|
if (isNotFilter(filter)) {
|
||||||
const filterValue = filter.not;
|
const filterValue = filter.not;
|
||||||
|
|
||||||
if (!isDefined(filterValue)) {
|
if (!isNonNullable(filterValue)) {
|
||||||
throw new Error('Unexpected value for "not" filter : ' + filterValue);
|
throw new Error('Unexpected value for "not" filter : ' + filterValue);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -117,7 +117,7 @@ export const isRecordMatchingFilter = ({
|
|||||||
}
|
}
|
||||||
|
|
||||||
return Object.entries(filter).every(([filterKey, filterValue]) => {
|
return Object.entries(filter).every(([filterKey, filterValue]) => {
|
||||||
if (!isDefined(filterValue)) {
|
if (!isNonNullable(filterValue)) {
|
||||||
throw new Error(
|
throw new Error(
|
||||||
'Unexpected value for filter key "' + filterKey + '" : ' + filterValue,
|
'Unexpected value for filter key "' + filterKey + '" : ' + filterValue,
|
||||||
);
|
);
|
||||||
@ -129,7 +129,7 @@ export const isRecordMatchingFilter = ({
|
|||||||
(field) => field.name === filterKey,
|
(field) => field.name === filterKey,
|
||||||
);
|
);
|
||||||
|
|
||||||
if (!isDefined(objectMetadataField)) {
|
if (!isNonNullable(objectMetadataField)) {
|
||||||
throw new Error(
|
throw new Error(
|
||||||
'Field metadata item "' +
|
'Field metadata item "' +
|
||||||
filterKey +
|
filterKey +
|
||||||
|
|||||||
@ -11,7 +11,7 @@ import {
|
|||||||
import { makeAndFilterVariables } from '@/object-record/utils/makeAndFilterVariables';
|
import { makeAndFilterVariables } from '@/object-record/utils/makeAndFilterVariables';
|
||||||
import { ViewFilterOperand } from '@/views/types/ViewFilterOperand';
|
import { ViewFilterOperand } from '@/views/types/ViewFilterOperand';
|
||||||
import { Field } from '~/generated/graphql';
|
import { Field } from '~/generated/graphql';
|
||||||
import { isDefined } from '~/utils/isDefined';
|
import { isNonNullable } from '~/utils/isNonNullable';
|
||||||
|
|
||||||
import { Filter } from '../../object-filter-dropdown/types/Filter';
|
import { Filter } from '../../object-filter-dropdown/types/Filter';
|
||||||
|
|
||||||
@ -38,7 +38,7 @@ export const turnObjectDropdownFilterIntoQueryFilter = (
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!isDefined(rawUIFilter.value) || rawUIFilter.value === '') {
|
if (!isNonNullable(rawUIFilter.value) || rawUIFilter.value === '') {
|
||||||
return undefined;
|
return undefined;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -30,7 +30,7 @@ import {
|
|||||||
FileFolder,
|
FileFolder,
|
||||||
useUploadImageMutation,
|
useUploadImageMutation,
|
||||||
} from '~/generated/graphql';
|
} from '~/generated/graphql';
|
||||||
import { isDefined } from '~/utils/isDefined';
|
import { isNonNullable } from '~/utils/isNonNullable';
|
||||||
|
|
||||||
type RecordShowContainerProps = {
|
type RecordShowContainerProps = {
|
||||||
objectNameSingular: string;
|
objectNameSingular: string;
|
||||||
@ -131,7 +131,7 @@ export const RecordShowContainer = ({
|
|||||||
<RecoilScope CustomRecoilScopeContext={ShowPageRecoilScopeContext}>
|
<RecoilScope CustomRecoilScopeContext={ShowPageRecoilScopeContext}>
|
||||||
<ShowPageContainer>
|
<ShowPageContainer>
|
||||||
<ShowPageLeftContainer>
|
<ShowPageLeftContainer>
|
||||||
{!recordLoading && isDefined(recordFromStore) && (
|
{!recordLoading && isNonNullable(recordFromStore) && (
|
||||||
<>
|
<>
|
||||||
<ShowPageSummaryCard
|
<ShowPageSummaryCard
|
||||||
id={objectRecordId}
|
id={objectRecordId}
|
||||||
|
|||||||
@ -6,7 +6,7 @@ import { Activity } from '@/activities/types/Activity';
|
|||||||
import { useFindOneRecord } from '@/object-record/hooks/useFindOneRecord';
|
import { useFindOneRecord } from '@/object-record/hooks/useFindOneRecord';
|
||||||
import { recordLoadingFamilyState } from '@/object-record/record-store/states/recordLoadingFamilyState';
|
import { recordLoadingFamilyState } from '@/object-record/record-store/states/recordLoadingFamilyState';
|
||||||
import { recordStoreFamilyState } from '@/object-record/record-store/states/recordStoreFamilyState';
|
import { recordStoreFamilyState } from '@/object-record/record-store/states/recordStoreFamilyState';
|
||||||
import { isDefined } from '~/utils/isDefined';
|
import { isNonNullable } from '~/utils/isNonNullable';
|
||||||
|
|
||||||
export const RecordShowContainer = ({
|
export const RecordShowContainer = ({
|
||||||
objectRecordId,
|
objectRecordId,
|
||||||
@ -38,7 +38,7 @@ export const RecordShowContainer = ({
|
|||||||
const { makeActivityWithoutConnection } = useActivityConnectionUtils();
|
const { makeActivityWithoutConnection } = useActivityConnectionUtils();
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (!loading && isDefined(record)) {
|
if (!loading && isNonNullable(record)) {
|
||||||
const { activity: activityWithoutConnection } =
|
const { activity: activityWithoutConnection } =
|
||||||
makeActivityWithoutConnection(record as any);
|
makeActivityWithoutConnection(record as any);
|
||||||
|
|
||||||
|
|||||||
@ -13,7 +13,7 @@ import { SelectableList } from '@/ui/layout/selectable-list/components/Selectabl
|
|||||||
import { MenuItem } from '@/ui/navigation/menu-item/components/MenuItem';
|
import { MenuItem } from '@/ui/navigation/menu-item/components/MenuItem';
|
||||||
import { MenuItemSelect } from '@/ui/navigation/menu-item/components/MenuItemSelect';
|
import { MenuItemSelect } from '@/ui/navigation/menu-item/components/MenuItemSelect';
|
||||||
import { useScopedHotkeys } from '@/ui/utilities/hotkey/hooks/useScopedHotkeys';
|
import { useScopedHotkeys } from '@/ui/utilities/hotkey/hooks/useScopedHotkeys';
|
||||||
import { assertNotNull } from '~/utils/assert';
|
import { isNonNullable } from '~/utils/isNonNullable';
|
||||||
|
|
||||||
import { EntityForSelect } from '../types/EntityForSelect';
|
import { EntityForSelect } from '../types/EntityForSelect';
|
||||||
import { RelationPickerHotkeyScope } from '../types/RelationPickerHotkeyScope';
|
import { RelationPickerHotkeyScope } from '../types/RelationPickerHotkeyScope';
|
||||||
@ -55,7 +55,7 @@ export const SingleEntitySelectMenuItems = ({
|
|||||||
|
|
||||||
const entitiesInDropdown = [selectedEntity, ...entitiesToSelect].filter(
|
const entitiesInDropdown = [selectedEntity, ...entitiesToSelect].filter(
|
||||||
(entity): entity is EntityForSelect =>
|
(entity): entity is EntityForSelect =>
|
||||||
assertNotNull(entity) && isNonEmptyString(entity.name),
|
isNonNullable(entity) && isNonEmptyString(entity.name),
|
||||||
);
|
);
|
||||||
|
|
||||||
useScopedHotkeys(
|
useScopedHotkeys(
|
||||||
|
|||||||
@ -6,7 +6,7 @@ import {
|
|||||||
import { useFilteredSearchEntityQuery } from '@/search/hooks/useFilteredSearchEntityQuery';
|
import { useFilteredSearchEntityQuery } from '@/search/hooks/useFilteredSearchEntityQuery';
|
||||||
import { DropdownMenuSearchInput } from '@/ui/layout/dropdown/components/DropdownMenuSearchInput';
|
import { DropdownMenuSearchInput } from '@/ui/layout/dropdown/components/DropdownMenuSearchInput';
|
||||||
import { DropdownMenuSeparator } from '@/ui/layout/dropdown/components/DropdownMenuSeparator';
|
import { DropdownMenuSeparator } from '@/ui/layout/dropdown/components/DropdownMenuSeparator';
|
||||||
import { isDefined } from '~/utils/isDefined';
|
import { isNonNullable } from '~/utils/isNonNullable';
|
||||||
|
|
||||||
import { useEntitySelectSearch } from '../hooks/useEntitySelectSearch';
|
import { useEntitySelectSearch } from '../hooks/useEntitySelectSearch';
|
||||||
|
|
||||||
@ -42,7 +42,7 @@ export const SingleEntitySelectMenuItemsWithSearch = ({
|
|||||||
relationPickerScopeId,
|
relationPickerScopeId,
|
||||||
});
|
});
|
||||||
|
|
||||||
const showCreateButton = isDefined(onCreate) && searchFilter !== '';
|
const showCreateButton = isNonNullable(onCreate) && searchFilter !== '';
|
||||||
|
|
||||||
const entities = useFilteredSearchEntityQuery({
|
const entities = useFilteredSearchEntityQuery({
|
||||||
filters: [
|
filters: [
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
import { ObjectMetadataItem } from '@/object-metadata/types/ObjectMetadataItem';
|
import { ObjectMetadataItem } from '@/object-metadata/types/ObjectMetadataItem';
|
||||||
import { DEFAULT_SEARCH_REQUEST_LIMIT } from '@/object-record/constants/DefaultSearchRequestLimit';
|
import { DEFAULT_SEARCH_REQUEST_LIMIT } from '@/object-record/constants/DefaultSearchRequestLimit';
|
||||||
import { isDefined } from '~/utils/isDefined';
|
import { isNonNullable } from '~/utils/isNonNullable';
|
||||||
import { capitalize } from '~/utils/string/capitalize';
|
import { capitalize } from '~/utils/string/capitalize';
|
||||||
|
|
||||||
export const useLimitPerMetadataItem = ({
|
export const useLimitPerMetadataItem = ({
|
||||||
@ -15,7 +15,7 @@ export const useLimitPerMetadataItem = ({
|
|||||||
.map(({ nameSingular }) => {
|
.map(({ nameSingular }) => {
|
||||||
return [`limit${capitalize(nameSingular)}`, limit];
|
return [`limit${capitalize(nameSingular)}`, limit];
|
||||||
})
|
})
|
||||||
.filter(isDefined),
|
.filter(isNonNullable),
|
||||||
);
|
);
|
||||||
|
|
||||||
return {
|
return {
|
||||||
|
|||||||
@ -5,7 +5,7 @@ import { objectMetadataItemsByNamePluralMapSelector } from '@/object-metadata/st
|
|||||||
import { getObjectRecordIdentifier } from '@/object-metadata/utils/getObjectRecordIdentifier';
|
import { getObjectRecordIdentifier } from '@/object-metadata/utils/getObjectRecordIdentifier';
|
||||||
import { ObjectRecordForSelect } from '@/object-record/relation-picker/hooks/useMultiObjectSearch';
|
import { ObjectRecordForSelect } from '@/object-record/relation-picker/hooks/useMultiObjectSearch';
|
||||||
import { ObjectRecordConnection } from '@/object-record/types/ObjectRecordConnection';
|
import { ObjectRecordConnection } from '@/object-record/types/ObjectRecordConnection';
|
||||||
import { isDefined } from '~/utils/isDefined';
|
import { isNonNullable } from '~/utils/isNonNullable';
|
||||||
|
|
||||||
export type MultiObjectRecordQueryResult = {
|
export type MultiObjectRecordQueryResult = {
|
||||||
[namePlural: string]: ObjectRecordConnection;
|
[namePlural: string]: ObjectRecordConnection;
|
||||||
@ -30,7 +30,7 @@ export const useMultiObjectRecordsQueryResultFormattedAsObjectRecordForSelectArr
|
|||||||
const objectMetadataItem =
|
const objectMetadataItem =
|
||||||
objectMetadataItemsByNamePluralMap.get(namePlural);
|
objectMetadataItemsByNamePluralMap.get(namePlural);
|
||||||
|
|
||||||
if (!isDefined(objectMetadataItem)) return [];
|
if (!isNonNullable(objectMetadataItem)) return [];
|
||||||
|
|
||||||
return objectRecordConnection.edges.map(({ node }) => ({
|
return objectRecordConnection.edges.map(({ node }) => ({
|
||||||
objectMetadataItem,
|
objectMetadataItem,
|
||||||
|
|||||||
@ -13,7 +13,7 @@ import {
|
|||||||
import { SelectedObjectRecordId } from '@/object-record/relation-picker/hooks/useMultiObjectSearch';
|
import { SelectedObjectRecordId } from '@/object-record/relation-picker/hooks/useMultiObjectSearch';
|
||||||
import { useOrderByFieldPerMetadataItem } from '@/object-record/relation-picker/hooks/useOrderByFieldPerMetadataItem';
|
import { useOrderByFieldPerMetadataItem } from '@/object-record/relation-picker/hooks/useOrderByFieldPerMetadataItem';
|
||||||
import { useSearchFilterPerMetadataItem } from '@/object-record/relation-picker/hooks/useSearchFilterPerMetadataItem';
|
import { useSearchFilterPerMetadataItem } from '@/object-record/relation-picker/hooks/useSearchFilterPerMetadataItem';
|
||||||
import { isDefined } from '~/utils/isDefined';
|
import { isNonNullable } from '~/utils/isNonNullable';
|
||||||
import { capitalize } from '~/utils/string/capitalize';
|
import { capitalize } from '~/utils/string/capitalize';
|
||||||
|
|
||||||
export const useMultiObjectSearchMatchesSearchFilterAndSelectedItemsQuery = ({
|
export const useMultiObjectSearchMatchesSearchFilterAndSelectedItemsQuery = ({
|
||||||
@ -71,7 +71,7 @@ export const useMultiObjectSearchMatchesSearchFilterAndSelectedItemsQuery = ({
|
|||||||
},
|
},
|
||||||
];
|
];
|
||||||
})
|
})
|
||||||
.filter(isDefined),
|
.filter(isNonNullable),
|
||||||
);
|
);
|
||||||
|
|
||||||
const { orderByFieldPerMetadataItem } = useOrderByFieldPerMetadataItem({
|
const { orderByFieldPerMetadataItem } = useOrderByFieldPerMetadataItem({
|
||||||
@ -99,7 +99,7 @@ export const useMultiObjectSearchMatchesSearchFilterAndSelectedItemsQuery = ({
|
|||||||
...orderByFieldPerMetadataItem,
|
...orderByFieldPerMetadataItem,
|
||||||
...limitPerMetadataItem,
|
...limitPerMetadataItem,
|
||||||
},
|
},
|
||||||
skip: !isDefined(multiSelectQueryForSelectedIds),
|
skip: !isNonNullable(multiSelectQueryForSelectedIds),
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|||||||
@ -14,7 +14,7 @@ import { SelectedObjectRecordId } from '@/object-record/relation-picker/hooks/us
|
|||||||
import { useOrderByFieldPerMetadataItem } from '@/object-record/relation-picker/hooks/useOrderByFieldPerMetadataItem';
|
import { useOrderByFieldPerMetadataItem } from '@/object-record/relation-picker/hooks/useOrderByFieldPerMetadataItem';
|
||||||
import { useSearchFilterPerMetadataItem } from '@/object-record/relation-picker/hooks/useSearchFilterPerMetadataItem';
|
import { useSearchFilterPerMetadataItem } from '@/object-record/relation-picker/hooks/useSearchFilterPerMetadataItem';
|
||||||
import { makeAndFilterVariables } from '@/object-record/utils/makeAndFilterVariables';
|
import { makeAndFilterVariables } from '@/object-record/utils/makeAndFilterVariables';
|
||||||
import { isDefined } from '~/utils/isDefined';
|
import { isNonNullable } from '~/utils/isNonNullable';
|
||||||
import { capitalize } from '~/utils/string/capitalize';
|
import { capitalize } from '~/utils/string/capitalize';
|
||||||
|
|
||||||
export const useMultiObjectSearchMatchesSearchFilterAndToSelectQuery = ({
|
export const useMultiObjectSearchMatchesSearchFilterAndToSelectQuery = ({
|
||||||
@ -72,7 +72,7 @@ export const useMultiObjectSearchMatchesSearchFilterAndToSelectQuery = ({
|
|||||||
makeAndFilterVariables(searchFilters),
|
makeAndFilterVariables(searchFilters),
|
||||||
];
|
];
|
||||||
})
|
})
|
||||||
.filter(isDefined),
|
.filter(isNonNullable),
|
||||||
);
|
);
|
||||||
|
|
||||||
const { orderByFieldPerMetadataItem } = useOrderByFieldPerMetadataItem({
|
const { orderByFieldPerMetadataItem } = useOrderByFieldPerMetadataItem({
|
||||||
@ -98,7 +98,7 @@ export const useMultiObjectSearchMatchesSearchFilterAndToSelectQuery = ({
|
|||||||
...orderByFieldPerMetadataItem,
|
...orderByFieldPerMetadataItem,
|
||||||
...limitPerMetadataItem,
|
...limitPerMetadataItem,
|
||||||
},
|
},
|
||||||
skip: !isDefined(multiSelectQuery),
|
skip: !isNonNullable(multiSelectQuery),
|
||||||
});
|
});
|
||||||
|
|
||||||
const {
|
const {
|
||||||
|
|||||||
@ -12,7 +12,7 @@ import {
|
|||||||
} from '@/object-record/relation-picker/hooks/useMultiObjectRecordsQueryResultFormattedAsObjectRecordForSelectArray';
|
} from '@/object-record/relation-picker/hooks/useMultiObjectRecordsQueryResultFormattedAsObjectRecordForSelectArray';
|
||||||
import { SelectedObjectRecordId } from '@/object-record/relation-picker/hooks/useMultiObjectSearch';
|
import { SelectedObjectRecordId } from '@/object-record/relation-picker/hooks/useMultiObjectSearch';
|
||||||
import { useOrderByFieldPerMetadataItem } from '@/object-record/relation-picker/hooks/useOrderByFieldPerMetadataItem';
|
import { useOrderByFieldPerMetadataItem } from '@/object-record/relation-picker/hooks/useOrderByFieldPerMetadataItem';
|
||||||
import { isDefined } from '~/utils/isDefined';
|
import { isNonNullable } from '~/utils/isNonNullable';
|
||||||
import { capitalize } from '~/utils/string/capitalize';
|
import { capitalize } from '~/utils/string/capitalize';
|
||||||
|
|
||||||
export const EMPTY_QUERY = gql`
|
export const EMPTY_QUERY = gql`
|
||||||
@ -56,7 +56,7 @@ export const useMultiObjectSearchSelectedItemsQuery = ({
|
|||||||
},
|
},
|
||||||
];
|
];
|
||||||
})
|
})
|
||||||
.filter(isDefined),
|
.filter(isNonNullable),
|
||||||
);
|
);
|
||||||
|
|
||||||
const { orderByFieldPerMetadataItem } = useOrderByFieldPerMetadataItem({
|
const { orderByFieldPerMetadataItem } = useOrderByFieldPerMetadataItem({
|
||||||
@ -83,7 +83,7 @@ export const useMultiObjectSearchSelectedItemsQuery = ({
|
|||||||
...orderByFieldPerMetadataItem,
|
...orderByFieldPerMetadataItem,
|
||||||
...limitPerMetadataItem,
|
...limitPerMetadataItem,
|
||||||
},
|
},
|
||||||
skip: !isDefined(multiSelectQueryForSelectedIds),
|
skip: !isNonNullable(multiSelectQueryForSelectedIds),
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
import { ObjectMetadataItem } from '@/object-metadata/types/ObjectMetadataItem';
|
import { ObjectMetadataItem } from '@/object-metadata/types/ObjectMetadataItem';
|
||||||
import { getObjectOrderByField } from '@/object-metadata/utils/getObjectOrderByField';
|
import { getObjectOrderByField } from '@/object-metadata/utils/getObjectOrderByField';
|
||||||
import { isDefined } from '~/utils/isDefined';
|
import { isNonNullable } from '~/utils/isNonNullable';
|
||||||
import { capitalize } from '~/utils/string/capitalize';
|
import { capitalize } from '~/utils/string/capitalize';
|
||||||
|
|
||||||
export const useOrderByFieldPerMetadataItem = ({
|
export const useOrderByFieldPerMetadataItem = ({
|
||||||
@ -20,7 +20,7 @@ export const useOrderByFieldPerMetadataItem = ({
|
|||||||
},
|
},
|
||||||
];
|
];
|
||||||
})
|
})
|
||||||
.filter(isDefined),
|
.filter(isNonNullable),
|
||||||
);
|
);
|
||||||
|
|
||||||
return {
|
return {
|
||||||
|
|||||||
@ -3,7 +3,7 @@ import { getLabelIdentifierFieldMetadataItem } from '@/object-metadata/utils/get
|
|||||||
import { ObjectRecordQueryFilter } from '@/object-record/record-filter/types/ObjectRecordQueryFilter';
|
import { ObjectRecordQueryFilter } from '@/object-record/record-filter/types/ObjectRecordQueryFilter';
|
||||||
import { makeOrFilterVariables } from '@/object-record/utils/makeOrFilterVariables';
|
import { makeOrFilterVariables } from '@/object-record/utils/makeOrFilterVariables';
|
||||||
import { FieldMetadataType } from '~/generated/graphql';
|
import { FieldMetadataType } from '~/generated/graphql';
|
||||||
import { isDefined } from '~/utils/isDefined';
|
import { isNonNullable } from '~/utils/isNonNullable';
|
||||||
|
|
||||||
export const useSearchFilterPerMetadataItem = ({
|
export const useSearchFilterPerMetadataItem = ({
|
||||||
objectMetadataItems,
|
objectMetadataItems,
|
||||||
@ -64,7 +64,7 @@ export const useSearchFilterPerMetadataItem = ({
|
|||||||
|
|
||||||
return [objectMetadataItem.nameSingular, searchFilter] as const;
|
return [objectMetadataItem.nameSingular, searchFilter] as const;
|
||||||
})
|
})
|
||||||
.filter(isDefined),
|
.filter(isNonNullable),
|
||||||
);
|
);
|
||||||
|
|
||||||
return {
|
return {
|
||||||
|
|||||||
@ -1,12 +1,15 @@
|
|||||||
import { ObjectRecordEdge } from '@/object-record/types/ObjectRecordEdge';
|
import { ObjectRecordEdge } from '@/object-record/types/ObjectRecordEdge';
|
||||||
import { isDefined } from '~/utils/isDefined';
|
import { isNonNullable } from '~/utils/isNonNullable';
|
||||||
|
|
||||||
export const getChildRelationArray = ({
|
export const getChildRelationArray = ({
|
||||||
childRelation,
|
childRelation,
|
||||||
}: {
|
}: {
|
||||||
childRelation: any;
|
childRelation: any;
|
||||||
}) => {
|
}) => {
|
||||||
if (isDefined(childRelation.edges) && Array.isArray(childRelation.edges)) {
|
if (
|
||||||
|
isNonNullable(childRelation.edges) &&
|
||||||
|
Array.isArray(childRelation.edges)
|
||||||
|
) {
|
||||||
return childRelation.edges.map((edge: ObjectRecordEdge) => edge.node);
|
return childRelation.edges.map((edge: ObjectRecordEdge) => edge.node);
|
||||||
} else {
|
} else {
|
||||||
return childRelation;
|
return childRelation;
|
||||||
|
|||||||
@ -1,10 +1,10 @@
|
|||||||
import { ObjectRecordQueryFilter } from '@/object-record/record-filter/types/ObjectRecordQueryFilter';
|
import { ObjectRecordQueryFilter } from '@/object-record/record-filter/types/ObjectRecordQueryFilter';
|
||||||
import { isDefined } from '~/utils/isDefined';
|
import { isNonNullable } from '~/utils/isNonNullable';
|
||||||
|
|
||||||
export const makeAndFilterVariables = (
|
export const makeAndFilterVariables = (
|
||||||
filters: (ObjectRecordQueryFilter | undefined)[],
|
filters: (ObjectRecordQueryFilter | undefined)[],
|
||||||
): ObjectRecordQueryFilter | undefined => {
|
): ObjectRecordQueryFilter | undefined => {
|
||||||
const definedFilters = filters.filter(isDefined);
|
const definedFilters = filters.filter(isNonNullable);
|
||||||
|
|
||||||
if (!definedFilters.length) return undefined;
|
if (!definedFilters.length) return undefined;
|
||||||
|
|
||||||
|
|||||||
@ -1,10 +1,10 @@
|
|||||||
import { ObjectRecordQueryFilter } from '@/object-record/record-filter/types/ObjectRecordQueryFilter';
|
import { ObjectRecordQueryFilter } from '@/object-record/record-filter/types/ObjectRecordQueryFilter';
|
||||||
import { isDefined } from '~/utils/isDefined';
|
import { isNonNullable } from '~/utils/isNonNullable';
|
||||||
|
|
||||||
export const makeOrFilterVariables = (
|
export const makeOrFilterVariables = (
|
||||||
filters: (ObjectRecordQueryFilter | undefined)[],
|
filters: (ObjectRecordQueryFilter | undefined)[],
|
||||||
): ObjectRecordQueryFilter | undefined => {
|
): ObjectRecordQueryFilter | undefined => {
|
||||||
const definedFilters = filters.filter(isDefined);
|
const definedFilters = filters.filter(isNonNullable);
|
||||||
|
|
||||||
if (!definedFilters.length) return undefined;
|
if (!definedFilters.length) return undefined;
|
||||||
|
|
||||||
|
|||||||
@ -5,7 +5,7 @@ import { ObjectMetadataItem } from '@/object-metadata/types/ObjectMetadataItem';
|
|||||||
import { isFieldRelationValue } from '@/object-record/record-field/types/guards/isFieldRelationValue';
|
import { isFieldRelationValue } from '@/object-record/record-field/types/guards/isFieldRelationValue';
|
||||||
import { sanitizeLink } from '@/object-record/utils/sanitizeLinkRecordInput';
|
import { sanitizeLink } from '@/object-record/utils/sanitizeLinkRecordInput';
|
||||||
import { FieldMetadataType } from '~/generated/graphql';
|
import { FieldMetadataType } from '~/generated/graphql';
|
||||||
import { isDefined } from '~/utils/isDefined';
|
import { isNonNullable } from '~/utils/isNonNullable';
|
||||||
|
|
||||||
export const sanitizeRecordInput = ({
|
export const sanitizeRecordInput = ({
|
||||||
objectMetadataItem,
|
objectMetadataItem,
|
||||||
@ -39,7 +39,7 @@ export const sanitizeRecordInput = ({
|
|||||||
|
|
||||||
return [fieldName, fieldValue];
|
return [fieldName, fieldValue];
|
||||||
})
|
})
|
||||||
.filter(isDefined),
|
.filter(isNonNullable),
|
||||||
);
|
);
|
||||||
if (
|
if (
|
||||||
objectMetadataItem.nameSingular !== CoreObjectNameSingular.Company ||
|
objectMetadataItem.nameSingular !== CoreObjectNameSingular.Company ||
|
||||||
|
|||||||
@ -2,7 +2,7 @@ import { DateTime } from 'luxon';
|
|||||||
|
|
||||||
import { OrderBy } from '@/object-metadata/types/OrderBy';
|
import { OrderBy } from '@/object-metadata/types/OrderBy';
|
||||||
import { ObjectRecord } from '@/object-record/types/ObjectRecord';
|
import { ObjectRecord } from '@/object-record/types/ObjectRecord';
|
||||||
import { isDefined } from '~/utils/isDefined';
|
import { isNonNullable } from '~/utils/isNonNullable';
|
||||||
|
|
||||||
const SORT_BEFORE = -1;
|
const SORT_BEFORE = -1;
|
||||||
const SORT_AFTER = 1;
|
const SORT_AFTER = 1;
|
||||||
@ -14,11 +14,11 @@ export const sortObjectRecordByDateField =
|
|||||||
const aDate = a[dateField];
|
const aDate = a[dateField];
|
||||||
const bDate = b[dateField];
|
const bDate = b[dateField];
|
||||||
|
|
||||||
if (!isDefined(aDate) && !isDefined(bDate)) {
|
if (!isNonNullable(aDate) && !isNonNullable(bDate)) {
|
||||||
return SORT_EQUAL;
|
return SORT_EQUAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!isDefined(aDate)) {
|
if (!isNonNullable(aDate)) {
|
||||||
if (sortDirection === 'AscNullsFirst') {
|
if (sortDirection === 'AscNullsFirst') {
|
||||||
return SORT_BEFORE;
|
return SORT_BEFORE;
|
||||||
} else if (sortDirection === 'DescNullsFirst') {
|
} else if (sortDirection === 'DescNullsFirst') {
|
||||||
@ -32,7 +32,7 @@ export const sortObjectRecordByDateField =
|
|||||||
throw new Error(`Invalid sortDirection: ${sortDirection}`);
|
throw new Error(`Invalid sortDirection: ${sortDirection}`);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!isDefined(bDate)) {
|
if (!isNonNullable(bDate)) {
|
||||||
if (sortDirection === 'AscNullsFirst') {
|
if (sortDirection === 'AscNullsFirst') {
|
||||||
return SORT_AFTER;
|
return SORT_AFTER;
|
||||||
} else if (sortDirection === 'DescNullsFirst') {
|
} else if (sortDirection === 'DescNullsFirst') {
|
||||||
|
|||||||
@ -9,7 +9,7 @@ import { EntityForSelect } from '@/object-record/relation-picker/types/EntityFor
|
|||||||
import { ObjectRecord } from '@/object-record/types/ObjectRecord';
|
import { ObjectRecord } from '@/object-record/types/ObjectRecord';
|
||||||
import { makeAndFilterVariables } from '@/object-record/utils/makeAndFilterVariables';
|
import { makeAndFilterVariables } from '@/object-record/utils/makeAndFilterVariables';
|
||||||
import { makeOrFilterVariables } from '@/object-record/utils/makeOrFilterVariables';
|
import { makeOrFilterVariables } from '@/object-record/utils/makeOrFilterVariables';
|
||||||
import { assertNotNull } from '~/utils/assert';
|
import { isNonNullable } from '~/utils/isNonNullable';
|
||||||
|
|
||||||
type SearchFilter = { fieldNames: string[]; filter: string | number };
|
type SearchFilter = { fieldNames: string[]; filter: string | number };
|
||||||
|
|
||||||
@ -104,13 +104,13 @@ export const useFilteredSearchEntityQuery = ({
|
|||||||
return {
|
return {
|
||||||
selectedEntities: selectedRecords
|
selectedEntities: selectedRecords
|
||||||
.map(mappingFunction)
|
.map(mappingFunction)
|
||||||
.filter(assertNotNull),
|
.filter(isNonNullable),
|
||||||
filteredSelectedEntities: filteredSelectedRecords
|
filteredSelectedEntities: filteredSelectedRecords
|
||||||
.map(mappingFunction)
|
.map(mappingFunction)
|
||||||
.filter(assertNotNull),
|
.filter(isNonNullable),
|
||||||
entitiesToSelect: recordsToSelect
|
entitiesToSelect: recordsToSelect
|
||||||
.map(mappingFunction)
|
.map(mappingFunction)
|
||||||
.filter(assertNotNull),
|
.filter(isNonNullable),
|
||||||
loading:
|
loading:
|
||||||
recordsToSelectLoading ||
|
recordsToSelectLoading ||
|
||||||
filteredSelectedRecordsLoading ||
|
filteredSelectedRecordsLoading ||
|
||||||
|
|||||||
@ -1,7 +1,7 @@
|
|||||||
import styled from '@emotion/styled';
|
import styled from '@emotion/styled';
|
||||||
|
|
||||||
import { RawData } from '@/spreadsheet-import/types';
|
import { RawData } from '@/spreadsheet-import/types';
|
||||||
import { assertNotNull } from '~/utils/assert';
|
import { isNonNullable } from '~/utils/isNonNullable';
|
||||||
|
|
||||||
import { Column } from '../MatchColumnsStep';
|
import { Column } from '../MatchColumnsStep';
|
||||||
|
|
||||||
@ -39,7 +39,7 @@ export const UserTableColumn = <T extends string>({
|
|||||||
entries,
|
entries,
|
||||||
}: UserTableColumnProps<T>) => {
|
}: UserTableColumnProps<T>) => {
|
||||||
const { header } = column;
|
const { header } = column;
|
||||||
const entry = entries.find(assertNotNull);
|
const entry = entries.find(isNonNullable);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<StyledContainer>
|
<StyledContainer>
|
||||||
|
|||||||
@ -5,7 +5,7 @@ import { Key } from 'ts-key-enum';
|
|||||||
import { FieldDoubleText } from '@/object-record/record-field/types/FieldDoubleText';
|
import { FieldDoubleText } from '@/object-record/record-field/types/FieldDoubleText';
|
||||||
import { useScopedHotkeys } from '@/ui/utilities/hotkey/hooks/useScopedHotkeys';
|
import { useScopedHotkeys } from '@/ui/utilities/hotkey/hooks/useScopedHotkeys';
|
||||||
import { useListenClickOutside } from '@/ui/utilities/pointer-event/hooks/useListenClickOutside';
|
import { useListenClickOutside } from '@/ui/utilities/pointer-event/hooks/useListenClickOutside';
|
||||||
import { isDefined } from '~/utils/isDefined';
|
import { isNonNullable } from '~/utils/isNonNullable';
|
||||||
|
|
||||||
import { StyledInput } from './TextInput';
|
import { StyledInput } from './TextInput';
|
||||||
|
|
||||||
@ -147,7 +147,7 @@ export const DoubleTextInput = ({
|
|||||||
secondValue: secondInternalValue,
|
secondValue: secondInternalValue,
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
enabled: isDefined(onClickOutside),
|
enabled: isNonNullable(onClickOutside),
|
||||||
});
|
});
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
|||||||
@ -10,7 +10,7 @@ import { useScopedHotkeys } from '@/ui/utilities/hotkey/hooks/useScopedHotkeys';
|
|||||||
import { useClickOutsideListener } from '@/ui/utilities/pointer-event/hooks/useClickOutsideListener';
|
import { useClickOutsideListener } from '@/ui/utilities/pointer-event/hooks/useClickOutsideListener';
|
||||||
import { ClickOutsideMode } from '@/ui/utilities/pointer-event/hooks/useListenClickOutside';
|
import { ClickOutsideMode } from '@/ui/utilities/pointer-event/hooks/useListenClickOutside';
|
||||||
import { useIsMobile } from '@/ui/utilities/responsive/hooks/useIsMobile';
|
import { useIsMobile } from '@/ui/utilities/responsive/hooks/useIsMobile';
|
||||||
import { isDefined } from '~/utils/isDefined';
|
import { isNonNullable } from '~/utils/isNonNullable';
|
||||||
|
|
||||||
import { useRightDrawer } from '../hooks/useRightDrawer';
|
import { useRightDrawer } from '../hooks/useRightDrawer';
|
||||||
import { isRightDrawerExpandedState } from '../states/isRightDrawerExpandedState';
|
import { isRightDrawerExpandedState } from '../states/isRightDrawerExpandedState';
|
||||||
@ -84,7 +84,7 @@ export const RightDrawer = () => {
|
|||||||
: theme.rightDrawerWidth
|
: theme.rightDrawerWidth
|
||||||
: '0';
|
: '0';
|
||||||
|
|
||||||
if (!isDefined(rightDrawerPage)) {
|
if (!isNonNullable(rightDrawerPage)) {
|
||||||
return <></>;
|
return <></>;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
import { useRecoilCallback } from 'recoil';
|
import { useRecoilCallback } from 'recoil';
|
||||||
|
|
||||||
import { isDefined } from '~/utils/isDefined';
|
import { isNonNullable } from '~/utils/isNonNullable';
|
||||||
|
|
||||||
import { DEFAULT_HOTKEYS_SCOPE_CUSTOM_SCOPES } from '../constants/DefaultHotkeysScopeCustomScopes';
|
import { DEFAULT_HOTKEYS_SCOPE_CUSTOM_SCOPES } from '../constants/DefaultHotkeysScopeCustomScopes';
|
||||||
import { currentHotkeyScopeState } from '../states/internal/currentHotkeyScopeState';
|
import { currentHotkeyScopeState } from '../states/internal/currentHotkeyScopeState';
|
||||||
@ -30,7 +30,7 @@ export const useSetHotkeyScope = () =>
|
|||||||
.valueOrThrow();
|
.valueOrThrow();
|
||||||
|
|
||||||
if (currentHotkeyScope.scope === hotkeyScopeToSet) {
|
if (currentHotkeyScope.scope === hotkeyScopeToSet) {
|
||||||
if (!isDefined(customScopes)) {
|
if (!isNonNullable(customScopes)) {
|
||||||
if (
|
if (
|
||||||
isCustomScopesEqual(
|
isCustomScopesEqual(
|
||||||
currentHotkeyScope?.customScopes,
|
currentHotkeyScope?.customScopes,
|
||||||
|
|||||||
@ -8,7 +8,7 @@ import {
|
|||||||
} from '@/ui/utilities/pointer-event/hooks/useListenClickOutsideV2';
|
} from '@/ui/utilities/pointer-event/hooks/useListenClickOutsideV2';
|
||||||
import { ClickOutsideListenerCallback } from '@/ui/utilities/pointer-event/types/ClickOutsideListenerCallback';
|
import { ClickOutsideListenerCallback } from '@/ui/utilities/pointer-event/types/ClickOutsideListenerCallback';
|
||||||
import { getScopeIdFromComponentId } from '@/ui/utilities/recoil-scope/utils/getScopeIdFromComponentId';
|
import { getScopeIdFromComponentId } from '@/ui/utilities/recoil-scope/utils/getScopeIdFromComponentId';
|
||||||
import { isDefined } from '~/utils/isDefined';
|
import { isNonNullable } from '~/utils/isNonNullable';
|
||||||
|
|
||||||
export const useClickOutsideListener = (componentId: string) => {
|
export const useClickOutsideListener = (componentId: string) => {
|
||||||
// TODO: improve typing
|
// TODO: improve typing
|
||||||
@ -67,7 +67,7 @@ export const useClickOutsideListener = (componentId: string) => {
|
|||||||
(callback) => callback.callbackId === callbackId,
|
(callback) => callback.callbackId === callbackId,
|
||||||
);
|
);
|
||||||
|
|
||||||
if (!isDefined(existingCallbackWithSameId)) {
|
if (!isNonNullable(existingCallbackWithSameId)) {
|
||||||
const existingCallbacksWithNewCallback = existingCallbacks.concat({
|
const existingCallbacksWithNewCallback = existingCallbacks.concat({
|
||||||
callbackId,
|
callbackId,
|
||||||
callbackFunction,
|
callbackFunction,
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
import { useContext } from 'react';
|
import { useContext } from 'react';
|
||||||
|
|
||||||
import { isDefined } from '~/utils/isDefined';
|
import { isNonNullable } from '~/utils/isNonNullable';
|
||||||
|
|
||||||
import { ScopeInternalContext } from '../types/ScopeInternalContext';
|
import { ScopeInternalContext } from '../types/ScopeInternalContext';
|
||||||
|
|
||||||
@ -9,7 +9,7 @@ export const useScopeInternalContextOrThrow = <T extends { scopeId: string }>(
|
|||||||
) => {
|
) => {
|
||||||
const context = useContext(Context);
|
const context = useContext(Context);
|
||||||
|
|
||||||
if (!isDefined(context)) {
|
if (!isNonNullable(context)) {
|
||||||
throw new Error(
|
throw new Error(
|
||||||
`Using a scope context without a ScopeInternalContext.Provider wrapper for context : ${Context.displayName}.`,
|
`Using a scope context without a ScopeInternalContext.Provider wrapper for context : ${Context.displayName}.`,
|
||||||
);
|
);
|
||||||
|
|||||||
@ -20,7 +20,7 @@ import { MenuItem } from '@/ui/navigation/menu-item/components/MenuItem';
|
|||||||
import { MenuItemDraggable } from '@/ui/navigation/menu-item/components/MenuItemDraggable';
|
import { MenuItemDraggable } from '@/ui/navigation/menu-item/components/MenuItemDraggable';
|
||||||
import { useListenClickOutside } from '@/ui/utilities/pointer-event/hooks/useListenClickOutside';
|
import { useListenClickOutside } from '@/ui/utilities/pointer-event/hooks/useListenClickOutside';
|
||||||
import { groupArrayItemsBy } from '~/utils/array/groupArrayItemsBy';
|
import { groupArrayItemsBy } from '~/utils/array/groupArrayItemsBy';
|
||||||
import { isDefined } from '~/utils/isDefined';
|
import { isNonNullable } from '~/utils/isNonNullable';
|
||||||
|
|
||||||
type ViewFieldsVisibilityDropdownSectionProps = {
|
type ViewFieldsVisibilityDropdownSectionProps = {
|
||||||
fields: Omit<ColumnDefinition<FieldMetadata>, 'size'>[];
|
fields: Omit<ColumnDefinition<FieldMetadata>, 'size'>[];
|
||||||
@ -69,7 +69,7 @@ export const ViewFieldsVisibilityDropdownSection = ({
|
|||||||
Icon: field.isVisible ? IconMinus : IconPlus,
|
Icon: field.isVisible ? IconMinus : IconPlus,
|
||||||
onClick: () => onVisibilityChange(field),
|
onClick: () => onVisibilityChange(field),
|
||||||
},
|
},
|
||||||
].filter(isDefined);
|
].filter(isNonNullable);
|
||||||
|
|
||||||
return iconButtons.length ? iconButtons : undefined;
|
return iconButtons.length ? iconButtons : undefined;
|
||||||
};
|
};
|
||||||
@ -134,7 +134,7 @@ export const ViewFieldsVisibilityDropdownSection = ({
|
|||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
</DropdownMenuItemsContainer>
|
</DropdownMenuItemsContainer>
|
||||||
{isDefined(openToolTipIndex) &&
|
{isNonNullable(openToolTipIndex) &&
|
||||||
createPortal(
|
createPortal(
|
||||||
<AppTooltip
|
<AppTooltip
|
||||||
anchorSelect={`.${title}-${
|
anchorSelect={`.${title}-${
|
||||||
|
|||||||
@ -20,7 +20,7 @@ import { MOBILE_VIEWPORT } from '@/ui/theme/constants/MobileViewport';
|
|||||||
import { HotkeyScope } from '@/ui/utilities/hotkey/types/HotkeyScope';
|
import { HotkeyScope } from '@/ui/utilities/hotkey/types/HotkeyScope';
|
||||||
import { VIEWS_DROPDOWN_ID } from '@/views/constants/ViewsDropdownId';
|
import { VIEWS_DROPDOWN_ID } from '@/views/constants/ViewsDropdownId';
|
||||||
import { useViewBar } from '@/views/hooks/useViewBar';
|
import { useViewBar } from '@/views/hooks/useViewBar';
|
||||||
import { assertNotNull } from '~/utils/assert';
|
import { isNonNullable } from '~/utils/isNonNullable';
|
||||||
|
|
||||||
import { useViewScopedStates } from '../hooks/internal/useViewScopedStates';
|
import { useViewScopedStates } from '../hooks/internal/useViewScopedStates';
|
||||||
|
|
||||||
@ -161,7 +161,7 @@ export const ViewsDropdownButton = ({
|
|||||||
handleDeleteViewButtonClick(event, view.id),
|
handleDeleteViewButtonClick(event, view.id),
|
||||||
}
|
}
|
||||||
: null,
|
: null,
|
||||||
].filter(assertNotNull)}
|
].filter(isNonNullable)}
|
||||||
onClick={() => handleViewSelect(view.id)}
|
onClick={() => handleViewSelect(view.id)}
|
||||||
LeftIcon={IconList}
|
LeftIcon={IconList}
|
||||||
text={view.name}
|
text={view.name}
|
||||||
|
|||||||
@ -14,7 +14,7 @@ import { useGenerateFindManyRecordsQuery } from '@/object-record/hooks/useGenera
|
|||||||
import { ObjectRecord } from '@/object-record/types/ObjectRecord';
|
import { ObjectRecord } from '@/object-record/types/ObjectRecord';
|
||||||
import { ViewFilter } from '@/views/types/ViewFilter';
|
import { ViewFilter } from '@/views/types/ViewFilter';
|
||||||
import { ViewFilterOperand } from '@/views/types/ViewFilterOperand';
|
import { ViewFilterOperand } from '@/views/types/ViewFilterOperand';
|
||||||
import { assertNotNull } from '~/utils/assert';
|
import { isNonNullable } from '~/utils/isNonNullable';
|
||||||
|
|
||||||
const filterQueryParamsSchema = z.object({
|
const filterQueryParamsSchema = z.object({
|
||||||
filter: z.record(
|
filter: z.record(
|
||||||
@ -142,7 +142,7 @@ export const useFiltersFromQueryParams = () => {
|
|||||||
},
|
},
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
).filter(assertNotNull);
|
).filter(isNonNullable);
|
||||||
},
|
},
|
||||||
[
|
[
|
||||||
apolloClient,
|
apolloClient,
|
||||||
|
|||||||
@ -7,8 +7,8 @@ import { useAvailableScopeIdOrThrow } from '@/ui/utilities/recoil-scope/scopes-i
|
|||||||
import { ViewField } from '@/views/types/ViewField';
|
import { ViewField } from '@/views/types/ViewField';
|
||||||
import { ViewFilter } from '@/views/types/ViewFilter';
|
import { ViewFilter } from '@/views/types/ViewFilter';
|
||||||
import { ViewSort } from '@/views/types/ViewSort';
|
import { ViewSort } from '@/views/types/ViewSort';
|
||||||
import { assertNotNull } from '~/utils/assert';
|
|
||||||
import { isDeeplyEqual } from '~/utils/isDeeplyEqual';
|
import { isDeeplyEqual } from '~/utils/isDeeplyEqual';
|
||||||
|
import { isNonNullable } from '~/utils/isNonNullable';
|
||||||
|
|
||||||
import { ViewScopeInternalContext } from '../scopes/scope-internal-context/ViewScopeInternalContext';
|
import { ViewScopeInternalContext } from '../scopes/scope-internal-context/ViewScopeInternalContext';
|
||||||
import { currentViewFieldsScopedFamilyState } from '../states/currentViewFieldsScopedFamilyState';
|
import { currentViewFieldsScopedFamilyState } from '../states/currentViewFieldsScopedFamilyState';
|
||||||
@ -116,9 +116,7 @@ export const useViewBar = (props?: UseViewProps) => {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const queriedViewFields = viewFields
|
const queriedViewFields = viewFields.filter(isNonNullable);
|
||||||
.map((viewField) => viewField)
|
|
||||||
.filter(assertNotNull);
|
|
||||||
|
|
||||||
if (isPersistingView) {
|
if (isPersistingView) {
|
||||||
return;
|
return;
|
||||||
@ -173,7 +171,7 @@ export const useViewBar = (props?: UseViewProps) => {
|
|||||||
definition: availableFilterDefinition,
|
definition: availableFilterDefinition,
|
||||||
};
|
};
|
||||||
})
|
})
|
||||||
.filter(assertNotNull);
|
.filter(isNonNullable);
|
||||||
|
|
||||||
if (!isDeeplyEqual(savedViewFilters, queriedViewFilters)) {
|
if (!isDeeplyEqual(savedViewFilters, queriedViewFilters)) {
|
||||||
set(savedViewFiltersState, queriedViewFilters);
|
set(savedViewFiltersState, queriedViewFilters);
|
||||||
@ -220,7 +218,7 @@ export const useViewBar = (props?: UseViewProps) => {
|
|||||||
definition: availableSortDefinition,
|
definition: availableSortDefinition,
|
||||||
};
|
};
|
||||||
})
|
})
|
||||||
.filter(assertNotNull);
|
.filter(isNonNullable);
|
||||||
|
|
||||||
if (!isDeeplyEqual(savedViewSorts, queriedViewSorts)) {
|
if (!isDeeplyEqual(savedViewSorts, queriedViewSorts)) {
|
||||||
set(savedViewSortsState, queriedViewSorts);
|
set(savedViewSortsState, queriedViewSorts);
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
import { BoardFieldDefinition } from '@/object-record/record-board-deprecated/types/BoardFieldDefinition';
|
import { BoardFieldDefinition } from '@/object-record/record-board-deprecated/types/BoardFieldDefinition';
|
||||||
import { FieldMetadata } from '@/object-record/record-field/types/FieldMetadata';
|
import { FieldMetadata } from '@/object-record/record-field/types/FieldMetadata';
|
||||||
import { assertNotNull } from '~/utils/assert';
|
import { isNonNullable } from '~/utils/isNonNullable';
|
||||||
|
|
||||||
import { ViewField } from '../types/ViewField';
|
import { ViewField } from '../types/ViewField';
|
||||||
|
|
||||||
@ -28,5 +28,5 @@ export const mapViewFieldsToBoardFieldDefinitions = (
|
|||||||
}
|
}
|
||||||
: null;
|
: null;
|
||||||
})
|
})
|
||||||
.filter(assertNotNull);
|
.filter(isNonNullable);
|
||||||
};
|
};
|
||||||
|
|||||||
@ -2,7 +2,7 @@ import { FieldMetadata } from '@/object-record/record-field/types/FieldMetadata'
|
|||||||
import { ColumnDefinition } from '@/object-record/record-table/types/ColumnDefinition';
|
import { ColumnDefinition } from '@/object-record/record-table/types/ColumnDefinition';
|
||||||
import { mapArrayToObject } from '~/utils/array/mapArrayToObject';
|
import { mapArrayToObject } from '~/utils/array/mapArrayToObject';
|
||||||
import { moveArrayItem } from '~/utils/array/moveArrayItem';
|
import { moveArrayItem } from '~/utils/array/moveArrayItem';
|
||||||
import { assertNotNull } from '~/utils/assert';
|
import { isNonNullable } from '~/utils/isNonNullable';
|
||||||
|
|
||||||
import { ViewField } from '../types/ViewField';
|
import { ViewField } from '../types/ViewField';
|
||||||
|
|
||||||
@ -48,7 +48,7 @@ export const mapViewFieldsToColumnDefinitions = ({
|
|||||||
viewFieldId: viewField.id,
|
viewFieldId: viewField.id,
|
||||||
};
|
};
|
||||||
})
|
})
|
||||||
.filter(assertNotNull);
|
.filter(isNonNullable);
|
||||||
|
|
||||||
// No label identifier set for this object
|
// No label identifier set for this object
|
||||||
if (!labelIdentifierFieldMetadataId) return columnDefinitionsFromViewFields;
|
if (!labelIdentifierFieldMetadataId) return columnDefinitionsFromViewFields;
|
||||||
|
|||||||
@ -16,7 +16,7 @@ import { ShowPageAddButton } from '@/ui/layout/show-page/components/ShowPageAddB
|
|||||||
import { ShowPageMoreButton } from '@/ui/layout/show-page/components/ShowPageMoreButton';
|
import { ShowPageMoreButton } from '@/ui/layout/show-page/components/ShowPageMoreButton';
|
||||||
import { PageTitle } from '@/ui/utilities/page-title/PageTitle';
|
import { PageTitle } from '@/ui/utilities/page-title/PageTitle';
|
||||||
import { FieldMetadataType } from '~/generated-metadata/graphql';
|
import { FieldMetadataType } from '~/generated-metadata/graphql';
|
||||||
import { isDefined } from '~/utils/isDefined';
|
import { isNonNullable } from '~/utils/isNonNullable';
|
||||||
|
|
||||||
export const RecordShowPage = () => {
|
export const RecordShowPage = () => {
|
||||||
const { objectNameSingular, objectRecordId } = useParams<{
|
const { objectNameSingular, objectRecordId } = useParams<{
|
||||||
@ -55,7 +55,7 @@ export const RecordShowPage = () => {
|
|||||||
(favorite) => favorite.recordId === objectRecordId,
|
(favorite) => favorite.recordId === objectRecordId,
|
||||||
);
|
);
|
||||||
|
|
||||||
const isFavorite = isDefined(correspondingFavorite);
|
const isFavorite = isNonNullable(correspondingFavorite);
|
||||||
|
|
||||||
const handleFavoriteButtonClick = async () => {
|
const handleFavoriteButtonClick = async () => {
|
||||||
if (!objectNameSingular || !record) return;
|
if (!objectNameSingular || !record) return;
|
||||||
|
|||||||
@ -1,7 +1,7 @@
|
|||||||
import { isObject, isString } from '@sniptt/guards';
|
import { isObject, isString } from '@sniptt/guards';
|
||||||
import { GraphQLVariables } from 'msw';
|
import { GraphQLVariables } from 'msw';
|
||||||
|
|
||||||
import { isDefined } from '../../utils/isDefined';
|
import { isNonNullable } from '../../utils/isNonNullable';
|
||||||
|
|
||||||
type StringFilter = {
|
type StringFilter = {
|
||||||
equals?: string;
|
equals?: string;
|
||||||
@ -133,7 +133,7 @@ export const fetchOneFromData = <DataT extends { id: string }>(
|
|||||||
data: Array<DataT>,
|
data: Array<DataT>,
|
||||||
id: string,
|
id: string,
|
||||||
): DataT | undefined => {
|
): DataT | undefined => {
|
||||||
if (!isDefined(id)) {
|
if (!isNonNullable(id)) {
|
||||||
throw new Error(
|
throw new Error(
|
||||||
`id is not defined in updateOneFromData, check that you provided where.id if needed.`,
|
`id is not defined in updateOneFromData, check that you provided where.id if needed.`,
|
||||||
);
|
);
|
||||||
@ -147,7 +147,7 @@ export const updateOneFromData = <DataT extends { id: string }>(
|
|||||||
id: string | undefined,
|
id: string | undefined,
|
||||||
payload: GraphQLVariables,
|
payload: GraphQLVariables,
|
||||||
): DataT | undefined => {
|
): DataT | undefined => {
|
||||||
if (!isDefined(id)) {
|
if (!isNonNullable(id)) {
|
||||||
throw new Error(
|
throw new Error(
|
||||||
`id is not defined in updateOneFromData, check that you provided where.id if needed.`,
|
`id is not defined in updateOneFromData, check that you provided where.id if needed.`,
|
||||||
);
|
);
|
||||||
|
|||||||
@ -1,19 +0,0 @@
|
|||||||
import { assertNotNull } from '~/utils/assert';
|
|
||||||
|
|
||||||
describe('assert', () => {
|
|
||||||
it('should return true for a NonNullable value', () => {
|
|
||||||
expect(assertNotNull(1)).toBeTruthy();
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should return true for a NonNullable value', () => {
|
|
||||||
expect(assertNotNull('')).toBeTruthy();
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should return false for a null value', () => {
|
|
||||||
expect(assertNotNull(null)).toBeFalsy();
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should return false for an undefined value', () => {
|
|
||||||
expect(assertNotNull(undefined)).toBeFalsy();
|
|
||||||
});
|
|
||||||
});
|
|
||||||
@ -1,19 +0,0 @@
|
|||||||
import { isDefined } from '~/utils/isDefined';
|
|
||||||
|
|
||||||
describe('isDefined', () => {
|
|
||||||
it('should return true for a NonNullable value', () => {
|
|
||||||
expect(isDefined(1)).toBe(true);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should return true for a NonNullable value', () => {
|
|
||||||
expect(isDefined('')).toBe(true);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should return false for a null value', () => {
|
|
||||||
expect(isDefined(null)).toBe(false);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should return false for an undefined value', () => {
|
|
||||||
expect(isDefined(undefined)).toBe(false);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
@ -0,0 +1,15 @@
|
|||||||
|
import { isNonNullable } from '~/utils/isNonNullable';
|
||||||
|
|
||||||
|
describe('isNonNullable', () => {
|
||||||
|
it('returns true if value is not undefined nor null', () => {
|
||||||
|
expect(isNonNullable('')).toBe(true);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('returns false if value is null', () => {
|
||||||
|
expect(isNonNullable(null)).toBe(false);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('returns false if value is undefined', () => {
|
||||||
|
expect(isNonNullable(undefined)).toBe(false);
|
||||||
|
});
|
||||||
|
});
|
||||||
@ -0,0 +1,30 @@
|
|||||||
|
import { parseApolloStoreFieldName } from '../parseApolloStoreFieldName';
|
||||||
|
|
||||||
|
describe('parseApolloStoreFieldName', () => {
|
||||||
|
it('returns an empty object if string is not a valid store field name', () => {
|
||||||
|
const result = parseApolloStoreFieldName('////');
|
||||||
|
expect(result).toEqual({});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('returns the field name and parsed variables if they exist', () => {
|
||||||
|
const result = parseApolloStoreFieldName('fieldName({"key":"value"})');
|
||||||
|
expect(result).toEqual({
|
||||||
|
fieldName: 'fieldName',
|
||||||
|
fieldVariables: { key: 'value' },
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('returns only the field name if the variables cannot be parsed', () => {
|
||||||
|
const result = parseApolloStoreFieldName('fieldName(notJson)');
|
||||||
|
expect(result).toEqual({
|
||||||
|
fieldName: 'fieldName',
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('returns only the field name if there are no variables', () => {
|
||||||
|
const result = parseApolloStoreFieldName('fieldName');
|
||||||
|
expect(result).toEqual({
|
||||||
|
fieldName: 'fieldName',
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
35
packages/twenty-front/src/utils/__tests__/sort.test.ts
Normal file
35
packages/twenty-front/src/utils/__tests__/sort.test.ts
Normal file
@ -0,0 +1,35 @@
|
|||||||
|
import { sortAsc, sortDesc, sortNullsFirst, sortNullsLast } from '../sort';
|
||||||
|
|
||||||
|
describe('sort', () => {
|
||||||
|
describe('sortNullsFirst', () => {
|
||||||
|
it('should sort nulls first', () => {
|
||||||
|
expect(sortNullsFirst(null, 'a')).toBe(-1);
|
||||||
|
expect(sortNullsFirst('a', null)).toBe(1);
|
||||||
|
expect(sortNullsFirst('a', 'a')).toBe(0);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('sortNullsLast', () => {
|
||||||
|
it('should sort nulls last', () => {
|
||||||
|
expect(sortNullsLast(null, 'a')).toBe(1);
|
||||||
|
expect(sortNullsLast('a', null)).toBe(-1);
|
||||||
|
expect(sortNullsLast('a', 'a')).toBe(0);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('sortAsc', () => {
|
||||||
|
it('should sort in ascending order', () => {
|
||||||
|
expect(sortAsc('a', 'b')).toBe(-1);
|
||||||
|
expect(sortAsc('b', 'a')).toBe(1);
|
||||||
|
expect(sortAsc('a', 'a')).toBe(0);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('sortDesc', () => {
|
||||||
|
it('should sort in descending order', () => {
|
||||||
|
expect(sortDesc('a', 'b')).toBe(1);
|
||||||
|
expect(sortDesc('b', 'a')).toBe(-1);
|
||||||
|
expect(sortDesc('a', 'a')).toBe(0);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
@ -0,0 +1,25 @@
|
|||||||
|
import { groupArrayItemsBy } from '../groupArrayItemsBy';
|
||||||
|
|
||||||
|
describe('groupArrayItemsBy', () => {
|
||||||
|
it('groups an array of objects by a computed key', () => {
|
||||||
|
// Given
|
||||||
|
const array = [
|
||||||
|
{ id: '1', type: 'fruit', value: 'apple' },
|
||||||
|
{ id: '2', type: 'fruit', value: 'banana' },
|
||||||
|
{ id: '3', type: 'vegetable', value: 'carrot' },
|
||||||
|
];
|
||||||
|
const computeGroupKey = ({ type }: (typeof array)[0]) => type;
|
||||||
|
|
||||||
|
// When
|
||||||
|
const result = groupArrayItemsBy(array, computeGroupKey);
|
||||||
|
|
||||||
|
// Then
|
||||||
|
expect(result).toEqual({
|
||||||
|
fruit: [
|
||||||
|
{ id: '1', type: 'fruit', value: 'apple' },
|
||||||
|
{ id: '2', type: 'fruit', value: 'banana' },
|
||||||
|
],
|
||||||
|
vegetable: [{ id: '3', type: 'vegetable', value: 'carrot' }],
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
@ -0,0 +1,23 @@
|
|||||||
|
import { mapArrayToObject } from '~/utils/array/mapArrayToObject';
|
||||||
|
|
||||||
|
describe('mapArrayToObject', () => {
|
||||||
|
it('maps an array of objects to an object with computed keys', () => {
|
||||||
|
// Given
|
||||||
|
const array = [
|
||||||
|
{ id: '1', value: 'one' },
|
||||||
|
{ id: '2', value: 'two' },
|
||||||
|
{ id: '3', value: 'three' },
|
||||||
|
];
|
||||||
|
const computeItemKey = ({ id }: { id: string }) => id;
|
||||||
|
|
||||||
|
// When
|
||||||
|
const result = mapArrayToObject(array, computeItemKey);
|
||||||
|
|
||||||
|
// Then
|
||||||
|
expect(result).toEqual({
|
||||||
|
'1': { id: '1', value: 'one' },
|
||||||
|
'2': { id: '2', value: 'two' },
|
||||||
|
'3': { id: '3', value: 'three' },
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
@ -1,8 +1,30 @@
|
|||||||
export const groupArrayItemsBy = <Item, Key extends string>(
|
/**
|
||||||
array: Item[],
|
* Groups an array of items by a key computed from each item.
|
||||||
computeGroupKey: (item: Item) => Key,
|
*
|
||||||
|
* @param array - The array to group.
|
||||||
|
* @param computeGroupKey - A function that computes the group key to which the item belongs.
|
||||||
|
*
|
||||||
|
* @returns An object with items grouped by a computed key.
|
||||||
|
*
|
||||||
|
* @example
|
||||||
|
* groupArrayItemsBy(
|
||||||
|
* [{ id: '1', type: 'fruit' }, { id: '2', type: 'vegetable' }, { id: '3', type: 'fruit' }],
|
||||||
|
* ({ type }) => type,
|
||||||
|
* )
|
||||||
|
* ⬇️
|
||||||
|
* {
|
||||||
|
* fruit: [{ id: '1', type: 'fruit' }, { id: '3', type: 'fruit' }],
|
||||||
|
* vegetable: [{ id: '2', type: 'vegetable' }],
|
||||||
|
* }
|
||||||
|
*/
|
||||||
|
export const groupArrayItemsBy = <
|
||||||
|
ArrayItem extends Record<string, unknown>,
|
||||||
|
Key extends string,
|
||||||
|
>(
|
||||||
|
array: ArrayItem[],
|
||||||
|
computeGroupKey: (item: ArrayItem) => Key,
|
||||||
) =>
|
) =>
|
||||||
array.reduce<Partial<Record<Key, Item[]>>>((result, item) => {
|
array.reduce<Partial<Record<Key, ArrayItem[]>>>((result, item) => {
|
||||||
const groupKey = computeGroupKey(item);
|
const groupKey = computeGroupKey(item);
|
||||||
const previousGroup = result[groupKey] || [];
|
const previousGroup = result[groupKey] || [];
|
||||||
|
|
||||||
|
|||||||
@ -1,4 +1,27 @@
|
|||||||
export const mapArrayToObject = <ArrayItem>(
|
/**
|
||||||
|
* Transforms an array of items into an object where the keys are computed from each item.
|
||||||
|
*
|
||||||
|
* @param array - The array to transform.
|
||||||
|
* @param computeItemKey - A function that computes a key from an item.
|
||||||
|
*
|
||||||
|
* @returns An object where the keys are computed from the items in the array.
|
||||||
|
*
|
||||||
|
* @example
|
||||||
|
* mapArrayToObject(
|
||||||
|
* [{ id: '1', type: 'fruit' }, { id: '2', type: 'vegetable' }, { id: '3', type: 'fruit' }],
|
||||||
|
* ({ id }) => id,
|
||||||
|
* )
|
||||||
|
* ⬇️
|
||||||
|
* {
|
||||||
|
* '1': { id: '1', type: 'fruit' },
|
||||||
|
* '2': { id: '2', type: 'vegetable' },
|
||||||
|
* '3': { id: '3', type: 'fruit' },
|
||||||
|
* }
|
||||||
|
*/
|
||||||
|
export const mapArrayToObject = <ArrayItem, Key extends string>(
|
||||||
array: ArrayItem[],
|
array: ArrayItem[],
|
||||||
computeItemKey: (item: ArrayItem) => string,
|
computeItemKey: (item: ArrayItem) => Key,
|
||||||
) => Object.fromEntries(array.map((item) => [computeItemKey(item), item]));
|
) =>
|
||||||
|
Object.fromEntries(
|
||||||
|
array.map((item) => [computeItemKey(item), item]),
|
||||||
|
) as Record<Key, ArrayItem>;
|
||||||
|
|||||||
@ -1,5 +1,19 @@
|
|||||||
export const moveArrayItem = <Item>(
|
/**
|
||||||
array: Item[],
|
* Moves an item in an array from one index to another.
|
||||||
|
*
|
||||||
|
* @param array - The array to move an item in.
|
||||||
|
* @param indices - The indices to move the item from and to.
|
||||||
|
* @param indices.fromIndex - The index to move the item from.
|
||||||
|
* @param indices.toIndex - The index to move the item to.
|
||||||
|
*
|
||||||
|
* @returns A new array with the item moved to the new index.
|
||||||
|
*
|
||||||
|
* @example
|
||||||
|
* moveArrayItem(['a', 'b', 'c'], { fromIndex: 0, toIndex: 2 })
|
||||||
|
* => ['b', 'c', 'a']
|
||||||
|
*/
|
||||||
|
export const moveArrayItem = <ArrayItem>(
|
||||||
|
array: ArrayItem[],
|
||||||
{ fromIndex, toIndex }: { fromIndex: number; toIndex: number },
|
{ fromIndex, toIndex }: { fromIndex: number; toIndex: number },
|
||||||
) => {
|
) => {
|
||||||
if (!(fromIndex in array) || !(toIndex in array) || fromIndex === toIndex) {
|
if (!(fromIndex in array) || !(toIndex in array) || fromIndex === toIndex) {
|
||||||
|
|||||||
@ -1,2 +0,0 @@
|
|||||||
export const assertNotNull = <T>(item: T): item is NonNullable<T> =>
|
|
||||||
item !== null && item !== undefined;
|
|
||||||
@ -1,7 +1,7 @@
|
|||||||
import { isDefined } from './isDefined';
|
import { isNonNullable } from './isNonNullable';
|
||||||
|
|
||||||
export const isDomain = (url: string | undefined | null) =>
|
export const isDomain = (url: string | undefined | null) =>
|
||||||
isDefined(url) &&
|
isNonNullable(url) &&
|
||||||
/^((?!-))(xn--)?[a-z0-9][a-z0-9-_]{0,61}[a-z0-9]{0,1}\.(xn--)?([a-z0-9-]{1,61}|[a-z0-9-]{1,30}\.[a-z]{2,})$/.test(
|
/^((?!-))(xn--)?[a-z0-9][a-z0-9-_]{0,61}[a-z0-9]{0,1}\.(xn--)?([a-z0-9-]{1,61}|[a-z0-9-]{1,30}\.[a-z]{2,})$/.test(
|
||||||
url,
|
url,
|
||||||
);
|
);
|
||||||
|
|||||||
@ -1,7 +1,7 @@
|
|||||||
import { isDefined } from './isDefined';
|
import { isNonNullable } from './isNonNullable';
|
||||||
|
|
||||||
export const isURL = (url: string | undefined | null) =>
|
export const isURL = (url: string | undefined | null) =>
|
||||||
isDefined(url) &&
|
isNonNullable(url) &&
|
||||||
url.match(
|
url.match(
|
||||||
/^(https?:\/\/)?(www.)?[-a-zA-Z0-9@:%._+~#=]{1,256}\.[a-z]{2,63}\b([-a-zA-Z0-9@:%_+.~#?&//=]*)/i,
|
/^(https?:\/\/)?(www.)?[-a-zA-Z0-9@:%._+~#=]{1,256}\.[a-z]{2,63}\b([-a-zA-Z0-9@:%_+.~#?&//=]*)/i,
|
||||||
);
|
);
|
||||||
|
|||||||
@ -1,3 +0,0 @@
|
|||||||
export const isDefined = <T>(
|
|
||||||
value: T | undefined | null,
|
|
||||||
): value is NonNullable<T> => value !== undefined && value !== null;
|
|
||||||
4
packages/twenty-front/src/utils/isNonNullable.ts
Normal file
4
packages/twenty-front/src/utils/isNonNullable.ts
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
import { isNull, isUndefined } from '@sniptt/guards';
|
||||||
|
|
||||||
|
export const isNonNullable = <T>(value: T): value is NonNullable<T> =>
|
||||||
|
!isUndefined(value) && !isNull(value);
|
||||||
@ -8,19 +8,22 @@ export const parseApolloStoreFieldName = <
|
|||||||
>(
|
>(
|
||||||
storeFieldName: string,
|
storeFieldName: string,
|
||||||
) => {
|
) => {
|
||||||
const matches = storeFieldName.match(/([a-zA-Z][a-zA-Z0-9 ]*)\((.*)\)/);
|
const matches = storeFieldName.match(/([a-zA-Z][a-zA-Z0-9 ]*)(\((.*)\))?/);
|
||||||
|
|
||||||
if (!matches?.[1]) return {};
|
const fieldName = matches?.[1];
|
||||||
|
|
||||||
const [, , stringifiedVariables] = matches;
|
if (!fieldName) {
|
||||||
const fieldName = matches[1] as string;
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
|
const stringifiedVariables = matches[3];
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const fieldArguments = stringifiedVariables
|
const fieldVariables = stringifiedVariables
|
||||||
? (JSON.parse(stringifiedVariables) as Variables)
|
? (JSON.parse(stringifiedVariables) as Variables)
|
||||||
: undefined;
|
: undefined;
|
||||||
|
|
||||||
return { fieldName, fieldArguments };
|
return { fieldName, fieldVariables };
|
||||||
} catch {
|
} catch {
|
||||||
return { fieldName };
|
return { fieldName };
|
||||||
}
|
}
|
||||||
|
|||||||
@ -13,7 +13,7 @@ export const sortNullsLast = (
|
|||||||
export const sortAsc = (
|
export const sortAsc = (
|
||||||
fieldValueA: string | number,
|
fieldValueA: string | number,
|
||||||
fieldValueB: string | number,
|
fieldValueB: string | number,
|
||||||
) => (fieldValueA < fieldValueB ? -1 : 1);
|
) => (fieldValueA === fieldValueB ? 0 : fieldValueA < fieldValueB ? -1 : 1);
|
||||||
|
|
||||||
export const sortDesc = (
|
export const sortDesc = (
|
||||||
fieldValueA: string | number,
|
fieldValueA: string | number,
|
||||||
|
|||||||
Reference in New Issue
Block a user