From f93d6de9fcdae62791950ac3245940de89878cc0 Mon Sep 17 00:00:00 2001 From: Derikyan Date: Tue, 22 Oct 2024 19:07:33 +0400 Subject: [PATCH 1/3] feat(chat): Marketplace no results found and Suggested results (Issue #2308) --- .../src/components/Common/NoResultsFound.tsx | 23 +++- .../Marketplace/ApplicationCard.tsx | 7 ++ .../ApplicationDetails/ApplicationFooter.tsx | 37 ++++--- .../components/Marketplace/SearchHeader.tsx | 2 +- .../components/Marketplace/TabRenderer.tsx | 103 ++++++++++++++---- 5 files changed, 131 insertions(+), 41 deletions(-) diff --git a/apps/chat/src/components/Common/NoResultsFound.tsx b/apps/chat/src/components/Common/NoResultsFound.tsx index ea66ba8295..43a89184e5 100644 --- a/apps/chat/src/components/Common/NoResultsFound.tsx +++ b/apps/chat/src/components/Common/NoResultsFound.tsx @@ -4,15 +4,30 @@ import { Translation } from '@/src/types/translation'; import Magnifier from '../../../public/images/icons/search-alt.svg'; -export const NoResultsFound = () => { +interface NoResultsFoundProps { + iconSize?: number; + fontSize?: string; + gap?: string; +} + +export const NoResultsFound = ({ + iconSize = 60, + fontSize = 'text-sm', + gap = 'gap-3', +}: NoResultsFoundProps) => { const { t } = useTranslation(Translation.Common); + return (
- - {t('No results found')} + + {t('No results found')}
); }; diff --git a/apps/chat/src/components/Marketplace/ApplicationCard.tsx b/apps/chat/src/components/Marketplace/ApplicationCard.tsx index 73cf210546..8495a525b8 100644 --- a/apps/chat/src/components/Marketplace/ApplicationCard.tsx +++ b/apps/chat/src/components/Marketplace/ApplicationCard.tsx @@ -23,6 +23,7 @@ import { Translation } from '@/src/types/translation'; import { useAppSelector } from '@/src/store/hooks'; import { MarketplaceSelectors } from '@/src/store/marketplace/marketplace.reducers'; +import { ModelsSelectors } from '@/src/store/models/models.reducers'; import { MarketplaceTabs } from '@/src/constants/marketplace'; @@ -86,6 +87,10 @@ export const ApplicationCard = ({ getRootId({ featureType: FeatureType.Application }), ); + const installedModelIds = useAppSelector( + ModelsSelectors.selectInstalledModelIds, + ); + const menuItems: DisplayMenuItemProps[] = useMemo( () => [ { @@ -136,6 +141,7 @@ export const ApplicationCard = ({ display: !isMyEntity && selectedTab === MarketplaceTabs.MY_APPLICATIONS && + installedModelIds.has(entity.reference) && !!onRemove, Icon: (props: TablerIconsProps) => ( @@ -146,6 +152,7 @@ export const ApplicationCard = ({ }, }, ], + [entity, onPublish, t, selectedTab, onDelete, isMyEntity, onEdit, onRemove], ); diff --git a/apps/chat/src/components/Marketplace/ApplicationDetails/ApplicationFooter.tsx b/apps/chat/src/components/Marketplace/ApplicationDetails/ApplicationFooter.tsx index 4ac975ee8d..ac2186148e 100644 --- a/apps/chat/src/components/Marketplace/ApplicationDetails/ApplicationFooter.tsx +++ b/apps/chat/src/components/Marketplace/ApplicationDetails/ApplicationFooter.tsx @@ -14,6 +14,9 @@ import { FeatureType } from '@/src/types/common'; import { DialAIEntityModel } from '@/src/types/models'; import { Translation } from '@/src/types/translation'; +import { useAppSelector } from '@/src/store/hooks'; +import { ModelsSelectors } from '@/src/store/models/models.reducers'; + import { ModelVersionSelect } from '../../Chat/ModelVersionSelect'; import Tooltip from '../../Common/Tooltip'; @@ -49,6 +52,9 @@ export const ApplicationDetailsFooter = ({ getRootId({ featureType: FeatureType.Application }), ); const isPublicApp = isEntityPublic(entity); + const installedModelIds = useAppSelector( + ModelsSelectors.selectInstalledModelIds, + ); return (
@@ -58,20 +64,23 @@ export const ApplicationDetailsFooter = ({ className="shrink-0 text-accent-primary md:hidden [&_path]:fill-current" size={24} /> */} - {(isMyAppsTab || isMyApp) && ( - - - - )} + {(isMyAppsTab || isMyApp) && + installedModelIds.has(entity.reference) && ( + + + + )} {isApplicationId(entity.id) && ( diff --git a/apps/chat/src/components/Marketplace/SearchHeader.tsx b/apps/chat/src/components/Marketplace/SearchHeader.tsx index 0376ce552c..3ab1dd1c41 100644 --- a/apps/chat/src/components/Marketplace/SearchHeader.tsx +++ b/apps/chat/src/components/Marketplace/SearchHeader.tsx @@ -125,7 +125,7 @@ export const SearchHeader = ({ }; return ( -
+
{/*
{t('{{label}}: {{count}} items', { count: items, diff --git a/apps/chat/src/components/Marketplace/TabRenderer.tsx b/apps/chat/src/components/Marketplace/TabRenderer.tsx index 9623b6fd20..a9ed5e5831 100644 --- a/apps/chat/src/components/Marketplace/TabRenderer.tsx +++ b/apps/chat/src/components/Marketplace/TabRenderer.tsx @@ -1,5 +1,7 @@ import { useCallback, useMemo, useState } from 'react'; +import { useTranslation } from 'next-i18next'; + import { isQuickApp } from '@/src/utils/app/application'; import { groupModelsAndSaveOrder } from '@/src/utils/app/conversation'; import { getFolderIdFromEntityId } from '@/src/utils/app/folders'; @@ -14,6 +16,7 @@ import { } from '@/src/types/applications'; import { DialAIEntityModel } from '@/src/types/models'; import { SharingType } from '@/src/types/share'; +import { Translation } from '@/src/types/translation'; import { ApplicationActions } from '@/src/store/application/application.reducers'; import { useAppDispatch, useAppSelector } from '@/src/store/hooks'; @@ -38,6 +41,9 @@ import { CardsList } from '@/src/components/Marketplace/CardsList'; import { MarketplaceBanner } from '@/src/components/Marketplace/MarketplaceBanner'; import { SearchHeader } from '@/src/components/Marketplace/SearchHeader'; +import Magnifier from '../../../public/images/icons/search-alt.svg'; +import { NoResultsFound } from '../Common/NoResultsFound'; + import { PublishActions, ShareEntity } from '@epam/ai-dial-shared'; import intersection from 'lodash-es/intersection'; import orderBy from 'lodash-es/orderBy'; @@ -80,6 +86,11 @@ interface TabRendererProps { } export const TabRenderer = ({ isMobile }: TabRendererProps) => { + const { t } = useTranslation(Translation.Marketplace); + const [suggestedResults, setSuggestedResults] = useState< + DialAIEntityModel[] | null + >(null); + const dispatch = useAppDispatch(); const installedModelIds = useAppSelector( @@ -110,7 +121,12 @@ export const TabRenderer = ({ isMobile }: TabRendererProps) => { const [detailsModelReference, setDetailsModelReference] = useState(); const displayedEntities = useMemo(() => { - const filteredEntities = allModels.filter( + const entitiesForTab = + selectedTab === MarketplaceTabs.MY_APPLICATIONS + ? allModels.filter((entity) => installedModelIds.has(entity.reference)) + : allModels; + + const allEntities = allModels.filter( (entity) => (doesEntityContainSearchTerm(entity, searchTerm) || (entity.version && @@ -127,22 +143,25 @@ export const TabRenderer = ({ isMobile }: TabRendererProps) => { : true), ); - const entitiesForTab = + const filteredEntities = selectedTab === MarketplaceTabs.MY_APPLICATIONS - ? filteredEntities.filter((entity) => - installedModelIds.has(entity.reference), - ) - : filteredEntities; - - const groupedEntities = groupModelsAndSaveOrder(entitiesForTab).slice( - 0, - Number.MAX_SAFE_INTEGER, - ); + ? intersection(entitiesForTab, allEntities) + : allEntities; + const groupedEntities = groupModelsAndSaveOrder(filteredEntities); const orderedEntities = groupedEntities.map( ({ entities }) => orderBy(entities, 'version', 'desc')[0], ); + if ( + selectedTab === MarketplaceTabs.MY_APPLICATIONS && + orderedEntities.length === 0 + ) { + setSuggestedResults(allEntities); + } else { + setSuggestedResults(null); + } + return orderedEntities; }, [installedModelIds, allModels, searchTerm, selectedFilters, selectedTab]); @@ -241,23 +260,63 @@ export const TabRenderer = ({ isMobile }: TabRendererProps) => { return ( <> -
+
- - + {displayedEntities.length > 0 ? ( + + ) : ( + <> + {selectedTab === MarketplaceTabs.MY_APPLICATIONS && + suggestedResults && + suggestedResults?.length > 0 ? ( + <> +
+ + + {t( + 'No results found in My workspace. Look at suggested results from DIAL Marketplace.', + )} + +
+ + {t('Suggested results from DIAL Marketplace')} + + + + ) : ( +
+ + + {t("Sorry, we couldn't find any results for your search.")} + +
+ )} + + )} {/* MODALS */} {!!( From 7642ca1ee0ddf95772d45f8cc5d79d4dbac7e2fb Mon Sep 17 00:00:00 2001 From: Derikyan Date: Thu, 24 Oct 2024 00:34:05 +0400 Subject: [PATCH 2/3] fix comments --- .../src/components/Common/NoResultsFound.tsx | 15 +++++---- .../Marketplace/ApplicationCard.tsx | 12 ++++++- .../components/Marketplace/Marketplace.tsx | 2 +- .../components/Marketplace/TabRenderer.tsx | 31 +++++++------------ 4 files changed, 33 insertions(+), 27 deletions(-) diff --git a/apps/chat/src/components/Common/NoResultsFound.tsx b/apps/chat/src/components/Common/NoResultsFound.tsx index 43a89184e5..9e7d59da41 100644 --- a/apps/chat/src/components/Common/NoResultsFound.tsx +++ b/apps/chat/src/components/Common/NoResultsFound.tsx @@ -1,25 +1,28 @@ import { useTranslation } from 'next-i18next'; +import classNames from 'classnames'; + import { Translation } from '@/src/types/translation'; import Magnifier from '../../../public/images/icons/search-alt.svg'; interface NoResultsFoundProps { iconSize?: number; - fontSize?: string; - gap?: string; + className?: string; } export const NoResultsFound = ({ iconSize = 60, - fontSize = 'text-sm', - gap = 'gap-3', + className = 'text-sm gap-3', }: NoResultsFoundProps) => { const { t } = useTranslation(Translation.Common); return (
- {t('No results found')} + {t('No results found')}
); }; diff --git a/apps/chat/src/components/Marketplace/ApplicationCard.tsx b/apps/chat/src/components/Marketplace/ApplicationCard.tsx index 518898b742..6c5b68a024 100644 --- a/apps/chat/src/components/Marketplace/ApplicationCard.tsx +++ b/apps/chat/src/components/Marketplace/ApplicationCard.tsx @@ -154,7 +154,17 @@ export const ApplicationCard = ({ }, ], - [entity, onPublish, t, selectedTab, onDelete, isMyEntity, onEdit, onRemove], + [ + t, + isMyEntity, + onEdit, + onPublish, + entity, + onDelete, + selectedTab, + installedModelIds, + onRemove, + ], ); const iconSize = diff --git a/apps/chat/src/components/Marketplace/Marketplace.tsx b/apps/chat/src/components/Marketplace/Marketplace.tsx index 4333d24485..777742d494 100644 --- a/apps/chat/src/components/Marketplace/Marketplace.tsx +++ b/apps/chat/src/components/Marketplace/Marketplace.tsx @@ -80,7 +80,7 @@ export const Marketplace = () => { return (
{isLoading ? ( diff --git a/apps/chat/src/components/Marketplace/TabRenderer.tsx b/apps/chat/src/components/Marketplace/TabRenderer.tsx index 5cc094fa1b..58277c3893 100644 --- a/apps/chat/src/components/Marketplace/TabRenderer.tsx +++ b/apps/chat/src/components/Marketplace/TabRenderer.tsx @@ -121,12 +121,7 @@ export const TabRenderer = ({ screenState }: TabRendererProps) => { const [detailsModelReference, setDetailsModelReference] = useState(); const displayedEntities = useMemo(() => { - const entitiesForTab = - selectedTab === MarketplaceTabs.MY_APPLICATIONS - ? allModels.filter((entity) => installedModelIds.has(entity.reference)) - : allModels; - - const allEntities = allModels.filter( + const filteredEntities = allModels.filter( (entity) => (doesEntityContainSearchTerm(entity, searchTerm) || (entity.version && @@ -143,21 +138,23 @@ export const TabRenderer = ({ screenState }: TabRendererProps) => { : true), ); - const filteredEntities = + const entitiesForTab = selectedTab === MarketplaceTabs.MY_APPLICATIONS - ? intersection(entitiesForTab, allEntities) - : allEntities; + ? filteredEntities.filter((entity) => + installedModelIds.has(entity.reference), + ) + : filteredEntities; - const groupedEntities = groupModelsAndSaveOrder(filteredEntities); + const groupedEntities = groupModelsAndSaveOrder(entitiesForTab); const orderedEntities = groupedEntities.map( ({ entities }) => orderBy(entities, 'version', 'desc')[0], ); if ( selectedTab === MarketplaceTabs.MY_APPLICATIONS && - orderedEntities.length === 0 + !entitiesForTab.length ) { - setSuggestedResults(allEntities); + setSuggestedResults(filteredEntities); } else { setSuggestedResults(null); } @@ -280,8 +277,7 @@ export const TabRenderer = ({ screenState }: TabRendererProps) => { ) : ( <> {selectedTab === MarketplaceTabs.MY_APPLICATIONS && - suggestedResults && - suggestedResults?.length > 0 ? ( + suggestedResults?.length ? ( <>
@@ -305,11 +301,8 @@ export const TabRenderer = ({ screenState }: TabRendererProps) => { /> ) : ( -
- +
+ {t("Sorry, we couldn't find any results for your search.")} From 513e79a00a44d1df0fd7a8c13950811381972226 Mon Sep 17 00:00:00 2001 From: Derikyan Date: Thu, 24 Oct 2024 13:13:51 +0400 Subject: [PATCH 3/3] fix comments --- .../Marketplace/ApplicationCard.tsx | 11 +------ .../ApplicationDetails/ApplicationFooter.tsx | 32 ++++++++----------- 2 files changed, 15 insertions(+), 28 deletions(-) diff --git a/apps/chat/src/components/Marketplace/ApplicationCard.tsx b/apps/chat/src/components/Marketplace/ApplicationCard.tsx index 4fa08b76b9..27f545f9db 100644 --- a/apps/chat/src/components/Marketplace/ApplicationCard.tsx +++ b/apps/chat/src/components/Marketplace/ApplicationCard.tsx @@ -20,11 +20,8 @@ import { DialAIEntityModel } from '@/src/types/models'; import { Translation } from '@/src/types/translation'; import { useAppSelector } from '@/src/store/hooks'; -import { MarketplaceSelectors } from '@/src/store/marketplace/marketplace.reducers'; import { ModelsSelectors } from '@/src/store/models/models.reducers'; -import { MarketplaceTabs } from '@/src/constants/marketplace'; - import { ModelIcon } from '@/src/components/Chatbar/ModelIcon'; import ContextMenu from '@/src/components/Common/ContextMenu'; import { EntityMarkdownDescription } from '@/src/components/Common/MarkdownDescription'; @@ -82,8 +79,6 @@ export const ApplicationCard = ({ }: ApplicationCardProps) => { const { t } = useTranslation(Translation.Marketplace); - const selectedTab = useAppSelector(MarketplaceSelectors.selectSelectedTab); - const isMyEntity = entity.id.startsWith( getRootId({ featureType: FeatureType.Application }), ); @@ -140,10 +135,7 @@ export const ApplicationCard = ({ name: t('Remove'), dataQa: 'remove', display: - !isMyEntity && - selectedTab === MarketplaceTabs.MY_APPLICATIONS && - installedModelIds.has(entity.reference) && - !!onRemove, + !isMyEntity && installedModelIds.has(entity.reference) && !!onRemove, Icon: (props: TablerIconsProps) => ( ), @@ -161,7 +153,6 @@ export const ApplicationCard = ({ onPublish, entity, onDelete, - selectedTab, installedModelIds, onRemove, ], diff --git a/apps/chat/src/components/Marketplace/ApplicationDetails/ApplicationFooter.tsx b/apps/chat/src/components/Marketplace/ApplicationDetails/ApplicationFooter.tsx index ac2186148e..7111c4233a 100644 --- a/apps/chat/src/components/Marketplace/ApplicationDetails/ApplicationFooter.tsx +++ b/apps/chat/src/components/Marketplace/ApplicationDetails/ApplicationFooter.tsx @@ -38,7 +38,6 @@ interface Props { export const ApplicationDetailsFooter = ({ entity, allVersions, - isMyAppsTab, onChangeVersion, onPublish, onUseEntity, @@ -64,23 +63,20 @@ export const ApplicationDetailsFooter = ({ className="shrink-0 text-accent-primary md:hidden [&_path]:fill-current" size={24} /> */} - {(isMyAppsTab || isMyApp) && - installedModelIds.has(entity.reference) && ( - - - - )} + {(isMyApp || installedModelIds.has(entity.reference)) && ( + + + + )} {isApplicationId(entity.id) && (