Fix/close filter by enter (#16643)

Fixes #16636 

Added useCloseDropdown() hook and set onEnter prop to
onEnter={closeDropDown()} using dropdownID

EDIT from @charlesBochet after refactoring:
- ObjectDropdownFilters are used in 3 places: Main Filter menu,
EditableChip, AdvancedFilters
- deprecate vectorSearch in view filter area, we are not using them, we
are doing a anyField filter now. While refactoring the points below, I
did not want to maintain vectorSearch as it was not used anymore
- stop confusing the dropdownId (which is an id to interact with a
specific dropdown) and componentInstanceIds (which is used to scope
component states) for EditableFilter case
- I haven't fixed the confusion for MainFilter case
- It was already handled for AdvancedFilter case

---------

Co-authored-by: Charles Bochet <charles@twenty.com>
Co-authored-by: Lucas Bordeau <bordeau.lucas@gmail.com>
This commit is contained in:
Manikanth Martha
2025-12-18 19:55:56 +05:30
committed by GitHub
parent 52cf3775b3
commit 4bdd866a20
58 changed files with 183 additions and 537 deletions
@@ -49,12 +49,8 @@ export const AdvancedFilterDropdownFilterInput = ({
<AdvancedFilterDropdownTextInput recordFilter={recordFilter} />
))}
{filterType === 'RATING' && <ObjectFilterDropdownRatingInput />}
{filterType === 'DATE_TIME' && (
<ObjectFilterDropdownDateTimeInput instanceId={filterDropdownId} />
)}
{filterType === 'DATE' && (
<ObjectFilterDropdownDateInput instanceId={filterDropdownId} />
)}
{filterType === 'DATE_TIME' && <ObjectFilterDropdownDateTimeInput />}
{filterType === 'DATE' && <ObjectFilterDropdownDateInput />}
{filterType === 'RELATION' && (
<DropdownContent widthInPixels={GenericDropdownContentWidth.ExtraLarge}>
<ObjectFilterDropdownSearchInput />
@@ -69,7 +65,7 @@ export const AdvancedFilterDropdownFilterInput = ({
(isActorSourceCompositeFilter ? (
<ObjectFilterDropdownSourceSelect dropdownId={filterDropdownId} />
) : (
<ObjectFilterDropdownTextInput />
<ObjectFilterDropdownTextInput filterDropdownId={filterDropdownId} />
))}
{['SELECT', 'MULTI_SELECT'].includes(filterType) && (
<DropdownContent widthInPixels={GenericDropdownContentWidth.ExtraLarge}>
@@ -0,0 +1 @@
export const SEARCH_VECTOR_FIELD_NAME = 'searchVector';
@@ -21,13 +21,7 @@ import {
import { dateLocaleState } from '~/localization/states/dateLocaleState';
import { formatDateString } from '~/utils/string/formatDateString';
type ObjectFilterDropdownDateInputProps = {
instanceId: string;
};
export const ObjectFilterDropdownDateInput = ({
instanceId,
}: ObjectFilterDropdownDateInputProps) => {
export const ObjectFilterDropdownDateInput = () => {
const { dateFormat, timeZone } = useContext(UserContext);
const dateLocale = useRecoilValue(dateLocaleState);
const currentWorkspaceMember = useRecoilValue(currentWorkspaceMemberState);
@@ -112,7 +106,7 @@ export const ObjectFilterDropdownDateInput = ({
return (
<DatePicker
instanceId={instanceId}
instanceId={`object-filter-dropdown-date-input`}
relativeDate={relativeDate}
isRelative={isRelativeOperand}
date={plainDateValue ?? null}
@@ -21,13 +21,7 @@ import {
import { dateLocaleState } from '~/localization/states/dateLocaleState';
import { formatDateTimeString } from '~/utils/string/formatDateTimeString';
type ObjectFilterDropdownDateTimeInputProps = {
instanceId: string;
};
export const ObjectFilterDropdownDateTimeInput = ({
instanceId,
}: ObjectFilterDropdownDateTimeInputProps) => {
export const ObjectFilterDropdownDateTimeInput = () => {
const { dateFormat, timeFormat, timeZone } = useContext(UserContext);
const dateLocale = useRecoilValue(dateLocaleState);
const currentWorkspaceMember = useRecoilValue(currentWorkspaceMemberState);
@@ -115,7 +109,7 @@ export const ObjectFilterDropdownDateTimeInput = ({
return (
<DateTimePicker
instanceId={instanceId}
instanceId={`object-filter-dropdown-date-time-input`}
relativeDate={relativeDate}
isRelative={isRelativeOperand}
date={internalDate}
@@ -12,7 +12,6 @@ import { ObjectFilterDropdownBooleanSelect } from '@/object-record/object-filter
import { ObjectFilterDropdownDateTimeInput } from '@/object-record/object-filter-dropdown/components/ObjectFilterDropdownDateTimeInput';
import { ObjectFilterDropdownInnerSelectOperandDropdown } from '@/object-record/object-filter-dropdown/components/ObjectFilterDropdownInnerSelectOperandDropdown';
import { ObjectFilterDropdownTextInput } from '@/object-record/object-filter-dropdown/components/ObjectFilterDropdownTextInput';
import { ObjectFilterDropdownVectorSearchInput } from '@/object-record/object-filter-dropdown/components/ObjectFilterDropdownVectorSearchInput';
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 { fieldMetadataItemUsedInDropdownComponentSelector } from '@/object-record/object-filter-dropdown/states/fieldMetadataItemUsedInDropdownComponentSelector';
@@ -31,12 +30,10 @@ export const ObjectFilterDropdownFilterInput = ({
}: ObjectFilterDropdownFilterInputProps) => {
const fieldMetadataItemUsedInDropdown = useRecoilComponentValue(
fieldMetadataItemUsedInDropdownComponentSelector,
filterDropdownId,
);
const selectedOperandInDropdown = useRecoilComponentValue(
selectedOperandInDropdownComponentState,
filterDropdownId,
);
const isOperandWithFilterValue =
@@ -54,13 +51,6 @@ export const ObjectFilterDropdownFilterInput = ({
ViewFilterOperand.IS_RELATIVE,
].includes(selectedOperandInDropdown);
const isVectorSearchFilter =
selectedOperandInDropdown === ViewFilterOperand.VECTOR_SEARCH;
if (isVectorSearchFilter && isDefined(filterDropdownId)) {
return <ObjectFilterDropdownVectorSearchInput />;
}
if (!isDefined(fieldMetadataItemUsedInDropdown)) {
return null;
}
@@ -82,7 +72,7 @@ export const ObjectFilterDropdownFilterInput = ({
<>
<ObjectFilterDropdownInnerSelectOperandDropdown />
<DropdownMenuSeparator />
<ObjectFilterDropdownDateInput instanceId={filterDropdownId} />
<ObjectFilterDropdownDateInput />
</>
);
} else if (filterType === 'DATE_TIME') {
@@ -90,7 +80,7 @@ export const ObjectFilterDropdownFilterInput = ({
<>
<ObjectFilterDropdownInnerSelectOperandDropdown />
<DropdownMenuSeparator />
<ObjectFilterDropdownDateTimeInput instanceId={filterDropdownId} />
<ObjectFilterDropdownDateTimeInput />
</>
);
} else {
@@ -99,10 +89,12 @@ export const ObjectFilterDropdownFilterInput = ({
<ObjectFilterDropdownInnerSelectOperandDropdown />
<DropdownMenuSeparator />
{TEXT_FILTER_TYPES.includes(filterType) && (
<ObjectFilterDropdownTextInput />
<ObjectFilterDropdownTextInput filterDropdownId={filterDropdownId} />
)}
{NUMBER_FILTER_TYPES.includes(filterType) && (
<ObjectFilterDropdownNumberInput />
<ObjectFilterDropdownNumberInput
filterDropdownId={filterDropdownId}
/>
)}
{filterType === 'RATING' && <ObjectFilterDropdownRatingInput />}
{filterType === 'RELATION' && (
@@ -115,9 +107,17 @@ export const ObjectFilterDropdownFilterInput = ({
/>
</>
)}
{filterType === 'ACTOR' && <ObjectFilterDropdownTextInput />}
{filterType === 'ADDRESS' && <ObjectFilterDropdownTextInput />}
{filterType === 'CURRENCY' && <ObjectFilterDropdownNumberInput />}
{filterType === 'ACTOR' && (
<ObjectFilterDropdownTextInput filterDropdownId={filterDropdownId} />
)}
{filterType === 'ADDRESS' && (
<ObjectFilterDropdownTextInput filterDropdownId={filterDropdownId} />
)}
{filterType === 'CURRENCY' && (
<ObjectFilterDropdownNumberInput
filterDropdownId={filterDropdownId}
/>
)}
{['SELECT', 'MULTI_SELECT'].includes(filterType) && (
<>
<ObjectFilterDropdownSearchInput />
@@ -1,28 +1,20 @@
import { fieldMetadataItemUsedInDropdownComponentSelector } from '@/object-record/object-filter-dropdown/states/fieldMetadataItemUsedInDropdownComponentSelector';
import { selectedOperandInDropdownComponentState } from '@/object-record/object-filter-dropdown/states/selectedOperandInDropdownComponentState';
import { DropdownMenuHeader } from '@/ui/layout/dropdown/components/DropdownMenuHeader/DropdownMenuHeader';
import { DropdownMenuHeaderLeftComponent } from '@/ui/layout/dropdown/components/DropdownMenuHeader/internal/DropdownMenuHeaderLeftComponent';
import { DropdownComponentInstanceContext } from '@/ui/layout/dropdown/contexts/DropdownComponentInstanceContext';
import { useCloseDropdown } from '@/ui/layout/dropdown/hooks/useCloseDropdown';
import { useRecoilComponentValue } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentValue';
import { ViewBarFilterDropdownFilterInputMenuHeader } from '@/views/components/ViewBarFilterDropdownFilterInputMenuHeader';
import { VIEW_BAR_FILTER_DROPDOWN_ID } from '@/views/constants/ViewBarFilterDropdownId';
import { useLingui } from '@lingui/react/macro';
import { ViewBarFilterDropdownIds } from '@/views/constants/ViewBarFilterDropdownIds';
import { useContext } from 'react';
import { ViewFilterOperand } from 'twenty-shared/types';
import { IconX } from 'twenty-ui/display';
// TODO: we shouldn't guess in which parent we are, this should be splitted in two components, one for each case
export const ObjectFilterDropdownFilterInputHeader = () => {
const { t } = useLingui();
const fieldMetadataItemUsedInDropdown = useRecoilComponentValue(
fieldMetadataItemUsedInDropdownComponentSelector,
);
const selectedOperandInDropdown = useRecoilComponentValue(
selectedOperandInDropdownComponentState,
);
const { closeDropdown } = useCloseDropdown();
const dropdownInstanceId = useContext(
@@ -30,10 +22,7 @@ export const ObjectFilterDropdownFilterInputHeader = () => {
)?.instanceId;
const isInViewBarFilterDropdown =
dropdownInstanceId === VIEW_BAR_FILTER_DROPDOWN_ID;
const isVectorSearchFilter =
selectedOperandInDropdown === ViewFilterOperand.VECTOR_SEARCH;
dropdownInstanceId === ViewBarFilterDropdownIds.MAIN;
if (isInViewBarFilterDropdown) {
return <ViewBarFilterDropdownFilterInputMenuHeader />;
@@ -47,9 +36,7 @@ export const ObjectFilterDropdownFilterInputHeader = () => {
/>
}
>
{isVectorSearchFilter
? t`Search`
: fieldMetadataItemUsedInDropdown?.label}
{fieldMetadataItemUsedInDropdown?.label}
</DropdownMenuHeader>
);
}
@@ -5,9 +5,16 @@ import { useObjectFilterDropdownFilterValue } from '@/object-record/object-filte
import { fieldMetadataItemUsedInDropdownComponentSelector } from '@/object-record/object-filter-dropdown/states/fieldMetadataItemUsedInDropdownComponentSelector';
import { DropdownMenuInput } from '@/ui/layout/dropdown/components/DropdownMenuInput';
import { DropdownMenuItemsContainer } from '@/ui/layout/dropdown/components/DropdownMenuItemsContainer';
import { useCloseDropdown } from '@/ui/layout/dropdown/hooks/useCloseDropdown';
import { useRecoilComponentValue } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentValue';
export const ObjectFilterDropdownNumberInput = () => {
type ObjectFilterDropdownNumberInputProps = {
filterDropdownId: string;
};
export const ObjectFilterDropdownNumberInput = ({
filterDropdownId,
}: ObjectFilterDropdownNumberInputProps) => {
const fieldMetadataItemUsedInDropdown = useRecoilComponentValue(
fieldMetadataItemUsedInDropdownComponentSelector,
);
@@ -18,6 +25,8 @@ export const ObjectFilterDropdownNumberInput = () => {
const { applyObjectFilterDropdownFilterValue } =
useApplyObjectFilterDropdownFilterValue();
const { closeDropdown } = useCloseDropdown();
const [hasFocused, setHasFocused] = useState(false);
const handleInputRef = useCallback(
@@ -40,13 +49,14 @@ export const ObjectFilterDropdownNumberInput = () => {
return (
<DropdownMenuItemsContainer>
<DropdownMenuInput
instanceId="object-filter-dropdown-number-input"
instanceId={filterDropdownId}
ref={handleInputRef}
value={objectFilterDropdownFilterValue}
autoFocus
type="number"
placeholder={fieldMetadataItemUsedInDropdown?.label}
onChange={handleInputChange}
onEnter={() => closeDropdown(filterDropdownId)}
/>
</DropdownMenuItemsContainer>
);
@@ -5,9 +5,16 @@ import { useObjectFilterDropdownFilterValue } from '@/object-record/object-filte
import { fieldMetadataItemUsedInDropdownComponentSelector } from '@/object-record/object-filter-dropdown/states/fieldMetadataItemUsedInDropdownComponentSelector';
import { DropdownMenuInput } from '@/ui/layout/dropdown/components/DropdownMenuInput';
import { DropdownMenuItemsContainer } from '@/ui/layout/dropdown/components/DropdownMenuItemsContainer';
import { useCloseDropdown } from '@/ui/layout/dropdown/hooks/useCloseDropdown';
import { useRecoilComponentValue } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentValue';
export const ObjectFilterDropdownTextInput = () => {
type ObjectFilterDropdownTextInputProps = {
filterDropdownId: string;
};
export const ObjectFilterDropdownTextInput = ({
filterDropdownId,
}: ObjectFilterDropdownTextInputProps) => {
const fieldMetadataItemUsedInDropdown = useRecoilComponentValue(
fieldMetadataItemUsedInDropdownComponentSelector,
);
@@ -18,6 +25,8 @@ export const ObjectFilterDropdownTextInput = () => {
const { applyObjectFilterDropdownFilterValue } =
useApplyObjectFilterDropdownFilterValue();
const { closeDropdown } = useCloseDropdown();
const [hasFocused, setHasFocused] = useState(false);
const handleInputRef = useCallback(
@@ -40,13 +49,16 @@ export const ObjectFilterDropdownTextInput = () => {
return (
<DropdownMenuItemsContainer>
<DropdownMenuInput
instanceId="object-filter-dropdown-text-input"
instanceId={filterDropdownId}
ref={handleInputRef}
value={objectFilterDropdownFilterValue ?? ''}
autoFocus
type="text"
placeholder={fieldMetadataItemUsedInDropdown?.label}
onChange={handleInputChange}
onEnter={() => {
closeDropdown(filterDropdownId);
}}
/>
</DropdownMenuItemsContainer>
);
@@ -1,38 +0,0 @@
import { DropdownMenuSearchInput } from '@/ui/layout/dropdown/components/DropdownMenuSearchInput';
import { useRecoilComponentState } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentState';
import { useVectorSearchFilterActions } from '@/views/hooks/useVectorSearchFilterActions';
import { vectorSearchInputComponentState } from '@/views/states/vectorSearchInputComponentState';
import { useLingui } from '@lingui/react/macro';
import { useDebouncedCallback } from 'use-debounce';
export const ObjectFilterDropdownVectorSearchInput = () => {
const { t } = useLingui();
const [vectorSearchInputValue, setVectorSearchInputValue] =
useRecoilComponentState(vectorSearchInputComponentState);
const { applyVectorSearchFilter } = useVectorSearchFilterActions();
const debouncedApplyVectorSearchFilter = useDebouncedCallback(
(value: string) => {
applyVectorSearchFilter(value);
},
500,
);
const handleSearchChange = (e: React.ChangeEvent<HTMLInputElement>) => {
const inputValue = e.target.value;
setVectorSearchInputValue(inputValue);
debouncedApplyVectorSearchFilter(inputValue);
};
return (
<DropdownMenuSearchInput
autoFocus
type="text"
value={vectorSearchInputValue}
placeholder={t`Search`}
onChange={handleSearchChange}
/>
);
};
@@ -17,7 +17,7 @@ import { RecordCalendarMonth } from '@/object-record/record-calendar/month/compo
import { currentRecordFieldsComponentState } from '@/object-record/record-field/states/currentRecordFieldsComponentState';
import { type RecordField } from '@/object-record/record-field/types/RecordField';
import { useRecordIndexFieldMetadataDerivedStates } from '@/object-record/record-index/hooks/useRecordIndexFieldMetadataDerivedStates';
import { VIEW_BAR_FILTER_DROPDOWN_ID } from '@/views/constants/ViewBarFilterDropdownId';
import { ViewBarFilterDropdownIds } from '@/views/constants/ViewBarFilterDropdownIds';
import { coreViewsState } from '@/views/states/coreViewState';
import { useSetRecoilState } from 'recoil';
import { ComponentDecorator, RouterDecorator } from 'twenty-ui/testing';
@@ -101,7 +101,7 @@ const meta: Meta<typeof RecordCalendarMonth> = {
componentInstanceId={instanceId}
>
<ObjectFilterDropdownComponentInstanceContext.Provider
value={{ instanceId: VIEW_BAR_FILTER_DROPDOWN_ID }}
value={{ instanceId: ViewBarFilterDropdownIds.MAIN }}
>
<RecordTableComponentInstanceContext.Provider
value={{
@@ -5,19 +5,18 @@ import {
MultiItemBaseInput,
type MultiItemBaseInputProps,
} from '@/object-record/record-field/ui/meta-types/input/components/MultiItemBaseInput';
import { MULTI_ITEM_FIELD_INPUT_DROPDOWN_ID_PREFIX } from '@/object-record/record-field/ui/meta-types/input/constants/MultiItemFieldInputDropdownClickOutsideId';
import { RecordFieldComponentInstanceContext } from '@/object-record/record-field/ui/states/contexts/RecordFieldComponentInstanceContext';
import { type PhoneRecord } from '@/object-record/record-field/ui/types/FieldMetadata';
import { PHONE_COUNTRY_CODE_PICKER_DROPDOWN_ID } from '@/ui/input/components/internal/phone/constants/PhoneCountryCodePickerDropdownId';
import { DropdownContent } from '@/ui/layout/dropdown/components/DropdownContent';
import { DropdownMenuItemsContainer } from '@/ui/layout/dropdown/components/DropdownMenuItemsContainer';
import { DropdownMenuSeparator } from '@/ui/layout/dropdown/components/DropdownMenuSeparator';
import { activeDropdownFocusIdState } from '@/ui/layout/dropdown/states/activeDropdownFocusIdState';
import { currentFocusedItemSelector } from '@/ui/utilities/focus/states/currentFocusedItemSelector';
import { FocusComponentType } from '@/ui/utilities/focus/types/FocusComponentType';
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 { useRecoilValue } from 'recoil';
import { CustomError, isDefined } from 'twenty-shared/utils';
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';
@@ -73,17 +72,14 @@ export const MultiItemFieldInput = <T,>({
RecordFieldComponentInstanceContext,
);
const activeDropdownFocusId = useRecoilValue(activeDropdownFocusIdState);
const currentFocusedItem = useRecoilValue(currentFocusedItemSelector);
useListenClickOutside({
refs: [containerRef],
callback: (event) => {
if (
(isDefined(activeDropdownFocusId) &&
activeDropdownFocusId.startsWith(
MULTI_ITEM_FIELD_INPUT_DROPDOWN_ID_PREFIX,
)) ||
activeDropdownFocusId === PHONE_COUNTRY_CODE_PICKER_DROPDOWN_ID
currentFocusedItem?.componentInstance.componentType !==
FocusComponentType.OPENED_FIELD_INPUT
) {
return;
}
@@ -2,9 +2,6 @@ import { AdvancedFilterContext } from '@/object-record/advanced-filter/states/co
import { currentRecordFiltersComponentState } from '@/object-record/record-filter/states/currentRecordFiltersComponentState';
import { useRecoilComponentCallbackState } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentCallbackState';
import { getSnapshotValue } from '@/ui/utilities/state/utils/getSnapshotValue';
import { VIEW_BAR_FILTER_DROPDOWN_ID } from '@/views/constants/ViewBarFilterDropdownId';
import { vectorSearchInputComponentState } from '@/views/states/vectorSearchInputComponentState';
import { isVectorSearchFilter } from '@/views/utils/isVectorSearchFilter';
import { useContext } from 'react';
import { useRecoilCallback } from 'recoil';
import { isDefined } from 'twenty-shared/utils';
@@ -32,15 +29,6 @@ export const useRemoveRecordFilter = () => {
return;
}
if (isVectorSearchFilter(filterToRemove)) {
set(
vectorSearchInputComponentState.atomFamily({
instanceId: VIEW_BAR_FILTER_DROPDOWN_ID,
}),
'',
);
}
set(currentRecordFiltersCallbackState, (currentRecordFilters) => {
const newCurrentRecordFilters = [...currentRecordFilters];
@@ -4,6 +4,7 @@ import { useUpsertRecordFilter } from '@/object-record/record-filter/hooks/useUp
import { currentRecordFiltersComponentState } from '@/object-record/record-filter/states/currentRecordFiltersComponentState';
import { useOpenDropdown } from '@/ui/layout/dropdown/hooks/useOpenDropdown';
import { useRecoilComponentValue } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentValue';
import { getEditableChipDropdownId } from '@/views/editable-chip/utils/getEditableChipDropdownId';
import { useSetEditableFilterChipDropdownStates } from '@/views/hooks/useSetEditableFilterChipDropdownStates';
import { isDefined } from 'twenty-shared/utils';
@@ -46,8 +47,9 @@ export const useOpenRecordFilterChipFromTableHeader = () => {
if (isDefined(existingNonAdvancedRecordFilter)) {
setEditableFilterChipDropdownStates(existingNonAdvancedRecordFilter);
openDropdown({
dropdownComponentInstanceIdFromProps:
existingNonAdvancedRecordFilter.id,
dropdownComponentInstanceIdFromProps: getEditableChipDropdownId({
recordFilterId: existingNonAdvancedRecordFilter.id,
}),
});
return;
}
@@ -59,7 +61,11 @@ export const useOpenRecordFilterChipFromTableHeader = () => {
upsertRecordFilter(newRecordFilter);
setEditableFilterChipDropdownStates(newRecordFilter);
openDropdown({ dropdownComponentInstanceIdFromProps: newRecordFilter.id });
openDropdown({
dropdownComponentInstanceIdFromProps: getEditableChipDropdownId({
recordFilterId: newRecordFilter.id,
}),
});
};
return { openRecordFilterChipFromTableHeader };
@@ -1,4 +1,4 @@
import { SEARCH_VECTOR_FIELD_NAME } from '@/views/constants/ViewFieldConstants';
import { SEARCH_VECTOR_FIELD_NAME } from '@/object-record/constants/SearchVectorFieldName';
export const isSystemSearchVectorField = (fieldName: string): boolean => {
return fieldName === SEARCH_VECTOR_FIELD_NAME;