From d50cf5291a50d0306ea2cae9e5c1413f06004654 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tha=C3=AFs?= Date: Wed, 29 Nov 2023 16:42:36 +0100 Subject: [PATCH] feat: reorder select field options (#2766) Closes #2703 --- .../SettingsObjectFieldSelectForm.tsx | 93 ++++++++++++------- ...SettingsObjectFieldSelectFormOptionRow.tsx | 16 +++- ...gsObjectFieldTypeSelectSection.stories.tsx | 42 ++++++++- .../data-model/hooks/useFieldMetadataForm.ts | 14 ++- .../SettingsObjectFieldSelectFormOption.ts | 2 +- front/src/modules/ui/input/constants/icons.ts | 1 - 6 files changed, 123 insertions(+), 45 deletions(-) diff --git a/front/src/modules/settings/data-model/components/SettingsObjectFieldSelectForm.tsx b/front/src/modules/settings/data-model/components/SettingsObjectFieldSelectForm.tsx index 1f25ee326..732d43f7f 100644 --- a/front/src/modules/settings/data-model/components/SettingsObjectFieldSelectForm.tsx +++ b/front/src/modules/settings/data-model/components/SettingsObjectFieldSelectForm.tsx @@ -1,7 +1,11 @@ import styled from '@emotion/styled'; +import { DropResult } from '@hello-pangea/dnd'; +import { v4 } from 'uuid'; import { IconPlus } from '@/ui/display/icon'; import { Button } from '@/ui/input/button/components/Button'; +import { DraggableItem } from '@/ui/layout/draggable-list/components/DraggableItem'; +import { DraggableList } from '@/ui/layout/draggable-list/components/DraggableList'; import { mainColorNames, ThemeColor } from '@/ui/theme/constants/colors'; import { SettingsObjectFieldSelectFormOption } from '../types/SettingsObjectFieldSelectFormOption'; @@ -18,6 +22,7 @@ type SettingsObjectFieldSelectFormProps = { const StyledContainer = styled.div` padding: ${({ theme }) => theme.spacing(4)}; + padding-bottom: ${({ theme }) => theme.spacing(3.5)}; `; const StyledLabel = styled.span` @@ -30,12 +35,6 @@ const StyledLabel = styled.span` text-transform: uppercase; `; -const StyledRows = styled.div` - display: flex; - flex-direction: column; - gap: ${({ theme }) => theme.spacing(1)}; -`; - const StyledButton = styled(Button)` border-bottom: 0; border-left: 0; @@ -57,39 +56,66 @@ export const SettingsObjectFieldSelectForm = ({ onChange, values, }: SettingsObjectFieldSelectFormProps) => { + const handleDragEnd = (result: DropResult) => { + if (!result.destination) return; + + const nextOptions = [...values]; + const [movedOption] = nextOptions.splice(result.source.index, 1); + + nextOptions.splice(result.destination.index, 0, movedOption); + + onChange(nextOptions); + }; + return ( <> Options - - {values.map((option, index) => ( - { - const hasDefaultOptionChanged = - !option.isDefault && nextOption.isDefault; - const nextOptions = hasDefaultOptionChanged - ? values.map((value) => ({ ...value, isDefault: false })) - : [...values]; + + {values.map((option, index) => ( + { + const hasDefaultOptionChanged = + !option.isDefault && nextOption.isDefault; + const nextOptions = hasDefaultOptionChanged + ? values.map((value) => ({ + ...value, + isDefault: false, + })) + : [...values]; - nextOptions.splice(index, 1, nextOption); + nextOptions.splice(index, 1, nextOption); - onChange(nextOptions); - }} - onRemove={ - values.length > 1 - ? () => { - const nextOptions = [...values]; - nextOptions.splice(index, 1); - onChange(nextOptions); - } - : undefined - } - option={option} - /> - ))} - + onChange(nextOptions); + }} + onRemove={ + values.length > 1 + ? () => { + const nextOptions = [...values]; + nextOptions.splice(index, 1); + onChange(nextOptions); + } + : undefined + } + option={option} + /> + } + /> + ))} + + } + /> void; onRemove?: () => void; @@ -33,11 +36,12 @@ const StyledRow = styled.div` align-items: center; display: flex; height: ${({ theme }) => theme.spacing(6)}; - padding: ${({ theme }) => theme.spacing(1)} 0; + padding: ${({ theme }) => theme.spacing(1.5)} 0; `; const StyledColorSample = styled(ColorSample)` cursor: pointer; + margin-left: 9px; margin-right: 14px; `; @@ -51,11 +55,14 @@ const StyledOptionInput = styled(TextInput)` `; export const SettingsObjectFieldSelectFormOptionRow = ({ + className, isDefault, onChange, onRemove, option, }: SettingsObjectFieldSelectFormOptionRowProps) => { + const theme = useTheme(); + const dropdownScopeIds = useMemo(() => { const baseScopeId = `select-field-option-row-${v4()}`; return { color: `${baseScopeId}-color`, actions: `${baseScopeId}-actions` }; @@ -69,7 +76,12 @@ export const SettingsObjectFieldSelectFormOptionRow = ({ }); return ( - + + = { args: { fieldMetadata: fieldMetadataWithoutId, objectMetadataId: mockedCompaniesMetadata.node.id, - values: { - type: FieldMetadataType.Text, - } as SettingsObjectFieldTypeSelectSectionFormValues, + values: fieldMetadataFormDefaultValues, }, parameters: { + container: { width: 512 }, msw: graphqlMocks, }, }; @@ -92,6 +92,7 @@ export const WithRelationForm: Story = { )?.node, relationFieldMetadata, values: { + ...fieldMetadataFormDefaultValues, type: FieldMetadataType.Relation, relation: { field: relationFieldMetadata, @@ -101,3 +102,38 @@ export const WithRelationForm: Story = { } as unknown as SettingsObjectFieldTypeSelectSectionFormValues, }, }; + +export const WithSelectForm: Story = { + args: { + fieldMetadata: { label: 'Industry', icon: 'IconBuildingFactory2' }, + values: { + ...fieldMetadataFormDefaultValues, + type: FieldMetadataType.Enum, + select: [ + { + color: 'pink', + isDefault: true, + label: '💊 Health', + value: 'HEALTH', + }, + { + color: 'purple', + label: '🏭 Industry', + value: 'INDUSTRY', + }, + { color: 'sky', label: '🤖 SaaS', value: 'SAAS' }, + { + color: 'turquoise', + label: '🌿 Green tech', + value: 'GREEN_TECH', + }, + { + color: 'yellow', + label: '🚲 Mobility', + value: 'MOBILITY', + }, + { color: 'green', label: '🌏 NGO', value: 'NGO' }, + ], + }, + }, +}; diff --git a/front/src/modules/settings/data-model/hooks/useFieldMetadataForm.ts b/front/src/modules/settings/data-model/hooks/useFieldMetadataForm.ts index cad06a3f7..0d350f3f5 100644 --- a/front/src/modules/settings/data-model/hooks/useFieldMetadataForm.ts +++ b/front/src/modules/settings/data-model/hooks/useFieldMetadataForm.ts @@ -1,5 +1,6 @@ import { useState } from 'react'; import { DeepPartial } from 'react-hook-form'; +import { v4 } from 'uuid'; import { z } from 'zod'; import { themeColorSchema } from '@/ui/theme/utils/themeColorSchema'; @@ -20,7 +21,7 @@ type FormValues = { select: SettingsObjectFieldTypeSelectSectionFormValues['select']; }; -const defaultValues: FormValues = { +export const fieldMetadataFormDefaultValues: FormValues = { icon: 'IconUsers', label: '', type: FieldMetadataType.Text, @@ -29,7 +30,7 @@ const defaultValues: FormValues = { objectMetadataId: '', field: { label: '' }, }, - select: [{ color: 'green', label: 'Option 1' }], + select: [{ color: 'green', label: 'Option 1', value: v4() }], }; const fieldSchema = z.object({ @@ -96,9 +97,12 @@ type PartialFormValues = Partial> & export const useFieldMetadataForm = () => { const [isInitialized, setIsInitialized] = useState(false); - const [initialFormValues, setInitialFormValues] = - useState(defaultValues); - const [formValues, setFormValues] = useState(defaultValues); + const [initialFormValues, setInitialFormValues] = useState( + fieldMetadataFormDefaultValues, + ); + const [formValues, setFormValues] = useState( + fieldMetadataFormDefaultValues, + ); const [hasFieldFormChanged, setHasFieldFormChanged] = useState(false); const [hasRelationFormChanged, setHasRelationFormChanged] = useState(false); const [hasSelectFormChanged, setHasSelectFormChanged] = useState(false); diff --git a/front/src/modules/settings/data-model/types/SettingsObjectFieldSelectFormOption.ts b/front/src/modules/settings/data-model/types/SettingsObjectFieldSelectFormOption.ts index bce7e2e7f..7ff6063ea 100644 --- a/front/src/modules/settings/data-model/types/SettingsObjectFieldSelectFormOption.ts +++ b/front/src/modules/settings/data-model/types/SettingsObjectFieldSelectFormOption.ts @@ -4,5 +4,5 @@ export type SettingsObjectFieldSelectFormOption = { color: ThemeColor; isDefault?: boolean; label: string; - value?: string; + value: string; }; diff --git a/front/src/modules/ui/input/constants/icons.ts b/front/src/modules/ui/input/constants/icons.ts index 39b003d56..cda8a1281 100644 --- a/front/src/modules/ui/input/constants/icons.ts +++ b/front/src/modules/ui/input/constants/icons.ts @@ -812,7 +812,6 @@ export { IconBrandTabler, IconBrandTailwind, IconBrandTaobao, - IconBrandTeams, IconBrandTed, IconBrandTelegram, IconBrandTerraform,