From fe1f3b25f6fb159306ab0da62d4674965a1558e2 Mon Sep 17 00:00:00 2001 From: Thibault Reidy Date: Mon, 4 Mar 2024 14:42:15 +0100 Subject: [PATCH 1/7] feat: add checkbox in DescriptionForm to allow to add description above --- package.json | 6 +-- src/components/item/form/DescriptionForm.tsx | 47 ++++++++++++++++--- src/components/item/form/EditModalWrapper.tsx | 4 ++ src/components/main/ItemsGrid.tsx | 15 +++++- src/components/main/ItemsTable.tsx | 5 ++ src/components/main/ItemsToolbar.tsx | 28 ++++++----- src/langs/constants.ts | 2 + src/langs/en.json | 3 +- src/langs/fr.json | 3 +- yarn.lock | 28 +++++------ 10 files changed, 102 insertions(+), 39 deletions(-) diff --git a/package.json b/package.json index ae8ee9d8a..90efdff84 100644 --- a/package.json +++ b/package.json @@ -20,10 +20,10 @@ "@emotion/react": "11.11.4", "@emotion/styled": "11.11.0", "@graasp/chatbox": "3.1.0", - "@graasp/query-client": "2.7.1", - "@graasp/sdk": "4.0.1", + "@graasp/query-client": "github:graasp/graasp-query-client#694-display-description-above-or-below-item", + "@graasp/sdk": "4.1.0", "@graasp/translations": "1.25.2", - "@graasp/ui": "4.8.5", + "@graasp/ui": "4.9.0", "@mui/icons-material": "5.15.11", "@mui/lab": "5.0.0-alpha.166", "@mui/material": "5.15.11", diff --git a/src/components/item/form/DescriptionForm.tsx b/src/components/item/form/DescriptionForm.tsx index a21ee87ae..5aa8cea7c 100644 --- a/src/components/item/form/DescriptionForm.tsx +++ b/src/components/item/form/DescriptionForm.tsx @@ -1,6 +1,11 @@ -import { DiscriminatedItem } from '@graasp/sdk'; +import { Checkbox, FormControlLabel, Stack } from '@mui/material'; + +import { DescriptionPlacement, DiscriminatedItem } from '@graasp/sdk'; import TextEditor from '@graasp/ui/text-editor'; +import { useBuilderTranslation } from '@/config/i18n'; +import { BUILDER } from '@/langs/constants'; + type DescriptionFormProps = { id?: string; item?: DiscriminatedItem; @@ -14,19 +19,47 @@ const DescriptionForm = ({ item, setChanges, }: DescriptionFormProps): JSX.Element => { + const { t } = useBuilderTranslation(); + const onChange = (content: string): void => { setChanges({ description: content, }); }; + const onCheckBoxChanged = (checked: boolean): void => { + setChanges({ + settings: { + descriptionPlacement: checked + ? DescriptionPlacement.ABOVE + : DescriptionPlacement.BELOW, + }, + }); + }; + return ( - + + + onCheckBoxChanged(checked)} + /> + } + label={t(BUILDER.ITEM_SETTINGS_DESCRIPTION_PLACEMENT_ABOVE)} + /> + ); }; diff --git a/src/components/item/form/EditModalWrapper.tsx b/src/components/item/form/EditModalWrapper.tsx index 115364479..69b782eb1 100644 --- a/src/components/item/form/EditModalWrapper.tsx +++ b/src/components/item/form/EditModalWrapper.tsx @@ -87,6 +87,10 @@ const EditModalWrapper = ({ extra: !isEqual(item.extra, updatedItem.extra) ? (updatedItem.extra as any) : undefined, + // only patch settings it it has been changed + ...(!isEqual(item.settings, updatedItem.settings) + ? { settings: updatedItem.settings } + : {}), }); } diff --git a/src/components/main/ItemsGrid.tsx b/src/components/main/ItemsGrid.tsx index 494ff0040..d6fc4eb4c 100644 --- a/src/components/main/ItemsGrid.tsx +++ b/src/components/main/ItemsGrid.tsx @@ -1,7 +1,13 @@ import { Box, Grid, Pagination } from '@mui/material'; -import { DiscriminatedItem, ItemMembership, ResultOf } from '@graasp/sdk'; +import { + DescriptionPlacement, + DiscriminatedItem, + ItemMembership, + ResultOf, +} from '@graasp/sdk'; +import { hooks } from '@/config/queryClient'; import { ShowOnlyMeChangeType } from '@/config/types'; import { ITEM_PAGE_SIZE } from '../../config/constants'; @@ -14,6 +20,8 @@ import EmptyItem from './EmptyItem'; import ItemCard from './ItemCard'; import ItemsToolbar from './ItemsToolbar'; +const { useItem } = hooks; + type Props = { id?: string; items?: DiscriminatedItem[]; @@ -50,6 +58,7 @@ const ItemsGrid = ({ page = 1, }: Props): JSX.Element => { const pagesCount = Math.ceil(Math.max(1, totalCount / ITEM_PAGE_SIZE)); + const { data: parentItem } = useItem(parentId); const renderItems = () => { if (!items?.length) { return ( @@ -79,6 +88,10 @@ const ItemsGrid = ({ } + showSubTitleAbove={ + parentItem?.settings.descriptionPlacement === + DescriptionPlacement.ABOVE + } headerElements={headerElements} onShowOnlyMeChange={onShowOnlyMeChange} showOnlyMe={showOnlyMe} diff --git a/src/components/main/ItemsTable.tsx b/src/components/main/ItemsTable.tsx index 5568427ad..73aefcadf 100644 --- a/src/components/main/ItemsTable.tsx +++ b/src/components/main/ItemsTable.tsx @@ -2,6 +2,7 @@ import { useCallback } from 'react'; import { useNavigate, useParams } from 'react-router-dom'; import { + DescriptionPlacement, DiscriminatedItem, ItemMembership, ItemType, @@ -275,6 +276,10 @@ const ItemsTable = ({ : null} + showSubTitleAbove={ + parentItem?.settings.descriptionPlacement === + DescriptionPlacement.ABOVE + } headerElements={headerElements} onShowOnlyMeChange={onShowOnlyMeChange} showOnlyMe={showOnlyMe} diff --git a/src/components/main/ItemsToolbar.tsx b/src/components/main/ItemsToolbar.tsx index 382baf078..d4f6d4c04 100644 --- a/src/components/main/ItemsToolbar.tsx +++ b/src/components/main/ItemsToolbar.tsx @@ -9,6 +9,7 @@ import SelectTypes from '../common/SelectTypes'; type Props = { title: string; subTitleElement?: JSX.Element | null; + showSubTitleAbove?: boolean; headerElements?: JSX.Element[]; onShowOnlyMeChange?: ShowOnlyMeChangeType; showOnlyMe?: boolean; @@ -17,6 +18,7 @@ type Props = { const ItemsToolbar = ({ title, subTitleElement, + showSubTitleAbove, headerElements, onShowOnlyMeChange, showOnlyMe, @@ -24,20 +26,22 @@ const ItemsToolbar = ({ const { t } = useBuilderTranslation(); return ( <> - - - {title} - - - {headerElements} + + + + {title} + + + {headerElements} + + {subTitleElement} - {subTitleElement} {onShowOnlyMeChange && ( Date: Tue, 5 Mar 2024 08:29:34 +0100 Subject: [PATCH 2/7] feat: use select instead of checkbox for description placement --- src/components/item/form/DescriptionForm.tsx | 57 +++++++++++++------- src/langs/constants.ts | 4 ++ src/langs/en.json | 4 +- src/langs/fr.json | 4 +- 4 files changed, 47 insertions(+), 22 deletions(-) diff --git a/src/components/item/form/DescriptionForm.tsx b/src/components/item/form/DescriptionForm.tsx index 5aa8cea7c..7e7286da1 100644 --- a/src/components/item/form/DescriptionForm.tsx +++ b/src/components/item/form/DescriptionForm.tsx @@ -1,11 +1,23 @@ -import { Checkbox, FormControlLabel, Stack } from '@mui/material'; +import { + FormControl, + InputLabel, + MenuItem, + Select, + Stack, +} from '@mui/material'; -import { DescriptionPlacement, DiscriminatedItem } from '@graasp/sdk'; +import { + DescriptionPlacement, + DescriptionPlacementType, + DiscriminatedItem, +} from '@graasp/sdk'; import TextEditor from '@graasp/ui/text-editor'; import { useBuilderTranslation } from '@/config/i18n'; import { BUILDER } from '@/langs/constants'; +const DEFAULT_PLACEMENT = DescriptionPlacement.BELOW; + type DescriptionFormProps = { id?: string; item?: DiscriminatedItem; @@ -27,12 +39,10 @@ const DescriptionForm = ({ }); }; - const onCheckBoxChanged = (checked: boolean): void => { + const onPlacementChanged = (placement: string): void => { setChanges({ settings: { - descriptionPlacement: checked - ? DescriptionPlacement.ABOVE - : DescriptionPlacement.BELOW, + descriptionPlacement: placement as DescriptionPlacementType, }, }); }; @@ -45,20 +55,27 @@ const DescriptionForm = ({ onChange={onChange} showActions={false} /> - onCheckBoxChanged(checked)} - /> - } - label={t(BUILDER.ITEM_SETTINGS_DESCRIPTION_PLACEMENT_ABOVE)} - /> + + + {t(BUILDER.ITEM_SETTINGS_DESCRIPTION_PLACEMENT_LABEL)} + + + ); }; diff --git a/src/langs/constants.ts b/src/langs/constants.ts index a53a90535..2f9d6afc5 100644 --- a/src/langs/constants.ts +++ b/src/langs/constants.ts @@ -412,4 +412,8 @@ export const BUILDER = { 'ITEM_SETTINGS_IS_COLLAPSED_ENABLED_TEXT', ITEM_SETTINGS_DESCRIPTION_PLACEMENT_ABOVE: 'ITEM_SETTINGS_DESCRIPTION_PLACEMENT_ABOVE', + ITEM_SETTINGS_DESCRIPTION_PLACEMENT_BELOW: + 'ITEM_SETTINGS_DESCRIPTION_PLACEMENT_BELOW', + ITEM_SETTINGS_DESCRIPTION_PLACEMENT_LABEL: + 'ITEM_SETTINGS_DESCRIPTION_PLACEMENT_LABEL', }; diff --git a/src/langs/en.json b/src/langs/en.json index 6d87c4ae1..e859a4207 100644 --- a/src/langs/en.json +++ b/src/langs/en.json @@ -349,5 +349,7 @@ "ITEM_SETTINGS_IS_COLLAPSED_DISABLED_TEXT": "This item is not collapsed", "ITEM_SETTINGS_IS_COLLAPSED_ENABLED_TEXT": "This item is collapsed", "ITEM_SETTINGS_IS_COLLAPSED_TITLE": "Collapse item", - "ITEM_SETTINGS_DESCRIPTION_PLACEMENT_ABOVE": "Display the description above the content" + "ITEM_SETTINGS_DESCRIPTION_PLACEMENT_ABOVE": "Display the description above the content", + "ITEM_SETTINGS_DESCRIPTION_PLACEMENT_BELOW": "Display the description below the content", + "ITEM_SETTINGS_DESCRIPTION_PLACEMENT_LABEL": "Placement of the description" } diff --git a/src/langs/fr.json b/src/langs/fr.json index ad88f09e9..7995db006 100644 --- a/src/langs/fr.json +++ b/src/langs/fr.json @@ -338,5 +338,7 @@ "ITEM_SETTINGS_IS_COLLAPSED_DISABLED_TEXT": "Cet élément n'est pas minifié", "ITEM_SETTINGS_IS_COLLAPSED_ENABLED_TEXT": "Cet élément est minifié", "ITEM_SETTINGS_IS_COLLAPSED_TITLE": "Minifier un élément", - "ITEM_SETTINGS_DESCRIPTION_PLACEMENT_ABOVE": "Afficher la description au-dessus du contenu" + "ITEM_SETTINGS_DESCRIPTION_PLACEMENT_ABOVE": "Afficher la description au-dessus du contenu", + "ITEM_SETTINGS_DESCRIPTION_PLACEMENT_BELOW": "Afficher la description en-dessous du contenu", + "ITEM_SETTINGS_DESCRIPTION_PLACEMENT_LABEL": "Placement de la description" } From 82157395e736bf148c42095d968364c3fd74f88f Mon Sep 17 00:00:00 2001 From: Thibault Reidy Date: Wed, 6 Mar 2024 08:43:33 +0100 Subject: [PATCH 3/7] feat: update query-client to 2.8.0 --- package.json | 2 +- yarn.lock | 18 +++++------------- 2 files changed, 6 insertions(+), 14 deletions(-) diff --git a/package.json b/package.json index 90efdff84..6bee74bc7 100644 --- a/package.json +++ b/package.json @@ -20,7 +20,7 @@ "@emotion/react": "11.11.4", "@emotion/styled": "11.11.0", "@graasp/chatbox": "3.1.0", - "@graasp/query-client": "github:graasp/graasp-query-client#694-display-description-above-or-below-item", + "@graasp/query-client": "2.8.0", "@graasp/sdk": "4.1.0", "@graasp/translations": "1.25.2", "@graasp/ui": "4.9.0", diff --git a/yarn.lock b/yarn.lock index 81d3935f3..386f57bb0 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1458,21 +1458,20 @@ __metadata: languageName: node linkType: hard -"@graasp/query-client@github:graasp/graasp-query-client#694-display-description-above-or-below-item": - version: 2.7.1 - resolution: "@graasp/query-client@https://github.com/graasp/graasp-query-client.git#commit=38a39f2d84011762b35b81b7fbb7f88a53d92e58" +"@graasp/query-client@npm:2.8.0": + version: 2.8.0 + resolution: "@graasp/query-client@npm:2.8.0" dependencies: "@tanstack/react-query": "npm:4.36.1" "@tanstack/react-query-devtools": "npm:4.36.1" axios: "npm:1.6.7" - crypto-js: "npm:4.2.0" http-status-codes: "npm:2.3.0" qs: "npm:6.11.2" peerDependencies: "@graasp/sdk": ^4.0.0 "@graasp/translations": ^1.23.0 react: ^18.0.0 - checksum: 10/38eb9762c13c029dca861c03b36ecad70e3718a90bded965c14cb1435397feea96ca6dcfaaca190d52f8a2386d8dd8c9d38bd847ea8e321a4296187eea9f3b4f + checksum: 10/45b85f125668c5824c26fc866a89d71ee38d886bf1172c0176bbd8b4f64eda88c47ea9668c9705ec5ef4c2dd1204464ae7d62befd72c82ac2963b1f2bee5f050 languageName: node linkType: hard @@ -5085,13 +5084,6 @@ __metadata: languageName: node linkType: hard -"crypto-js@npm:4.2.0": - version: 4.2.0 - resolution: "crypto-js@npm:4.2.0" - checksum: 10/c7bcc56a6e01c3c397e95aa4a74e4241321f04677f9a618a8f48a63b5781617248afb9adb0629824792e7ec20ca0d4241a49b6b2938ae6f973ec4efc5c53c924 - languageName: node - linkType: hard - "css-box-model@npm:^1.2.0": version: 1.2.1 resolution: "css-box-model@npm:1.2.1" @@ -7239,7 +7231,7 @@ __metadata: "@emotion/react": "npm:11.11.4" "@emotion/styled": "npm:11.11.0" "@graasp/chatbox": "npm:3.1.0" - "@graasp/query-client": "github:graasp/graasp-query-client#694-display-description-above-or-below-item" + "@graasp/query-client": "npm:2.8.0" "@graasp/sdk": "npm:4.1.0" "@graasp/translations": "npm:1.25.2" "@graasp/ui": "npm:4.9.0" From d80a90456a7025c866fa77aafeecdf596ee49dd4 Mon Sep 17 00:00:00 2001 From: Thibault Reidy Date: Wed, 6 Mar 2024 10:10:47 +0100 Subject: [PATCH 4/7] feat: remove displaying description above folder --- src/components/main/ItemsGrid.tsx | 15 +-------------- src/components/main/ItemsTable.tsx | 5 ----- src/components/main/ItemsToolbar.tsx | 28 ++++++++++++---------------- 3 files changed, 13 insertions(+), 35 deletions(-) diff --git a/src/components/main/ItemsGrid.tsx b/src/components/main/ItemsGrid.tsx index d6fc4eb4c..494ff0040 100644 --- a/src/components/main/ItemsGrid.tsx +++ b/src/components/main/ItemsGrid.tsx @@ -1,13 +1,7 @@ import { Box, Grid, Pagination } from '@mui/material'; -import { - DescriptionPlacement, - DiscriminatedItem, - ItemMembership, - ResultOf, -} from '@graasp/sdk'; +import { DiscriminatedItem, ItemMembership, ResultOf } from '@graasp/sdk'; -import { hooks } from '@/config/queryClient'; import { ShowOnlyMeChangeType } from '@/config/types'; import { ITEM_PAGE_SIZE } from '../../config/constants'; @@ -20,8 +14,6 @@ import EmptyItem from './EmptyItem'; import ItemCard from './ItemCard'; import ItemsToolbar from './ItemsToolbar'; -const { useItem } = hooks; - type Props = { id?: string; items?: DiscriminatedItem[]; @@ -58,7 +50,6 @@ const ItemsGrid = ({ page = 1, }: Props): JSX.Element => { const pagesCount = Math.ceil(Math.max(1, totalCount / ITEM_PAGE_SIZE)); - const { data: parentItem } = useItem(parentId); const renderItems = () => { if (!items?.length) { return ( @@ -88,10 +79,6 @@ const ItemsGrid = ({ } - showSubTitleAbove={ - parentItem?.settings.descriptionPlacement === - DescriptionPlacement.ABOVE - } headerElements={headerElements} onShowOnlyMeChange={onShowOnlyMeChange} showOnlyMe={showOnlyMe} diff --git a/src/components/main/ItemsTable.tsx b/src/components/main/ItemsTable.tsx index 73aefcadf..5568427ad 100644 --- a/src/components/main/ItemsTable.tsx +++ b/src/components/main/ItemsTable.tsx @@ -2,7 +2,6 @@ import { useCallback } from 'react'; import { useNavigate, useParams } from 'react-router-dom'; import { - DescriptionPlacement, DiscriminatedItem, ItemMembership, ItemType, @@ -276,10 +275,6 @@ const ItemsTable = ({ : null} - showSubTitleAbove={ - parentItem?.settings.descriptionPlacement === - DescriptionPlacement.ABOVE - } headerElements={headerElements} onShowOnlyMeChange={onShowOnlyMeChange} showOnlyMe={showOnlyMe} diff --git a/src/components/main/ItemsToolbar.tsx b/src/components/main/ItemsToolbar.tsx index d4f6d4c04..382baf078 100644 --- a/src/components/main/ItemsToolbar.tsx +++ b/src/components/main/ItemsToolbar.tsx @@ -9,7 +9,6 @@ import SelectTypes from '../common/SelectTypes'; type Props = { title: string; subTitleElement?: JSX.Element | null; - showSubTitleAbove?: boolean; headerElements?: JSX.Element[]; onShowOnlyMeChange?: ShowOnlyMeChangeType; showOnlyMe?: boolean; @@ -18,7 +17,6 @@ type Props = { const ItemsToolbar = ({ title, subTitleElement, - showSubTitleAbove, headerElements, onShowOnlyMeChange, showOnlyMe, @@ -26,22 +24,20 @@ const ItemsToolbar = ({ const { t } = useBuilderTranslation(); return ( <> - - - - {title} - - - {headerElements} - + + + {title} + + + {headerElements} - {subTitleElement} + {subTitleElement} {onShowOnlyMeChange && ( Date: Wed, 6 Mar 2024 15:22:51 +0100 Subject: [PATCH 5/7] feat: add description placement in settings and edit item --- src/components/item/form/DescriptionForm.tsx | 51 +++++------------ .../item/form/DescriptionPlacementForm.tsx | 56 +++++++++++++++++++ .../settings/ItemSettingCheckBoxProperty.tsx | 41 ++++++++++++++ .../item/settings/ItemSettingProperty.tsx | 25 ++------- .../item/settings/ItemSettingsProperties.tsx | 42 ++++++++++---- src/langs/constants.ts | 6 +- src/langs/en.json | 7 ++- src/langs/fr.json | 7 ++- 8 files changed, 158 insertions(+), 77 deletions(-) create mode 100644 src/components/item/form/DescriptionPlacementForm.tsx create mode 100644 src/components/item/settings/ItemSettingCheckBoxProperty.tsx diff --git a/src/components/item/form/DescriptionForm.tsx b/src/components/item/form/DescriptionForm.tsx index 7e7286da1..c0acded90 100644 --- a/src/components/item/form/DescriptionForm.tsx +++ b/src/components/item/form/DescriptionForm.tsx @@ -1,22 +1,13 @@ -import { - FormControl, - InputLabel, - MenuItem, - Select, - Stack, -} from '@mui/material'; +import { Stack } from '@mui/material'; import { - DescriptionPlacement, DescriptionPlacementType, DiscriminatedItem, + ItemType, } from '@graasp/sdk'; import TextEditor from '@graasp/ui/text-editor'; -import { useBuilderTranslation } from '@/config/i18n'; -import { BUILDER } from '@/langs/constants'; - -const DEFAULT_PLACEMENT = DescriptionPlacement.BELOW; +import DescriptionPlacementForm from './DescriptionPlacementForm'; type DescriptionFormProps = { id?: string; @@ -31,51 +22,35 @@ const DescriptionForm = ({ item, setChanges, }: DescriptionFormProps): JSX.Element => { - const { t } = useBuilderTranslation(); - const onChange = (content: string): void => { setChanges({ description: content, }); }; - const onPlacementChanged = (placement: string): void => { + const onPlacementChanged = (placement: DescriptionPlacementType): void => { setChanges({ settings: { - descriptionPlacement: placement as DescriptionPlacementType, + descriptionPlacement: placement, }, }); }; return ( - + - - - {t(BUILDER.ITEM_SETTINGS_DESCRIPTION_PLACEMENT_LABEL)} - - - + + {updatedProperties.type !== ItemType.FOLDER && ( + + )} ); }; diff --git a/src/components/item/form/DescriptionPlacementForm.tsx b/src/components/item/form/DescriptionPlacementForm.tsx new file mode 100644 index 000000000..b5dc0f434 --- /dev/null +++ b/src/components/item/form/DescriptionPlacementForm.tsx @@ -0,0 +1,56 @@ +import { MenuItem, Select } from '@mui/material'; + +import { + DescriptionPlacement, + DescriptionPlacementType, + DiscriminatedItem, +} from '@graasp/sdk'; + +import { useBuilderTranslation } from '@/config/i18n'; +import { BUILDER } from '@/langs/constants'; + +import ItemSettingProperty from '../settings/ItemSettingProperty'; + +const DEFAULT_PLACEMENT = DescriptionPlacement.BELOW; + +type DescriptionPlacementFormProps = { + updatedProperties: Partial; + onPlacementChanged: (payload: DescriptionPlacementType) => void; +}; + +const DescriptionPlacementForm = ({ + updatedProperties, + onPlacementChanged, +}: DescriptionPlacementFormProps): JSX.Element | null => { + const { t } = useBuilderTranslation(); + + const handlePlacementChanged = (placement: string): void => { + onPlacementChanged(placement as DescriptionPlacementType); + }; + + return ( + handlePlacementChanged(e.target.value)} + size="small" + > + + {t(BUILDER.ITEM_SETTINGS_DESCRIPTION_PLACEMENT_ABOVE)} + + + {t(BUILDER.ITEM_SETTINGS_DESCRIPTION_PLACEMENT_BELOW)} + + + } + /> + ); +}; + +export default DescriptionPlacementForm; diff --git a/src/components/item/settings/ItemSettingCheckBoxProperty.tsx b/src/components/item/settings/ItemSettingCheckBoxProperty.tsx new file mode 100644 index 000000000..bca578f99 --- /dev/null +++ b/src/components/item/settings/ItemSettingCheckBoxProperty.tsx @@ -0,0 +1,41 @@ +import { Switch } from '@mui/material'; + +import ItemSettingProperty from './ItemSettingProperty'; + +type Props = { + onClick: (checked: boolean) => void; + title: string; + checked: boolean; + valueText: string; + id?: string; + disabled?: boolean; + icon?: JSX.Element; +}; + +const ItemSettingCheckBoxProperty = ({ + onClick, + title, + checked = false, + id, + disabled, + icon, + valueText, +}: Props): JSX.Element => ( + { + onClick(e.target.checked); + }} + /> + } + /> +); + +export default ItemSettingCheckBoxProperty; diff --git a/src/components/item/settings/ItemSettingProperty.tsx b/src/components/item/settings/ItemSettingProperty.tsx index 7e86307e3..1ece7a4b8 100644 --- a/src/components/item/settings/ItemSettingProperty.tsx +++ b/src/components/item/settings/ItemSettingProperty.tsx @@ -1,23 +1,17 @@ -import { Stack, Switch, Typography } from '@mui/material'; +import { Stack, Typography } from '@mui/material'; type Props = { - onClick: (checked: boolean) => void; title: string; - checked: boolean; valueText: string; - id?: string; - disabled?: boolean; + inputSetting: JSX.Element; icon?: JSX.Element; }; const ItemSettingProperty = ({ - onClick, title, - checked = false, - id, - disabled, - icon, valueText, + inputSetting, + icon, }: Props): JSX.Element => ( - - { - onClick(e.target.checked); - }} - /> - + {inputSetting} ); diff --git a/src/components/item/settings/ItemSettingsProperties.tsx b/src/components/item/settings/ItemSettingsProperties.tsx index ddf3f723a..5da84aad6 100644 --- a/src/components/item/settings/ItemSettingsProperties.tsx +++ b/src/components/item/settings/ItemSettingsProperties.tsx @@ -18,25 +18,28 @@ import { } from '@/config/selectors'; import { BUILDER } from '@/langs/constants'; +import DescriptionPlacementForm from '../form/DescriptionPlacementForm'; import FileSettings from './FileSettings'; -import ItemSettingProperty from './ItemSettingProperty'; +import ItemSettingCheckBoxProperty from './ItemSettingCheckBoxProperty'; import LinkSettings from './LinkSettings'; type Props = { item: DiscriminatedItem; }; +type ItemSetting = DiscriminatedItem['settings']; + const ItemSettingsProperties = ({ item }: Props): JSX.Element => { const { t: translateBuilder } = useBuilderTranslation(); const { mutate: editItem } = mutations.useEditItem(); const { settings } = item; - const handleOnToggle = ( - event: { target: { checked: boolean } }, - settingKey: string, - ): void => { - const newValue = event.target.checked; + // TODO: remove | string in settingKey when enableAnalytics is added to settings in SDK... + const handleSettingChanged = ( + settingKey: K | string, + newValue: unknown, + ) => { editItem({ id: item.id, name: item.name, @@ -46,6 +49,13 @@ const ItemSettingsProperties = ({ item }: Props): JSX.Element => { }); }; + const handleOnToggle = ( + event: { target: { checked: boolean } }, + settingKey: K | string, + ): void => { + handleSettingChanged(settingKey, event.target.checked); + }; + const renderSettingsPerType = () => { switch (item.type) { case ItemType.LINK: @@ -55,7 +65,7 @@ const ItemSettingsProperties = ({ item }: Props): JSX.Element => { return ; case ItemType.APP: return ( - { {translateBuilder(BUILDER.SETTINGS_TITLE)} - } checked={Boolean(settings.isCollapsible)} @@ -105,7 +115,7 @@ const ItemSettingsProperties = ({ item }: Props): JSX.Element => { })()} /> - { } /> - { : translateBuilder(BUILDER.ITEM_SETTINGS_SHOW_CHAT_DISABLED_TEXT) } /> - { + // TODO: add enableAnalytics in the ItemSettings type handleOnToggle({ target: { checked } }, 'enableAnalytics'); }} valueText="Coming soon" @@ -158,6 +169,15 @@ const ItemSettingsProperties = ({ item }: Props): JSX.Element => { /> {renderSettingsPerType()} + + {item.type !== ItemType.FOLDER && ( + + handleSettingChanged('descriptionPlacement', newPlacement) + } + /> + )} ); }; diff --git a/src/langs/constants.ts b/src/langs/constants.ts index 2f9d6afc5..a95076f0b 100644 --- a/src/langs/constants.ts +++ b/src/langs/constants.ts @@ -414,6 +414,8 @@ export const BUILDER = { 'ITEM_SETTINGS_DESCRIPTION_PLACEMENT_ABOVE', ITEM_SETTINGS_DESCRIPTION_PLACEMENT_BELOW: 'ITEM_SETTINGS_DESCRIPTION_PLACEMENT_BELOW', - ITEM_SETTINGS_DESCRIPTION_PLACEMENT_LABEL: - 'ITEM_SETTINGS_DESCRIPTION_PLACEMENT_LABEL', + ITEM_SETTINGS_DESCRIPTION_PLACEMENT_TITLE: + 'ITEM_SETTINGS_DESCRIPTION_PLACEMENT_TITLE', + ITEM_SETTINGS_DESCRIPTION_PLACEMENT_TEXT: + 'ITEM_SETTINGS_DESCRIPTION_PLACEMENT_TEXT', }; diff --git a/src/langs/en.json b/src/langs/en.json index e859a4207..1c91d4301 100644 --- a/src/langs/en.json +++ b/src/langs/en.json @@ -349,7 +349,8 @@ "ITEM_SETTINGS_IS_COLLAPSED_DISABLED_TEXT": "This item is not collapsed", "ITEM_SETTINGS_IS_COLLAPSED_ENABLED_TEXT": "This item is collapsed", "ITEM_SETTINGS_IS_COLLAPSED_TITLE": "Collapse item", - "ITEM_SETTINGS_DESCRIPTION_PLACEMENT_ABOVE": "Display the description above the content", - "ITEM_SETTINGS_DESCRIPTION_PLACEMENT_BELOW": "Display the description below the content", - "ITEM_SETTINGS_DESCRIPTION_PLACEMENT_LABEL": "Placement of the description" + "ITEM_SETTINGS_DESCRIPTION_PLACEMENT_ABOVE": "Above the content", + "ITEM_SETTINGS_DESCRIPTION_PLACEMENT_BELOW": "Below the content", + "ITEM_SETTINGS_DESCRIPTION_PLACEMENT_TITLE": "Placement", + "ITEM_SETTINGS_DESCRIPTION_PLACEMENT_TEXT": "Placement of the description" } diff --git a/src/langs/fr.json b/src/langs/fr.json index 7995db006..df3046606 100644 --- a/src/langs/fr.json +++ b/src/langs/fr.json @@ -338,7 +338,8 @@ "ITEM_SETTINGS_IS_COLLAPSED_DISABLED_TEXT": "Cet élément n'est pas minifié", "ITEM_SETTINGS_IS_COLLAPSED_ENABLED_TEXT": "Cet élément est minifié", "ITEM_SETTINGS_IS_COLLAPSED_TITLE": "Minifier un élément", - "ITEM_SETTINGS_DESCRIPTION_PLACEMENT_ABOVE": "Afficher la description au-dessus du contenu", - "ITEM_SETTINGS_DESCRIPTION_PLACEMENT_BELOW": "Afficher la description en-dessous du contenu", - "ITEM_SETTINGS_DESCRIPTION_PLACEMENT_LABEL": "Placement de la description" + "ITEM_SETTINGS_DESCRIPTION_PLACEMENT_ABOVE": "Au-dessus du contenu", + "ITEM_SETTINGS_DESCRIPTION_PLACEMENT_BELOW": "En-dessous du contenu", + "ITEM_SETTINGS_DESCRIPTION_PLACEMENT_TITLE": "Placement", + "ITEM_SETTINGS_DESCRIPTION_PLACEMENT_TEXT": "Placement de la description" } From 06bbcb0a499dc1b41df8869b3d14f6f2b519d5ff Mon Sep 17 00:00:00 2001 From: Thibault Reidy Date: Wed, 6 Mar 2024 16:26:50 +0100 Subject: [PATCH 6/7] test: add tests to verify description placement feature --- cypress/e2e/item/create/createFolder.cy.ts | 12 ++++++ cypress/e2e/item/edit/editFile.cy.ts | 25 ++++++++++++ cypress/e2e/item/settings/itemSettings.cy.ts | 39 ++++++++++++++++++- .../item/form/DescriptionPlacementForm.tsx | 15 ++++++- src/config/selectors.ts | 7 ++++ 5 files changed, 95 insertions(+), 3 deletions(-) diff --git a/cypress/e2e/item/create/createFolder.cy.ts b/cypress/e2e/item/create/createFolder.cy.ts index f1213ae63..d9a680012 100644 --- a/cypress/e2e/item/create/createFolder.cy.ts +++ b/cypress/e2e/item/create/createFolder.cy.ts @@ -3,6 +3,7 @@ import { CREATE_ITEM_BUTTON_ID, ITEM_FORM_CONFIRM_BUTTON_ID, ITEM_FORM_NAME_INPUT_ID, + ITEM_SETTING_DESCRIPTION_PLACEMENT_SELECT_ID, buildItemsTableRowIdAttribute, } from '../../../../src/config/selectors'; import ItemLayoutMode from '../../../../src/enums/itemLayoutMode'; @@ -52,6 +53,17 @@ describe('Create Folder', () => { true, ); }); + + it('description placement should not exist for folder', () => { + // create + cy.setUpApi(); + cy.visit(HOME_PATH); + createFolder(CREATED_BLANK_NAME_ITEM, { confirm: false }); + + cy.get(`#${ITEM_SETTING_DESCRIPTION_PLACEMENT_SELECT_ID}`).should( + 'not.exist', + ); + }); }); describe('Grid', () => { diff --git a/cypress/e2e/item/edit/editFile.cy.ts b/cypress/e2e/item/edit/editFile.cy.ts index ff529a14b..0271c3add 100644 --- a/cypress/e2e/item/edit/editFile.cy.ts +++ b/cypress/e2e/item/edit/editFile.cy.ts @@ -1,7 +1,12 @@ +import { DescriptionPlacement } from '@graasp/sdk'; + import { HOME_PATH, buildItemPath } from '../../../../src/config/paths'; import { EDIT_ITEM_MODAL_CANCEL_BUTTON_ID, + ITEM_FORM_CONFIRM_BUTTON_ID, + ITEM_SETTING_DESCRIPTION_PLACEMENT_SELECT_ID, TEXT_EDITOR_CLASS, + buildDescriptionPlacementId, buildEditButtonId, } from '../../../../src/config/selectors'; import { ItemLayoutMode } from '../../../../src/enums'; @@ -28,6 +33,26 @@ describe('Edit File', () => { }); }); + it('edit description placement to above', () => { + const { id } = IMAGE_ITEM_DEFAULT; + cy.visit(buildItemPath(id)); + + cy.get(`#${buildEditButtonId(id)}`).click(); + + cy.get(`#${ITEM_SETTING_DESCRIPTION_PLACEMENT_SELECT_ID}`).click(); + cy.get( + `#${buildDescriptionPlacementId(DescriptionPlacement.ABOVE)}`, + ).click(); + cy.get(`#${ITEM_FORM_CONFIRM_BUTTON_ID}`).click(); + + cy.wait(`@editItem`).then(({ request: { url, body } }) => { + expect(url).to.contain(id); + expect(body?.settings).to.contain({ + descriptionPlacement: DescriptionPlacement.ABOVE, + }); + }); + }); + it("edit s3File's caption", () => { const { id } = VIDEO_ITEM_S3; cy.visit(buildItemPath(id)); diff --git a/cypress/e2e/item/settings/itemSettings.cy.ts b/cypress/e2e/item/settings/itemSettings.cy.ts index 5955fd587..a680cc989 100644 --- a/cypress/e2e/item/settings/itemSettings.cy.ts +++ b/cypress/e2e/item/settings/itemSettings.cy.ts @@ -1,4 +1,9 @@ -import { ItemType, MaxWidth, getFileExtra } from '@graasp/sdk'; +import { + DescriptionPlacement, + ItemType, + MaxWidth, + getFileExtra, +} from '@graasp/sdk'; import { langs } from '@graasp/translations'; import { getMemberById } from '@/utils/member'; @@ -17,12 +22,14 @@ import { ITEM_PANEL_NAME_ID, ITEM_PANEL_TABLE_ID, ITEM_SETTINGS_BUTTON_CLASS, + ITEM_SETTING_DESCRIPTION_PLACEMENT_SELECT_ID, LANGUAGE_SELECTOR_ID, SETTINGS_CHATBOX_TOGGLE_ID, SETTINGS_LINK_SHOW_BUTTON_ID, SETTINGS_LINK_SHOW_IFRAME_ID, SETTINGS_PINNED_TOGGLE_ID, SETTINGS_SAVE_ACTIONS_TOGGLE_ID, + buildDescriptionPlacementId, } from '../../../../src/config/selectors'; import { ITEM_WITH_CHATBOX_MESSAGES, @@ -372,5 +379,35 @@ describe('Item Settings', () => { ); }); }); + + describe('DescriptionPlacement Settings', () => { + it('folder should not have description placement', () => { + const { id, type } = ITEMS_SETTINGS.items[1]; + cy.visit(buildItemSettingsPath(id)); + + cy.get(`#${ITEM_PANEL_TABLE_ID}`).contains(type); + + cy.get(`#${ITEM_SETTING_DESCRIPTION_PLACEMENT_SELECT_ID}`).should( + 'not.exist', + ); + }); + + it('update placement to above for file', () => { + const { id } = IMAGE_ITEM_DEFAULT; + cy.visit(buildItemSettingsPath(id)); + + cy.get(`#${ITEM_SETTING_DESCRIPTION_PLACEMENT_SELECT_ID}`).click(); + cy.get( + `#${buildDescriptionPlacementId(DescriptionPlacement.ABOVE)}`, + ).click(); + + cy.wait(`@editItem`).then(({ request: { url, body } }) => { + expect(url).to.contain(id); + expect(body?.settings).to.contain({ + descriptionPlacement: DescriptionPlacement.ABOVE, + }); + }); + }); + }); }); }); diff --git a/src/components/item/form/DescriptionPlacementForm.tsx b/src/components/item/form/DescriptionPlacementForm.tsx index b5dc0f434..6cabb785e 100644 --- a/src/components/item/form/DescriptionPlacementForm.tsx +++ b/src/components/item/form/DescriptionPlacementForm.tsx @@ -7,6 +7,10 @@ import { } from '@graasp/sdk'; import { useBuilderTranslation } from '@/config/i18n'; +import { + ITEM_SETTING_DESCRIPTION_PLACEMENT_SELECT_ID, + buildDescriptionPlacementId, +} from '@/config/selectors'; import { BUILDER } from '@/langs/constants'; import ItemSettingProperty from '../settings/ItemSettingProperty'; @@ -34,6 +38,7 @@ const DescriptionPlacementForm = ({ valueText={t(BUILDER.ITEM_SETTINGS_DESCRIPTION_PLACEMENT_TEXT)} inputSetting={ diff --git a/src/config/selectors.ts b/src/config/selectors.ts index d45676837..16c53760f 100644 --- a/src/config/selectors.ts +++ b/src/config/selectors.ts @@ -1,5 +1,7 @@ // todo: this makes tests slow because it compiles ui everytime // import { Platform } from '@graasp/ui'; +import { DescriptionPlacementType } from '@graasp/sdk'; + import { ShortLinkPlatform } from '@/utils/shortLink'; export const SHARED_ITEMS_ROOT_CONTAINER = 'sharedItemsPageRootContainer'; @@ -348,3 +350,8 @@ export const ACCESSIBLE_ITEMS_NEXT_PAGE_BUTTON_SELECTOR = `#${ACCESSIBLE_ITEMS_T export const MY_GRAASP_ITEM_PATH = 'myGraaspItemPath'; export const LANGUAGE_SELECTOR_ID = 'languageSelector'; export const LAYOUT_MODE_BUTTON_ID = 'layoutModeButton'; +export const ITEM_SETTING_DESCRIPTION_PLACEMENT_SELECT_ID = + 'itemSettingDescriptionPlacementSelect'; +export const buildDescriptionPlacementId = ( + placement: DescriptionPlacementType, +): string => `itemSettingDescriptionPlacement-${placement}`; From e0dacb3b1a417025d1251f5180b04d8502274971 Mon Sep 17 00:00:00 2001 From: Thibault Reidy Date: Wed, 6 Mar 2024 16:35:19 +0100 Subject: [PATCH 7/7] feat: remove description of the description's placement setting --- src/components/item/form/DescriptionPlacementForm.tsx | 1 - src/components/item/settings/ItemSettingProperty.tsx | 10 ++++++---- src/langs/constants.ts | 2 -- src/langs/en.json | 3 +-- src/langs/fr.json | 3 +-- 5 files changed, 8 insertions(+), 11 deletions(-) diff --git a/src/components/item/form/DescriptionPlacementForm.tsx b/src/components/item/form/DescriptionPlacementForm.tsx index 6cabb785e..73af54479 100644 --- a/src/components/item/form/DescriptionPlacementForm.tsx +++ b/src/components/item/form/DescriptionPlacementForm.tsx @@ -35,7 +35,6 @@ const DescriptionPlacementForm = ({ return ( - - {valueText} - + {valueText && ( + + {valueText} + + )} {inputSetting} diff --git a/src/langs/constants.ts b/src/langs/constants.ts index a95076f0b..038b5aec4 100644 --- a/src/langs/constants.ts +++ b/src/langs/constants.ts @@ -416,6 +416,4 @@ export const BUILDER = { 'ITEM_SETTINGS_DESCRIPTION_PLACEMENT_BELOW', ITEM_SETTINGS_DESCRIPTION_PLACEMENT_TITLE: 'ITEM_SETTINGS_DESCRIPTION_PLACEMENT_TITLE', - ITEM_SETTINGS_DESCRIPTION_PLACEMENT_TEXT: - 'ITEM_SETTINGS_DESCRIPTION_PLACEMENT_TEXT', }; diff --git a/src/langs/en.json b/src/langs/en.json index 1c91d4301..3adf95635 100644 --- a/src/langs/en.json +++ b/src/langs/en.json @@ -351,6 +351,5 @@ "ITEM_SETTINGS_IS_COLLAPSED_TITLE": "Collapse item", "ITEM_SETTINGS_DESCRIPTION_PLACEMENT_ABOVE": "Above the content", "ITEM_SETTINGS_DESCRIPTION_PLACEMENT_BELOW": "Below the content", - "ITEM_SETTINGS_DESCRIPTION_PLACEMENT_TITLE": "Placement", - "ITEM_SETTINGS_DESCRIPTION_PLACEMENT_TEXT": "Placement of the description" + "ITEM_SETTINGS_DESCRIPTION_PLACEMENT_TITLE": "Placement of the description" } diff --git a/src/langs/fr.json b/src/langs/fr.json index df3046606..251f291e7 100644 --- a/src/langs/fr.json +++ b/src/langs/fr.json @@ -340,6 +340,5 @@ "ITEM_SETTINGS_IS_COLLAPSED_TITLE": "Minifier un élément", "ITEM_SETTINGS_DESCRIPTION_PLACEMENT_ABOVE": "Au-dessus du contenu", "ITEM_SETTINGS_DESCRIPTION_PLACEMENT_BELOW": "En-dessous du contenu", - "ITEM_SETTINGS_DESCRIPTION_PLACEMENT_TITLE": "Placement", - "ITEM_SETTINGS_DESCRIPTION_PLACEMENT_TEXT": "Placement de la description" + "ITEM_SETTINGS_DESCRIPTION_PLACEMENT_TITLE": "Placement de la description" }