feat: add Relation field form (#2572)

* feat: add useCreateOneRelationMetadata and useRelationMetadata

Closes #2423

* feat: add Relation field form

Closes #2003

---------

Co-authored-by: Charles Bochet <charles@twenty.com>
This commit is contained in:
Thaïs
2023-11-17 23:38:39 +01:00
committed by GitHub
parent fea0bbeb2a
commit 18dac1a2b6
34 changed files with 1285 additions and 643 deletions

View File

@ -19,6 +19,7 @@ import { IconPickerHotkeyScope } from '../types/IconPickerHotkeyScope';
type IconPickerProps = {
disabled?: boolean;
dropdownScopeId?: string;
onChange: (params: { iconKey: string; Icon: IconComponent }) => void;
selectedIconKey?: string;
onClickOutside?: () => void;
@ -44,6 +45,7 @@ const convertIconKeyToLabel = (iconKey: string) =>
export const IconPicker = ({
disabled,
dropdownScopeId = 'icon-picker',
onChange,
selectedIconKey,
onClickOutside,
@ -53,7 +55,7 @@ export const IconPicker = ({
}: IconPickerProps) => {
const [searchString, setSearchString] = useState('');
const { closeDropdown } = useDropdown({ dropdownScopeId: 'icon-picker' });
const { closeDropdown } = useDropdown({ dropdownScopeId });
const { icons, isLoadingIcons: isLoading } = useLazyLoadIcons();
@ -75,7 +77,7 @@ export const IconPicker = ({
}, [icons, searchString, selectedIconKey]);
return (
<DropdownScope dropdownScopeId="icon-picker">
<DropdownScope dropdownScopeId={dropdownScopeId}>
<Dropdown
dropdownHotkeyScope={{ scope: IconPickerHotkeyScope.IconPicker }}
clickableComponent={

View File

@ -12,14 +12,16 @@ import { MenuItem } from '@/ui/navigation/menu-item/components/MenuItem';
import { SelectHotkeyScope } from '../types/SelectHotkeyScope';
export type SelectProps<Value extends string | number | null> = {
className?: string;
disabled?: boolean;
dropdownScopeId: string;
label?: string;
onChange?: (value: Value) => void;
options: { value: Value; label: string; Icon?: IconComponent }[];
value?: Value;
};
const StyledContainer = styled.div<{ disabled?: boolean }>`
const StyledControlContainer = styled.div<{ disabled?: boolean }>`
align-items: center;
background-color: ${({ theme }) => theme.background.transparent.lighter};
border: 1px solid ${({ theme }) => theme.border.color.medium};
@ -34,7 +36,16 @@ const StyledContainer = styled.div<{ disabled?: boolean }>`
padding: 0 ${({ theme }) => theme.spacing(2)};
`;
const StyledLabel = styled.div`
const StyledLabel = styled.span`
color: ${({ theme }) => theme.font.color.light};
display: block;
font-size: ${({ theme }) => theme.font.size.xs};
font-weight: ${({ theme }) => theme.font.weight.semiBold};
margin-bottom: ${({ theme }) => theme.spacing(1)};
text-transform: uppercase;
`;
const StyledControlLabel = styled.div`
align-items: center;
display: flex;
gap: ${({ theme }) => theme.spacing(1)};
@ -46,8 +57,10 @@ const StyledIconChevronDown = styled(IconChevronDown)<{ disabled?: boolean }>`
`;
export const Select = <Value extends string | number | null>({
className,
disabled,
dropdownScopeId,
label,
onChange,
options,
value,
@ -59,46 +72,49 @@ export const Select = <Value extends string | number | null>({
const { closeDropdown } = useDropdown({ dropdownScopeId });
const selectControl = (
<StyledContainer disabled={disabled}>
<StyledLabel>
{!!selectedOption.Icon && (
<StyledControlContainer disabled={disabled}>
<StyledControlLabel>
{!!selectedOption?.Icon && (
<selectedOption.Icon
color={disabled ? theme.font.color.light : theme.font.color.primary}
size={theme.icon.size.md}
stroke={theme.icon.stroke.sm}
/>
)}
{selectedOption.label}
</StyledLabel>
{selectedOption?.label}
</StyledControlLabel>
<StyledIconChevronDown disabled={disabled} size={theme.icon.size.md} />
</StyledContainer>
</StyledControlContainer>
);
return disabled ? (
selectControl
) : (
<DropdownScope dropdownScopeId={dropdownScopeId}>
<Dropdown
dropdownMenuWidth={176}
dropdownPlacement="bottom-start"
clickableComponent={selectControl}
dropdownComponents={
<DropdownMenuItemsContainer>
{options.map((option) => (
<MenuItem
key={option.value}
LeftIcon={option.Icon}
text={option.label}
onClick={() => {
onChange?.(option.value);
closeDropdown();
}}
/>
))}
</DropdownMenuItemsContainer>
}
dropdownHotkeyScope={{ scope: SelectHotkeyScope.Select }}
/>
<div className={className}>
{!!label && <StyledLabel>{label}</StyledLabel>}
<Dropdown
dropdownMenuWidth={176}
dropdownPlacement="bottom-start"
clickableComponent={selectControl}
dropdownComponents={
<DropdownMenuItemsContainer>
{options.map((option) => (
<MenuItem
key={option.value}
LeftIcon={option.Icon}
text={option.label}
onClick={() => {
onChange?.(option.value);
closeDropdown();
}}
/>
))}
</DropdownMenuItemsContainer>
}
dropdownHotkeyScope={{ scope: SelectHotkeyScope.Select }}
/>
</div>
</DropdownScope>
);
};