Skip to content

Commit

Permalink
feat(chat): add new application type filters (Issue #2996) (#2998)
Browse files Browse the repository at this point in the history
  • Loading branch information
IlyaBondar authored and Alexander-Kezik committed Jan 23, 2025
1 parent beb8b51 commit 6edbfe0
Show file tree
Hide file tree
Showing 14 changed files with 160 additions and 91 deletions.
6 changes: 2 additions & 4 deletions apps/chat/src/components/Chat/TalkTo/TalkToCard.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ import {
isExecutableApp,
} from '@/src/utils/app/application';
import { isOldConversationReplay } from '@/src/utils/app/conversation';
import { getRootId } from '@/src/utils/app/id';
import { isMyApplication } from '@/src/utils/app/id';
import { canWriteSharedWithMe } from '@/src/utils/app/share';
import { PseudoModel, isPseudoModel } from '@/src/utils/server/api';

Expand Down Expand Up @@ -124,9 +124,7 @@ export const TalkToCard = ({
);
const isAdmin = useAppSelector(AuthSelectors.selectIsAdmin);

const isMyEntity = entity.id.startsWith(
getRootId({ featureType: FeatureType.Application }),
);
const isMyEntity = isMyApplication(entity);

const canWrite = canWriteSharedWithMe(entity);

Expand Down
10 changes: 2 additions & 8 deletions apps/chat/src/components/Common/FolderContextMenu.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ import {
hasInvalidNameInPath,
isEntityNameInvalid,
} from '@/src/utils/app/common';
import { getRootId, isEntityIdExternal } from '@/src/utils/app/id';
import { isEntityIdExternal, isMyEntity } from '@/src/utils/app/id';
import { isEntityIdPublic } from '@/src/utils/app/publications';

import { AdditionalItemData, FeatureType } from '@/src/types/common';
Expand Down Expand Up @@ -166,13 +166,7 @@ export const FolderContextMenu = ({
{
name: t('Delete'),
display:
(!!onDelete &&
folder.id.startsWith(
getRootId({
featureType,
}),
)) ||
!!folder.temporary,
(!!onDelete && isMyEntity(folder, featureType)) || !!folder.temporary,
dataQa: 'delete',
Icon: IconTrashX,
onClick: onDelete,
Expand Down
9 changes: 2 additions & 7 deletions apps/chat/src/components/Files/FileItemContextMenu.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import { MouseEvent, MouseEventHandler, useMemo } from 'react';

import { useTranslation } from 'next-i18next';

import { getRootId } from '@/src/utils/app/id';
import { isMyEntity } from '@/src/utils/app/id';

import { FeatureType } from '@/src/types/common';
import { DialFile } from '@/src/types/files';
Expand Down Expand Up @@ -111,12 +111,7 @@ export function FileItemContextMenu({
{
name: t('Delete'),
dataQa: 'delete',
display:
file.id.startsWith(
getRootId({
featureType: FeatureType.File,
}),
) || !!file.sharedWithMe,
display: isMyEntity(file, FeatureType.File) || !!file.sharedWithMe,
Icon: IconTrashX,
onClick: onDelete,
},
Expand Down
6 changes: 2 additions & 4 deletions apps/chat/src/components/Marketplace/ApplicationCard.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ import {
isApplicationStatusUpdating,
isExecutableApp,
} from '@/src/utils/app/application';
import { getRootId } from '@/src/utils/app/id';
import { isMyApplication } from '@/src/utils/app/id';
import { isMediumScreen } from '@/src/utils/app/mobile';
import { isEntityIdPublic } from '@/src/utils/app/publications';
import { canWriteSharedWithMe } from '@/src/utils/app/share';
Expand Down Expand Up @@ -142,9 +142,7 @@ export const ApplicationCard = ({
);
const isAdmin = useAppSelector(AuthSelectors.selectIsAdmin);

const isMyApp = entity.id.startsWith(
getRootId({ featureType: FeatureType.Application }),
);
const isMyApp = isMyApplication(entity);

const canWrite = canWriteSharedWithMe(entity);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,15 +21,14 @@ import {
isApplicationStatusUpdating,
isExecutableApp,
} from '@/src/utils/app/application';
import { getRootId, isApplicationId } from '@/src/utils/app/id';
import { isApplicationId, isMyApplication } from '@/src/utils/app/id';
import { isEntityIdPublic } from '@/src/utils/app/publications';
import { canWriteSharedWithMe } from '@/src/utils/app/share';

import {
ApplicationStatus,
SimpleApplicationStatus,
} from '@/src/types/applications';
import { FeatureType } from '@/src/types/common';
import { DialAIEntityModel } from '@/src/types/models';
import { Translation } from '@/src/types/translation';

Expand Down Expand Up @@ -111,9 +110,7 @@ export const ApplicationDetailsFooter = ({
ModelsSelectors.selectInstalledModelIds,
);

const isMyApp = entity.id.startsWith(
getRootId({ featureType: FeatureType.Application }),
);
const isMyApp = isMyApplication(entity);
const isAdmin = useAppSelector(AuthSelectors.selectIsAdmin);
const isPublicApp = isEntityIdPublic(entity);
const Bookmark = installedModelIds.has(entity.reference)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import classNames from 'classnames';
import { useScreenState } from '@/src/hooks/useScreenState';

import { isApplicationPublic } from '@/src/utils/app/application';
import { getRootId } from '@/src/utils/app/id';
import { isMyApplication } from '@/src/utils/app/id';

import { FeatureType, ScreenState } from '@/src/types/common';
import { DialAIEntityModel } from '@/src/types/models';
Expand Down Expand Up @@ -44,9 +44,7 @@ export const ApplicationDetailsHeader = ({ entity }: Props) => {
? MOBILE_SHARE_ICON_SIZE
: DESKTOP_SHARE_ICON_SIZE;

const isMyApp = entity.id.startsWith(
getRootId({ featureType: FeatureType.Application }),
);
const isMyApp = isMyApplication(entity);
const isPublicApp = isApplicationPublic(entity);
const handleOpenSharing: MouseEventHandler<HTMLButtonElement> =
useCallback(() => {
Expand Down
22 changes: 12 additions & 10 deletions apps/chat/src/components/Marketplace/MarketplaceFilterbar.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,6 @@ import {
ENTITY_TYPES,
FilterTypes,
MarketplaceTabs,
SOURCE_TYPES,
} from '@/src/constants/marketplace';

import Tooltip from '../Common/Tooltip';
Expand Down Expand Up @@ -189,6 +188,7 @@ export const MarketplaceFilterbar = () => {
const selectedTab = useAppSelector(MarketplaceSelectors.selectSelectedTab);

const topics = useAppSelector(ModelsSelectors.selectModelTopics);
const sourceTypes = useAppSelector(MarketplaceSelectors.selectSourceTypes);

const [openedSections, setOpenedSections] = useState({
[FilterTypes.ENTITY_TYPE]: true,
Expand Down Expand Up @@ -276,15 +276,17 @@ export const MarketplaceFilterbar = () => {
onToggleFilterSection={handleToggleFilterSection}
onApplyFilter={handleApplyFilter}
/>
<FilterSection
sectionName={t('Sources')}
filterValues={SOURCE_TYPES}
openedSections={openedSections}
selectedFilters={selectedFilters}
filterType={FilterTypes.SOURCES}
onToggleFilterSection={handleToggleFilterSection}
onApplyFilter={handleApplyFilter}
/>
{sourceTypes.length > 1 && (
<FilterSection
sectionName={t('Sources')}
filterValues={sourceTypes}
openedSections={openedSections}
selectedFilters={selectedFilters}
filterType={FilterTypes.SOURCES}
onToggleFilterSection={handleToggleFilterSection}
onApplyFilter={handleApplyFilter}
/>
)}
</div>
)}
</nav>
Expand Down
40 changes: 7 additions & 33 deletions apps/chat/src/components/Marketplace/TabRenderer.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,17 +6,18 @@ import { useTranslation } from 'next-i18next';
import { getApplicationType } from '@/src/utils/app/application';
import { groupModelsAndSaveOrder } from '@/src/utils/app/conversation';
import { getFolderIdFromEntityId } from '@/src/utils/app/folders';
import { getRootId } from '@/src/utils/app/id';
import { isEntityIdPublic } from '@/src/utils/app/publications';
import { doesEntityContainSearchTerm } from '@/src/utils/app/search';
import { translate } from '@/src/utils/app/translation';
import {
doesApplicationMatchFilters,
doesApplicationMatchSearchTerm,
} from '@/src/utils/marketplace';
import { ApiUtils } from '@/src/utils/server/api';

import {
ApplicationActionType,
ApplicationType,
} from '@/src/types/applications';
import { FeatureType, ScreenState } from '@/src/types/common';
import { ScreenState } from '@/src/types/common';
import { DialAIEntityModel } from '@/src/types/models';
import { SharingType } from '@/src/types/share';
import { Translation } from '@/src/types/translation';
Expand All @@ -36,7 +37,6 @@ import {
DeleteType,
FilterTypes,
MarketplaceTabs,
SourceType,
} from '@/src/constants/marketplace';

import { PublishModal } from '@/src/components/Chat/Publish/PublishWizard';
Expand All @@ -51,7 +51,6 @@ 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';

interface NoAgentsFoundProps {
children: React.ReactNode;
Expand Down Expand Up @@ -264,33 +263,8 @@ export const TabRenderer = ({ screenState }: TabRendererProps) => {
const displayedEntities = useMemo(() => {
const filteredEntities = allModels.filter(
(entity) =>
(doesEntityContainSearchTerm(entity, searchTerm) ||
(entity.version &&
doesEntityContainSearchTerm(
{ name: entity.version },
searchTerm,
))) &&
(selectedFilters[FilterTypes.ENTITY_TYPE].length
? selectedFilters[FilterTypes.ENTITY_TYPE].includes(entity.type)
: true) &&
(selectedFilters[FilterTypes.TOPICS].length
? intersection(selectedFilters[FilterTypes.TOPICS], entity.topics)
.length
: true) &&
(selectedFilters[FilterTypes.SOURCES].length
? (selectedFilters[FilterTypes.SOURCES].includes(
SourceType.SharedWithMe,
) &&
entity.sharedWithMe) ||
(selectedFilters[FilterTypes.SOURCES].includes(
SourceType.CreatedByMe,
) &&
entity.id.startsWith(
getRootId({ featureType: FeatureType.Application }),
)) ||
(selectedFilters[FilterTypes.SOURCES].includes(SourceType.Public) &&
isEntityIdPublic(entity))
: true),
doesApplicationMatchSearchTerm(entity, searchTerm) &&
doesApplicationMatchFilters(entity, selectedFilters),
);

const isInstalledModel = (entity: DialAIEntityModel) =>
Expand Down
16 changes: 10 additions & 6 deletions apps/chat/src/constants/marketplace.ts
Original file line number Diff line number Diff line change
Expand Up @@ -37,11 +37,15 @@ export const ENTITY_TYPES = [
export enum SourceType {
Public = 'Public',
SharedWithMe = 'Shared with me',
CreatedByMe = 'Created by me',
MyCustomApps = 'My Custom Apps',
MyQuickApps = 'My Quick Apps',
MyCodeApps = 'My Code Apps',
}

export const SOURCE_TYPES = [
SourceType.Public,
SourceType.SharedWithMe,
SourceType.CreatedByMe,
];
export const SourceTypeOrder = {
[SourceType.Public]: 1,
[SourceType.SharedWithMe]: 2,
[SourceType.MyCustomApps]: 3,
[SourceType.MyQuickApps]: 4,
[SourceType.MyCodeApps]: 5,
};
11 changes: 7 additions & 4 deletions apps/chat/src/store/marketplace/marketplace.epics.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,13 +10,16 @@ import {
FilterTypes,
MarketplaceQueryParams,
MarketplaceTabs,
SOURCE_TYPES,
SourceType,
} from '@/src/constants/marketplace';

import { ModelsSelectors } from '../models/models.reducers';
import { UIActions } from '../ui/ui.reducers';
import { MarketplaceActions, MarketplaceState } from './marketplace.reducers';
import {
MarketplaceActions,
MarketplaceSelectors,
MarketplaceState,
} from './marketplace.reducers';
import {
selectDetailsModel,
selectSearchTerm,
Expand Down Expand Up @@ -142,10 +145,10 @@ const initQueryParamsEpic: AppEpic = (action$, state$) =>
const types = ((query[MarketplaceQueryParams.types] as string) ?? '')
.split(',')
.filter((type) => type && ENTITY_TYPES.includes(type as EntityType));

const sourceTypes = MarketplaceSelectors.selectSourceTypes(state);
const sources = ((query[MarketplaceQueryParams.sources] as string) ?? '')
.split(',')
.filter((type) => type && SOURCE_TYPES.includes(type as SourceType));
.filter((type) => type && sourceTypes.includes(type as SourceType));

updatedMarketplaceState.selectedFilters = {
[FilterTypes.ENTITY_TYPE]: types,
Expand Down
37 changes: 37 additions & 0 deletions apps/chat/src/store/marketplace/marketplace.selectors.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,18 @@
import { createSelector } from '@reduxjs/toolkit';

import {
isApplicationPublic,
isExecutableApp,
isQuickApp,
} from '@/src/utils/app/application';
import { isMyApplication } from '@/src/utils/app/id';

import { DialAIEntityModel } from '@/src/types/models';

import { SourceType, SourceTypeOrder } from '@/src/constants/marketplace';

import { RootState } from '../index';
import { ModelsSelectors } from '../models/models.reducers';
import { MarketplaceState } from './marketplace.reducers';

import { UploadStatus } from '@epam/ai-dial-shared';
Expand Down Expand Up @@ -43,3 +55,28 @@ export const selectDetailsModel = createSelector(
[rootSelector],
(state) => state.detailsModel,
);

export const selectSourceTypes = createSelector(
[ModelsSelectors.selectModels],
(models: DialAIEntityModel[]) => {
const sourceTypes = new Set<SourceType>([SourceType.Public]);

models.forEach((model) => {
if (isMyApplication(model)) {
if (isQuickApp(model)) {
sourceTypes.add(SourceType.MyQuickApps);
} else if (isExecutableApp(model)) {
sourceTypes.add(SourceType.MyCodeApps);
} else {
sourceTypes.add(SourceType.MyCustomApps);
}
} else if (!isApplicationPublic(model)) {
sourceTypes.add(SourceType.SharedWithMe);
}
});

return Array.from(sourceTypes).sort(
(a, b) => SourceTypeOrder[a] - SourceTypeOrder[b],
);
},
);
8 changes: 2 additions & 6 deletions apps/chat/src/store/models/models.epics.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ import { combineEpics } from 'redux-observable';

import { ClientDataService } from '@/src/utils/app/data/client-data-service';
import { DataService } from '@/src/utils/app/data/data-service';
import { getRootId } from '@/src/utils/app/id';
import { isMyApplication } from '@/src/utils/app/id';
import { translate } from '@/src/utils/app/translation';

import { ApplicationStatus } from '@/src/types/applications';
Expand Down Expand Up @@ -176,11 +176,7 @@ const getInstalledModelIdsEpic: AppEpic = (action$, state$) =>
const allModels = ModelsSelectors.selectModels(state$.value);

return allModels
.filter((model) =>
model.id.startsWith(
getRootId({ featureType: FeatureType.Application }),
),
)
.filter((model) => isMyApplication(model))
.map((app) => app.reference);
}),
switchMap((myAppIds) => {
Expand Down
6 changes: 6 additions & 0 deletions apps/chat/src/utils/app/id.ts
Original file line number Diff line number Diff line change
Expand Up @@ -71,3 +71,9 @@ export const isEntityIdExternal = (entity: { id: string }) => {
const bucket = getEntityBucket(entity);
return bucket !== LOCAL_BUCKET && bucket !== BucketService.getBucket();
};

export const isMyEntity = (entity: { id: string }, featureType: FeatureType) =>
entity.id.startsWith(getRootId({ featureType }));

export const isMyApplication = (entity: { id: string }) =>
isMyEntity(entity, FeatureType.Application);
Loading

0 comments on commit 6edbfe0

Please sign in to comment.