diff --git a/packages/twenty-front/src/modules/object-record/advanced-filter/components/AdvancedFilterAddFilterRuleSelect.tsx b/packages/twenty-front/src/modules/object-record/advanced-filter/components/AdvancedFilterAddFilterRuleSelect.tsx
index 64a0c04f6..018d8cf3b 100644
--- a/packages/twenty-front/src/modules/object-record/advanced-filter/components/AdvancedFilterAddFilterRuleSelect.tsx
+++ b/packages/twenty-front/src/modules/object-record/advanced-filter/components/AdvancedFilterAddFilterRuleSelect.tsx
@@ -1,3 +1,4 @@
+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';
@@ -17,7 +18,6 @@ import { useDropdown } from '@/ui/layout/dropdown/hooks/useDropdown';
import { useGetCurrentViewOnly } from '@/views/hooks/useGetCurrentViewOnly';
import { isDefined } from 'twenty-shared/utils';
import { IconLibraryPlus, IconPlus } from 'twenty-ui/display';
-import { LightButton } from 'twenty-ui/input';
import { MenuItem } from 'twenty-ui/navigation';
import { v4 } from 'uuid';
@@ -137,9 +137,13 @@ export const AdvancedFilterAddFilterRuleSelect = ({
if (!isFilterRuleGroupOptionVisible) {
return (
-
);
@@ -149,7 +153,14 @@ export const AdvancedFilterAddFilterRuleSelect = ({
+
}
dropdownComponents={
diff --git a/packages/twenty-front/src/modules/object-record/advanced-filter/components/AdvancedFilterRecordFilterOperandSelect.tsx b/packages/twenty-front/src/modules/object-record/advanced-filter/components/AdvancedFilterRecordFilterOperandSelect.tsx
index d4c997084..237b2edb6 100644
--- a/packages/twenty-front/src/modules/object-record/advanced-filter/components/AdvancedFilterRecordFilterOperandSelect.tsx
+++ b/packages/twenty-front/src/modules/object-record/advanced-filter/components/AdvancedFilterRecordFilterOperandSelect.tsx
@@ -1,39 +1,23 @@
-import { DEFAULT_ADVANCED_FILTER_DROPDOWN_OFFSET } from '@/object-record/advanced-filter/constants/DefaultAdvancedFilterDropdownOffset';
-import { useApplyObjectFilterDropdownOperand } from '@/object-record/object-filter-dropdown/hooks/useApplyObjectFilterDropdownOperand';
-
+import { AdvancedFilterRecordFilterOperandSelectContent } from '@/object-record/advanced-filter/components/AdvancedFilterRecordFilterOperandSelectContent';
import { getOperandLabel } from '@/object-record/object-filter-dropdown/utils/getOperandLabel';
import { currentRecordFiltersComponentState } from '@/object-record/record-filter/states/currentRecordFiltersComponentState';
import { getRecordFilterOperands } from '@/object-record/record-filter/utils/getRecordFilterOperands';
import { SelectControl } from '@/ui/input/components/SelectControl';
-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 { GenericDropdownContentWidth } from '@/ui/layout/dropdown/constants/GenericDropdownContentWidth';
-import { useDropdown } from '@/ui/layout/dropdown/hooks/useDropdown';
-import { SelectableList } from '@/ui/layout/selectable-list/components/SelectableList';
-import { SelectableListItem } from '@/ui/layout/selectable-list/components/SelectableListItem';
-import { selectedItemIdComponentState } from '@/ui/layout/selectable-list/states/selectedItemIdComponentState';
import { useRecoilComponentValueV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentValueV2';
-import { ViewFilterOperand } from '@/views/types/ViewFilterOperand';
import styled from '@emotion/styled';
import { isDefined } from 'twenty-shared/utils';
-import { MenuItem } from 'twenty-ui/navigation';
-const StyledContainer = styled.div<{ width?: string }>`
- width: ${({ width }) => width ?? '100px'};
+const StyledContainer = styled.div`
+ width: 100px;
`;
type AdvancedFilterRecordFilterOperandSelectProps = {
recordFilterId: string;
- widthFromProps?: string;
};
export const AdvancedFilterRecordFilterOperandSelect = ({
recordFilterId,
- widthFromProps,
}: AdvancedFilterRecordFilterOperandSelectProps) => {
- const dropdownId = `advanced-filter-view-filter-operand-${recordFilterId}`;
-
const currentRecordFilters = useRecoilComponentValueV2(
currentRecordFiltersComponentState,
);
@@ -44,17 +28,6 @@ export const AdvancedFilterRecordFilterOperandSelect = ({
const isDisabled = !filter?.fieldMetadataId;
- const { closeDropdown } = useDropdown(dropdownId);
-
- const { applyObjectFilterDropdownOperand } =
- useApplyObjectFilterDropdownOperand();
-
- const handleOperandChange = (operand: ViewFilterOperand) => {
- closeDropdown();
-
- applyObjectFilterDropdownOperand(operand);
- };
-
const filterType = filter?.type;
const operandsForFilterType = isDefined(filterType)
@@ -64,12 +37,7 @@ export const AdvancedFilterRecordFilterOperandSelect = ({
})
: [];
- const selectedItemId = useRecoilComponentValueV2(
- selectedItemIdComponentState,
- dropdownId,
- );
-
- if (isDisabled === true) {
+ if (isDisabled) {
return (
-
- }
- dropdownComponents={
-
-
- operand,
- )}
- selectableListInstanceId={dropdownId}
- >
- {operandsForFilterType.map((filterOperand, index) => (
- {
- handleOperandChange(filterOperand);
- }}
- >
-
- ))}
-
-
-
- }
- dropdownHotkeyScope={{ scope: dropdownId }}
- dropdownOffset={DEFAULT_ADVANCED_FILTER_DROPDOWN_OFFSET}
- dropdownPlacement="bottom-start"
+
+
);
diff --git a/packages/twenty-front/src/modules/object-record/advanced-filter/components/AdvancedFilterRecordFilterOperandSelectContent.tsx b/packages/twenty-front/src/modules/object-record/advanced-filter/components/AdvancedFilterRecordFilterOperandSelectContent.tsx
new file mode 100644
index 000000000..45c825ccc
--- /dev/null
+++ b/packages/twenty-front/src/modules/object-record/advanced-filter/components/AdvancedFilterRecordFilterOperandSelectContent.tsx
@@ -0,0 +1,98 @@
+import { DEFAULT_ADVANCED_FILTER_DROPDOWN_OFFSET } from '@/object-record/advanced-filter/constants/DefaultAdvancedFilterDropdownOffset';
+import { useApplyObjectFilterDropdownOperand } from '@/object-record/object-filter-dropdown/hooks/useApplyObjectFilterDropdownOperand';
+
+import { getOperandLabel } from '@/object-record/object-filter-dropdown/utils/getOperandLabel';
+import { RecordFilter } from '@/object-record/record-filter/types/RecordFilter';
+import { RecordFilterOperand } from '@/object-record/record-filter/types/RecordFilterOperand';
+import { SelectControl } from '@/ui/input/components/SelectControl';
+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 { GenericDropdownContentWidth } from '@/ui/layout/dropdown/constants/GenericDropdownContentWidth';
+import { useDropdown } from '@/ui/layout/dropdown/hooks/useDropdown';
+import { SelectableList } from '@/ui/layout/selectable-list/components/SelectableList';
+import { SelectableListItem } from '@/ui/layout/selectable-list/components/SelectableListItem';
+import { selectedItemIdComponentState } from '@/ui/layout/selectable-list/states/selectedItemIdComponentState';
+import { useRecoilComponentValueV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentValueV2';
+import { ViewFilterOperand } from '@/views/types/ViewFilterOperand';
+import { MenuItem } from 'twenty-ui/navigation';
+
+type AdvancedFilterRecordFilterOperandSelectContentProps = {
+ recordFilterId: string;
+ filter: RecordFilter;
+ operandsForFilterType: readonly RecordFilterOperand[];
+};
+
+export const AdvancedFilterRecordFilterOperandSelectContent = ({
+ recordFilterId,
+ filter,
+ operandsForFilterType,
+}: AdvancedFilterRecordFilterOperandSelectContentProps) => {
+ const dropdownId = `advanced-filter-view-filter-operand-${recordFilterId}`;
+
+ const { closeDropdown } = useDropdown(dropdownId);
+
+ const { applyObjectFilterDropdownOperand } =
+ useApplyObjectFilterDropdownOperand();
+
+ const handleOperandChange = (operand: ViewFilterOperand) => {
+ closeDropdown();
+
+ applyObjectFilterDropdownOperand(operand);
+ };
+
+ const selectedItemId = useRecoilComponentValueV2(
+ selectedItemIdComponentState,
+ dropdownId,
+ );
+
+ return (
+
+ }
+ dropdownComponents={
+
+
+ operand,
+ )}
+ selectableListInstanceId={dropdownId}
+ >
+ {operandsForFilterType.map((filterOperand, index) => (
+ {
+ handleOperandChange(filterOperand);
+ }}
+ >
+
+ ))}
+
+
+
+ }
+ dropdownHotkeyScope={{ scope: dropdownId }}
+ dropdownOffset={DEFAULT_ADVANCED_FILTER_DROPDOWN_OFFSET}
+ dropdownPlacement="bottom-start"
+ />
+ );
+};
diff --git a/packages/twenty-front/src/modules/object-record/record-field/form-types/components/FormCountryMultiSelectInput.tsx b/packages/twenty-front/src/modules/object-record/record-field/form-types/components/FormCountryMultiSelectInput.tsx
new file mode 100644
index 000000000..28d6422cd
--- /dev/null
+++ b/packages/twenty-front/src/modules/object-record/record-field/form-types/components/FormCountryMultiSelectInput.tsx
@@ -0,0 +1,58 @@
+import { useMemo } from 'react';
+
+import { FormMultiSelectFieldInput } from '@/object-record/record-field/form-types/components/FormMultiSelectFieldInput';
+import { VariablePickerComponent } from '@/object-record/record-field/form-types/types/VariablePickerComponent';
+import { FieldMultiSelectValue } from '@/object-record/record-field/types/FieldMetadata';
+import { useCountries } from '@/ui/input/components/internal/hooks/useCountries';
+import { IconComponentProps } from 'twenty-ui/display';
+import { SelectOption } from 'twenty-ui/input';
+
+export const FormCountryMultiSelectInput = ({
+ onChange,
+ defaultValue,
+ label,
+ readonly = false,
+ VariablePicker,
+}: {
+ onChange: (value: string | FieldMultiSelectValue) => void;
+ defaultValue?: string | FieldMultiSelectValue;
+ label?: string;
+ readonly?: boolean;
+ VariablePicker?: VariablePickerComponent;
+}) => {
+ const countries = useCountries();
+
+ const options: SelectOption[] = useMemo(
+ () =>
+ countries.map(({ countryName, Flag }) => ({
+ label: countryName,
+ value: countryName,
+ Icon: (props: IconComponentProps) =>
+ Flag({ width: props.size, height: props.size }),
+ })),
+ [countries],
+ );
+
+ const onCountryChange = (value: string | FieldMultiSelectValue) => {
+ if (readonly) {
+ return;
+ }
+
+ if (value === null) {
+ onChange('');
+ } else {
+ onChange(value);
+ }
+ };
+
+ return (
+
+ );
+};
diff --git a/packages/twenty-front/src/modules/object-record/record-filter/utils/compute-record-gql-operation-filter/turnRecordFilterIntoGqlOperationFilter.ts b/packages/twenty-front/src/modules/object-record/record-filter/utils/compute-record-gql-operation-filter/turnRecordFilterIntoGqlOperationFilter.ts
index 88628f587..82a53e4d5 100644
--- a/packages/twenty-front/src/modules/object-record/record-filter/utils/compute-record-gql-operation-filter/turnRecordFilterIntoGqlOperationFilter.ts
+++ b/packages/twenty-front/src/modules/object-record/record-filter/utils/compute-record-gql-operation-filter/turnRecordFilterIntoGqlOperationFilter.ts
@@ -367,7 +367,9 @@ export const turnRecordFilterIntoRecordGqlOperationFilter = ({
subFieldName,
)
) {
- const parsedCurrencyCodes = JSON.parse(recordFilter.value) as string[];
+ const parsedCurrencyCodes = arrayOfStringsOrVariablesSchema.parse(
+ recordFilter.value,
+ );
if (parsedCurrencyCodes.length === 0) return undefined;
@@ -543,14 +545,11 @@ export const turnRecordFilterIntoRecordGqlOperationFilter = ({
};
} else {
if (subFieldName === 'addressCountry') {
- const parsedCountryCodes = JSON.parse(
+ const parsedCountryCodes = arrayOfStringsOrVariablesSchema.parse(
recordFilter.value,
- ) as string[];
+ );
- if (
- recordFilter.value === '[]' ||
- parsedCountryCodes.length === 0
- ) {
+ if (parsedCountryCodes.length === 0) {
return {};
}
diff --git a/packages/twenty-front/src/modules/object-record/record-filter/utils/getRecordFilterOperands.ts b/packages/twenty-front/src/modules/object-record/record-filter/utils/getRecordFilterOperands.ts
index c3d83330c..ab8585598 100644
--- a/packages/twenty-front/src/modules/object-record/record-filter/utils/getRecordFilterOperands.ts
+++ b/packages/twenty-front/src/modules/object-record/record-filter/utils/getRecordFilterOperands.ts
@@ -150,7 +150,7 @@ export const COMPOSITE_FIELD_FILTER_OPERANDS_MAP = {
export const getRecordFilterOperands = ({
filterType,
subFieldName,
-}: GetRecordFilterOperandsParams) => {
+}: GetRecordFilterOperandsParams): readonly RecordFilterOperand[] => {
switch (filterType) {
case 'TEXT':
case 'EMAILS':
diff --git a/packages/twenty-front/src/modules/workflow/workflow-steps/workflow-actions/find-records-action/components/WorkflowAdvancedFilterRecordFilterColumn.tsx b/packages/twenty-front/src/modules/workflow/workflow-steps/workflow-actions/find-records-action/components/WorkflowAdvancedFilterRecordFilterColumn.tsx
index 17ca45ca6..c0aeacf31 100644
--- a/packages/twenty-front/src/modules/workflow/workflow-steps/workflow-actions/find-records-action/components/WorkflowAdvancedFilterRecordFilterColumn.tsx
+++ b/packages/twenty-front/src/modules/workflow/workflow-steps/workflow-actions/find-records-action/components/WorkflowAdvancedFilterRecordFilterColumn.tsx
@@ -1,5 +1,4 @@
import { AdvancedFilterFieldSelectDropdownButton } from '@/object-record/advanced-filter/components/AdvancedFilterFieldSelectDropdownButton';
-import { AdvancedFilterRecordFilterOperandSelect } from '@/object-record/advanced-filter/components/AdvancedFilterRecordFilterOperandSelect';
import { AdvancedFilterRecordFilterOptionsDropdown } from '@/object-record/advanced-filter/components/AdvancedFilterRecordFilterOptionsDropdown';
import { getAdvancedFilterObjectFilterDropdownComponentInstanceId } from '@/object-record/advanced-filter/utils/getAdvancedFilterObjectFilterDropdownComponentInstanceId';
import { ObjectFilterDropdownComponentInstanceContext } from '@/object-record/object-filter-dropdown/states/contexts/ObjectFilterDropdownComponentInstanceContext';
@@ -8,6 +7,7 @@ import { RecordFilter } from '@/object-record/record-filter/types/RecordFilter';
import { WorkflowAdvancedFilterDropdownColumn } from '@/workflow/workflow-steps/workflow-actions/find-records-action/components/WorkflowAdvancedFilterDropdownColumn';
import { WorkflowAdvancedFilterValueFormInput } from '@/workflow/workflow-steps/workflow-actions/find-records-action/components/WorkflowAdvancedFilterFormInput';
import { WorkflowAdvancedFilterLogicalOperatorCell } from '@/workflow/workflow-steps/workflow-actions/find-records-action/components/WorkflowAdvancedFilterLogicalOperatorCell';
+import { WorkflowAdvancedFilterRecordFilterOperandSelect } from '@/workflow/workflow-steps/workflow-actions/find-records-action/components/WorkflowAdvancedFilterRecordFilterOperandSelect';
import styled from '@emotion/styled';
const StyledContainer = styled.div`
@@ -47,9 +47,8 @@ export const WorkflowAdvancedFilterRecordFilterColumn = ({
-
{
+ const currentRecordFilters = useRecoilComponentValueV2(
+ currentRecordFiltersComponentState,
+ );
+
+ const filter = currentRecordFilters.find(
+ (recordFilter) => recordFilter.id === recordFilterId,
+ );
+
+ const isDisabled = !filter?.fieldMetadataId;
+
+ const filterType = filter?.type;
+
+ const operandsForFilterType = isDefined(filterType)
+ ? getRecordFilterOperands({
+ filterType,
+ subFieldName: filter?.subFieldName,
+ }).filter((operand) => operand !== RecordFilterOperand.IsRelative)
+ : [];
+
+ if (isDisabled) {
+ return (
+
+ );
+ }
+
+ return (
+
+ );
+};
diff --git a/packages/twenty-front/src/modules/workflow/workflow-steps/workflow-actions/find-records-action/components/WorkflowAdvancedFilterValueFormCompositeFieldInput.tsx b/packages/twenty-front/src/modules/workflow/workflow-steps/workflow-actions/find-records-action/components/WorkflowAdvancedFilterValueFormCompositeFieldInput.tsx
index 3542ee53f..7b4bbc65d 100644
--- a/packages/twenty-front/src/modules/workflow/workflow-steps/workflow-actions/find-records-action/components/WorkflowAdvancedFilterValueFormCompositeFieldInput.tsx
+++ b/packages/twenty-front/src/modules/workflow/workflow-steps/workflow-actions/find-records-action/components/WorkflowAdvancedFilterValueFormCompositeFieldInput.tsx
@@ -1,9 +1,10 @@
import { subFieldNameUsedInDropdownComponentState } from '@/object-record/object-filter-dropdown/states/subFieldNameUsedInDropdownComponentState';
-import { FormCountryCodeSelectInput } from '@/object-record/record-field/form-types/components/FormCountryCodeSelectInput';
-import { FormCountrySelectInput } from '@/object-record/record-field/form-types/components/FormCountrySelectInput';
+import { FormCountryMultiSelectInput } from '@/object-record/record-field/form-types/components/FormCountryMultiSelectInput';
+import { FormMultiSelectFieldInput } from '@/object-record/record-field/form-types/components/FormMultiSelectFieldInput';
import { FormNumberFieldInput } from '@/object-record/record-field/form-types/components/FormNumberFieldInput';
import { FormTextFieldInput } from '@/object-record/record-field/form-types/components/FormTextFieldInput';
import { RecordFilter } from '@/object-record/record-filter/types/RecordFilter';
+import { CURRENCIES } from '@/settings/data-model/constants/Currencies';
import { useRecoilComponentValueV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentValueV2';
import { WorkflowVariablePicker } from '@/workflow/workflow-variables/components/WorkflowVariablePicker';
import { JsonValue } from 'type-fest';
@@ -25,8 +26,8 @@ export const WorkflowAdvancedFilterValueFormCompositeFieldInput = ({
<>
{filterType === 'ADDRESS' ? (
subFieldNameUsedInDropdown === 'addressCountry' ? (
-
@@ -39,10 +40,11 @@ export const WorkflowAdvancedFilterValueFormCompositeFieldInput = ({
)
) : filterType === 'CURRENCY' ? (
recordFilter.subFieldName === 'currencyCode' ? (
-
) : recordFilter.subFieldName === 'amountMicros' ? (