feature to reset value in select field (#6067)

Fixes #6064 



https://github.com/twentyhq/twenty/assets/55168611/8c553422-6ad2-4e6b-bd00-962dd81c0a93

---------

Co-authored-by: Lucas Bordeau <bordeau.lucas@gmail.com>
This commit is contained in:
Sudarsh
2024-07-02 16:46:17 +05:30
committed by GitHub
parent 88915291d9
commit ea7d52fba8
4 changed files with 45 additions and 7 deletions

View File

@ -2,6 +2,7 @@ import { useContext } from 'react';
import { useRecoilCallback } from 'recoil'; import { useRecoilCallback } from 'recoil';
import { objectMetadataItemsState } from '@/object-metadata/states/objectMetadataItemsState'; import { objectMetadataItemsState } from '@/object-metadata/states/objectMetadataItemsState';
import { useSetRecordFieldValue } from '@/object-record/record-store/contexts/RecordFieldValueSelectorContext';
import { recordStoreFamilySelector } from '@/object-record/record-store/states/selectors/recordStoreFamilySelector'; import { recordStoreFamilySelector } from '@/object-record/record-store/states/selectors/recordStoreFamilySelector';
import { generateEmptyFieldValue } from '@/object-record/utils/generateEmptyFieldValue'; import { generateEmptyFieldValue } from '@/object-record/utils/generateEmptyFieldValue';
@ -16,6 +17,8 @@ export const useClearField = () => {
const [updateRecord] = useUpdateRecord(); const [updateRecord] = useUpdateRecord();
const setRecordFieldValue = useSetRecordFieldValue();
const clearField = useRecoilCallback( const clearField = useRecoilCallback(
({ snapshot, set }) => ({ snapshot, set }) =>
() => { () => {
@ -46,6 +49,8 @@ export const useClearField = () => {
emptyFieldValue, emptyFieldValue,
); );
setRecordFieldValue(entityId, fieldName, emptyFieldValue);
updateRecord?.({ updateRecord?.({
variables: { variables: {
where: { id: entityId }, where: { id: entityId },
@ -55,7 +60,7 @@ export const useClearField = () => {
}, },
}); });
}, },
[entityId, fieldDefinition, updateRecord], [entityId, fieldDefinition, updateRecord, setRecordFieldValue],
); );
return clearField; return clearField;

View File

@ -2,6 +2,7 @@ import React, { useRef, useState } from 'react';
import styled from '@emotion/styled'; import styled from '@emotion/styled';
import { Key } from 'ts-key-enum'; import { Key } from 'ts-key-enum';
import { useClearField } from '@/object-record/record-field/hooks/useClearField';
import { useSelectField } from '@/object-record/record-field/meta-types/hooks/useSelectField'; import { useSelectField } from '@/object-record/record-field/meta-types/hooks/useSelectField';
import { FieldInputEvent } from '@/object-record/record-field/types/FieldInputEvent'; import { FieldInputEvent } from '@/object-record/record-field/types/FieldInputEvent';
import { DropdownMenu } from '@/ui/layout/dropdown/components/DropdownMenu'; import { DropdownMenu } from '@/ui/layout/dropdown/components/DropdownMenu';
@ -30,12 +31,15 @@ export const SelectFieldInput = ({
}: SelectFieldInputProps) => { }: SelectFieldInputProps) => {
const { persistField, fieldDefinition, fieldValue, hotkeyScope } = const { persistField, fieldDefinition, fieldValue, hotkeyScope } =
useSelectField(); useSelectField();
const clearField = useClearField();
const [searchFilter, setSearchFilter] = useState(''); const [searchFilter, setSearchFilter] = useState('');
const containerRef = useRef<HTMLDivElement>(null); const containerRef = useRef<HTMLDivElement>(null);
const selectedOption = fieldDefinition.metadata.options.find( const selectedOption = fieldDefinition.metadata.options.find(
(option) => option.value === fieldValue, (option) => option.value === fieldValue,
); );
const optionsToSelect = const optionsToSelect =
fieldDefinition.metadata.options.filter((option) => { fieldDefinition.metadata.options.filter((option) => {
return ( return (
@ -43,10 +47,17 @@ export const SelectFieldInput = ({
option.label.toLowerCase().includes(searchFilter.toLowerCase()) option.label.toLowerCase().includes(searchFilter.toLowerCase())
); );
}) || []; }) || [];
const optionsInDropDown = selectedOption const optionsInDropDown = selectedOption
? [selectedOption, ...optionsToSelect] ? [selectedOption, ...optionsToSelect]
: optionsToSelect; : optionsToSelect;
// handlers
const handleClearField = () => {
clearField();
onCancel?.();
};
useListenClickOutside({ useListenClickOutside({
refs: [containerRef], refs: [containerRef],
callback: (event) => { callback: (event) => {
@ -85,7 +96,17 @@ export const SelectFieldInput = ({
autoFocus autoFocus
/> />
<DropdownMenuSeparator /> <DropdownMenuSeparator />
<DropdownMenuItemsContainer hasMaxHeight> <DropdownMenuItemsContainer hasMaxHeight>
<MenuItemSelectTag
key={`No ${fieldDefinition.label}`}
selected={false}
text={`No ${fieldDefinition.label}`}
color="transparent"
variant="outline"
onClick={handleClearField}
/>
{optionsInDropDown.map((option) => { {optionsInDropDown.map((option) => {
return ( return (
<MenuItemSelectTag <MenuItemSelectTag

View File

@ -9,8 +9,9 @@ type MenuItemSelectTagProps = {
selected: boolean; selected: boolean;
className?: string; className?: string;
onClick?: () => void; onClick?: () => void;
color: ThemeColor; color: ThemeColor | 'transparent';
text: string; text: string;
variant?: 'solid' | 'outline';
}; };
export const MenuItemSelectTag = ({ export const MenuItemSelectTag = ({
@ -19,6 +20,7 @@ export const MenuItemSelectTag = ({
className, className,
onClick, onClick,
text, text,
variant = 'solid',
}: MenuItemSelectTagProps) => { }: MenuItemSelectTagProps) => {
const theme = useTheme(); const theme = useTheme();
@ -29,7 +31,7 @@ export const MenuItemSelectTag = ({
selected={selected} selected={selected}
> >
<StyledMenuItemLeftContent> <StyledMenuItemLeftContent>
<Tag color={color} text={text} /> <Tag variant={variant} color={color} text={text} />
</StyledMenuItemLeftContent> </StyledMenuItemLeftContent>
{selected && <IconCheck size={theme.icon.size.sm} />} {selected && <IconCheck size={theme.icon.size.sm} />}
</StyledMenuItemSelect> </StyledMenuItemSelect>

View File

@ -16,14 +16,17 @@ const spacing1 = THEME_COMMON.spacing(1);
const StyledTag = styled.h3<{ const StyledTag = styled.h3<{
theme: ThemeType; theme: ThemeType;
color: ThemeColor; color: TagColor;
weight: TagWeight; weight: TagWeight;
variant: TagVariant;
preventShrink?: boolean; preventShrink?: boolean;
}>` }>`
align-items: center; align-items: center;
background: ${({ color, theme }) => theme.tag.background[color]}; background: ${({ color, theme }) =>
color === 'transparent' ? color : theme.tag.background[color]};
border-radius: ${BORDER_COMMON.radius.sm}; border-radius: ${BORDER_COMMON.radius.sm};
color: ${({ color, theme }) => theme.tag.text[color]}; color: ${({ color, theme }) =>
color === 'transparent' ? theme.tag.text['gray'] : theme.tag.text[color]};
display: inline-flex; display: inline-flex;
font-size: ${({ theme }) => theme.font.size.md}; font-size: ${({ theme }) => theme.font.size.md};
font-style: normal; font-style: normal;
@ -35,6 +38,8 @@ const StyledTag = styled.h3<{
margin: 0; margin: 0;
overflow: hidden; overflow: hidden;
padding: 0 ${spacing2}; padding: 0 ${spacing2};
border: ${({ variant, theme }) =>
variant === 'outline' ? `2px dashed ${theme.tag.background['gray']}` : ''};
gap: ${spacing1}; gap: ${spacing1};
@ -58,14 +63,17 @@ const StyledIconContainer = styled.div`
`; `;
type TagWeight = 'regular' | 'medium'; type TagWeight = 'regular' | 'medium';
type TagVariant = 'solid' | 'outline';
type TagColor = ThemeColor | 'transparent';
type TagProps = { type TagProps = {
className?: string; className?: string;
color: ThemeColor; color: TagColor;
text: string; text: string;
Icon?: IconComponent; Icon?: IconComponent;
onClick?: () => void; onClick?: () => void;
weight?: TagWeight; weight?: TagWeight;
variant?: TagVariant;
preventShrink?: boolean; preventShrink?: boolean;
}; };
@ -77,6 +85,7 @@ export const Tag = ({
Icon, Icon,
onClick, onClick,
weight = 'regular', weight = 'regular',
variant = 'solid',
preventShrink, preventShrink,
}: TagProps) => { }: TagProps) => {
const { theme } = useContext(ThemeContext); const { theme } = useContext(ThemeContext);
@ -88,6 +97,7 @@ export const Tag = ({
color={color} color={color}
onClick={onClick} onClick={onClick}
weight={weight} weight={weight}
variant={variant}
preventShrink={preventShrink} preventShrink={preventShrink}
> >
{!!Icon && ( {!!Icon && (