From 48174ee3d0fcf3475576481efca8ecbfe791ff7b Mon Sep 17 00:00:00 2001 From: Abdelhalim Khouas Date: Mon, 8 Jan 2024 14:10:39 +0300 Subject: [PATCH 1/6] add search input in media panel --- .../itemBrowser/ItemBrowser.styles.tsx | 16 +++ src/components/itemBrowser/ItemBrowser.tsx | 102 +++++++++++++++--- 2 files changed, 103 insertions(+), 15 deletions(-) diff --git a/src/components/itemBrowser/ItemBrowser.styles.tsx b/src/components/itemBrowser/ItemBrowser.styles.tsx index f86297aa..a13b6e3f 100644 --- a/src/components/itemBrowser/ItemBrowser.styles.tsx +++ b/src/components/itemBrowser/ItemBrowser.styles.tsx @@ -88,3 +88,19 @@ export const BreadCrumbsWrapper = styled.div` display: flex; margin-bottom: 1rem; `; + +export const SearchInputWrapper = styled.div<{ hasSearchQuery?: boolean; isMobile?: boolean }>` + width: ${(props) => (props.isMobile ? '100%' : '16.25rem')}; + ${(props) => + props.hasSearchQuery && + ` + margin-bottom: 1rem; + `}; +`; + +export const EmptySearchResultContainer = styled.div` + padding: 0 3.75rem 0 calc(3.75rem - 1.25rem); + color: ${Colors.SECONDARY_FONT}; + font-size: 0.875rem; + text-align: center; +`; diff --git a/src/components/itemBrowser/ItemBrowser.tsx b/src/components/itemBrowser/ItemBrowser.tsx index f2a1b7a0..a4f3711e 100644 --- a/src/components/itemBrowser/ItemBrowser.tsx +++ b/src/components/itemBrowser/ItemBrowser.tsx @@ -1,7 +1,10 @@ import { + AvailableIcons, BreadCrumb, PreviewCard as ChiliPreview, Colors, + Icon, + Input, Panel, PreviewCardVariant, PreviewType, @@ -15,7 +18,13 @@ import { useVariablePanelContext } from '../../contexts/VariablePanelContext'; import { ContentType } from '../../contexts/VariablePanelContext.types'; import { AssetType } from '../../utils/ApiTypes'; import { getDataIdForSUI, getDataTestIdForSUI } from '../../utils/dataIds'; -import { BreadCrumbsWrapper, LoadPageContainer, ResourcesContainer } from './ItemBrowser.styles'; +import { + BreadCrumbsWrapper, + LoadPageContainer, + ResourcesContainer, + SearchInputWrapper, + EmptySearchResultContainer, +} from './ItemBrowser.styles'; import { ItemCache } from './ItemCache'; const TOP_BAR_HEIGHT_REM = '4rem'; @@ -68,6 +77,8 @@ function ItemBrowser< }); const [isLoading, setIsLoading] = useState(false); const [list, setList] = useState[]>([]); + const [searchKeyWord, setSearchKeyWord] = useState(''); + const [searchQuery, setSearchQuery] = useState(''); const moreData = !!nextPageToken?.token; const { @@ -94,7 +105,7 @@ function ItemBrowser< return { token: null, requested: true }; }); setList(() => []); - }, [navigationStack]); + }, [navigationStack, searchQuery]); useEffect(() => { setBreadcrumbStack([]); @@ -110,7 +121,6 @@ function ItemBrowser< // in case the useEffect runs again (dependencies change) while the promise did not resolve, the cleanup function // makes sure that the result that is not relevant anymore, won't affect the state. let ignore = false; - if (!nextPageToken.requested) return; setIsLoading(true); // declare the async data fetching function @@ -123,6 +133,7 @@ function ItemBrowser< collection: `/${navigationStack?.join('/') ?? ''}`, pageToken: nextPageToken.token ? nextPageToken.token : '', pageSize: 15, + filter: [searchQuery], }, {}, ); @@ -168,7 +179,7 @@ function ItemBrowser< ignore = true; }; // eslint-disable-next-line react-hooks/exhaustive-deps - }, [nextPageToken, contentType]); + }, [nextPageToken, contentType, searchQuery]); useEffect(() => { return () => { @@ -251,6 +262,11 @@ function ItemBrowser< // eslint-disable-next-line no-nested-ternary const panelTitle = isMobileSize ? null : contentType === ContentType.IMAGE_PANEL ? imagePanelTitle : null; + const handleSearch = (keyword: string) => { + setSearchQuery(keyword); + setNavigationStack([]); + setBreadcrumbStack([]); + }; return ( - - { - const newNavigationStack = navigationStack?.splice(0, navigationStack.indexOf(breadCrumb) + 1); - const newBreadcrumbStack = breadcrumbStack?.splice(0, breadcrumbStack.indexOf(breadCrumb) + 1); - setNavigationStack(newNavigationStack); - setBreadcrumbStack(newBreadcrumbStack); + + setSearchKeyWord(e.target.value)} + onBlur={() => handleSearch(searchKeyWord)} + width="260px" + leftIcon={{ + icon: ( + + ), + label: 'Search icon', }} + dataId={getDataIdForSUI('media-panel-search-input')} + dataTestId={getDataTestIdForSUI('media-panel-search-input')} + rightIcon={ + searchKeyWord + ? { + label: 'Clear search icon', + icon: ( + + ), + onClick: () => { + setSearchKeyWord(''); + setSearchQuery(''); + }, + } + : undefined + } + isHighlightOnClick /> - + + {!searchQuery && ( + + { + const newNavigationStack = navigationStack?.splice( + 0, + navigationStack.indexOf(breadCrumb) + 1, + ); + const newBreadcrumbStack = breadcrumbStack?.splice( + 0, + breadcrumbStack.indexOf(breadCrumb) + 1, + ); + setNavigationStack(newNavigationStack); + setBreadcrumbStack(newBreadcrumbStack); + }} + /> + + )} + {elements.length === 0 && !isLoading && searchQuery && ( + + No search results found. Maybe try another keyword? + + )} Date: Thu, 11 Jan 2024 10:48:50 +0300 Subject: [PATCH 2/6] Add search input to assets panel --- src/components/itemBrowser/ItemBrowser.tsx | 90 +++++++++++----------- 1 file changed, 47 insertions(+), 43 deletions(-) diff --git a/src/components/itemBrowser/ItemBrowser.tsx b/src/components/itemBrowser/ItemBrowser.tsx index a4f3711e..5013eb58 100644 --- a/src/components/itemBrowser/ItemBrowser.tsx +++ b/src/components/itemBrowser/ItemBrowser.tsx @@ -218,6 +218,8 @@ function ItemBrowser< } else { selectItem(listItem.instance); setNavigationStack([]); + setSearchQuery(''); + setSearchKeyWord(''); } }; @@ -276,49 +278,51 @@ function ItemBrowser< isModal={false} padding="0" > - - setSearchKeyWord(e.target.value)} - onBlur={() => handleSearch(searchKeyWord)} - width="260px" - leftIcon={{ - icon: ( - - ), - label: 'Search icon', - }} - dataId={getDataIdForSUI('media-panel-search-input')} - dataTestId={getDataTestIdForSUI('media-panel-search-input')} - rightIcon={ - searchKeyWord - ? { - label: 'Clear search icon', - icon: ( - - ), - onClick: () => { - setSearchKeyWord(''); - setSearchQuery(''); - }, - } - : undefined - } - isHighlightOnClick - /> - + {connectorCapabilities[connectorId]?.filtering && ( + + setSearchKeyWord(e.target.value)} + onBlur={() => handleSearch(searchKeyWord)} + width="260px" + leftIcon={{ + icon: ( + + ), + label: 'Search icon', + }} + dataId={getDataIdForSUI('media-panel-search-input')} + dataTestId={getDataTestIdForSUI('media-panel-search-input')} + rightIcon={ + searchKeyWord + ? { + label: 'Clear search icon', + icon: ( + + ), + onClick: () => { + setSearchKeyWord(''); + setSearchQuery(''); + }, + } + : undefined + } + isHighlightOnClick + /> + + )} {!searchQuery && ( Date: Thu, 11 Jan 2024 10:49:32 +0300 Subject: [PATCH 3/6] make search and breadcrumbs positon fixed on mobile --- src/components/itemBrowser/ItemBrowser.styles.tsx | 3 +++ src/components/variables/VariablesPanel.tsx | 1 + 2 files changed, 4 insertions(+) diff --git a/src/components/itemBrowser/ItemBrowser.styles.tsx b/src/components/itemBrowser/ItemBrowser.styles.tsx index a13b6e3f..a0401ef8 100644 --- a/src/components/itemBrowser/ItemBrowser.styles.tsx +++ b/src/components/itemBrowser/ItemBrowser.styles.tsx @@ -9,6 +9,9 @@ export const ResourcesContainer = styled.div` ${mobileMediaQuery} { grid-template-columns: minmax(7.5rem, 1fr) minmax(7.5rem, 1fr); gap: 1rem; + max-height: 500px; + overflow: scroll; + height: auto; } `; diff --git a/src/components/variables/VariablesPanel.tsx b/src/components/variables/VariablesPanel.tsx index f00559de..f50ebc62 100644 --- a/src/components/variables/VariablesPanel.tsx +++ b/src/components/variables/VariablesPanel.tsx @@ -59,6 +59,7 @@ function VariablesPanel(props: VariablesPanelProps) { onTrayHidden={showVariablesPanel} styles={css` height: ${contentType === ContentType.IMAGE_PANEL ? '100%' : 'auto'}; + overflow: ${showVariablesList ? 'auto' : 'hidden'}; `} hideCloseButton={mobileOptionsListOpen} > From 9b3192a465431a79c2786ccde13166048edf3b40 Mon Sep 17 00:00:00 2001 From: Abdelhalim Khouas Date: Thu, 11 Jan 2024 11:53:02 +0300 Subject: [PATCH 4/6] Add test cases to the search input --- src/tests/LeftPanel.test.tsx | 62 +++++++++++++++++++++++++++++++++--- 1 file changed, 58 insertions(+), 4 deletions(-) diff --git a/src/tests/LeftPanel.test.tsx b/src/tests/LeftPanel.test.tsx index ad709227..234cdac3 100644 --- a/src/tests/LeftPanel.test.tsx +++ b/src/tests/LeftPanel.test.tsx @@ -1,6 +1,6 @@ import { getDataTestId } from '@chili-publish/grafx-shared-components'; import EditorSDK from '@chili-publish/studio-sdk'; -import { render, waitFor } from '@testing-library/react'; +import { render, waitFor, screen } from '@testing-library/react'; import { mock } from 'jest-mock-extended'; import { act } from 'react-dom/test-utils'; import LeftPanel from '../components/layout-panels/leftPanel/LeftPanel'; @@ -10,11 +10,11 @@ import { mockConnectors } from './mocks/mockConnectors'; import { variables } from './mocks/mockVariables'; import { getDataTestIdForSUI } from '../utils/dataIds'; +jest.mock('@chili-publish/studio-sdk'); +const mockSDK = mock(); + beforeEach(() => { - jest.mock('@chili-publish/studio-sdk'); - const mockSDK = mock(); global.URL.createObjectURL = jest.fn(); - mockSDK.mediaConnector.query = jest .fn() .mockImplementation() @@ -207,4 +207,58 @@ describe('Image Panel', () => { expect(window.SDK.variable.setImageVariableConnector).toBeCalledTimes(1); expect(window.SDK.variable.setValue).toBeCalledTimes(1); }); + test('Do not render search input when filtering is not supported', async () => { + mockSDK.mediaConnector.getCapabilities = jest + .fn() + .mockImplementation() + .mockReturnValue( + Promise.resolve({ + parsedData: { + copy: false, + detail: true, + filtering: false, + query: true, + remove: false, + upload: false, + }, + }), + ); + + const { getAllByTestId, getAllByRole } = render( + + + , + ); + const imagePicker = await waitFor(() => getAllByTestId(getDataTestId('image-picker-content'))[0]); + await act(async () => { + imagePicker.click(); + }); + const image = getAllByRole('img', { name: /grafx/i })[0]; + + await act(async () => { + image.click(); + }); + + const input = screen.queryByTestId(getDataTestIdForSUI('media-panel-search-input')); + expect(input).toBeNull(); + }); + test('Render search input when filtering is supported', async () => { + const { getAllByTestId, getAllByRole, getByTestId } = render( + + + , + ); + const imagePicker = await waitFor(() => getAllByTestId(getDataTestId('image-picker-content'))[0]); + await act(async () => { + imagePicker.click(); + }); + const image = getAllByRole('img', { name: /grafx/i })[0]; + + await act(async () => { + image.click(); + }); + + const input = getByTestId(getDataTestIdForSUI('media-panel-search-input')); + expect(input).toBeInTheDocument(); + }); }); From 8c6577d284ef4ebd284bb62b5a8d2894e823782f Mon Sep 17 00:00:00 2001 From: Abdelhalim Khouas Date: Mon, 15 Jan 2024 12:37:37 +0300 Subject: [PATCH 5/6] fix height calculation to prevent issues using scrollIntoView --- src/App.css | 2 +- src/App.styles.tsx | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/App.css b/src/App.css index 7453fb22..0d06d85b 100644 --- a/src/App.css +++ b/src/App.css @@ -5,7 +5,7 @@ } .sui-canvas { - height: calc(100% - 4rem - 5rem); + height: calc(100% - 5rem); width: 100%; } diff --git a/src/App.styles.tsx b/src/App.styles.tsx index e1e16dc2..a126fba4 100644 --- a/src/App.styles.tsx +++ b/src/App.styles.tsx @@ -2,7 +2,7 @@ import styled from 'styled-components'; export const MainContentContainer = styled.div` display: flex; - height: 100vh; + height: calc(100vh - 4rem); width: 100%; `; From d7e48c927584422c483d8a57fc50c8631b968a17 Mon Sep 17 00:00:00 2001 From: Abdelhalim Khouas Date: Mon, 15 Jan 2024 12:40:07 +0300 Subject: [PATCH 6/6] fix left panel margin --- src/components/layout-panels/leftPanel/LeftPanel.styles.tsx | 1 - 1 file changed, 1 deletion(-) diff --git a/src/components/layout-panels/leftPanel/LeftPanel.styles.tsx b/src/components/layout-panels/leftPanel/LeftPanel.styles.tsx index 4b0c8804..9dbf4baf 100644 --- a/src/components/layout-panels/leftPanel/LeftPanel.styles.tsx +++ b/src/components/layout-panels/leftPanel/LeftPanel.styles.tsx @@ -7,7 +7,6 @@ export const LeftPanelContainer = styled.div` background-color: ${Colors.PRIMARY_WHITE}; border-right: 2px solid ${Colors.PRIMARY_DROPDOWN_BACKGROUND}; overflow: scroll; - margin-bottom: 3rem; padding-left: 0; &::-webkit-scrollbar {