Enable find records action + Implement readonly (#12636)

- Add readonly in context
- Avoid using it in AdvancedFilters component directly. Keeping it
workflow related

<img width="495" alt="Capture d’écran 2025-06-16 à 18 23 34"
src="https://github.com/user-attachments/assets/dfdfdb71-d5a9-4eed-8938-b06790c62bcd"
/>
This commit is contained in:
Thomas Trompette
2025-06-17 11:02:13 +02:00
committed by GitHub
parent 18d154282e
commit f7396e3531
15 changed files with 183 additions and 71 deletions

View File

@ -1,13 +1,5 @@
import { useGetFieldMetadataItemById } from '@/object-metadata/hooks/useGetFieldMetadataItemById';
import { getCompositeSubFieldLabel } from '@/object-record/object-filter-dropdown/utils/getCompositeSubFieldLabel';
import { isCompositeFieldType } from '@/object-record/object-filter-dropdown/utils/isCompositeFieldType';
import { currentRecordFiltersComponentState } from '@/object-record/record-filter/states/currentRecordFiltersComponentState';
import { isValidSubFieldName } from '@/settings/data-model/utils/isValidSubFieldName';
import { useRecordFilterField } from '@/object-record/advanced-filter/hooks/useRecordFilterField';
import { SelectControl } from '@/ui/input/components/SelectControl';
import { useRecoilComponentValueV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentValueV2';
import { isNonEmptyString } from '@sniptt/guards';
import { isDefined } from 'twenty-shared/utils';
import { useIcons } from 'twenty-ui/display';
type AdvancedFilterFieldSelectDropdownButtonClickableSelectProps = {
recordFilterId: string;
@ -16,47 +8,14 @@ type AdvancedFilterFieldSelectDropdownButtonClickableSelectProps = {
export const AdvancedFilterFieldSelectDropdownButtonClickableSelect = ({
recordFilterId,
}: AdvancedFilterFieldSelectDropdownButtonClickableSelectProps) => {
const currentRecordFilters = useRecoilComponentValueV2(
currentRecordFiltersComponentState,
);
const recordFilter = currentRecordFilters.find(
(recordFilter) => recordFilter.id === recordFilterId,
);
const { getFieldMetadataItemById } = useGetFieldMetadataItemById();
const fieldMetadataItem = isNonEmptyString(recordFilter?.fieldMetadataId)
? getFieldMetadataItemById(recordFilter?.fieldMetadataId)
: undefined;
const { getIcon } = useIcons();
const fieldIcon = isDefined(fieldMetadataItem?.icon)
? getIcon(fieldMetadataItem?.icon)
: undefined;
const subFieldLabel =
isDefined(fieldMetadataItem) &&
isCompositeFieldType(fieldMetadataItem.type) &&
isNonEmptyString(recordFilter?.subFieldName) &&
isValidSubFieldName(recordFilter.subFieldName)
? getCompositeSubFieldLabel(
fieldMetadataItem.type,
recordFilter.subFieldName,
)
: '';
const fieldNameLabel = isNonEmptyString(subFieldLabel)
? `${recordFilter?.label} / ${subFieldLabel}`
: (recordFilter?.label ?? '');
const { label, icon } = useRecordFilterField(recordFilterId);
return (
<SelectControl
selectedOption={{
label: fieldNameLabel,
label,
value: null,
Icon: fieldIcon,
Icon: icon,
}}
/>
);

View File

@ -0,0 +1,51 @@
import { useGetFieldMetadataItemById } from '@/object-metadata/hooks/useGetFieldMetadataItemById';
import { getCompositeSubFieldLabel } from '@/object-record/object-filter-dropdown/utils/getCompositeSubFieldLabel';
import { isCompositeFieldType } from '@/object-record/object-filter-dropdown/utils/isCompositeFieldType';
import { currentRecordFiltersComponentState } from '@/object-record/record-filter/states/currentRecordFiltersComponentState';
import { isValidSubFieldName } from '@/settings/data-model/utils/isValidSubFieldName';
import { useRecoilComponentValueV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentValueV2';
import { isNonEmptyString } from '@sniptt/guards';
import { isDefined } from 'twenty-shared/utils';
import { useIcons } from 'twenty-ui/display';
export const useRecordFilterField = (recordFilterId: string) => {
const currentRecordFilters = useRecoilComponentValueV2(
currentRecordFiltersComponentState,
);
const recordFilter = currentRecordFilters.find(
(recordFilter) => recordFilter.id === recordFilterId,
);
const { getFieldMetadataItemById } = useGetFieldMetadataItemById();
const fieldMetadataItem = isNonEmptyString(recordFilter?.fieldMetadataId)
? getFieldMetadataItemById(recordFilter?.fieldMetadataId)
: undefined;
const { getIcon } = useIcons();
const icon = isDefined(fieldMetadataItem?.icon)
? getIcon(fieldMetadataItem?.icon)
: undefined;
const subFieldLabel =
isDefined(fieldMetadataItem) &&
isCompositeFieldType(fieldMetadataItem.type) &&
isNonEmptyString(recordFilter?.subFieldName) &&
isValidSubFieldName(recordFilter.subFieldName)
? getCompositeSubFieldLabel(
fieldMetadataItem.type,
recordFilter.subFieldName,
)
: '';
const label = isNonEmptyString(subFieldLabel)
? `${recordFilter?.label} / ${subFieldLabel}`
: (recordFilter?.label ?? '');
return {
label,
icon,
};
};

View File

@ -3,6 +3,7 @@ import { createContext } from 'react';
type AdvancedFilterContextType = {
onUpdate?: () => void;
isWorkflowFindRecords?: boolean;
readonly?: boolean;
};
export const AdvancedFilterContext = createContext<AdvancedFilterContextType>(