diff --git a/modules/apps/frontend-data-set/frontend-data-set-admin-web/src/main/resources/META-INF/resources/item/selector/FDSAdminItemSelector.tsx b/modules/apps/frontend-data-set/frontend-data-set-admin-web/src/main/resources/META-INF/resources/item/selector/FDSAdminItemSelector.tsx index 91fda4b52bacf2..4558fc54a6a103 100644 --- a/modules/apps/frontend-data-set/frontend-data-set-admin-web/src/main/resources/META-INF/resources/item/selector/FDSAdminItemSelector.tsx +++ b/modules/apps/frontend-data-set/frontend-data-set-admin-web/src/main/resources/META-INF/resources/item/selector/FDSAdminItemSelector.tsx @@ -25,8 +25,39 @@ const views = [ name: 'list', schema: { description: 'description', + sticker: 'sticker', symbol: 'symbol', title: 'label', + tooltip: 'tooltip', + }, + setItemComponentProps: ({item, props}: {item: any; props: any}) => { + if ( + !item.dataSetToDataSetCardsSections.length && + !item.dataSetToDataSetTableSections.length && + !item.dataSetToDataSetListSections.length + ) { + return { + ...props, + item: { + ...item, + sticker: {displayType: 'warning'}, + symbol: 'exclamation-circle', + tooltip: Liferay.Language.get( + 'no-visualization-modes-have-been-defined' + ), + }, + }; + } + else { + return { + ...props, + item: { + ...item, + sticker: {displayType: 'unstyled'}, + symbol: 'catalog', + }, + }; + } }, }, ]; @@ -67,7 +98,12 @@ const FDSAdminItemSelector = ({ diff --git a/modules/apps/frontend-data-set/frontend-data-set-web/src/main/resources/META-INF/resources/utils/types.ts b/modules/apps/frontend-data-set/frontend-data-set-web/src/main/resources/META-INF/resources/utils/types.ts index 17e2ab1127b4fc..aa2da8a9516274 100644 --- a/modules/apps/frontend-data-set/frontend-data-set-web/src/main/resources/META-INF/resources/utils/types.ts +++ b/modules/apps/frontend-data-set/frontend-data-set-web/src/main/resources/META-INF/resources/utils/types.ts @@ -245,9 +245,10 @@ export interface IListSchema { description: string; image?: string; sticker?: string; - symbol: string; + symbol?: string; title: string; titleRenderer: IListTitleRenderer; + tooltip?: string; } export type ISchema = ITableSchema | ICardSchema | IListSchema; diff --git a/modules/apps/frontend-data-set/frontend-data-set-web/src/main/resources/META-INF/resources/views/list/List.tsx b/modules/apps/frontend-data-set/frontend-data-set-web/src/main/resources/META-INF/resources/views/list/List.tsx index d1cf0f9a803482..b1c412d5bb0e65 100644 --- a/modules/apps/frontend-data-set/frontend-data-set-web/src/main/resources/META-INF/resources/views/list/List.tsx +++ b/modules/apps/frontend-data-set/frontend-data-set-web/src/main/resources/META-INF/resources/views/list/List.tsx @@ -8,6 +8,7 @@ import ClayIcon from '@clayui/icon'; import ClayLayout from '@clayui/layout'; import ClayList from '@clayui/list'; import ClaySticker from '@clayui/sticker'; +import {ClayTooltipProvider} from '@clayui/tooltip'; import classNames from 'classnames'; import {getObjectValueFromPath} from 'frontend-js-web'; import React, {forwardRef, useContext} from 'react'; @@ -56,12 +57,14 @@ const ListItem = forwardRef( ( { className, + clayListItemProps, item, items, onItemSelectionChange, schema, }: { className: string; + clayListItemProps: Object; item: any; items: any[]; onItemSelectionChange: Function; @@ -77,12 +80,15 @@ const ListItem = forwardRef( selectionType, } = useContext(FrontendDataSetContext); - const [viewsContext] = useContext(ViewsContext); - - const activeView: IView = viewsContext.activeView; - - const {description, image, sticker, symbol, title, titleRenderer} = - schema; + const { + description, + image, + sticker, + symbol, + title, + titleRenderer, + tooltip, + } = schema; const SelectionInput = selectionType === 'single' ? ClayRadio : ClayCheckbox; @@ -92,18 +98,14 @@ const ListItem = forwardRef( path: selectedItemsKey, }); - const props = { - className: classNames(className, { - active: selectedItemsValue?.includes(itemId), - }), - flex: true, - }; - return ( {selectable && ( @@ -134,11 +136,21 @@ const ListItem = forwardRef( symbol && item[symbol] && ( - - {item[symbol] && ( + {tooltip && item[tooltip] ? ( + + + + + + + + ) : ( + - )} - + + )} ) )} @@ -165,8 +177,8 @@ const ListItem = forwardRef( )} - - {(itemsActions || item.actionDropdownItems) && ( + {(itemsActions || item.actionDropdownItems) && ( + ( items={items} onItemSelectionChange={onItemSelectionChange} /> - )} - + + )} ); } ); const ListItemOptionalDropTarget = ({ + clayListItemProps, item, items, onItemSelectionChange, schema, }: { + clayListItemProps?: object; item: any; items: any[]; onItemSelectionChange: Function; @@ -197,6 +211,7 @@ const ListItemOptionalDropTarget = ({ return ( { const {selectedItemsKey} = useContext(FrontendDataSetContext); + const [viewsContext] = useContext(ViewsContext); + if (!items?.length) { return null; } + const activeView: IView = viewsContext.activeView; + + const props = { + items, + onItemSelectionChange, + schema, + }; + return ( ( ))} diff --git a/modules/apps/portal-language/portal-language-lang/src/main/resources/content/Language.properties b/modules/apps/portal-language/portal-language-lang/src/main/resources/content/Language.properties index d9e42bc2936639..57a4ce9f3737ec 100644 --- a/modules/apps/portal-language/portal-language-lang/src/main/resources/content/Language.properties +++ b/modules/apps/portal-language/portal-language-lang/src/main/resources/content/Language.properties @@ -12836,6 +12836,7 @@ no-variations=No Variations no-version-was-found=No version was found. no-video-preview-available=No video preview available. no-views-created=No Views Created +no-visualization-modes-have-been-defined=No visualization modes have been defined. The Data Set will not be displayed. no-vocabularies=No Vocabularies no-vocabularies-yet=No Vocabularies Yet no-warehouses-were-found=No warehouses were found. diff --git a/modules/test/playwright/tests/frontend-data-set-admin-web/main/tests/data-set-fragment/dataSets.spec.ts b/modules/test/playwright/tests/frontend-data-set-admin-web/main/tests/data-set-fragment/dataSets.spec.ts index 540ddeb463c102..e1cc19d4991824 100644 --- a/modules/test/playwright/tests/frontend-data-set-admin-web/main/tests/data-set-fragment/dataSets.spec.ts +++ b/modules/test/playwright/tests/frontend-data-set-admin-web/main/tests/data-set-fragment/dataSets.spec.ts @@ -90,11 +90,14 @@ test( async ({dataSetFragmentPage, dataSetManagerApiHelpers, layout, page}) => { const dataSetERC1 = getRandomString(); const dataSetERC2 = getRandomString(); + const dataSetERC3 = getRandomString(); const dataSetLabel1 = getRandomString(); const dataSetLabel2 = getRandomString(); + const dataSetLabel3 = getRandomString(); dataSetERCs.push(dataSetERC1); dataSetERCs.push(dataSetERC2); + dataSetERCs.push(dataSetERC3); const dataSetInput1 = dataSetFragmentPage.selectDataSetModalFrame.locator( @@ -104,6 +107,10 @@ test( dataSetFragmentPage.selectDataSetModalFrame.locator( `li:has-text("${dataSetLabel2}") input.custom-control-input` ); + const dataSetInput3 = + dataSetFragmentPage.selectDataSetModalFrame.locator( + `li:has-text("${dataSetLabel3}")` + ); await test.step('Create data sets', async () => { await dataSetManagerApiHelpers.createDataSet({ @@ -115,6 +122,11 @@ test( erc: dataSetERC2, label: dataSetLabel2, }); + + await dataSetManagerApiHelpers.createDataSet({ + erc: dataSetERC3, + label: dataSetLabel3, + }); }); await test.step('Create sample data for data sets', async () => { @@ -141,7 +153,7 @@ test( await dataSetFragmentPage.addDataSetFragment(layout); }); - await test.step('Check that only one data set can be selected', async () => { + await test.step('Open Data Set selection list', async () => { await dataSetFragmentPage.selectDataSetButton.click(); await page.getByRole('dialog').isVisible(); @@ -149,7 +161,17 @@ test( await page.getByRole('heading', {name: 'Select'}).isVisible(); await dataSetFragmentPage.selectionListContainer.waitFor(); + }); + + await test.step('Check that data set without visualization modes are marked', async () => { + const warningIcon = dataSetInput3.locator( + 'svg.lexicon-icon-exclamation-circle' + ); + await expect(warningIcon).toBeVisible(); + }); + + await test.step('Check that only one data set can be selected', async () => { await dataSetInput1.setChecked(true); await expect(dataSetInput1).toBeChecked();