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