From 7ceaa879fe9ed07e798ed40c3ad4467ac7a42a41 Mon Sep 17 00:00:00 2001 From: "gitstart-app[bot]" <57568882+gitstart-app[bot]@users.noreply.github.com> Date: Fri, 11 Oct 2024 10:34:31 +0200 Subject: [PATCH] Avanced Settings: Custom API names for Select & Multi-Select Keys (#7489) ### Description - text input was changed because it renders an empty div as the right icon, but the margin and padding affect the layout - we have duplicated code on ExpandedWidthAnimationVariants.ts, because of an eslint rule that prevents more than one const definition, can we ignore the rule? - ### Demo ### Refs --------- Co-authored-by: gitstart-twenty Co-authored-by: gitstart-twenty <140154534+gitstart-twenty@users.noreply.github.com> Co-authored-by: Marie Stoppa --- .../AdvancedSettingsAnimationDurations.ts | 4 + .../ExpandedWidthAnimationVariants.ts | 31 ++++++++ .../SettingsDataModelFieldSelectForm.tsx | 77 +++++++++++++++++-- ...tingsDataModelFieldSelectFormOptionRow.tsx | 67 +++++++++++++--- .../hooks/useExpandedHeightAnimation.tsx | 2 +- 5 files changed, 164 insertions(+), 17 deletions(-) create mode 100644 packages/twenty-front/src/modules/settings/constants/AdvancedSettingsAnimationDurations.ts create mode 100644 packages/twenty-front/src/modules/settings/constants/ExpandedWidthAnimationVariants.ts diff --git a/packages/twenty-front/src/modules/settings/constants/AdvancedSettingsAnimationDurations.ts b/packages/twenty-front/src/modules/settings/constants/AdvancedSettingsAnimationDurations.ts new file mode 100644 index 000000000..2f40f4d08 --- /dev/null +++ b/packages/twenty-front/src/modules/settings/constants/AdvancedSettingsAnimationDurations.ts @@ -0,0 +1,4 @@ +export const ADVANCED_SETTINGS_ANIMATION_DURATION = { + opacity: 0.2, + size: 0.4, +}; diff --git a/packages/twenty-front/src/modules/settings/constants/ExpandedWidthAnimationVariants.ts b/packages/twenty-front/src/modules/settings/constants/ExpandedWidthAnimationVariants.ts new file mode 100644 index 000000000..b6f14423e --- /dev/null +++ b/packages/twenty-front/src/modules/settings/constants/ExpandedWidthAnimationVariants.ts @@ -0,0 +1,31 @@ +import { ADVANCED_SETTINGS_ANIMATION_DURATION } from '@/settings/constants/AdvancedSettingsAnimationDurations'; + +export const EXPANDED_WIDTH_ANIMATION_VARIANTS = { + initial: { + opacity: 0, + width: 0, + overflow: 'hidden', + transition: { + opacity: { duration: ADVANCED_SETTINGS_ANIMATION_DURATION.opacity }, + width: { duration: ADVANCED_SETTINGS_ANIMATION_DURATION.size }, + }, + }, + animate: { + opacity: 1, + width: '100%', + overflow: 'hidden', + transition: { + opacity: { duration: ADVANCED_SETTINGS_ANIMATION_DURATION.opacity }, + width: { duration: ADVANCED_SETTINGS_ANIMATION_DURATION.size }, + }, + }, + exit: { + opacity: 0, + width: 0, + overflow: 'hidden', + transition: { + opacity: { duration: ADVANCED_SETTINGS_ANIMATION_DURATION.opacity }, + width: { duration: ADVANCED_SETTINGS_ANIMATION_DURATION.size }, + }, + }, +}; diff --git a/packages/twenty-front/src/modules/settings/data-model/fields/forms/select/components/SettingsDataModelFieldSelectForm.tsx b/packages/twenty-front/src/modules/settings/data-model/fields/forms/select/components/SettingsDataModelFieldSelectForm.tsx index f1fdc6425..038c2a143 100644 --- a/packages/twenty-front/src/modules/settings/data-model/fields/forms/select/components/SettingsDataModelFieldSelectForm.tsx +++ b/packages/twenty-front/src/modules/settings/data-model/fields/forms/select/components/SettingsDataModelFieldSelectForm.tsx @@ -1,7 +1,7 @@ import styled from '@emotion/styled'; import { DropResult } from '@hello-pangea/dnd'; import { Controller, useFormContext } from 'react-hook-form'; -import { IconPlus } from 'twenty-ui'; +import { IconPlus, IconTool, MAIN_COLORS } from 'twenty-ui'; import { z } from 'zod'; import { @@ -24,6 +24,10 @@ import { moveArrayItem } from '~/utils/array/moveArrayItem'; import { toSpliced } from '~/utils/array/toSpliced'; import { applySimpleQuotesToString } from '~/utils/string/applySimpleQuotesToString'; +import { EXPANDED_WIDTH_ANIMATION_VARIANTS } from '@/settings/constants/ExpandedWidthAnimationVariants'; +import { isAdvancedModeEnabledState } from '@/ui/navigation/navigation-drawer/states/isAdvancedModeEnabledState'; +import { AnimatePresence, motion } from 'framer-motion'; +import { useRecoilValue } from 'recoil'; import { SettingsDataModelFieldSelectFormOptionRow } from './SettingsDataModelFieldSelectFormOptionRow'; export const settingsDataModelFieldSelectFormSchema = z.object({ @@ -56,13 +60,49 @@ const StyledContainer = styled(CardContent)` padding-bottom: ${({ theme }) => theme.spacing(3.5)}; `; -const StyledLabel = styled.span` +const StyledOptionsLabel = styled.div<{ + isAdvancedModeEnabled: boolean; +}>` color: ${({ theme }) => theme.font.color.light}; - display: block; font-size: ${({ theme }) => theme.font.size.xs}; font-weight: ${({ theme }) => theme.font.weight.semiBold}; - margin-bottom: 6px; + margin-bottom: ${({ theme }) => theme.spacing(1.5)}; margin-top: ${({ theme }) => theme.spacing(1)}; + width: 100%; + margin-left: ${({ theme, isAdvancedModeEnabled }) => + theme.spacing(isAdvancedModeEnabled ? 10 : 0)}; +`; + +const StyledApiKeyContainer = styled.div` + display: flex; + gap: ${({ theme }) => theme.spacing(2)}; + width: 100%; +`; + +const StyledApiKey = styled.span` + color: ${({ theme }) => theme.font.color.light}; + font-size: ${({ theme }) => theme.font.size.xs}; + font-weight: ${({ theme }) => theme.font.weight.semiBold}; + margin-bottom: ${({ theme }) => theme.spacing(1.5)}; + margin-top: ${({ theme }) => theme.spacing(1)}; + width: 100%; + white-space: nowrap; +`; + +const StyledLabelContainer = styled.div` + display: flex; +`; + +const StyledIconContainer = styled.div` + border-right: 1px solid ${MAIN_COLORS.yellow}; + display: flex; + + margin-bottom: ${({ theme }) => theme.spacing(1.5)}; + margin-top: ${({ theme }) => theme.spacing(1)}; +`; + +const StyledIconTool = styled(IconTool)` + margin-right: ${({ theme }) => theme.spacing(0.5)}; `; const StyledFooter = styled(CardFooter)` @@ -80,6 +120,7 @@ export const SettingsDataModelFieldSelectForm = ({ }: SettingsDataModelFieldSelectFormProps) => { const { initialDefaultValue, initialOptions } = useSelectSettingsFormInitialValues({ fieldMetadataItem }); + const isAdvancedModeEnabled = useRecoilValue(isAdvancedModeEnabledState); const { control, @@ -205,7 +246,33 @@ export const SettingsDataModelFieldSelectForm = ({ render={({ field: { onChange, value: options } }) => ( <> - Options + + + {isAdvancedModeEnabled && ( + + + + + + API keys + + + )} + + + Options + + handleDragEnd(options, result, onChange)} draggableItems={ diff --git a/packages/twenty-front/src/modules/settings/data-model/fields/forms/select/components/SettingsDataModelFieldSelectFormOptionRow.tsx b/packages/twenty-front/src/modules/settings/data-model/fields/forms/select/components/SettingsDataModelFieldSelectFormOptionRow.tsx index d9be3fff7..d0c74e805 100644 --- a/packages/twenty-front/src/modules/settings/data-model/fields/forms/select/components/SettingsDataModelFieldSelectFormOptionRow.tsx +++ b/packages/twenty-front/src/modules/settings/data-model/fields/forms/select/components/SettingsDataModelFieldSelectFormOptionRow.tsx @@ -13,6 +13,7 @@ import { import { v4 } from 'uuid'; import { FieldMetadataItemOption } from '@/object-metadata/types/FieldMetadataItem'; +import { EXPANDED_WIDTH_ANIMATION_VARIANTS } from '@/settings/constants/ExpandedWidthAnimationVariants'; import { OPTION_VALUE_MAXIMUM_LENGTH } from '@/settings/data-model/constants/OptionValueMaximumLength'; import { getOptionValueFromLabel } from '@/settings/data-model/fields/forms/select/utils/getOptionValueFromLabel'; import { LightIconButton } from '@/ui/input/button/components/LightIconButton'; @@ -23,6 +24,9 @@ import { DropdownMenuItemsContainer } from '@/ui/layout/dropdown/components/Drop import { useDropdown } from '@/ui/layout/dropdown/hooks/useDropdown'; import { MenuItem } from '@/ui/navigation/menu-item/components/MenuItem'; import { MenuItemSelectColor } from '@/ui/navigation/menu-item/components/MenuItemSelectColor'; +import { isAdvancedModeEnabledState } from '@/ui/navigation/navigation-drawer/states/isAdvancedModeEnabledState'; +import { AnimatePresence, motion } from 'framer-motion'; +import { useRecoilValue } from 'recoil'; type SettingsDataModelFieldSelectFormOptionRowProps = { className?: string; @@ -45,19 +49,29 @@ const StyledRow = styled.div` const StyledColorSample = styled(ColorSample)` cursor: pointer; - margin-left: 9px; - margin-right: 14px; + margin-top: ${({ theme }) => theme.spacing(1)}; + margin-bottom: ${({ theme }) => theme.spacing(1)}; + + margin-right: ${({ theme }) => theme.spacing(3.5)}; + margin-left: ${({ theme }) => theme.spacing(3.5)}; `; const StyledOptionInput = styled(TextInput)` - flex: 1 0 auto; - margin-right: ${({ theme }) => theme.spacing(2)}; - + flex-grow: 1; + width: 100%; & input { height: ${({ theme }) => theme.spacing(6)}; } `; +const StyledIconGripVertical = styled(IconGripVertical)` + margin-right: ${({ theme }) => theme.spacing(0.75)}; +`; + +const StyledLightIconButton = styled(LightIconButton)` + margin-left: ${({ theme }) => theme.spacing(2)}; +`; + export const SettingsDataModelFieldSelectFormOptionRow = ({ className, isDefault, @@ -69,6 +83,7 @@ export const SettingsDataModelFieldSelectFormOptionRow = ({ option, isNewRow, }: SettingsDataModelFieldSelectFormOptionRowProps) => { + const isAdvancedModeEnabled = useRecoilValue(isAdvancedModeEnabledState); const theme = useTheme(); const dropdownIds = useMemo(() => { @@ -90,11 +105,34 @@ export const SettingsDataModelFieldSelectFormOptionRow = ({ return ( - + + {isAdvancedModeEnabled && ( + + + onChange({ + ...option, + value: getOptionValueFromLabel(input), + }) + } + RightIcon={isDefault ? IconCheck : undefined} + maxLength={OPTION_VALUE_MAXIMUM_LENGTH} + /> + + )} + + onChange={(label) => { + const optionNameHasBeenEdited = !( + option.value === getOptionValueFromLabel(option.label) + ); onChange({ ...option, label, - value: getOptionValueFromLabel(label), - }) - } + value: optionNameHasBeenEdited + ? option.value + : getOptionValueFromLabel(label), + }); + }} RightIcon={isDefault ? IconCheck : undefined} maxLength={OPTION_VALUE_MAXIMUM_LENGTH} onInputEnter={handleInputEnter} @@ -141,7 +184,9 @@ export const SettingsDataModelFieldSelectFormOptionRow = ({ dropdownHotkeyScope={{ scope: dropdownIds.actions, }} - clickableComponent={} + clickableComponent={ + + } dropdownComponents={ diff --git a/packages/twenty-front/src/modules/settings/hooks/useExpandedHeightAnimation.tsx b/packages/twenty-front/src/modules/settings/hooks/useExpandedHeightAnimation.tsx index e762990f0..0e7723c67 100644 --- a/packages/twenty-front/src/modules/settings/hooks/useExpandedHeightAnimation.tsx +++ b/packages/twenty-front/src/modules/settings/hooks/useExpandedHeightAnimation.tsx @@ -3,7 +3,7 @@ import { isDefined } from 'twenty-ui'; const transitionValues = { transition: { - opactity: { duration: 0.2 }, + opacity: { duration: 0.2 }, height: { duration: 0.4 }, }, };