[GroupBy] Add views filters to groupBy query (#14762)

Closes https://github.com/twentyhq/core-team-issues/issues/1560

If viewId is defined in a groupBy query, we want to apply all filters of
the view to the query.
This required to move a lot of code from twenty-front to twenty-shared
to convert the filters as stored in the db into graphql filters,
applying the right combinations between filters etc., which was
previously only done in the FE.

This PR does not handle any field filters, it will be done in a later pr
This commit is contained in:
Marie
2025-09-30 09:58:55 +02:00
committed by GitHub
parent 80fa4c6c26
commit da3c3d2b9d
174 changed files with 1192 additions and 483 deletions
@@ -6,13 +6,13 @@ import { contextStoreFiltersComponentState } from '@/context-store/states/contex
import { contextStoreTargetedRecordsRuleComponentState } from '@/context-store/states/contextStoreTargetedRecordsRuleComponentState';
import { computeContextStoreFilters } from '@/context-store/utils/computeContextStoreFilters';
import { DEFAULT_QUERY_PAGE_SIZE } from '@/object-record/constants/DefaultQueryPageSize';
import { type RecordGqlOperationFilter } from '@/object-record/graphql/types/RecordGqlOperationFilter';
import { useDestroyManyRecords } from '@/object-record/hooks/useDestroyManyRecords';
import { useLazyFetchAllRecords } from '@/object-record/hooks/useLazyFetchAllRecords';
import { useFilterValueDependencies } from '@/object-record/record-filter/hooks/useFilterValueDependencies';
import { useRecordIndexIdFromCurrentContextStore } from '@/object-record/record-index/hooks/useRecordIndexIdFromCurrentContextStore';
import { useResetTableRowSelection } from '@/object-record/record-table/hooks/internal/useResetTableRowSelection';
import { useRecoilComponentValue } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentValue';
import { type RecordGqlOperationFilter } from 'twenty-shared/types';
export const DestroyMultipleRecordsAction = () => {
const { recordIndexId, objectMetadataItem } =
@@ -6,13 +6,13 @@ import { contextStoreFiltersComponentState } from '@/context-store/states/contex
import { contextStoreTargetedRecordsRuleComponentState } from '@/context-store/states/contextStoreTargetedRecordsRuleComponentState';
import { computeContextStoreFilters } from '@/context-store/utils/computeContextStoreFilters';
import { DEFAULT_QUERY_PAGE_SIZE } from '@/object-record/constants/DefaultQueryPageSize';
import { type RecordGqlOperationFilter } from '@/object-record/graphql/types/RecordGqlOperationFilter';
import { useLazyFetchAllRecords } from '@/object-record/hooks/useLazyFetchAllRecords';
import { useRestoreManyRecords } from '@/object-record/hooks/useRestoreManyRecords';
import { useFilterValueDependencies } from '@/object-record/record-filter/hooks/useFilterValueDependencies';
import { useRecordIndexIdFromCurrentContextStore } from '@/object-record/record-index/hooks/useRecordIndexIdFromCurrentContextStore';
import { useResetTableRowSelection } from '@/object-record/record-table/hooks/internal/useResetTableRowSelection';
import { useRecoilComponentValue } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentValue';
import { type RecordGqlOperationFilter } from 'twenty-shared/types';
export const RestoreMultipleRecordsAction = () => {
const { recordIndexId, objectMetadataItem } =
@@ -8,10 +8,10 @@ import { type Note } from '@/activities/types/Note';
import { type Task } from '@/activities/types/Task';
import { useObjectMetadataItems } from '@/object-metadata/hooks/useObjectMetadataItems';
import { type CoreObjectNameSingular } from '@/object-metadata/types/CoreObjectNameSingular';
import { type RecordGqlOperationFilter } from '@/object-record/graphql/types/RecordGqlOperationFilter';
import { type RecordGqlOperationOrderBy } from '@/object-record/graphql/types/RecordGqlOperationOrderBy';
import { useFindManyRecords } from '@/object-record/hooks/useFindManyRecords';
import { recordStoreFamilyState } from '@/object-record/record-store/states/recordStoreFamilyState';
import { type RecordGqlOperationFilter } from 'twenty-shared/types';
import { sortByAscString } from '~/utils/array/sortByAscString';
export const useActivities = <T extends Task | Note>({
@@ -1,8 +1,10 @@
import { type ContextStoreTargetedRecordsRule } from '@/context-store/states/contextStoreTargetedRecordsRuleComponentState';
import { computeContextStoreFilters } from '@/context-store/utils/computeContextStoreFilters';
import { type RecordFilter } from '@/object-record/record-filter/types/RecordFilter';
import { type RecordFilterValueDependencies } from '@/object-record/record-filter/types/RecordFilterValueDependencies';
import { ViewFilterOperand } from 'twenty-shared/types';
import {
type RecordFilterValueDependencies,
ViewFilterOperand,
} from 'twenty-shared/types';
import { generatedMockObjectMetadataItems } from '~/testing/utils/generatedMockObjectMetadataItems';
describe('computeContextStoreFilters', () => {
@@ -1,12 +1,14 @@
import { type ContextStoreTargetedRecordsRule } from '@/context-store/states/contextStoreTargetedRecordsRuleComponentState';
import { type ObjectMetadataItem } from '@/object-metadata/types/ObjectMetadataItem';
import { type RecordGqlOperationFilter } from '@/object-record/graphql/types/RecordGqlOperationFilter';
import { type RecordFilterGroup } from '@/object-record/record-filter-group/types/RecordFilterGroup';
import { type RecordFilter } from '@/object-record/record-filter/types/RecordFilter';
import { type RecordFilterValueDependencies } from '@/object-record/record-filter/types/RecordFilterValueDependencies';
import { computeRecordGqlOperationFilter } from '@/object-record/record-filter/utils/computeRecordGqlOperationFilter';
import { turnAnyFieldFilterIntoRecordGqlFilter } from '@/object-record/record-filter/utils/turnAnyFieldFilterIntoRecordGqlFilter';
import { makeAndFilterVariables } from '@/object-record/utils/makeAndFilterVariables';
import {
type RecordFilterValueDependencies,
type RecordGqlOperationFilter,
} from 'twenty-shared/types';
import { computeRecordGqlOperationFilter } from 'twenty-shared/utils';
type ComputeContextStoreFiltersProps = {
contextStoreTargetedRecordsRule: ContextStoreTargetedRecordsRule;
@@ -1,9 +1,8 @@
import { AppErrorBoundaryEffect } from '@/error-handler/components/internal/AppErrorBoundaryEffect';
import { type CustomError } from '@/error-handler/CustomError';
import { checkIfItsAViteStaleChunkLazyLoadingError } from '@/error-handler/utils/checkIfItsAViteStaleChunkLazyLoadingError';
import { type ErrorInfo, type ReactNode } from 'react';
import { ErrorBoundary, type FallbackProps } from 'react-error-boundary';
import { isDefined } from 'twenty-shared/utils';
import { type CustomError, isDefined } from 'twenty-shared/utils';
type AppErrorBoundaryProps = {
children: ReactNode;
@@ -1,9 +1,8 @@
import { useCallback, useEffect } from 'react';
import { type CustomError } from '@/error-handler/CustomError';
import { useSnackBar } from '@/ui/feedback/snack-bar-manager/hooks/useSnackBar';
import isEmpty from 'lodash.isempty';
import { isDefined } from 'twenty-shared/utils';
import { isDefined, type CustomError } from 'twenty-shared/utils';
const hasErrorCode = (
error: CustomError | any,
@@ -1,5 +1,5 @@
import { CustomError } from '@/error-handler/CustomError';
import { FAVORITE_DROPPABLE_IDS } from '@/favorites/constants/FavoriteDroppableIds';
import { CustomError } from 'twenty-shared/utils';
export const validateAndExtractFolderId = (
droppableId: string,
@@ -1,8 +1,7 @@
import { useRecoilValue } from 'recoil';
import { CustomError } from '@/error-handler/CustomError';
import { objectMetadataItemsState } from '@/object-metadata/states/objectMetadataItemsState';
import { isDefined } from 'twenty-shared/utils';
import { CustomError, isDefined } from 'twenty-shared/utils';
export const useGetObjectMetadataItemById = () => {
const objectMetadataItems = useRecoilValue(objectMetadataItemsState);
@@ -1,8 +1,7 @@
import { useRecoilValue } from 'recoil';
import { CustomError } from '@/error-handler/CustomError';
import { objectMetadataItemsState } from '@/object-metadata/states/objectMetadataItemsState';
import { isDefined } from 'twenty-shared/utils';
import { CustomError, isDefined } from 'twenty-shared/utils';
export const useObjectMetadataItemById = ({
objectId,
@@ -1,6 +1,3 @@
import { FieldMetadataType } from '~/generated-metadata/graphql';
import { type FilterableAndTSVectorFieldType } from '@/object-record/record-filter/types/FilterableFieldType';
import { type ObjectMetadataItem } from '../types/ObjectMetadataItem';
export const getRelationObjectMetadataNameSingular = ({
@@ -10,50 +7,3 @@ export const getRelationObjectMetadataNameSingular = ({
}): string | undefined => {
return field.relation?.targetObjectMetadata.nameSingular;
};
export const getFilterTypeFromFieldType = (
fieldType: FieldMetadataType,
): FilterableAndTSVectorFieldType => {
switch (fieldType) {
case FieldMetadataType.DATE_TIME:
return 'DATE_TIME';
case FieldMetadataType.DATE:
return 'DATE';
case FieldMetadataType.LINKS:
return 'LINKS';
case FieldMetadataType.FULL_NAME:
return 'FULL_NAME';
case FieldMetadataType.NUMBER:
return 'NUMBER';
case FieldMetadataType.CURRENCY:
return 'CURRENCY';
case FieldMetadataType.EMAILS:
return 'EMAILS';
case FieldMetadataType.PHONES:
return 'PHONES';
case FieldMetadataType.RELATION:
return 'RELATION';
case FieldMetadataType.SELECT:
return 'SELECT';
case FieldMetadataType.MULTI_SELECT:
return 'MULTI_SELECT';
case FieldMetadataType.ADDRESS:
return 'ADDRESS';
case FieldMetadataType.RATING:
return 'RATING';
case FieldMetadataType.ACTOR:
return 'ACTOR';
case FieldMetadataType.ARRAY:
return 'ARRAY';
case FieldMetadataType.RAW_JSON:
return 'RAW_JSON';
case FieldMetadataType.BOOLEAN:
return 'BOOLEAN';
case FieldMetadataType.TS_VECTOR:
return 'TS_VECTOR';
case FieldMetadataType.UUID:
return 'UUID';
default:
return 'TEXT';
}
};
@@ -1,6 +1,5 @@
import { CustomError } from '@/error-handler/CustomError';
import { type ObjectMetadataItem } from '@/object-metadata/types/ObjectMetadataItem';
import { isDefined } from 'twenty-shared/utils';
import { CustomError, isDefined } from 'twenty-shared/utils';
type GetFieldMetadataItemByIdParams = {
fieldMetadataId: string;
@@ -1,12 +1,10 @@
import { ActionButton } from '@/action-menu/actions/display/components/ActionButton';
import { getFilterTypeFromFieldType } from '@/object-metadata/utils/formatFieldMetadataItemsAsFilterDefinitions';
import { useChildRecordFiltersAndRecordFilterGroups } from '@/object-record/advanced-filter/hooks/useChildRecordFiltersAndRecordFilterGroups';
import { useDefaultFieldMetadataItemForFilter } from '@/object-record/advanced-filter/hooks/useDefaultFieldMetadataItemForFilter';
import { useSetRecordFilterUsedInAdvancedFilterDropdownRow } from '@/object-record/advanced-filter/hooks/useSetRecordFilterUsedInAdvancedFilterDropdownRow';
import { getAdvancedFilterAddFilterRuleSelectDropdownId } from '@/object-record/advanced-filter/utils/getAdvancedFilterAddFilterRuleSelectDropdownId';
import { useUpsertRecordFilterGroup } from '@/object-record/record-filter-group/hooks/useUpsertRecordFilterGroup';
import { type RecordFilterGroup } from '@/object-record/record-filter-group/types/RecordFilterGroup';
import { RecordFilterGroupLogicalOperator } from '@/object-record/record-filter-group/types/RecordFilterGroupLogicalOperator';
import { useUpsertRecordFilter } from '@/object-record/record-filter/hooks/useUpsertRecordFilter';
import { type RecordFilter } from '@/object-record/record-filter/types/RecordFilter';
import { getDefaultSubFieldNameForCompositeFilterableFieldType } from '@/object-record/record-filter/utils/getDefaultSubFieldNameForCompositeFilterableFieldType';
@@ -16,7 +14,8 @@ import { DropdownContent } from '@/ui/layout/dropdown/components/DropdownContent
import { DropdownMenuItemsContainer } from '@/ui/layout/dropdown/components/DropdownMenuItemsContainer';
import { useCloseDropdown } from '@/ui/layout/dropdown/hooks/useCloseDropdown';
import { useGetCurrentViewOnly } from '@/views/hooks/useGetCurrentViewOnly';
import { isDefined } from 'twenty-shared/utils';
import { RecordFilterGroupLogicalOperator } from 'twenty-shared/types';
import { getFilterTypeFromFieldType, isDefined } from 'twenty-shared/utils';
import { IconLibraryPlus, IconPlus } from 'twenty-ui/display';
import { MenuItem } from 'twenty-ui/navigation';
import { v4 } from 'uuid';
@@ -13,13 +13,13 @@ import { ObjectFilterDropdownDateInput } from '@/object-record/object-filter-dro
import { ObjectFilterDropdownTextInput } from '@/object-record/object-filter-dropdown/components/ObjectFilterDropdownTextInput';
import { DATE_FILTER_TYPES } from '@/object-record/object-filter-dropdown/constants/DateFilterTypes';
import { subFieldNameUsedInDropdownComponentState } from '@/object-record/object-filter-dropdown/states/subFieldNameUsedInDropdownComponentState';
import { isExpectedSubFieldName } from '@/object-record/object-filter-dropdown/utils/isExpectedSubFieldName';
import { isFilterOnActorSourceSubField } from '@/object-record/object-filter-dropdown/utils/isFilterOnActorSourceSubField';
import { type RecordFilter } from '@/object-record/record-filter/types/RecordFilter';
import { DropdownContent } from '@/ui/layout/dropdown/components/DropdownContent';
import { GenericDropdownContentWidth } from '@/ui/layout/dropdown/constants/GenericDropdownContentWidth';
import { useRecoilComponentValue } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentValue';
import { FieldMetadataType } from 'twenty-shared/types';
import { isExpectedSubFieldName } from 'twenty-shared/utils';
type AdvancedFilterDropdownFilterInputProps = {
filterDropdownId: string;
@@ -10,7 +10,6 @@ import { useSelectableList } from '@/ui/layout/selectable-list/hooks/useSelectab
import { useRecoilComponentValue } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentValue';
import { type FieldMetadataItem } from '@/object-metadata/types/FieldMetadataItem';
import { getFilterTypeFromFieldType } from '@/object-metadata/utils/formatFieldMetadataItemsAsFilterDefinitions';
import { AdvancedFilterFieldSelectSearchInput } from '@/object-record/advanced-filter/components/AdvancedFilterFieldSelectSearchInput';
import { useAdvancedFilterFieldSelectDropdown } from '@/object-record/advanced-filter/hooks/useAdvancedFilterFieldSelectDropdown';
import { useSelectFieldUsedInAdvancedFilterDropdown } from '@/object-record/advanced-filter/hooks/useSelectFieldUsedInAdvancedFilterDropdown';
@@ -27,6 +26,7 @@ import { GenericDropdownContentWidth } from '@/ui/layout/dropdown/constants/Gene
import { useRecoilComponentState } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentState';
import { useSetRecoilComponentState } from '@/ui/utilities/state/component-state/hooks/useSetRecoilComponentState';
import { useLingui } from '@lingui/react/macro';
import { getFilterTypeFromFieldType } from 'twenty-shared/utils';
type AdvancedFilterFieldSelectMenuProps = {
recordFilterId: string;
@@ -2,9 +2,9 @@ import { ADVANCED_FILTER_LOGICAL_OPERATOR_OPTIONS } from '@/object-record/advanc
import { DEFAULT_ADVANCED_FILTER_DROPDOWN_OFFSET } from '@/object-record/advanced-filter/constants/DefaultAdvancedFilterDropdownOffset';
import { useUpsertRecordFilterGroup } from '@/object-record/record-filter-group/hooks/useUpsertRecordFilterGroup';
import { type RecordFilterGroup } from '@/object-record/record-filter-group/types/RecordFilterGroup';
import { type RecordFilterGroupLogicalOperator } from '@/object-record/record-filter-group/types/RecordFilterGroupLogicalOperator';
import { Select } from '@/ui/input/components/Select';
import { GenericDropdownContentWidth } from '@/ui/layout/dropdown/constants/GenericDropdownContentWidth';
import { type RecordFilterGroupLogicalOperator } from 'twenty-shared/types';
type AdvancedFilterLogicalOperatorDropdownProps = {
recordFilterGroup: RecordFilterGroup;
@@ -1,4 +1,4 @@
import { RecordFilterGroupLogicalOperator } from '@/object-record/record-filter-group/types/RecordFilterGroupLogicalOperator';
import { RecordFilterGroupLogicalOperator } from 'twenty-shared/types';
export const ADVANCED_FILTER_LOGICAL_OPERATOR_OPTIONS = [
{
@@ -1,5 +1,4 @@
import { useGetFieldMetadataItemByIdOrThrow } from '@/object-metadata/hooks/useGetFieldMetadataItemById';
import { getFilterTypeFromFieldType } from '@/object-metadata/utils/formatFieldMetadataItemsAsFilterDefinitions';
import { fieldMetadataItemIdUsedInDropdownComponentState } from '@/object-record/object-filter-dropdown/states/fieldMetadataItemIdUsedInDropdownComponentState';
import { objectFilterDropdownCurrentRecordFilterComponentState } from '@/object-record/object-filter-dropdown/states/objectFilterDropdownCurrentRecordFilterComponentState';
import { objectFilterDropdownSearchInputComponentState } from '@/object-record/object-filter-dropdown/states/objectFilterDropdownSearchInputComponentState';
@@ -18,7 +17,7 @@ import { usePushFocusItemToFocusStack } from '@/ui/utilities/focus/hooks/usePush
import { FocusComponentType } from '@/ui/utilities/focus/types/FocusComponentType';
import { useRecoilComponentValue } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentValue';
import { useSetRecoilComponentState } from '@/ui/utilities/state/component-state/hooks/useSetRecoilComponentState';
import { isDefined } from 'twenty-shared/utils';
import { getFilterTypeFromFieldType, isDefined } from 'twenty-shared/utils';
type SelectFilterParams = {
fieldMetadataItemId: string;
@@ -1,10 +1,10 @@
import { NUMBER_FILTER_TYPES } from '@/object-record/object-filter-dropdown/constants/NumberFilterTypes';
import { TEXT_FILTER_TYPES } from '@/object-record/object-filter-dropdown/constants/TextFilterTypes';
import { isExpectedSubFieldName } from '@/object-record/object-filter-dropdown/utils/isExpectedSubFieldName';
import { FieldMetadataType } from 'twenty-shared/types';
import { type RecordFilter } from '../../record-filter/types/RecordFilter';
import { type RecordFilter } from '@/object-record/record-filter/types/RecordFilter';
import { type CompositeFieldSubFieldName } from '@/settings/data-model/types/CompositeFieldSubFieldName';
import { FieldMetadataType } from 'twenty-shared/types';
import { isExpectedSubFieldName } from 'twenty-shared/utils';
export const shouldShowFilterTextInput = ({
recordFilter,
@@ -1,6 +1,6 @@
import { type RecordGqlOperationFilter } from '@/object-record/graphql/types/RecordGqlOperationFilter';
import { type RecordGqlOperationOrderBy } from '@/object-record/graphql/types/RecordGqlOperationOrderBy';
import { type QueryCursorDirection } from '@/object-record/utils/generateFindManyRecordsQuery';
import { type RecordGqlOperationFilter } from 'twenty-shared/types';
export type RecordGqlOperationVariables = {
filter?: RecordGqlOperationFilter;
@@ -3,12 +3,12 @@ import { useQuery } from '@apollo/client';
import { useApolloCoreClient } from '@/object-metadata/hooks/useApolloCoreClient';
import { useObjectMetadataItem } from '@/object-metadata/hooks/useObjectMetadataItem';
import { type RecordGqlFieldsAggregate } from '@/object-record/graphql/types/RecordGqlFieldsAggregate';
import { type RecordGqlOperationFilter } from '@/object-record/graphql/types/RecordGqlOperationFilter';
import { type RecordGqlOperationFindManyResult } from '@/object-record/graphql/types/RecordGqlOperationFindManyResult';
import { useAggregateRecordsQuery } from '@/object-record/hooks/useAggregateRecordsQuery';
import { useObjectPermissionsForObject } from '@/object-record/hooks/useObjectPermissionsForObject';
import { type ExtendedAggregateOperations } from '@/object-record/record-table/types/ExtendedAggregateOperations';
import isEmpty from 'lodash.isempty';
import { type RecordGqlOperationFilter } from 'twenty-shared/types';
import { isDefined } from 'twenty-shared/utils';
export type AggregateRecordsData = {
@@ -1,4 +1,3 @@
import { CustomError } from '@/error-handler/CustomError';
import { useApolloCoreClient } from '@/object-metadata/hooks/useApolloCoreClient';
import { useObjectMetadataItem } from '@/object-metadata/hooks/useObjectMetadataItem';
import { useObjectMetadataItems } from '@/object-metadata/hooks/useObjectMetadataItems';
@@ -8,7 +7,7 @@ import { computeDepthOneRecordGqlFieldsFromRecord } from '@/object-record/graphq
import { useObjectPermissions } from '@/object-record/hooks/useObjectPermissions';
import { useUpdateOneRecord } from '@/object-record/hooks/useUpdateOneRecord';
import { type ObjectRecord } from '@/object-record/types/ObjectRecord';
import { isDefined } from 'twenty-shared/utils';
import { CustomError, isDefined } from 'twenty-shared/utils';
type useAttachRelatedRecordFromRecordProps = {
recordObjectNameSingular: string;
@@ -15,8 +15,8 @@ import { type ObjectRecord } from '@/object-record/types/ObjectRecord';
import { type OnFindManyRecordsCompleted } from '@/object-record/types/OnFindManyRecordsCompleted';
import { getQueryIdentifier } from '@/object-record/utils/getQueryIdentifier';
import { type RecordGqlOperationFilter } from '@/object-record/graphql/types/RecordGqlOperationFilter';
import { QUERY_DEFAULT_LIMIT_RECORDS } from 'twenty-shared/constants';
import { type RecordGqlOperationFilter } from 'twenty-shared/types';
export type UseFindManyRecordsParams<T> = ObjectMetadataItemIdentifier &
RecordGqlOperationVariables & {
@@ -1,6 +1,5 @@
import { triggerUpdateRecordOptimisticEffect } from '@/apollo/optimistic-effect/utils/triggerUpdateRecordOptimisticEffect';
import { currentWorkspaceMemberState } from '@/auth/states/currentWorkspaceMemberState';
import { CustomError } from '@/error-handler/CustomError';
import { useApolloCoreClient } from '@/object-metadata/hooks/useApolloCoreClient';
import { useObjectMetadataItems } from '@/object-metadata/hooks/useObjectMetadataItems';
import { getObjectTypename } from '@/object-record/cache/utils/getObjectTypename';
@@ -23,7 +22,7 @@ import { sanitizeRecordInput } from '@/object-record/utils/sanitizeRecordInput';
import { isNull } from '@sniptt/guards';
import { useContext } from 'react';
import { useRecoilValue } from 'recoil';
import { isDefined } from 'twenty-shared/utils';
import { CustomError, isDefined } from 'twenty-shared/utils';
import { buildRecordFromKeysWithSameValue } from '~/utils/array/buildRecordFromKeysWithSameValue';
type UpdateManyRecordArgs = {
@@ -1,11 +1,10 @@
import { getFilterTypeFromFieldType } from '@/object-metadata/utils/formatFieldMetadataItemsAsFilterDefinitions';
import { DATE_FILTER_TYPES } from '@/object-record/object-filter-dropdown/constants/DateFilterTypes';
import { DATE_PICKER_DROPDOWN_CONTENT_WIDTH } from '@/object-record/object-filter-dropdown/constants/DatePickerDropdownContentWidth';
import { fieldMetadataItemUsedInDropdownComponentSelector } from '@/object-record/object-filter-dropdown/states/fieldMetadataItemUsedInDropdownComponentSelector';
import { DropdownContent } from '@/ui/layout/dropdown/components/DropdownContent';
import { GenericDropdownContentWidth } from '@/ui/layout/dropdown/constants/GenericDropdownContentWidth';
import { useRecoilComponentValue } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentValue';
import { isDefined } from 'twenty-shared/utils';
import { getFilterTypeFromFieldType, isDefined } from 'twenty-shared/utils';
export const ObjectFilterDropdownContentWrapper = ({
children,
@@ -6,14 +6,13 @@ import { getRelativeDateDisplayValue } from '@/object-record/object-filter-dropd
import { DateTimePicker } from '@/ui/input/components/internal/date/components/InternalDatePicker';
import { useRecoilComponentValue } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentValue';
import { computeVariableDateViewFilterValue } from '@/views/view-filter-value/utils/computeVariableDateViewFilterValue';
import { resolveDateViewFilterValue } from '@/views/view-filter-value/utils/resolveDateViewFilterValue';
import { useState } from 'react';
import {
ViewFilterOperand,
type VariableDateViewFilterValueDirection,
type VariableDateViewFilterValueUnit,
} from 'twenty-shared/types';
import { isDefined } from 'twenty-shared/utils';
import { isDefined, resolveDateViewFilterValue } from 'twenty-shared/utils';
import { FieldMetadataType } from '~/generated-metadata/graphql';
export const ObjectFilterDropdownDateInput = () => {
@@ -8,7 +8,6 @@ import { DropdownMenuSeparator } from '@/ui/layout/dropdown/components/DropdownM
import { ViewFilterOperand } from 'twenty-shared/types';
import { getFilterTypeFromFieldType } from '@/object-metadata/utils/formatFieldMetadataItemsAsFilterDefinitions';
import { ObjectFilterDropdownBooleanSelect } from '@/object-record/object-filter-dropdown/components/ObjectFilterDropdownBooleanSelect';
import { ObjectFilterDropdownInnerSelectOperandDropdown } from '@/object-record/object-filter-dropdown/components/ObjectFilterDropdownInnerSelectOperandDropdown';
import { ObjectFilterDropdownTextInput } from '@/object-record/object-filter-dropdown/components/ObjectFilterDropdownTextInput';
@@ -19,7 +18,7 @@ import { TEXT_FILTER_TYPES } from '@/object-record/object-filter-dropdown/consta
import { fieldMetadataItemUsedInDropdownComponentSelector } from '@/object-record/object-filter-dropdown/states/fieldMetadataItemUsedInDropdownComponentSelector';
import { selectedOperandInDropdownComponentState } from '@/object-record/object-filter-dropdown/states/selectedOperandInDropdownComponentState';
import { useRecoilComponentValue } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentValue';
import { isDefined } from 'twenty-shared/utils';
import { getFilterTypeFromFieldType, isDefined } from 'twenty-shared/utils';
type ObjectFilterDropdownFilterInputProps = {
filterDropdownId: string;
@@ -1,4 +1,3 @@
import { getFilterTypeFromFieldType } from '@/object-metadata/utils/formatFieldMetadataItemsAsFilterDefinitions';
import { DATE_FILTER_TYPES } from '@/object-record/object-filter-dropdown/constants/DateFilterTypes';
import { DATE_PICKER_DROPDOWN_CONTENT_WIDTH } from '@/object-record/object-filter-dropdown/constants/DatePickerDropdownContentWidth';
import { useApplyObjectFilterDropdownOperand } from '@/object-record/object-filter-dropdown/hooks/useApplyObjectFilterDropdownOperand';
@@ -11,7 +10,7 @@ import { getRecordFilterOperands } from '@/object-record/record-filter/utils/get
import { DropdownMenuInnerSelect } from '@/ui/layout/dropdown/components/DropdownMenuInnerSelect';
import { GenericDropdownContentWidth } from '@/ui/layout/dropdown/constants/GenericDropdownContentWidth';
import { useRecoilComponentValue } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentValue';
import { isDefined } from 'twenty-shared/utils';
import { getFilterTypeFromFieldType, isDefined } from 'twenty-shared/utils';
import { type SelectOption } from 'twenty-ui/input';
const OBJECT_FILTER_DROPDOWN_INNER_SELECT_OPERAND_DROPDOWN_ID =
@@ -1,10 +1,9 @@
import { RATING_VALUES } from '@/object-record/record-field/ui/meta-types/constants/RatingValues';
import { type FieldRatingValue } from '@/object-record/record-field/ui/types/FieldMetadata';
import { RatingInput } from '@/ui/field/input/components/RatingInput';
import { useApplyObjectFilterDropdownFilterValue } from '@/object-record/object-filter-dropdown/hooks/useApplyObjectFilterDropdownFilterValue';
import { useObjectFilterDropdownFilterValue } from '@/object-record/object-filter-dropdown/hooks/useObjectFilterDropdownFilterValue';
import { RatingInput } from '@/ui/field/input/components/RatingInput';
import styled from '@emotion/styled';
import { RATING_VALUES } from 'twenty-shared/constants';
import { type FieldRatingValue } from 'twenty-shared/types';
import { isDefined } from 'twenty-shared/utils';
const StyledRatingInputContainer = styled.div`
@@ -14,9 +14,11 @@ import { type SelectableItem } from '@/object-record/select/types/SelectableItem
import { DropdownMenuSeparator } from '@/ui/layout/dropdown/components/DropdownMenuSeparator';
import { useRecoilComponentValue } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentValue';
import { type RelationFilterValue } from '@/views/view-filter-value/types/RelationFilterValue';
import { arrayOfUuidOrVariableSchema } from '@/views/view-filter-value/validation-schemas/arrayOfUuidsOrVariablesSchema';
import { jsonRelationFilterValueSchema } from '@/views/view-filter-value/validation-schemas/jsonRelationFilterValueSchema';
import { isDefined } from 'twenty-shared/utils';
import {
arrayOfUuidOrVariableSchema,
isDefined,
jsonRelationFilterValueSchema,
} from 'twenty-shared/utils';
import { IconUserCircle } from 'twenty-ui/display';
export const EMPTY_FILTER_VALUE: string = JSON.stringify({
@@ -1,8 +1,8 @@
import { type FilterableFieldType } from '@/object-record/record-filter/types/FilterableFieldType';
import { RecordFilterOperand } from '@/object-record/record-filter/types/RecordFilterOperand';
import { getRecordFilterOperands } from '@/object-record/record-filter/utils/getRecordFilterOperands';
import { type CompositeFieldSubFieldName } from '@/settings/data-model/types/CompositeFieldSubFieldName';
import { type FieldType } from '@/settings/data-model/types/FieldType';
import { type FilterableFieldType } from 'twenty-shared/types';
describe('getOperandsForFilterType', () => {
const emptyOperands = [
@@ -1,7 +1,7 @@
import { type FilterableAndTSVectorFieldType } from '@/object-record/record-filter/types/FilterableFieldType';
import { type RecordFilter } from '@/object-record/record-filter/types/RecordFilter';
import { RecordFilterOperand } from '@/object-record/record-filter/types/RecordFilterOperand';
import { getDateFilterDisplayValue } from '@/object-record/record-filter/utils/getDateFilterDisplayValue';
import { type FilterableAndTSVectorFieldType } from 'twenty-shared/types';
export const getInitialFilterValue = (
newType: FilterableAndTSVectorFieldType,
@@ -1,4 +1,4 @@
import { type FilterableFieldType } from '@/object-record/record-filter/types/FilterableFieldType';
import { type FilterableFieldType } from 'twenty-shared/types';
export const getSubMenuOptions = (subMenu: FilterableFieldType | null) => {
switch (subMenu) {
@@ -1,7 +1,7 @@
import { type CompositeFilterableFieldType } from '@/object-record/record-filter/types/CompositeFilterableFieldType';
import { FILTERABLE_FIELD_TYPES } from '@/object-record/record-filter/types/FilterableFieldType';
import { COMPOSITE_FIELD_TYPES } from '@/settings/data-model/types/CompositeFieldType';
import { type FieldType } from '@/settings/data-model/types/FieldType';
import { FILTERABLE_FIELD_TYPES } from 'twenty-shared/types';
export const isCompositeFilterableFieldType = (
type: FieldType,
@@ -1,19 +0,0 @@
import { SETTINGS_COMPOSITE_FIELD_TYPE_CONFIGS } from '@/settings/data-model/constants/SettingsCompositeFieldTypeConfigs';
export const isExpectedSubFieldName = <
GivenFieldType extends keyof typeof SETTINGS_COMPOSITE_FIELD_TYPE_CONFIGS,
CompositeFieldTypeSettings extends
typeof SETTINGS_COMPOSITE_FIELD_TYPE_CONFIGS,
PossibleSubFieldsForGivenFieldType extends
CompositeFieldTypeSettings[GivenFieldType]['subFields'][number]['subFieldName'],
>(
fieldMetadataType: GivenFieldType,
subFieldName: PossibleSubFieldsForGivenFieldType,
subFieldNameToCheck: string | null | undefined,
): subFieldNameToCheck is PossibleSubFieldsForGivenFieldType => {
return (
SETTINGS_COMPOSITE_FIELD_TYPE_CONFIGS[fieldMetadataType].subFields
.map((subField) => subField.subFieldName)
.includes(subFieldName) && subFieldName === subFieldNameToCheck
);
};
@@ -1,8 +1,8 @@
import { CustomError } from '@/error-handler/CustomError';
import { AggregateOperations } from '@/object-record/record-table/constants/AggregateOperations';
import { DateAggregateOperations } from '@/object-record/record-table/constants/DateAggregateOperations';
import { type ExtendedAggregateOperations } from '@/object-record/record-table/types/ExtendedAggregateOperations';
import { t } from '@lingui/core/macro';
import { CustomError } from 'twenty-shared/utils';
export const getAggregateOperationLabel = (
operation: ExtendedAggregateOperations,
@@ -1,8 +1,8 @@
import { CustomError } from '@/error-handler/CustomError';
import { AggregateOperations } from '@/object-record/record-table/constants/AggregateOperations';
import { DateAggregateOperations } from '@/object-record/record-table/constants/DateAggregateOperations';
import { type ExtendedAggregateOperations } from '@/object-record/record-table/types/ExtendedAggregateOperations';
import { msg } from '@lingui/core/macro';
import { CustomError } from 'twenty-shared/utils';
export const getAggregateOperationShortLabel = (
operation: ExtendedAggregateOperations,
@@ -2,9 +2,11 @@ import { useRecordCalendarContextOrThrow } from '@/object-record/record-calendar
import { useRecordCalendarMonthDaysRange } from '@/object-record/record-calendar/month/hooks/useRecordCalendarMonthDaysRange';
import { type RecordFilter } from '@/object-record/record-filter/types/RecordFilter';
import { RecordFilterOperand } from '@/object-record/record-filter/types/RecordFilterOperand';
import { computeRecordGqlOperationFilter } from '@/object-record/record-filter/utils/computeRecordGqlOperationFilter';
import { useGetCurrentViewOnly } from '@/views/hooks/useGetCurrentViewOnly';
import { isDefined } from 'twenty-shared/utils';
import {
computeRecordGqlOperationFilter,
isDefined,
} from 'twenty-shared/utils';
const DATE_RANGE_FILTER_AFTER_ID = 'DATE_RANGE_FILTER_AFTER_ID';
const DATE_RANGE_FILTER_BEFORE_ID = 'DATE_RANGE_FILTER_BEFORE_ID';
@@ -3,7 +3,6 @@ import { useRecoilValue } from 'recoil';
import { useObjectMetadataItem } from '@/object-metadata/hooks/useObjectMetadataItem';
import { useObjectMetadataItems } from '@/object-metadata/hooks/useObjectMetadataItems';
import { type RecordGqlOperationFilter } from '@/object-record/graphql/types/RecordGqlOperationFilter';
import { useAggregateRecords } from '@/object-record/hooks/useAggregateRecords';
import { RecordDetailSectionContainer } from '@/object-record/record-field-list/record-detail-section/components/RecordDetailSectionContainer';
import { RecordDetailRelationRecordsList } from '@/object-record/record-field-list/record-detail-section/relation/components/RecordDetailRelationRecordsList';
@@ -24,7 +23,11 @@ import { useIsMobile } from '@/ui/utilities/responsive/hooks/useIsMobile';
import { useRecoilComponentValue } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentValue';
import { coreIndexViewIdFromObjectMetadataItemFamilySelector } from '@/views/states/selectors/coreIndexViewIdFromObjectMetadataItemFamilySelector';
import { useLingui } from '@lingui/react/macro';
import { AppPath, ViewFilterOperand } from 'twenty-shared/types';
import {
AppPath,
ViewFilterOperand,
type RecordGqlOperationFilter,
} from 'twenty-shared/types';
import { getAppPath } from 'twenty-shared/utils';
import { RelationType } from '~/generated-metadata/graphql';
@@ -4,8 +4,8 @@ import { useRecoilState } from 'recoil';
import { recordStoreFamilySelector } from '@/object-record/record-store/states/selectors/recordStoreFamilySelector';
import { FieldMetadataType } from '~/generated-metadata/graphql';
import { type FieldRatingValue } from 'twenty-shared/types';
import { FieldContext } from '../../contexts/FieldContext';
import { type FieldRatingValue } from '../../types/FieldMetadata';
import { assertFieldMetadata } from '../../types/guards/assertFieldMetadata';
import { isFieldRating } from '../../types/guards/isFieldRating';
@@ -1,8 +1,8 @@
import { useContext } from 'react';
import { type FieldRatingValue } from '@/object-record/record-field/ui/types/FieldMetadata';
import { useRecordFieldValue } from '@/object-record/record-store/contexts/RecordFieldValueSelectorContext';
import { type FieldRatingValue } from 'twenty-shared/types';
import { FieldContext } from '../../contexts/FieldContext';
export const useRatingFieldDisplay = () => {
@@ -1,7 +1,6 @@
import React, { useRef, useState } from 'react';
import { Key } from 'ts-key-enum';
import { CustomError } from '@/error-handler/CustomError';
import {
MultiItemBaseInput,
type MultiItemBaseInputProps,
@@ -14,6 +13,7 @@ import { DropdownMenuSeparator } from '@/ui/layout/dropdown/components/DropdownM
import { useHotkeysOnFocusedElement } from '@/ui/utilities/hotkey/hooks/useHotkeysOnFocusedElement';
import { useListenClickOutside } from '@/ui/utilities/pointer-event/hooks/useListenClickOutside';
import { useAvailableComponentInstanceIdOrThrow } from '@/ui/utilities/state/component-state/hooks/useAvailableComponentInstanceIdOrThrow';
import { CustomError } from 'twenty-shared/utils';
import { IconCheck, IconPlus } from 'twenty-ui/display';
import { LightIconButton } from 'twenty-ui/input';
import { MenuItem } from 'twenty-ui/navigation';
@@ -1,9 +1,9 @@
import { type FieldRatingValue } from '@/object-record/record-field/ui/types/FieldMetadata';
import { RatingInput } from '@/ui/field/input/components/RatingInput';
import { FieldContext } from '@/object-record/record-field/ui/contexts/FieldContext';
import { FieldInputEventContext } from '@/object-record/record-field/ui/contexts/FieldInputEventContext';
import { useContext } from 'react';
import { type FieldRatingValue } from 'twenty-shared/types';
import { useRatingField } from '../../hooks/useRatingField';
export const RatingFieldInput = () => {
@@ -10,8 +10,7 @@ import { RecordFieldComponentInstanceContext } from '@/object-record/record-fiel
import { RECORD_TABLE_CELL_INPUT_ID_PREFIX } from '@/object-record/record-table/constants/RecordTableCellInputIdPrefix';
import { getRecordFieldInputInstanceId } from '@/object-record/utils/getRecordFieldInputId';
import { FocusComponentType } from '@/ui/utilities/focus/types/FocusComponentType';
import { FieldMetadataType } from 'twenty-shared/types';
import { type FieldRatingValue } from '../../../../types/FieldMetadata';
import { FieldMetadataType, type FieldRatingValue } from 'twenty-shared/types';
import { useRatingField } from '../../../hooks/useRatingField';
import { RatingFieldInput } from '../RatingFieldInput';
@@ -12,7 +12,6 @@ import {
type FieldMultiSelectValue,
type FieldNumberValue,
type FieldPhonesValue,
type FieldRatingValue,
type FieldRelationFromManyValue,
type FieldRelationToOneValue,
type FieldSelectValue,
@@ -20,6 +19,7 @@ import {
type FieldUUidValue,
type PhoneRecord,
} from '@/object-record/record-field/ui/types/FieldMetadata';
import { type FieldRatingValue } from 'twenty-shared/types';
export type FieldTextDraftValue = string;
export type FieldNumberDraftValue = number;
@@ -1,5 +1,4 @@
import { type FieldMetadataItemRelation } from '@/object-metadata/types/FieldMetadataItemRelation';
import { type RATING_VALUES } from '@/object-record/record-field/ui/meta-types/constants/RatingValues';
import { type ZodHelperLiteral } from '@/object-record/record-field/ui/types/ZodHelperLiteral';
import { type ObjectRecord } from '@/object-record/types/ObjectRecord';
import {
@@ -251,7 +250,6 @@ export type FieldAddressValue = {
addressLat: number | null;
addressLng: number | null;
};
export type FieldRatingValue = (typeof RATING_VALUES)[number] | null;
export type FieldSelectValue = string | null;
export type FieldMultiSelectValue = string[] | null;
@@ -1,6 +1,5 @@
import { RATING_VALUES } from '@/object-record/record-field/ui/meta-types/constants/RatingValues';
import { type FieldRatingValue } from '../FieldMetadata';
import { RATING_VALUES } from 'twenty-shared/constants';
import { type FieldRatingValue } from 'twenty-shared/types';
export const isFieldRatingValue = (
fieldValue: unknown,
@@ -1,4 +1,3 @@
import { CustomError } from '@/error-handler/CustomError';
import { CurrencyCode } from '@/object-record/record-field/ui/types/CurrencyCode';
import { type FieldDefinition } from '@/object-record/record-field/ui/types/FieldDefinition';
import { type FieldInputDraftValue } from '@/object-record/record-field/ui/types/FieldInputDraftValue';
@@ -14,6 +13,7 @@ import { isFieldPhones } from '@/object-record/record-field/ui/types/guards/isFi
import { isFieldRelation } from '@/object-record/record-field/ui/types/guards/isFieldRelation';
import { isFieldText } from '@/object-record/record-field/ui/types/guards/isFieldText';
import { isFieldUuid } from '@/object-record/record-field/ui/types/guards/isFieldUuid';
import { CustomError } from 'twenty-shared/utils';
type computeDraftValueFromStringParams = {
fieldDefinition: Pick<FieldDefinition<FieldMetadata>, 'type'>;
@@ -1,4 +1,3 @@
import { CustomError } from '@/error-handler/CustomError';
import { CurrencyCode } from '@/object-record/record-field/ui/types/CurrencyCode';
import { type FieldDefinition } from '@/object-record/record-field/ui/types/FieldDefinition';
import { type FieldInputDraftValue } from '@/object-record/record-field/ui/types/FieldInputDraftValue';
@@ -13,6 +12,7 @@ import { isFieldRawJson } from '@/object-record/record-field/ui/types/guards/isF
import { isFieldRelation } from '@/object-record/record-field/ui/types/guards/isFieldRelation';
import { isFieldText } from '@/object-record/record-field/ui/types/guards/isFieldText';
import { isFieldUuid } from '@/object-record/record-field/ui/types/guards/isFieldUuid';
import { CustomError } from 'twenty-shared/utils';
type computeEmptyDraftValueParams = {
fieldDefinition: Pick<FieldDefinition<FieldMetadata>, 'type'>;
@@ -2,9 +2,9 @@ import { renderHook } from '@testing-library/react';
import { currentRecordFilterGroupsComponentState } from '@/object-record/record-filter-group/states/currentRecordFilterGroupsComponentState';
import { type RecordFilterGroup } from '@/object-record/record-filter-group/types/RecordFilterGroup';
import { RecordFilterGroupLogicalOperator } from '@/object-record/record-filter-group/types/RecordFilterGroupLogicalOperator';
import { useRecoilComponentValue } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentValue';
import { act } from 'react';
import { RecordFilterGroupLogicalOperator } from 'twenty-shared/types';
import { getJestMetadataAndApolloMocksWrapper } from '~/testing/jest/getJestMetadataAndApolloMocksWrapper';
import { useRemoveRecordFilterGroup } from '../useRemoveRecordFilterGroup';
import { useUpsertRecordFilterGroup } from '../useUpsertRecordFilterGroup';
@@ -4,8 +4,8 @@ import { act } from 'react';
import { useUpsertRecordFilterGroup } from '@/object-record/record-filter-group/hooks/useUpsertRecordFilterGroup';
import { currentRecordFilterGroupsComponentState } from '@/object-record/record-filter-group/states/currentRecordFilterGroupsComponentState';
import { type RecordFilterGroup } from '@/object-record/record-filter-group/types/RecordFilterGroup';
import { RecordFilterGroupLogicalOperator } from '@/object-record/record-filter-group/types/RecordFilterGroupLogicalOperator';
import { useRecoilComponentValue } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentValue';
import { RecordFilterGroupLogicalOperator } from 'twenty-shared/types';
import { getJestMetadataAndApolloMocksWrapper } from '~/testing/jest/getJestMetadataAndApolloMocksWrapper';
const Wrapper = getJestMetadataAndApolloMocksWrapper({
@@ -1,4 +1,4 @@
import { type RecordFilterGroupLogicalOperator } from '@/object-record/record-filter-group/types/RecordFilterGroupLogicalOperator';
import { type RecordFilterGroupLogicalOperator } from 'twenty-shared/types';
export type RecordFilterGroup = {
id: string;
@@ -1,9 +1,9 @@
import { type FieldMetadataItem } from '@/object-metadata/types/FieldMetadataItem';
import { getFilterTypeFromFieldType } from '@/object-metadata/utils/formatFieldMetadataItemsAsFilterDefinitions';
import { getInitialFilterValue } from '@/object-record/object-filter-dropdown/utils/getInitialFilterValue';
import { type RecordFilter } from '@/object-record/record-filter/types/RecordFilter';
import { getDefaultSubFieldNameForCompositeFilterableFieldType } from '@/object-record/record-filter/utils/getDefaultSubFieldNameForCompositeFilterableFieldType';
import { getRecordFilterOperands } from '@/object-record/record-filter/utils/getRecordFilterOperands';
import { getFilterTypeFromFieldType } from 'twenty-shared/utils';
import { v4 } from 'uuid';
export const useCreateEmptyRecordFilterFromFieldMetadataItem = () => {
@@ -1,11 +1,10 @@
import { getFilterTypeFromFieldType } from '@/object-metadata/utils/formatFieldMetadataItemsAsFilterDefinitions';
import { fieldMetadataItemUsedInDropdownComponentSelector } from '@/object-record/object-filter-dropdown/states/fieldMetadataItemUsedInDropdownComponentSelector';
import { selectedOperandInDropdownComponentState } from '@/object-record/object-filter-dropdown/states/selectedOperandInDropdownComponentState';
import { subFieldNameUsedInDropdownComponentState } from '@/object-record/object-filter-dropdown/states/subFieldNameUsedInDropdownComponentState';
import { type RecordFilter } from '@/object-record/record-filter/types/RecordFilter';
import { useRecoilComponentCallbackState } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentCallbackState';
import { useRecoilCallback } from 'recoil';
import { isDefined } from 'twenty-shared/utils';
import { getFilterTypeFromFieldType, isDefined } from 'twenty-shared/utils';
import { v4 } from 'uuid';
export const useCreateRecordFilterFromObjectFilterDropdownCurrentStates =
@@ -1,6 +1,6 @@
import { currentWorkspaceMemberState } from '@/auth/states/currentWorkspaceMemberState';
import { type RecordFilterValueDependencies } from '@/object-record/record-filter/types/RecordFilterValueDependencies';
import { useRecoilValue } from 'recoil';
import { type RecordFilterValueDependencies } from 'twenty-shared/types';
export const useFilterValueDependencies = (): {
filterValueDependencies: RecordFilterValueDependencies;
@@ -1,5 +1,5 @@
import { type FilterableFieldType } from '@/object-record/record-filter/types/FilterableFieldType';
import { type CompositeFieldType } from '@/settings/data-model/types/CompositeFieldType';
import { type FilterableFieldType } from 'twenty-shared/types';
export type CompositeFilterableFieldType = FilterableFieldType &
CompositeFieldType;
@@ -1,7 +1,9 @@
import { type FilterableAndTSVectorFieldType } from '@/object-record/record-filter/types/FilterableFieldType';
import { type FILTER_OPERANDS_MAP } from '@/object-record/record-filter/utils/getRecordFilterOperands';
import { type CompositeFieldSubFieldName } from '@/settings/data-model/types/CompositeFieldSubFieldName';
import { type ViewFilterOperand } from 'twenty-shared/types';
import {
type FilterableAndTSVectorFieldType,
type ViewFilterOperand,
} from 'twenty-shared/types';
export type RecordFilter = {
id: string;
@@ -1,5 +1,5 @@
import { type RecordGqlOperationFilter } from '@/object-record/graphql/types/RecordGqlOperationFilter';
import { combineFilters } from '../combineFilters';
import { type RecordGqlOperationFilter } from 'twenty-shared/types';
import { combineFilters } from 'twenty-shared/utils';
describe('combineFilters', () => {
it('should return empty object when all filters are empty', () => {
@@ -1,10 +1,14 @@
import { type FieldCurrencyValue } from '@/object-record/record-field/ui/types/FieldMetadata';
import { type RecordFilter } from '@/object-record/record-filter/types/RecordFilter';
import { RecordFilterOperand } from '@/object-record/record-filter/types/RecordFilterOperand';
import { type RecordFilterValueDependencies } from '@/object-record/record-filter/types/RecordFilterValueDependencies';
import { computeRecordGqlOperationFilter } from '@/object-record/record-filter/utils/computeRecordGqlOperationFilter';
import { ViewFilterOperand } from 'twenty-shared/types';
import { isDefined } from 'twenty-shared/utils';
import {
ViewFilterOperand,
type RecordFilterValueDependencies,
} from 'twenty-shared/types';
import {
computeRecordGqlOperationFilter,
isDefined,
} from 'twenty-shared/utils';
import { FieldMetadataType } from '~/generated-metadata/graphql';
import { getCompaniesMock } from '~/testing/mock-data/companies';
@@ -1,7 +1,7 @@
import { type RecordFilterGroup } from '@/object-record/record-filter-group/types/RecordFilterGroup';
import { RecordFilterGroupLogicalOperator } from '@/object-record/record-filter-group/types/RecordFilterGroupLogicalOperator';
import { type RecordFilter } from '@/object-record/record-filter/types/RecordFilter';
import { RecordFilterOperand } from '@/object-record/record-filter/types/RecordFilterOperand';
import { RecordFilterGroupLogicalOperator } from 'twenty-shared/types';
import { sortByProperty } from '~/utils/array/sortByProperty';
import { getAllRecordFilterDescendantsOfRecordFilterGroup } from '../getAllRecordFilterDescendantsOfRecordFilterGroup';
@@ -1,5 +1,5 @@
import { type CurrencyFilter } from '@/object-record/graphql/types/RecordGqlOperationFilter';
import { isMatchingCurrencyFilter } from '@/object-record/record-filter/utils/isMatchingCurrencyFilter';
import { type CurrencyFilter } from 'twenty-shared/types';
describe('isMatchingCurrencyFilter', () => {
describe('amountMicros', () => {
@@ -1,4 +1,4 @@
import { type RecordGqlOperationFilter } from '@/object-record/graphql/types/RecordGqlOperationFilter';
import { type RecordGqlOperationFilter } from 'twenty-shared/types';
import { getCompaniesMock } from '~/testing/mock-data/companies';
import { generatedMockObjectMetadataItems } from '~/testing/utils/generatedMockObjectMetadataItems';
@@ -1,30 +0,0 @@
import { type FieldMetadataItem } from '@/object-metadata/types/FieldMetadataItem';
import { getFilterTypeFromFieldType } from '@/object-metadata/utils/formatFieldMetadataItemsAsFilterDefinitions';
import { type FilterableAndTSVectorFieldType } from '@/object-record/record-filter/types/FilterableFieldType';
import { type RecordFilter } from '@/object-record/record-filter/types/RecordFilter';
import { isEmptinessOperand } from '@/object-record/record-filter/utils/isEmptinessOperand';
export const checkIfShouldComputeEmptinessFilter = ({
recordFilter,
correspondingFieldMetadataItem,
}: {
recordFilter: RecordFilter;
correspondingFieldMetadataItem: Pick<FieldMetadataItem, 'type'>;
}) => {
const isAnEmptinessOperand = isEmptinessOperand(recordFilter.operand);
const filterTypesThatHaveNoEmptinessOperand: FilterableAndTSVectorFieldType[] =
['BOOLEAN', 'TS_VECTOR'];
const filterType = getFilterTypeFromFieldType(
correspondingFieldMetadataItem.type,
);
const filterHasEmptinessOperands =
!filterTypesThatHaveNoEmptinessOperand.includes(filterType);
const shouldComputeEmptinessFilter =
filterHasEmptinessOperands && isAnEmptinessOperand;
return shouldComputeEmptinessFilter;
};
@@ -1,4 +1,4 @@
import { type FilterableAndTSVectorFieldType } from '@/object-record/record-filter/types/FilterableFieldType';
import { type FilterableAndTSVectorFieldType } from 'twenty-shared/types';
export const getDateFilterDisplayValue = (
value: Date,
@@ -7,7 +7,7 @@ import { assertUnreachable } from 'twenty-shared/utils';
export const getDefaultSubFieldNameForCompositeFilterableFieldType = (
fieldType: FieldType,
): CompositeFieldSubFieldName | undefined => {
if (!isCompositeFilterableFieldType(fieldType as any)) {
if (!isCompositeFilterableFieldType(fieldType)) {
return undefined;
}
@@ -1,15 +1,12 @@
import { isExpectedSubFieldName } from '@/object-record/object-filter-dropdown/utils/isExpectedSubFieldName';
import { isFilterOnActorSourceSubField } from '@/object-record/object-filter-dropdown/utils/isFilterOnActorSourceSubField';
import {
type FilterableAndTSVectorFieldType,
type FilterableFieldType,
} from '@/object-record/record-filter/types/FilterableFieldType';
import { type CompositeFieldSubFieldName } from '@/settings/data-model/types/CompositeFieldSubFieldName';
import {
FieldMetadataType,
ViewFilterOperand as RecordFilterOperand,
type FilterableAndTSVectorFieldType,
type FilterableFieldType,
} from 'twenty-shared/types';
import { assertUnreachable } from 'twenty-shared/utils';
import { assertUnreachable, isExpectedSubFieldName } from 'twenty-shared/utils';
export type GetRecordFilterOperandsParams = {
filterType: FilterableAndTSVectorFieldType;
@@ -168,7 +165,7 @@ export const getRecordFilterOperands = ({
FieldMetadataType.CURRENCY,
'currencyCode',
subFieldName,
)
) === true
) {
return COMPOSITE_FIELD_FILTER_OPERANDS_MAP.CURRENCY.currencyCode;
} else {
@@ -1,4 +1,4 @@
import { type ArrayFilter } from '@/object-record/graphql/types/RecordGqlOperationFilter';
import { type ArrayFilter } from 'twenty-shared/types';
export const isMatchingArrayFilter = ({
arrayFilter,
@@ -1,4 +1,4 @@
import { type BooleanFilter } from '@/object-record/graphql/types/RecordGqlOperationFilter';
import { type BooleanFilter } from 'twenty-shared/types';
export const isMatchingBooleanFilter = ({
booleanFilter,
@@ -1,5 +1,5 @@
import { type CurrencyFilter } from '@/object-record/graphql/types/RecordGqlOperationFilter';
import { isNonEmptyString } from '@sniptt/guards';
import { type CurrencyFilter } from 'twenty-shared/types';
import { isDefined } from 'twenty-shared/utils';
const isMatchingCurrencyCodeFilter = (
@@ -1,6 +1,5 @@
import { parseISO, isEqual, isAfter, isBefore } from 'date-fns';
import { type DateFilter } from '@/object-record//graphql/types/RecordGqlOperationFilter';
import { isAfter, isBefore, isEqual, parseISO } from 'date-fns';
import { type DateFilter } from 'twenty-shared/types';
export const isMatchingDateFilter = ({
dateFilter,
@@ -1,4 +1,4 @@
import { type FloatFilter } from '@/object-record/graphql/types/RecordGqlOperationFilter';
import { type FloatFilter } from 'twenty-shared/types';
export const isMatchingFloatFilter = ({
floatFilter,
@@ -1,4 +1,4 @@
import { type MultiSelectFilter } from '@/object-record/graphql/types/RecordGqlOperationFilter';
import { type MultiSelectFilter } from 'twenty-shared/types';
export const isMatchingMultiSelectFilter = ({
multiSelectFilter,
@@ -1,4 +1,4 @@
import { type RatingFilter } from '@/object-record/graphql/types/RecordGqlOperationFilter';
import { type RatingFilter } from 'twenty-shared/types';
export const isMatchingRatingFilter = ({
ratingFilter,
@@ -1,4 +1,4 @@
import { type RawJsonFilter } from '../../graphql/types/RecordGqlOperationFilter';
import { type RawJsonFilter } from 'twenty-shared/types';
export const isMatchingRawJsonFilter = ({
rawJsonFilter,
@@ -1,5 +1,5 @@
import { type RichTextV2Filter } from '@/object-record/graphql/types/RecordGqlOperationFilter';
import escapeRegExp from 'lodash.escaperegexp';
import { type RichTextV2Filter } from 'twenty-shared/types';
export const isMatchingRichTextV2Filter = ({
richTextV2Filter,
@@ -1,4 +1,4 @@
import { type SelectFilter } from '@/object-record/graphql/types/RecordGqlOperationFilter';
import { type SelectFilter } from 'twenty-shared/types';
export const isMatchingSelectFilter = ({
selectFilter,
@@ -1,5 +1,5 @@
import { type StringFilter } from '@/object-record/graphql/types/RecordGqlOperationFilter';
import escapeRegExp from 'lodash.escaperegexp';
import { type StringFilter } from 'twenty-shared/types';
export const isMatchingStringFilter = ({
stringFilter,
@@ -1,4 +1,4 @@
import { type TSVectorFilter } from '@/object-record/graphql/types/RecordGqlOperationFilter';
import { type TSVectorFilter } from 'twenty-shared/types';
export const isMatchingTSVectorFilter = ({
tsVectorFilter,
@@ -1,7 +1,4 @@
import {
type UUIDFilter,
type UUIDFilterValue,
} from '@/object-record/graphql/types/RecordGqlOperationFilter';
import { type UUIDFilter, type UUIDFilterValue } from 'twenty-shared/types';
export const isMatchingUUIDFilter = ({
uuidFilter,
@@ -1,6 +1,19 @@
import { isObject } from '@sniptt/guards';
import { type ObjectMetadataItem } from '@/object-metadata/types/ObjectMetadataItem';
import { isMatchingArrayFilter } from '@/object-record/record-filter/utils/isMatchingArrayFilter';
import { isMatchingBooleanFilter } from '@/object-record/record-filter/utils/isMatchingBooleanFilter';
import { isMatchingCurrencyFilter } from '@/object-record/record-filter/utils/isMatchingCurrencyFilter';
import { isMatchingDateFilter } from '@/object-record/record-filter/utils/isMatchingDateFilter';
import { isMatchingFloatFilter } from '@/object-record/record-filter/utils/isMatchingFloatFilter';
import { isMatchingMultiSelectFilter } from '@/object-record/record-filter/utils/isMatchingMultiSelectFilter';
import { isMatchingRatingFilter } from '@/object-record/record-filter/utils/isMatchingRatingFilter';
import { isMatchingRawJsonFilter } from '@/object-record/record-filter/utils/isMatchingRawJsonFilter';
import { isMatchingRichTextV2Filter } from '@/object-record/record-filter/utils/isMatchingRichTextV2Filter';
import { isMatchingSelectFilter } from '@/object-record/record-filter/utils/isMatchingSelectFilter';
import { isMatchingStringFilter } from '@/object-record/record-filter/utils/isMatchingStringFilter';
import { isMatchingTSVectorFilter } from '@/object-record/record-filter/utils/isMatchingTSVectorFilter';
import { isMatchingUUIDFilter } from '@/object-record/record-filter/utils/isMatchingUUIDFilter';
import {
type ActorFilter,
type AddressFilter,
@@ -26,20 +39,7 @@ import {
type StringFilter,
type TSVectorFilter,
type UUIDFilter,
} from '@/object-record/graphql/types/RecordGqlOperationFilter';
import { isMatchingArrayFilter } from '@/object-record/record-filter/utils/isMatchingArrayFilter';
import { isMatchingBooleanFilter } from '@/object-record/record-filter/utils/isMatchingBooleanFilter';
import { isMatchingCurrencyFilter } from '@/object-record/record-filter/utils/isMatchingCurrencyFilter';
import { isMatchingDateFilter } from '@/object-record/record-filter/utils/isMatchingDateFilter';
import { isMatchingFloatFilter } from '@/object-record/record-filter/utils/isMatchingFloatFilter';
import { isMatchingMultiSelectFilter } from '@/object-record/record-filter/utils/isMatchingMultiSelectFilter';
import { isMatchingRatingFilter } from '@/object-record/record-filter/utils/isMatchingRatingFilter';
import { isMatchingRawJsonFilter } from '@/object-record/record-filter/utils/isMatchingRawJsonFilter';
import { isMatchingRichTextV2Filter } from '@/object-record/record-filter/utils/isMatchingRichTextV2Filter';
import { isMatchingSelectFilter } from '@/object-record/record-filter/utils/isMatchingSelectFilter';
import { isMatchingStringFilter } from '@/object-record/record-filter/utils/isMatchingStringFilter';
import { isMatchingTSVectorFilter } from '@/object-record/record-filter/utils/isMatchingTSVectorFilter';
import { isMatchingUUIDFilter } from '@/object-record/record-filter/utils/isMatchingUUIDFilter';
} from 'twenty-shared/types';
import { isDefined } from 'twenty-shared/utils';
import { FieldMetadataType } from '~/generated-metadata/graphql';
import { isEmptyObject } from '~/utils/isEmptyObject';
@@ -1,13 +1,15 @@
import { type ObjectMetadataItem } from '@/object-metadata/types/ObjectMetadataItem';
import { type RecordGqlOperationFilter } from '@/object-record/graphql/types/RecordGqlOperationFilter';
import { type RecordFilter } from '@/object-record/record-filter/types/RecordFilter';
import { RecordFilterOperand } from '@/object-record/record-filter/types/RecordFilterOperand';
import { turnRecordFilterIntoRecordGqlOperationFilter } from '@/object-record/record-filter/utils/compute-record-gql-operation-filter/turnRecordFilterIntoGqlOperationFilter';
import { createAnyFieldRecordFilterBaseProperties } from '@/object-record/record-filter/utils/createAnyFieldRecordFilterBaseProperties';
import { filterSelectOptionsOfFieldMetadataItem } from '@/object-record/record-filter/utils/filterSelectOptionsOfFieldMetadataItem';
import { CURRENCIES } from '@/settings/data-model/constants/Currencies';
import { isNonEmptyString } from '@sniptt/guards';
import { isDefined } from 'twenty-shared/utils';
import { type RecordGqlOperationFilter } from 'twenty-shared/types';
import {
isDefined,
turnRecordFilterIntoRecordGqlOperationFilter,
} from 'twenty-shared/utils';
import { z } from 'zod';
import { FieldMetadataType } from '~/generated-metadata/graphql';
import { isNonEmptyArray } from '~/utils/isNonEmptyArray';
@@ -4,14 +4,15 @@ import { currentRecordFilterGroupsComponentState } from '@/object-record/record-
import { useFilterValueDependencies } from '@/object-record/record-filter/hooks/useFilterValueDependencies';
import { anyFieldFilterValueComponentState } from '@/object-record/record-filter/states/anyFieldFilterValueComponentState';
import { currentRecordFiltersComponentState } from '@/object-record/record-filter/states/currentRecordFiltersComponentState';
import { combineFilters } from '@/object-record/record-filter/utils/combineFilters';
import { computeRecordGqlOperationFilter } from '@/object-record/record-filter/utils/computeRecordGqlOperationFilter';
import { turnAnyFieldFilterIntoRecordGqlFilter } from '@/object-record/record-filter/utils/turnAnyFieldFilterIntoRecordGqlFilter';
import { useCurrentRecordGroupDefinition } from '@/object-record/record-group/hooks/useCurrentRecordGroupDefinition';
import { useRecordGroupFilter } from '@/object-record/record-group/hooks/useRecordGroupFilter';
import { currentRecordSortsComponentState } from '@/object-record/record-sort/states/currentRecordSortsComponentState';
import { useRecoilComponentValue } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentValue';
import {
combineFilters,
computeRecordGqlOperationFilter,
} from 'twenty-shared/utils';
export const useFindManyRecordIndexTableParams = (
objectNameSingular: string,
) => {
@@ -41,9 +42,9 @@ export const useFindManyRecordIndexTableParams = (
const currentFilters = computeRecordGqlOperationFilter({
fields: objectMetadataItem?.fields ?? [],
filterValueDependencies,
recordFilterGroups: currentRecordFilterGroups,
recordFilters: currentRecordFilters,
filterValueDependencies,
});
const anyFieldFilterValue = useRecoilComponentValue(
@@ -3,15 +3,14 @@ import { v4 } from 'uuid';
import { useColumnDefinitionsFromFieldMetadata } from '@/object-metadata/hooks/useColumnDefinitionsFromFieldMetadata';
import { useObjectMetadataItem } from '@/object-metadata/hooks/useObjectMetadataItem';
import { getFilterTypeFromFieldType } from '@/object-metadata/utils/formatFieldMetadataItemsAsFilterDefinitions';
import { useUpsertRecordFilter } from '@/object-record/record-filter/hooks/useUpsertRecordFilter';
import { type RecordFilter } from '@/object-record/record-filter/types/RecordFilter';
import { isSoftDeleteFilterActiveComponentState } from '@/object-record/record-table/states/isSoftDeleteFilterActiveComponentState';
import { useRecoilComponentCallbackState } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentCallbackState';
import { getFilterTypeFromFieldType, isDefined } from 'twenty-shared/utils';
import { useRecoilCallback } from 'recoil';
import { ViewFilterOperand } from 'twenty-shared/types';
import { isDefined } from 'twenty-shared/utils';
type UseHandleToggleTrashColumnFilterProps = {
objectNameSingular: string;
@@ -8,7 +8,6 @@ import { useSetRecordIdsForColumn } from '@/object-record/record-board/hooks/use
import { currentRecordFilterGroupsComponentState } from '@/object-record/record-filter-group/states/currentRecordFilterGroupsComponentState';
import { useFilterValueDependencies } from '@/object-record/record-filter/hooks/useFilterValueDependencies';
import { currentRecordFiltersComponentState } from '@/object-record/record-filter/states/currentRecordFiltersComponentState';
import { computeRecordGqlOperationFilter } from '@/object-record/record-filter/utils/computeRecordGqlOperationFilter';
import { recordGroupDefinitionFamilyState } from '@/object-record/record-group/states/recordGroupDefinitionFamilyState';
import { useRecordBoardRecordGqlFields } from '@/object-record/record-index/hooks/useRecordBoardRecordGqlFields';
@@ -16,11 +15,14 @@ import { type FieldMetadataItem } from '@/object-metadata/types/FieldMetadataIte
import { currentRecordSortsComponentState } from '@/object-record/record-sort/states/currentRecordSortsComponentState';
import { anyFieldFilterValueComponentState } from '@/object-record/record-filter/states/anyFieldFilterValueComponentState';
import { combineFilters } from '@/object-record/record-filter/utils/combineFilters';
import { turnAnyFieldFilterIntoRecordGqlFilter } from '@/object-record/record-filter/utils/turnAnyFieldFilterIntoRecordGqlFilter';
import { useUpsertRecordsInStore } from '@/object-record/record-store/hooks/useUpsertRecordsInStore';
import { useRecoilComponentValue } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentValue';
import { isDefined } from 'twenty-shared/utils';
import {
combineFilters,
computeRecordGqlOperationFilter,
isDefined,
} from 'twenty-shared/utils';
type UseLoadRecordIndexBoardProps = {
objectNameSingular: string;
@@ -6,14 +6,16 @@ import { currentRecordFilterGroupsComponentState } from '@/object-record/record-
import { useFilterValueDependencies } from '@/object-record/record-filter/hooks/useFilterValueDependencies';
import { anyFieldFilterValueComponentState } from '@/object-record/record-filter/states/anyFieldFilterValueComponentState';
import { currentRecordFiltersComponentState } from '@/object-record/record-filter/states/currentRecordFiltersComponentState';
import { computeRecordGqlOperationFilter } from '@/object-record/record-filter/utils/computeRecordGqlOperationFilter';
import { turnAnyFieldFilterIntoRecordGqlFilter } from '@/object-record/record-filter/utils/turnAnyFieldFilterIntoRecordGqlFilter';
import { recordIndexKanbanAggregateOperationState } from '@/object-record/record-index/states/recordIndexKanbanAggregateOperationState';
import { useRecoilComponentValue } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentValue';
import { UserContext } from '@/users/contexts/UserContext';
import { useContext } from 'react';
import { useRecoilValue } from 'recoil';
import { isDefined } from 'twenty-shared/utils';
import {
computeRecordGqlOperationFilter,
isDefined,
} from 'twenty-shared/utils';
import { dateLocaleState } from '~/localization/states/dateLocaleState';
type UseAggregateRecordsProps = {
@@ -4,7 +4,6 @@ import { currentRecordFilterGroupsComponentState } from '@/object-record/record-
import { useFilterValueDependencies } from '@/object-record/record-filter/hooks/useFilterValueDependencies';
import { anyFieldFilterValueComponentState } from '@/object-record/record-filter/states/anyFieldFilterValueComponentState';
import { currentRecordFiltersComponentState } from '@/object-record/record-filter/states/currentRecordFiltersComponentState';
import { computeRecordGqlOperationFilter } from '@/object-record/record-filter/utils/computeRecordGqlOperationFilter';
import { turnAnyFieldFilterIntoRecordGqlFilter } from '@/object-record/record-filter/utils/turnAnyFieldFilterIntoRecordGqlFilter';
import { useRecordGroupFilter } from '@/object-record/record-group/hooks/useRecordGroupFilter';
import { AggregateOperations } from '@/object-record/record-table/constants/AggregateOperations';
@@ -17,7 +16,11 @@ import { useRecoilComponentValue } from '@/ui/utilities/state/component-state/ho
import { UserContext } from '@/users/contexts/UserContext';
import { useContext } from 'react';
import { useRecoilValue } from 'recoil';
import { isDefined, isFieldMetadataDateKind } from 'twenty-shared/utils';
import {
computeRecordGqlOperationFilter,
isDefined,
isFieldMetadataDateKind,
} from 'twenty-shared/utils';
import { dateLocaleState } from '~/localization/states/dateLocaleState';
export const useAggregateRecordsForRecordTableColumnFooter = (
@@ -1,8 +1,10 @@
import { type FieldMetadataItemOption } from '@/object-metadata/types/FieldMetadataItem';
import { type FilterableFieldType } from '@/object-record/record-filter/types/FilterableFieldType';
import { type RecordFilter } from '@/object-record/record-filter/types/RecordFilter';
import { type ColorScheme } from '@/workspace-member/types/WorkspaceMember';
import { ViewFilterOperand } from 'twenty-shared/types';
import {
type FilterableFieldType,
ViewFilterOperand,
} from 'twenty-shared/types';
import { RelationType } from '~/generated-metadata/graphql';
import { buildValueFromFilter } from './buildRecordInputFromFilter';
@@ -1,10 +1,10 @@
import { RATING_VALUES } from '@/object-record/record-field/ui/meta-types/constants/RatingValues';
import { isFieldRatingValue } from '@/object-record/record-field/ui/types/guards/isFieldRatingValue';
import { emailSchema } from '@/object-record/record-field/ui/validation-schemas/emailSchema';
import { type SpreadsheetImportFieldValidationDefinition } from '@/spreadsheet-import/types';
import { t } from '@lingui/core/macro';
import { isDate, isString } from '@sniptt/guards';
import { parsePhoneNumberWithError } from 'libphonenumber-js';
import { RATING_VALUES } from 'twenty-shared/constants';
import {
absoluteUrlSchema,
getCountryCodesForCallingCode,
@@ -1,4 +1,4 @@
import { type RecordGqlOperationFilter } from '@/object-record/graphql/types/RecordGqlOperationFilter';
import { type RecordGqlOperationFilter } from 'twenty-shared/types';
import { isDefined } from 'twenty-shared/utils';
export const makeAndFilterVariables = (
@@ -1,4 +1,4 @@
import { type RecordGqlOperationFilter } from '@/object-record/graphql/types/RecordGqlOperationFilter';
import { type RecordGqlOperationFilter } from 'twenty-shared/types';
import { isDefined } from 'twenty-shared/utils';
export const makeOrFilterVariables = (
@@ -2,7 +2,7 @@ import { useCallback } from 'react';
import { type AppPath, ConnectedAccountProvider } from 'twenty-shared/types';
import { useRedirect } from '@/domain-manager/hooks/useRedirect';
import { CustomError } from '@/error-handler/CustomError';
import { CustomError } from 'twenty-shared/utils';
import { REACT_APP_SERVER_BASE_URL } from '~/config';
import {
type CalendarChannelVisibility,
@@ -1,4 +1,3 @@
import { CustomError } from '@/error-handler/CustomError';
import { Select } from '@/ui/input/components/Select';
import { SelectControl } from '@/ui/input/components/SelectControl';
import { TextArea } from '@/ui/input/components/TextArea';
@@ -7,6 +6,7 @@ import { Dropdown } from '@/ui/layout/dropdown/components/Dropdown';
import { DropdownContent } from '@/ui/layout/dropdown/components/DropdownContent';
import { DropdownMenuItemsContainer } from '@/ui/layout/dropdown/components/DropdownMenuItemsContainer';
import { type ConfigVariableValue } from 'twenty-shared/types';
import { CustomError } from 'twenty-shared/utils';
import { MenuItemMultiSelect } from 'twenty-ui/navigation';
import { ConfigVariableType } from '~/generated/graphql';
import { type ConfigVariableOptions } from '../types/ConfigVariableOptions';
@@ -1,6 +1,6 @@
import { CustomError } from '@/error-handler/CustomError';
import { useTheme } from '@emotion/react';
import { useLingui } from '@lingui/react/macro';
import { CustomError } from 'twenty-shared/utils';
import { ConfigSource } from '~/generated/graphql';
@@ -12,6 +12,7 @@ import {
import { COMPOSITE_FIELD_SUB_FIELD_LABELS } from '@/settings/data-model/constants/CompositeFieldSubFieldLabel';
import { type SettingsFieldTypeConfig } from '@/settings/data-model/constants/SettingsNonCompositeFieldTypeConfigs';
import { type CompositeFieldType } from '@/settings/data-model/types/CompositeFieldType';
import { COMPOSITE_FIELD_TYPE_SUB_FIELDS_NAMES } from 'twenty-shared/constants';
import { ConnectedAccountProvider } from 'twenty-shared/types';
import {
IllustrationIconCurrency,
@@ -51,7 +52,9 @@ export const SETTINGS_COMPOSITE_FIELD_TYPE_CONFIGS = {
Icon: IllustrationIconCurrency,
subFields: [
{
subFieldName: 'amountMicros',
subFieldName:
COMPOSITE_FIELD_TYPE_SUB_FIELDS_NAMES[FieldMetadataType.CURRENCY]
.amountMicros,
subFieldLabel:
COMPOSITE_FIELD_SUB_FIELD_LABELS[FieldMetadataType.CURRENCY]
.amountMicros,
@@ -60,7 +63,9 @@ export const SETTINGS_COMPOSITE_FIELD_TYPE_CONFIGS = {
isIncludedInUniqueConstraint: false,
},
{
subFieldName: 'currencyCode',
subFieldName:
COMPOSITE_FIELD_TYPE_SUB_FIELDS_NAMES[FieldMetadataType.CURRENCY]
.currencyCode,
subFieldLabel:
COMPOSITE_FIELD_SUB_FIELD_LABELS[FieldMetadataType.CURRENCY]
.currencyCode,
@@ -90,7 +95,9 @@ export const SETTINGS_COMPOSITE_FIELD_TYPE_CONFIGS = {
Icon: IllustrationIconMail,
subFields: [
{
subFieldName: 'primaryEmail',
subFieldName:
COMPOSITE_FIELD_TYPE_SUB_FIELDS_NAMES[FieldMetadataType.EMAILS]
.primaryEmail,
subFieldLabel:
COMPOSITE_FIELD_SUB_FIELD_LABELS[FieldMetadataType.EMAILS]
.primaryEmail,
@@ -99,7 +106,9 @@ export const SETTINGS_COMPOSITE_FIELD_TYPE_CONFIGS = {
isIncludedInUniqueConstraint: true,
},
{
subFieldName: 'additionalEmails',
subFieldName:
COMPOSITE_FIELD_TYPE_SUB_FIELDS_NAMES[FieldMetadataType.EMAILS]
.additionalEmails,
subFieldLabel:
COMPOSITE_FIELD_SUB_FIELD_LABELS[FieldMetadataType.EMAILS]
.additionalEmails,
@@ -133,7 +142,9 @@ export const SETTINGS_COMPOSITE_FIELD_TYPE_CONFIGS = {
Icon: IllustrationIconLink,
subFields: [
{
subFieldName: 'primaryLinkUrl',
subFieldName:
COMPOSITE_FIELD_TYPE_SUB_FIELDS_NAMES[FieldMetadataType.LINKS]
.primaryLinkUrl,
subFieldLabel:
COMPOSITE_FIELD_SUB_FIELD_LABELS[FieldMetadataType.LINKS]
.primaryLinkUrl,
@@ -142,7 +153,9 @@ export const SETTINGS_COMPOSITE_FIELD_TYPE_CONFIGS = {
isIncludedInUniqueConstraint: true,
},
{
subFieldName: 'primaryLinkLabel',
subFieldName:
COMPOSITE_FIELD_TYPE_SUB_FIELDS_NAMES[FieldMetadataType.LINKS]
.primaryLinkLabel,
subFieldLabel:
COMPOSITE_FIELD_SUB_FIELD_LABELS[FieldMetadataType.LINKS]
.primaryLinkLabel,
@@ -151,7 +164,9 @@ export const SETTINGS_COMPOSITE_FIELD_TYPE_CONFIGS = {
isIncludedInUniqueConstraint: false,
},
{
subFieldName: 'secondaryLinks',
subFieldName:
COMPOSITE_FIELD_TYPE_SUB_FIELDS_NAMES[FieldMetadataType.LINKS]
.secondaryLinks,
subFieldLabel:
COMPOSITE_FIELD_SUB_FIELD_LABELS[FieldMetadataType.LINKS]
.secondaryLinks,
@@ -184,7 +199,9 @@ export const SETTINGS_COMPOSITE_FIELD_TYPE_CONFIGS = {
Icon: IllustrationIconPhone,
subFields: [
{
subFieldName: 'primaryPhoneCallingCode',
subFieldName:
COMPOSITE_FIELD_TYPE_SUB_FIELDS_NAMES[FieldMetadataType.PHONES]
.primaryPhoneCallingCode,
subFieldLabel:
COMPOSITE_FIELD_SUB_FIELD_LABELS[FieldMetadataType.PHONES]
.primaryPhoneCallingCode,
@@ -193,7 +210,9 @@ export const SETTINGS_COMPOSITE_FIELD_TYPE_CONFIGS = {
isIncludedInUniqueConstraint: false,
},
{
subFieldName: 'primaryPhoneCountryCode',
subFieldName:
COMPOSITE_FIELD_TYPE_SUB_FIELDS_NAMES[FieldMetadataType.PHONES]
.primaryPhoneCountryCode,
subFieldLabel:
COMPOSITE_FIELD_SUB_FIELD_LABELS[FieldMetadataType.PHONES]
.primaryPhoneCountryCode,
@@ -202,7 +221,9 @@ export const SETTINGS_COMPOSITE_FIELD_TYPE_CONFIGS = {
isIncludedInUniqueConstraint: false,
},
{
subFieldName: 'primaryPhoneNumber',
subFieldName:
COMPOSITE_FIELD_TYPE_SUB_FIELDS_NAMES[FieldMetadataType.PHONES]
.primaryPhoneNumber,
subFieldLabel:
COMPOSITE_FIELD_SUB_FIELD_LABELS[FieldMetadataType.PHONES]
.primaryPhoneNumber,
@@ -211,7 +232,9 @@ export const SETTINGS_COMPOSITE_FIELD_TYPE_CONFIGS = {
isIncludedInUniqueConstraint: true,
},
{
subFieldName: 'additionalPhones',
subFieldName:
COMPOSITE_FIELD_TYPE_SUB_FIELDS_NAMES[FieldMetadataType.PHONES]
.additionalPhones,
subFieldLabel:
COMPOSITE_FIELD_SUB_FIELD_LABELS[FieldMetadataType.PHONES]
.additionalPhones,
@@ -252,7 +275,9 @@ export const SETTINGS_COMPOSITE_FIELD_TYPE_CONFIGS = {
Icon: IllustrationIconUser,
subFields: [
{
subFieldName: 'firstName',
subFieldName:
COMPOSITE_FIELD_TYPE_SUB_FIELDS_NAMES[FieldMetadataType.FULL_NAME]
.firstName,
subFieldLabel:
COMPOSITE_FIELD_SUB_FIELD_LABELS[FieldMetadataType.FULL_NAME]
.firstName,
@@ -261,7 +286,9 @@ export const SETTINGS_COMPOSITE_FIELD_TYPE_CONFIGS = {
isIncludedInUniqueConstraint: false,
},
{
subFieldName: 'lastName',
subFieldName:
COMPOSITE_FIELD_TYPE_SUB_FIELDS_NAMES[FieldMetadataType.FULL_NAME]
.lastName,
subFieldLabel:
COMPOSITE_FIELD_SUB_FIELD_LABELS[FieldMetadataType.FULL_NAME]
.lastName,
@@ -282,7 +309,9 @@ export const SETTINGS_COMPOSITE_FIELD_TYPE_CONFIGS = {
Icon: IllustrationIconMap,
subFields: [
{
subFieldName: 'addressStreet1',
subFieldName:
COMPOSITE_FIELD_TYPE_SUB_FIELDS_NAMES[FieldMetadataType.ADDRESS]
.addressStreet1,
subFieldLabel:
COMPOSITE_FIELD_SUB_FIELD_LABELS[FieldMetadataType.ADDRESS]
.addressStreet1,
@@ -291,7 +320,9 @@ export const SETTINGS_COMPOSITE_FIELD_TYPE_CONFIGS = {
isIncludedInUniqueConstraint: false,
},
{
subFieldName: 'addressStreet2',
subFieldName:
COMPOSITE_FIELD_TYPE_SUB_FIELDS_NAMES[FieldMetadataType.ADDRESS]
.addressStreet2,
subFieldLabel:
COMPOSITE_FIELD_SUB_FIELD_LABELS[FieldMetadataType.ADDRESS]
.addressStreet2,
@@ -300,7 +331,9 @@ export const SETTINGS_COMPOSITE_FIELD_TYPE_CONFIGS = {
isIncludedInUniqueConstraint: false,
},
{
subFieldName: 'addressCity',
subFieldName:
COMPOSITE_FIELD_TYPE_SUB_FIELDS_NAMES[FieldMetadataType.ADDRESS]
.addressCity,
subFieldLabel:
COMPOSITE_FIELD_SUB_FIELD_LABELS[FieldMetadataType.ADDRESS]
.addressCity,
@@ -309,7 +342,9 @@ export const SETTINGS_COMPOSITE_FIELD_TYPE_CONFIGS = {
isIncludedInUniqueConstraint: false,
},
{
subFieldName: 'addressState',
subFieldName:
COMPOSITE_FIELD_TYPE_SUB_FIELDS_NAMES[FieldMetadataType.ADDRESS]
.addressState,
subFieldLabel:
COMPOSITE_FIELD_SUB_FIELD_LABELS[FieldMetadataType.ADDRESS]
.addressState,
@@ -318,7 +353,9 @@ export const SETTINGS_COMPOSITE_FIELD_TYPE_CONFIGS = {
isIncludedInUniqueConstraint: false,
},
{
subFieldName: 'addressCountry',
subFieldName:
COMPOSITE_FIELD_TYPE_SUB_FIELDS_NAMES[FieldMetadataType.ADDRESS]
.addressCountry,
subFieldLabel:
COMPOSITE_FIELD_SUB_FIELD_LABELS[FieldMetadataType.ADDRESS]
.addressCountry,
@@ -327,7 +364,9 @@ export const SETTINGS_COMPOSITE_FIELD_TYPE_CONFIGS = {
isIncludedInUniqueConstraint: false,
},
{
subFieldName: 'addressPostcode',
subFieldName:
COMPOSITE_FIELD_TYPE_SUB_FIELDS_NAMES[FieldMetadataType.ADDRESS]
.addressPostcode,
subFieldLabel:
COMPOSITE_FIELD_SUB_FIELD_LABELS[FieldMetadataType.ADDRESS]
.addressPostcode,
@@ -336,7 +375,9 @@ export const SETTINGS_COMPOSITE_FIELD_TYPE_CONFIGS = {
isIncludedInUniqueConstraint: false,
},
{
subFieldName: 'addressLat',
subFieldName:
COMPOSITE_FIELD_TYPE_SUB_FIELDS_NAMES[FieldMetadataType.ADDRESS]
.addressLat,
subFieldLabel:
COMPOSITE_FIELD_SUB_FIELD_LABELS[FieldMetadataType.ADDRESS]
.addressLat,
@@ -345,7 +386,9 @@ export const SETTINGS_COMPOSITE_FIELD_TYPE_CONFIGS = {
isIncludedInUniqueConstraint: false,
},
{
subFieldName: 'addressLng',
subFieldName:
COMPOSITE_FIELD_TYPE_SUB_FIELDS_NAMES[FieldMetadataType.ADDRESS]
.addressLng,
subFieldLabel:
COMPOSITE_FIELD_SUB_FIELD_LABELS[FieldMetadataType.ADDRESS]
.addressLng,
@@ -394,7 +437,8 @@ export const SETTINGS_COMPOSITE_FIELD_TYPE_CONFIGS = {
category: 'Basic',
subFields: [
{
subFieldName: 'source',
subFieldName:
COMPOSITE_FIELD_TYPE_SUB_FIELDS_NAMES[FieldMetadataType.ACTOR].source,
subFieldLabel:
COMPOSITE_FIELD_SUB_FIELD_LABELS[FieldMetadataType.ACTOR].source,
isImportable: true,
@@ -402,7 +446,8 @@ export const SETTINGS_COMPOSITE_FIELD_TYPE_CONFIGS = {
isIncludedInUniqueConstraint: false,
},
{
subFieldName: 'name',
subFieldName:
COMPOSITE_FIELD_TYPE_SUB_FIELDS_NAMES[FieldMetadataType.ACTOR].name,
subFieldLabel:
COMPOSITE_FIELD_SUB_FIELD_LABELS[FieldMetadataType.ACTOR].name,
isImportable: true,
@@ -410,7 +455,9 @@ export const SETTINGS_COMPOSITE_FIELD_TYPE_CONFIGS = {
isIncludedInUniqueConstraint: false,
},
{
subFieldName: 'workspaceMemberId',
subFieldName:
COMPOSITE_FIELD_TYPE_SUB_FIELDS_NAMES[FieldMetadataType.ACTOR]
.workspaceMemberId,
subFieldLabel:
COMPOSITE_FIELD_SUB_FIELD_LABELS[FieldMetadataType.ACTOR]
.workspaceMemberId,
@@ -419,7 +466,9 @@ export const SETTINGS_COMPOSITE_FIELD_TYPE_CONFIGS = {
isIncludedInUniqueConstraint: false,
},
{
subFieldName: 'context',
subFieldName:
COMPOSITE_FIELD_TYPE_SUB_FIELDS_NAMES[FieldMetadataType.ACTOR]
.context,
subFieldLabel:
COMPOSITE_FIELD_SUB_FIELD_LABELS[FieldMetadataType.ACTOR].context,
isImportable: true,
@@ -454,7 +503,9 @@ export const SETTINGS_COMPOSITE_FIELD_TYPE_CONFIGS = {
category: 'Basic',
subFields: [
{
subFieldName: 'blocknote',
subFieldName:
COMPOSITE_FIELD_TYPE_SUB_FIELDS_NAMES[FieldMetadataType.RICH_TEXT_V2]
.blocknote,
subFieldLabel:
COMPOSITE_FIELD_SUB_FIELD_LABELS[FieldMetadataType.RICH_TEXT_V2]
.blocknote,
@@ -463,7 +514,9 @@ export const SETTINGS_COMPOSITE_FIELD_TYPE_CONFIGS = {
isIncludedInUniqueConstraint: false,
},
{
subFieldName: 'markdown',
subFieldName:
COMPOSITE_FIELD_TYPE_SUB_FIELDS_NAMES[FieldMetadataType.RICH_TEXT_V2]
.markdown,
subFieldLabel:
COMPOSITE_FIELD_SUB_FIELD_LABELS[FieldMetadataType.RICH_TEXT_V2]
.markdown,
@@ -6,7 +6,6 @@ import {
type FieldJsonValue,
type FieldMultiSelectValue,
type FieldNumberValue,
type FieldRatingValue,
type FieldRelationValue,
type FieldSelectValue,
type FieldTextValue,
@@ -15,6 +14,7 @@ import {
import { DEFAULT_DATE_VALUE } from '@/settings/data-model/constants/DefaultDateValue';
import { type SettingsFieldTypeCategoryType } from '@/settings/data-model/types/SettingsFieldTypeCategoryType';
import { type SettingsNonCompositeFieldType } from '@/settings/data-model/types/SettingsNonCompositeFieldType';
import { type FieldRatingValue } from 'twenty-shared/types';
import {
IllustrationIconArray,
IllustrationIconCalendarEvent,
@@ -3,11 +3,11 @@ import isEmpty from 'lodash.isempty';
import pickBy from 'lodash.pickby';
import { z } from 'zod';
import { CustomError } from '@/error-handler/CustomError';
import {
settingsIntegrationPostgreSQLConnectionFormSchema,
settingsIntegrationStripeConnectionFormSchema,
} from '@/settings/integrations/database-connection/components/SettingsIntegrationDatabaseConnectionForm';
import { CustomError } from 'twenty-shared/utils';
import { type RemoteServer } from '~/generated-metadata/graphql';
export const getEditionSchemaForForm = (databaseKey: string) => {
@@ -1,4 +1,3 @@
import { CustomError } from '@/error-handler/CustomError';
import { SETTINGS_PLAYGROUND_FORM_SCHEMA_SELECT_OPTIONS } from '@/settings/playground/constants/SettingsPlaygroundFormSchemaSelectOptions';
import { playgroundApiKeyState } from '@/settings/playground/states/playgroundApiKeyState';
import { PlaygroundSchemas } from '@/settings/playground/types/PlaygroundSchemas';
@@ -11,6 +10,7 @@ import { useLingui } from '@lingui/react/macro';
import { Controller, useForm } from 'react-hook-form';
import { useRecoilState } from 'recoil';
import { SettingsPath } from 'twenty-shared/types';
import { CustomError } from 'twenty-shared/utils';
import { IconApi, IconBrandGraphql } from 'twenty-ui/display';
import { Button } from 'twenty-ui/input';
import { z } from 'zod';
@@ -2,8 +2,8 @@ import { styled } from '@linaria/react';
import { useContext, useState } from 'react';
import { useClearField } from '@/object-record/record-field/ui/hooks/useClearField';
import { RATING_VALUES } from '@/object-record/record-field/ui/meta-types/constants/RatingValues';
import { type FieldRatingValue } from '@/object-record/record-field/ui/types/FieldMetadata';
import { RATING_VALUES } from 'twenty-shared/constants';
import { type FieldRatingValue } from 'twenty-shared/types';
import { IconTwentyStarFilled } from 'twenty-ui/display';
import { THEME_COMMON, ThemeContext } from 'twenty-ui/theme';
@@ -2,7 +2,6 @@ import { Select } from '@/ui/input/components/Select';
import { SettingsTextInput } from '@/ui/input/components/SettingsTextInput';
import { RELATIVE_DATE_DIRECTION_SELECT_OPTIONS } from '@/ui/input/components/internal/date/constants/RelativeDateDirectionSelectOptions';
import { RELATIVE_DATE_UNITS_SELECT_OPTIONS } from '@/ui/input/components/internal/date/constants/RelativeDateUnitSelectOptions';
import { variableDateViewFilterValuePartsSchema } from '@/views/view-filter-value/utils/resolveDateViewFilterValue';
import {
type VariableDateViewFilterValueDirection,
type VariableDateViewFilterValueUnit,
@@ -10,6 +9,7 @@ import {
import styled from '@emotion/styled';
import { useEffect, useState } from 'react';
import { variableDateViewFilterValuePartsSchema } from 'twenty-shared/utils';
const StyledContainer = styled.div<{ noPadding: boolean }>`
display: flex;
@@ -92,7 +92,8 @@ export const RelativeDatePickerHeader = (
};
if (
variableDateViewFilterValuePartsSchema.safeParse(valueParts).success
variableDateViewFilterValuePartsSchema.safeParse(valueParts)
.success === true
) {
props.onChange?.(valueParts);
}
@@ -10,7 +10,6 @@ import { VIEW_BAR_FILTER_BOTTOM_MENU_ITEM_IDS } from '@/views/constants/ViewBarF
import { VIEW_BAR_FILTER_DROPDOWN_ID } from '@/views/constants/ViewBarFilterDropdownId';
import { useSetRecordFilterUsedInAdvancedFilterDropdownRow } from '@/object-record/advanced-filter/hooks/useSetRecordFilterUsedInAdvancedFilterDropdownRow';
import { RecordFilterGroupLogicalOperator } from '@/object-record/record-filter-group/types/RecordFilterGroupLogicalOperator';
import { useCreateEmptyRecordFilterFromFieldMetadataItem } from '@/object-record/record-filter/hooks/useCreateEmptyRecordFilterFromFieldMetadataItem';
import { useCloseDropdown } from '@/ui/layout/dropdown/hooks/useCloseDropdown';
import { useOpenDropdown } from '@/ui/layout/dropdown/hooks/useOpenDropdown';
@@ -20,6 +19,7 @@ import { useGetCurrentViewOnly } from '@/views/hooks/useGetCurrentViewOnly';
import styled from '@emotion/styled';
import { useLingui } from '@lingui/react/macro';
import { useRecoilValue } from 'recoil';
import { RecordFilterGroupLogicalOperator } from 'twenty-shared/types';
import { isDefined } from 'twenty-shared/utils';
import { Pill } from 'twenty-ui/components';
import { IconFilter } from 'twenty-ui/display';

Some files were not shown because too many files have changed in this diff Show More