diff --git a/front/src/modules/keyboard-shortcut-menu/components/KeyboardShortcutMenu.tsx b/front/src/modules/keyboard-shortcut-menu/components/KeyboardShortcutMenu.tsx
index 0ae8bb2fb..15d988a03 100644
--- a/front/src/modules/keyboard-shortcut-menu/components/KeyboardShortcutMenu.tsx
+++ b/front/src/modules/keyboard-shortcut-menu/components/KeyboardShortcutMenu.tsx
@@ -20,7 +20,7 @@ export const KeyboardShortcutMenu = () => {
isKeyboardShortcutMenuOpenedState,
);
useScopedHotkeys(
- 'shift+?,meta+?,esc',
+ 'shift+?,meta+?',
() => {
toggleKeyboardShortcutMenu();
},
diff --git a/front/src/modules/object-metadata/utils/formatFieldMetadataItemsAsFilterDefinitions.ts b/front/src/modules/object-metadata/utils/formatFieldMetadataItemsAsFilterDefinitions.ts
index bdd1f4f08..8609f7417 100644
--- a/front/src/modules/object-metadata/utils/formatFieldMetadataItemsAsFilterDefinitions.ts
+++ b/front/src/modules/object-metadata/utils/formatFieldMetadataItemsAsFilterDefinitions.ts
@@ -12,14 +12,29 @@ export const formatFieldMetadataItemsAsFilterDefinitions = ({
if (
![
FieldMetadataType.DateTime,
- FieldMetadataType.Number,
- FieldMetadataType.Currency,
FieldMetadataType.Text,
- ].includes(field.type) ||
- field.name === 'probability'
+ FieldMetadataType.Email,
+ FieldMetadataType.Number,
+ FieldMetadataType.Link,
+ FieldMetadataType.FullName,
+ FieldMetadataType.Relation,
+ FieldMetadataType.Currency,
+ ].includes(field.type)
) {
return acc;
}
+
+ // Todo: remove once Rating fieldtype is implemented
+ if (field.name === 'probability') {
+ return acc;
+ }
+
+ if (field.type === FieldMetadataType.Relation) {
+ if (field.fromRelationMetadata) {
+ return acc;
+ }
+ }
+
return [...acc, formatFieldMetadataItemAsFilterDefinition({ field })];
}, [] as FilterDefinition[]);
@@ -34,9 +49,19 @@ const formatFieldMetadataItemAsFilterDefinition = ({
type:
field.type === FieldMetadataType.DateTime
? 'DATE_TIME'
+ : field.type === FieldMetadataType.Link
+ ? 'LINK'
+ : field.type === FieldMetadataType.FullName
+ ? 'FULL_NAME'
: field.type === FieldMetadataType.Number
? 'NUMBER'
: field.type === FieldMetadataType.Currency
? 'CURRENCY'
+ : field.type === FieldMetadataType.Email
+ ? 'TEXT'
+ : field.type === FieldMetadataType.Phone
+ ? 'TEXT'
+ : field.type === FieldMetadataType.Relation
+ ? 'RELATION'
: 'TEXT',
});
diff --git a/front/src/modules/ui/input/components/internal/relation-picker/RelationPicker.tsx b/front/src/modules/ui/input/components/internal/relation-picker/components/RelationPicker.tsx
similarity index 87%
rename from front/src/modules/ui/input/components/internal/relation-picker/RelationPicker.tsx
rename to front/src/modules/ui/input/components/internal/relation-picker/components/RelationPicker.tsx
index 53d93e974..5905205b2 100644
--- a/front/src/modules/ui/input/components/internal/relation-picker/RelationPicker.tsx
+++ b/front/src/modules/ui/input/components/internal/relation-picker/components/RelationPicker.tsx
@@ -4,16 +4,16 @@ import { useQuery } from '@apollo/client';
import { useObjectMetadataItem } from '@/object-metadata/hooks/useObjectMetadataItem';
import { useFilteredSearchEntityQuery } from '@/search/hooks/useFilteredSearchEntityQuery';
import { IconUserCircle } from '@/ui/display/icon';
+import { useRelationPicker } from '@/ui/input/components/internal/relation-picker/hooks/useRelationPicker';
import { SingleEntitySelect } from '@/ui/input/relation-picker/components/SingleEntitySelect';
import { relationPickerSearchFilterScopedState } from '@/ui/input/relation-picker/states/relationPickerSearchFilterScopedState';
import { EntityForSelect } from '@/ui/input/relation-picker/types/EntityForSelect';
-import { useRelationField } from '@/ui/object/field/meta-types/hooks/useRelationField';
import { FieldDefinition } from '@/ui/object/field/types/FieldDefinition';
import { FieldRelationMetadata } from '@/ui/object/field/types/FieldMetadata';
import { useRecoilScopedState } from '@/ui/utilities/recoil-scope/hooks/useRecoilScopedState';
export type RelationPickerProps = {
- recordId: string;
+ recordId?: string;
onSubmit: (newUser: EntityForSelect | null) => void;
onCancel?: () => void;
width?: number;
@@ -43,9 +43,9 @@ export const RelationPicker = ({
const useFindManyQuery = (options: any) => useQuery(findManyQuery, options);
- const { identifiersMapper, searchQuery } = useRelationField();
+ const { identifiersMapper, searchQuery } = useRelationPicker();
- const workspaceMembers = useFilteredSearchEntityQuery({
+ const records = useFilteredSearchEntityQuery({
queryHook: useFindManyQuery,
filters: [
{
@@ -74,11 +74,11 @@ export const RelationPicker = ({
);
diff --git a/front/src/modules/ui/object/field/meta-types/display/components/RelationFieldDisplay.tsx b/front/src/modules/ui/object/field/meta-types/display/components/RelationFieldDisplay.tsx
index 4495dd58d..dad9570ca 100644
--- a/front/src/modules/ui/object/field/meta-types/display/components/RelationFieldDisplay.tsx
+++ b/front/src/modules/ui/object/field/meta-types/display/components/RelationFieldDisplay.tsx
@@ -1,11 +1,12 @@
import { EntityChip } from '@/ui/display/chip/components/EntityChip';
+import { useRelationPicker } from '@/ui/input/components/internal/relation-picker/hooks/useRelationPicker';
import { useRelationField } from '../../hooks/useRelationField';
export const RelationFieldDisplay = () => {
const { fieldValue, fieldDefinition } = useRelationField();
- const { identifiersMapper } = useRelationField();
+ const { identifiersMapper } = useRelationPicker();
if (!fieldValue || !fieldDefinition || !identifiersMapper) {
return <>>;
diff --git a/front/src/modules/ui/object/field/meta-types/hooks/useRelationField.ts b/front/src/modules/ui/object/field/meta-types/hooks/useRelationField.ts
index 47541b1b4..a48f60a26 100644
--- a/front/src/modules/ui/object/field/meta-types/hooks/useRelationField.ts
+++ b/front/src/modules/ui/object/field/meta-types/hooks/useRelationField.ts
@@ -1,8 +1,6 @@
import { useContext } from 'react';
import { useRecoilState } from 'recoil';
-import { useRelationPicker } from '@/ui/input/components/internal/relation-picker/hooks/useRelationPicker';
-
import { FieldContext } from '../../contexts/FieldContext';
import { useFieldInitialValue } from '../../hooks/useFieldInitialValue';
import { entityFieldsFamilySelector } from '../../states/selectors/entityFieldsFamilySelector';
@@ -32,15 +30,11 @@ export const useRelationField = () => {
const initialValue = fieldInitialValue?.isEmpty ? null : fieldValue;
- const { identifiersMapper, searchQuery } = useRelationPicker();
-
return {
fieldDefinition,
fieldValue,
initialValue,
initialSearchValue,
setFieldValue,
- searchQuery,
- identifiersMapper,
};
};
diff --git a/front/src/modules/ui/object/field/meta-types/input/components/RelationFieldInput.tsx b/front/src/modules/ui/object/field/meta-types/input/components/RelationFieldInput.tsx
index 76f43c537..71294ea40 100644
--- a/front/src/modules/ui/object/field/meta-types/input/components/RelationFieldInput.tsx
+++ b/front/src/modules/ui/object/field/meta-types/input/components/RelationFieldInput.tsx
@@ -1,7 +1,7 @@
import { useEffect } from 'react';
import styled from '@emotion/styled';
-import { RelationPicker } from '@/ui/input/components/internal/relation-picker/RelationPicker';
+import { RelationPicker } from '@/ui/input/components/internal/relation-picker/components/RelationPicker';
import { EntityForSelect } from '@/ui/input/relation-picker/types/EntityForSelect';
import { usePersistField } from '../../../hooks/usePersistField';
diff --git a/front/src/modules/ui/object/object-filter-dropdown/components/MultipleFiltersDropdownButton.tsx b/front/src/modules/ui/object/object-filter-dropdown/components/MultipleFiltersDropdownButton.tsx
index ad5aad163..0c85e5f81 100644
--- a/front/src/modules/ui/object/object-filter-dropdown/components/MultipleFiltersDropdownButton.tsx
+++ b/front/src/modules/ui/object/object-filter-dropdown/components/MultipleFiltersDropdownButton.tsx
@@ -1,5 +1,6 @@
import { Dropdown } from '@/ui/layout/dropdown/components/Dropdown';
import { DropdownScope } from '@/ui/layout/dropdown/scopes/DropdownScope';
+import { useFilter } from '@/ui/object/object-filter-dropdown/hooks/useFilter';
import { HotkeyScope } from '@/ui/utilities/hotkey/types/HotkeyScope';
import { ObjectFilterDropdownId } from '../constants/ObjectFilterDropdownId';
@@ -14,9 +15,12 @@ type MultipleFiltersDropdownButtonProps = {
export const MultipleFiltersDropdownButton = ({
hotkeyScope,
}: MultipleFiltersDropdownButtonProps) => {
+ const { resetFilter } = useFilter();
+
return (
}
dropdownComponents={}
dropdownHotkeyScope={hotkeyScope}
diff --git a/front/src/modules/ui/object/object-filter-dropdown/components/MultipleFiltersDropdownContent.tsx b/front/src/modules/ui/object/object-filter-dropdown/components/MultipleFiltersDropdownContent.tsx
index 46b4006ff..7a38ceca0 100644
--- a/front/src/modules/ui/object/object-filter-dropdown/components/MultipleFiltersDropdownContent.tsx
+++ b/front/src/modules/ui/object/object-filter-dropdown/components/MultipleFiltersDropdownContent.tsx
@@ -30,19 +30,19 @@ export const MultipleFiltersDropdownContent = () => {
<>
- {filterDefinitionUsedInDropdown.type === 'TEXT' && (
-
- )}
+ {['TEXT', 'EMAIL', 'PHONE', 'FULL_NAME', 'LINK'].includes(
+ filterDefinitionUsedInDropdown.type,
+ ) && }
{['NUMBER', 'CURRENCY'].includes(
filterDefinitionUsedInDropdown.type,
) && }
{filterDefinitionUsedInDropdown.type === 'DATE_TIME' && (
)}
- {filterDefinitionUsedInDropdown.type === 'ENTITY' && (
+ {filterDefinitionUsedInDropdown.type === 'RELATION' && (
)}
- {filterDefinitionUsedInDropdown.type === 'ENTITY' && (
+ {filterDefinitionUsedInDropdown.type === 'RELATION' && (
)}
>
diff --git a/front/src/modules/ui/object/object-filter-dropdown/components/ObjectFilterDropdownButton.tsx b/front/src/modules/ui/object/object-filter-dropdown/components/ObjectFilterDropdownButton.tsx
index c00993935..9c2910da8 100644
--- a/front/src/modules/ui/object/object-filter-dropdown/components/ObjectFilterDropdownButton.tsx
+++ b/front/src/modules/ui/object/object-filter-dropdown/components/ObjectFilterDropdownButton.tsx
@@ -16,7 +16,7 @@ export const ObjectFilterDropdownButton = ({
const hasOnlyOneEntityFilter =
availableFilterDefinitions.length === 1 &&
- availableFilterDefinitions[0].type === 'ENTITY';
+ availableFilterDefinitions[0].type === 'RELATION';
if (!availableFilterDefinitions.length) {
return <>>;
diff --git a/front/src/modules/ui/object/object-filter-dropdown/components/ObjectFilterDropdownEntitySearchSelect.tsx b/front/src/modules/ui/object/object-filter-dropdown/components/ObjectFilterDropdownEntitySearchSelect.tsx
index 9e1b2b627..d93bb0d4d 100644
--- a/front/src/modules/ui/object/object-filter-dropdown/components/ObjectFilterDropdownEntitySearchSelect.tsx
+++ b/front/src/modules/ui/object/object-filter-dropdown/components/ObjectFilterDropdownEntitySearchSelect.tsx
@@ -3,6 +3,7 @@ import { useEffect, useState } from 'react';
import { EntitiesForMultipleEntitySelect } from '@/ui/input/relation-picker/components/MultipleEntitySelect';
import { SingleEntitySelectBase } from '@/ui/input/relation-picker/components/SingleEntitySelectBase';
import { EntityForSelect } from '@/ui/input/relation-picker/types/EntityForSelect';
+import { useDropdown } from '@/ui/layout/dropdown/hooks/useDropdown';
import { ViewFilterOperand } from '@/views/types/ViewFilterOperand';
import { useFilter } from '../hooks/useFilter';
@@ -21,9 +22,11 @@ export const ObjectFilterDropdownEntitySearchSelect = ({
selectFilter,
} = useFilter();
+ const { closeDropdown } = useDropdown();
+
const [isAllEntitySelected, setIsAllEntitySelected] = useState(false);
- const handleUserSelected = (
+ const handleRecordSelected = (
selectedEntity: EntityForSelect | null | undefined,
) => {
if (
@@ -39,6 +42,7 @@ export const ObjectFilterDropdownEntitySearchSelect = ({
}
setObjectFilterDropdownSelectedEntityId(selectedEntity.id);
+ closeDropdown();
selectFilter?.({
displayValue: selectedEntity.name,
@@ -69,6 +73,7 @@ export const ObjectFilterDropdownEntitySearchSelect = ({
setIsAllEntitySelected(true);
setObjectFilterDropdownSelectedEntityId(null);
+ closeDropdown();
selectFilter?.({
displayValue: filterDefinitionUsedInDropdown.selectAllLabel,
@@ -100,7 +105,7 @@ export const ObjectFilterDropdownEntitySearchSelect = ({
entitiesToSelect={entitiesForSelect.entitiesToSelect}
selectedEntity={entitiesForSelect.selectedEntities[0]}
loading={entitiesForSelect.loading}
- onEntitySelected={handleUserSelected}
+ onEntitySelected={handleRecordSelected}
SelectAllIcon={filterDefinitionUsedInDropdown?.SelectAllIcon}
selectAllLabel={filterDefinitionUsedInDropdown?.selectAllLabel}
isAllEntitySelected={isAllEntitySelected}
diff --git a/front/src/modules/ui/object/object-filter-dropdown/components/ObjectFilterDropdownEntitySelect.tsx b/front/src/modules/ui/object/object-filter-dropdown/components/ObjectFilterDropdownEntitySelect.tsx
index df846f817..e01825539 100644
--- a/front/src/modules/ui/object/object-filter-dropdown/components/ObjectFilterDropdownEntitySelect.tsx
+++ b/front/src/modules/ui/object/object-filter-dropdown/components/ObjectFilterDropdownEntitySelect.tsx
@@ -1,21 +1,52 @@
-import { DropdownMenuSeparator } from '@/ui/layout/dropdown/components/DropdownMenuSeparator';
-import { RecoilScope } from '@/ui/utilities/recoil-scope/components/RecoilScope';
+import { useQuery } from '@apollo/client';
+
+import { useObjectMetadataItem } from '@/object-metadata/hooks/useObjectMetadataItem';
+import { useFilteredSearchEntityQuery } from '@/search/hooks/useFilteredSearchEntityQuery';
+import { useRelationPicker } from '@/ui/input/components/internal/relation-picker/hooks/useRelationPicker';
+import { ObjectFilterDropdownEntitySearchSelect } from '@/ui/object/object-filter-dropdown/components/ObjectFilterDropdownEntitySearchSelect';
import { useFilter } from '../hooks/useFilter';
export const ObjectFilterDropdownEntitySelect = () => {
- const { filterDefinitionUsedInDropdown } = useFilter();
+ const {
+ filterDefinitionUsedInDropdown,
+ objectFilterDropdownSearchInput,
+ objectFilterDropdownSelectedEntityId,
+ } = useFilter();
- if (filterDefinitionUsedInDropdown?.type !== 'ENTITY') {
+ const { findManyQuery } = useObjectMetadataItem({
+ objectNameSingular: 'company',
+ });
+
+ const useFindManyQuery = (options: any) => useQuery(findManyQuery, options);
+
+ const { identifiersMapper, searchQuery } = useRelationPicker();
+
+ const filteredSearchEntityResults = useFilteredSearchEntityQuery({
+ queryHook: useFindManyQuery,
+ filters: [
+ {
+ fieldNames: searchQuery?.computeFilterFields?.('company') ?? [],
+ filter: objectFilterDropdownSearchInput,
+ },
+ ],
+ orderByField: 'createdAt',
+ selectedIds: objectFilterDropdownSelectedEntityId
+ ? [objectFilterDropdownSelectedEntityId]
+ : [],
+ mappingFunction: (record: any) => identifiersMapper?.(record, 'company'),
+ objectNamePlural: 'companies',
+ });
+
+ if (filterDefinitionUsedInDropdown?.type !== 'RELATION') {
return null;
}
return (
<>
-
-
- {filterDefinitionUsedInDropdown.entitySelectComponent}
-
+
>
);
};
diff --git a/front/src/modules/ui/object/object-filter-dropdown/components/ObjectFilterDropdownFilterSelect.tsx b/front/src/modules/ui/object/object-filter-dropdown/components/ObjectFilterDropdownFilterSelect.tsx
index 91ad36b8e..ec44c2078 100644
--- a/front/src/modules/ui/object/object-filter-dropdown/components/ObjectFilterDropdownFilterSelect.tsx
+++ b/front/src/modules/ui/object/object-filter-dropdown/components/ObjectFilterDropdownFilterSelect.tsx
@@ -21,27 +21,29 @@ export const ObjectFilterDropdownFilterSelect = () => {
return (
- {availableFilterDefinitions.map((availableFilterDefinition, index) => (
-
);
};
diff --git a/front/src/modules/ui/object/object-filter-dropdown/components/SingleEntityObjectFilterDropdownButton.tsx b/front/src/modules/ui/object/object-filter-dropdown/components/SingleEntityObjectFilterDropdownButton.tsx
index a3f799a3b..678cfd0ef 100644
--- a/front/src/modules/ui/object/object-filter-dropdown/components/SingleEntityObjectFilterDropdownButton.tsx
+++ b/front/src/modules/ui/object/object-filter-dropdown/components/SingleEntityObjectFilterDropdownButton.tsx
@@ -25,6 +25,7 @@ export const SingleEntityObjectFilterDropdownButton = ({
selectedFilter,
setFilterDefinitionUsedInDropdown,
setSelectedOperandInDropdown,
+ resetFilter,
} = useFilter();
const availableFilter = availableFilterDefinitions[0];
diff --git a/front/src/modules/ui/object/object-filter-dropdown/hooks/useFilter.ts b/front/src/modules/ui/object/object-filter-dropdown/hooks/useFilter.ts
index 686e38168..7ba1d7f8c 100644
--- a/front/src/modules/ui/object/object-filter-dropdown/hooks/useFilter.ts
+++ b/front/src/modules/ui/object/object-filter-dropdown/hooks/useFilter.ts
@@ -48,6 +48,18 @@ export const useFilter = (props?: UseFilterProps) => {
[setSelectedFilter, onFilterSelect],
);
+ const resetFilter = useCallback(() => {
+ setObjectFilterDropdownSearchInput('');
+ setObjectFilterDropdownSelectedEntityId(null);
+ setSelectedFilter(undefined);
+ setSelectedOperandInDropdown(null);
+ }, [
+ setObjectFilterDropdownSearchInput,
+ setObjectFilterDropdownSelectedEntityId,
+ setSelectedFilter,
+ setSelectedOperandInDropdown,
+ ]);
+
return {
scopeId,
availableFilterDefinitions,
@@ -67,5 +79,6 @@ export const useFilter = (props?: UseFilterProps) => {
selectedOperandInDropdown,
setSelectedOperandInDropdown,
selectFilter,
+ resetFilter,
};
};
diff --git a/front/src/modules/ui/object/object-filter-dropdown/types/FilterType.ts b/front/src/modules/ui/object/object-filter-dropdown/types/FilterType.ts
index 8d3c64cf0..2c182f0a8 100644
--- a/front/src/modules/ui/object/object-filter-dropdown/types/FilterType.ts
+++ b/front/src/modules/ui/object/object-filter-dropdown/types/FilterType.ts
@@ -1,6 +1,10 @@
export type FilterType =
| 'TEXT'
+ | 'PHONE'
+ | 'EMAIL'
| 'DATE_TIME'
- | 'ENTITY'
| 'NUMBER'
- | 'CURRENCY';
+ | 'CURRENCY'
+ | 'FULL_NAME'
+ | 'LINK'
+ | 'RELATION';
diff --git a/front/src/modules/ui/object/object-filter-dropdown/utils/getOperandsForFilterType.ts b/front/src/modules/ui/object/object-filter-dropdown/utils/getOperandsForFilterType.ts
index 752249c20..cd70c9334 100644
--- a/front/src/modules/ui/object/object-filter-dropdown/utils/getOperandsForFilterType.ts
+++ b/front/src/modules/ui/object/object-filter-dropdown/utils/getOperandsForFilterType.ts
@@ -7,12 +7,15 @@ export const getOperandsForFilterType = (
): ViewFilterOperand[] => {
switch (filterType) {
case 'TEXT':
+ case 'EMAIL':
+ case 'FULL_NAME':
+ case 'LINK':
return [ViewFilterOperand.Contains, ViewFilterOperand.DoesNotContain];
case 'CURRENCY':
case 'NUMBER':
case 'DATE_TIME':
return [ViewFilterOperand.GreaterThan, ViewFilterOperand.LessThan];
- case 'ENTITY':
+ case 'RELATION':
return [ViewFilterOperand.Is, ViewFilterOperand.IsNot];
default:
return [];
diff --git a/front/src/modules/ui/object/object-filter-dropdown/utils/turnFiltersIntoWhereClauseV2.ts b/front/src/modules/ui/object/object-filter-dropdown/utils/turnFiltersIntoWhereClauseV2.ts
index f2b5c02b2..504dd79e2 100644
--- a/front/src/modules/ui/object/object-filter-dropdown/utils/turnFiltersIntoWhereClauseV2.ts
+++ b/front/src/modules/ui/object/object-filter-dropdown/utils/turnFiltersIntoWhereClauseV2.ts
@@ -13,7 +13,7 @@ export const turnFiltersIntoWhereClauseV2 = (
filters: FilterToTurnIntoWhereClause[],
fields: Pick[],
) => {
- const whereClause: Record = {};
+ const whereClause: any[] = [];
filters.forEach((filter) => {
const correspondingField = fields.find(
@@ -26,53 +26,25 @@ export const turnFiltersIntoWhereClauseV2 = (
}
switch (filter.definition.type) {
+ case 'EMAIL':
+ case 'PHONE':
case 'TEXT':
switch (filter.operand) {
case ViewFilterOperand.Contains:
- whereClause[correspondingField.name] = {
- eq: filter.value,
- };
+ whereClause.push({
+ [correspondingField.name]: {
+ ilike: `%${filter.value}%`,
+ },
+ });
return;
case ViewFilterOperand.DoesNotContain:
- whereClause[correspondingField.name] = {
+ whereClause.push({
not: {
- eq: filter.value,
+ [correspondingField.name]: {
+ ilike: `%${filter.value}%`,
+ },
},
- };
- return;
- default:
- throw new Error(
- `Unknown operand ${filter.operand} for ${filter.definition.type} filter`,
- );
- }
- case 'NUMBER':
- switch (filter.operand) {
- case ViewFilterOperand.GreaterThan:
- whereClause[correspondingField.name] = {
- gte: parseFloat(filter.value),
- };
- return;
- case ViewFilterOperand.LessThan:
- whereClause[correspondingField.name] = {
- lte: parseFloat(filter.value),
- };
- return;
- default:
- throw new Error(
- `Unknown operand ${filter.operand} for ${filter.definition.type} filter`,
- );
- }
- case 'CURRENCY':
- switch (filter.operand) {
- case ViewFilterOperand.GreaterThan:
- whereClause[correspondingField.name] = {
- amountMicros: { gte: parseFloat(filter.value) * 1000000 },
- };
- return;
- case ViewFilterOperand.LessThan:
- whereClause[correspondingField.name] = {
- amountMicros: { lte: parseFloat(filter.value) * 1000000 },
- };
+ });
return;
default:
throw new Error(
@@ -82,14 +54,159 @@ export const turnFiltersIntoWhereClauseV2 = (
case 'DATE_TIME':
switch (filter.operand) {
case ViewFilterOperand.GreaterThan:
- whereClause[correspondingField.name] = {
- gte: filter.value,
- };
+ whereClause.push({
+ [correspondingField.name]: {
+ gte: filter.value,
+ },
+ });
return;
case ViewFilterOperand.LessThan:
- whereClause[correspondingField.name] = {
- lte: filter.value,
- };
+ whereClause.push({
+ [correspondingField.name]: {
+ lte: filter.value,
+ },
+ });
+ return;
+ default:
+ throw new Error(
+ `Unknown operand ${filter.operand} for ${filter.definition.type} filter`,
+ );
+ }
+ case 'NUMBER':
+ switch (filter.operand) {
+ case ViewFilterOperand.GreaterThan:
+ whereClause.push({
+ [correspondingField.name]: {
+ gte: parseFloat(filter.value),
+ },
+ });
+ return;
+ case ViewFilterOperand.LessThan:
+ whereClause.push({
+ [correspondingField.name]: {
+ lte: parseFloat(filter.value),
+ },
+ });
+ return;
+ default:
+ throw new Error(
+ `Unknown operand ${filter.operand} for ${filter.definition.type} filter`,
+ );
+ }
+ case 'RELATION':
+ switch (filter.operand) {
+ case ViewFilterOperand.Is:
+ whereClause.push({
+ [correspondingField.name + 'Id']: {
+ eq: filter.value,
+ },
+ });
+ return;
+ case ViewFilterOperand.IsNot:
+ whereClause.push({
+ [correspondingField.name + 'Id']: {
+ neq: filter.value,
+ },
+ });
+ return;
+ default:
+ throw new Error(
+ `Unknown operand ${filter.operand} for ${filter.definition.type} filter`,
+ );
+ }
+ case 'CURRENCY':
+ switch (filter.operand) {
+ case ViewFilterOperand.GreaterThan:
+ whereClause.push({
+ [correspondingField.name]: {
+ amountMicros: { gte: parseFloat(filter.value) * 1000000 },
+ },
+ });
+ return;
+ case ViewFilterOperand.LessThan:
+ whereClause.push({
+ [correspondingField.name]: {
+ amountMicros: { lte: parseFloat(filter.value) * 1000000 },
+ },
+ });
+ return;
+ default:
+ throw new Error(
+ `Unknown operand ${filter.operand} for ${filter.definition.type} filter`,
+ );
+ }
+ case 'LINK':
+ switch (filter.operand) {
+ case ViewFilterOperand.Contains:
+ whereClause.push({
+ [correspondingField.name]: {
+ url: {
+ ilike: `%${filter.value}%`,
+ },
+ },
+ });
+ return;
+ case ViewFilterOperand.DoesNotContain:
+ whereClause.push({
+ not: {
+ [correspondingField.name]: {
+ url: {
+ ilike: `%${filter.value}%`,
+ },
+ },
+ },
+ });
+ return;
+ default:
+ throw new Error(
+ `Unknown operand ${filter.operand} for ${filter.definition.type} filter`,
+ );
+ }
+ case 'FULL_NAME':
+ switch (filter.operand) {
+ case ViewFilterOperand.Contains:
+ whereClause.push({
+ or: [
+ {
+ [correspondingField.name]: {
+ firstName: {
+ ilike: `%${filter.value}%`,
+ },
+ },
+ },
+ {
+ [correspondingField.name]: {
+ firstName: {
+ ilike: `%${filter.value}%`,
+ },
+ },
+ },
+ ],
+ });
+ return;
+ case ViewFilterOperand.DoesNotContain:
+ whereClause.push({
+ and: [
+ {
+ not: {
+ [correspondingField.name]: {
+ firstName: {
+ ilike: `%${filter.value}%`,
+ },
+ },
+ },
+ },
+ {
+ not: {
+ [correspondingField.name]: {
+ lastName: {
+ ilike: `%${filter.value}%`,
+ },
+ },
+ },
+ },
+ ],
+ });
return;
default:
throw new Error(
@@ -100,5 +217,6 @@ export const turnFiltersIntoWhereClauseV2 = (
throw new Error('Unknown filter type');
}
});
- return whereClause;
+
+ return { and: whereClause };
};
diff --git a/front/src/modules/views/hooks/internal/useViewFilters.ts b/front/src/modules/views/hooks/internal/useViewFilters.ts
index 96a837c52..9dc152ca7 100644
--- a/front/src/modules/views/hooks/internal/useViewFilters.ts
+++ b/front/src/modules/views/hooks/internal/useViewFilters.ts
@@ -166,7 +166,7 @@ export const useViewFilters = (viewScopeId: string) => {
filter.fieldMetadataId === filterToUpsert.fieldMetadataId,
);
- if (existingFilterIndex === -1) {
+ if (existingFilterIndex === -1 && filterToUpsert.value !== '') {
filtersDraft.push({
...filterToUpsert,
id: existingSavedFilterId,
@@ -174,6 +174,11 @@ export const useViewFilters = (viewScopeId: string) => {
return filtersDraft;
}
+ if (filterToUpsert.value === '') {
+ filtersDraft.splice(existingFilterIndex, 1);
+ return filtersDraft;
+ }
+
filtersDraft[existingFilterIndex] = {
...filterToUpsert,
id: existingSavedFilterId,
diff --git a/front/src/pages/opportunities/constants/opportunityBoardFilterDefinitions.tsx b/front/src/pages/opportunities/constants/opportunityBoardFilterDefinitions.tsx
index 9b71f1969..76c885cf2 100644
--- a/front/src/pages/opportunities/constants/opportunityBoardFilterDefinitions.tsx
+++ b/front/src/pages/opportunities/constants/opportunityBoardFilterDefinitions.tsx
@@ -19,14 +19,12 @@ export const opportunityBoardFilterDefinitions: FilterDefinitionByEntity,
+ type: 'RELATION',
},
{
fieldMetadataId: 'pointOfContactId',
label: 'Point of contact',
iconName: 'IconUser',
- type: 'ENTITY',
- //entitySelectComponent: ,
+ type: 'RELATION',
},
];
diff --git a/front/src/pages/tasks/tasks-filter-definitions.tsx b/front/src/pages/tasks/tasks-filter-definitions.tsx
index 75d637871..27379f175 100644
--- a/front/src/pages/tasks/tasks-filter-definitions.tsx
+++ b/front/src/pages/tasks/tasks-filter-definitions.tsx
@@ -8,7 +8,7 @@ export const tasksFilterDefinitions: FilterDefinitionByEntity[] = [
fieldMetadataId: 'assigneeId',
label: 'Assignee',
iconName: 'IconUser',
- type: 'ENTITY',
+ type: 'RELATION',
entitySelectComponent: ,
selectAllLabel: 'All assignees',
SelectAllIcon: IconUserCircle,