Skip to content

Commit

Permalink
feat(chat): implement comparison different versions of conversations …
Browse files Browse the repository at this point in the history
…(Issue #2088) (#2902)
  • Loading branch information
IlyaBondar authored Jan 14, 2025
1 parent b60af4b commit 5691525
Show file tree
Hide file tree
Showing 10 changed files with 281 additions and 182 deletions.
153 changes: 77 additions & 76 deletions apps/chat/src/components/Chat/ChatCompareSelect.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,15 +9,15 @@ import { doesEntityContainSearchItem } from '@/src/utils/app/search';
import { getPublicItemIdWithoutVersion } from '@/src/utils/server/api';

import { Conversation } from '@/src/types/chat';
import { PublicVersionGroups } from '@/src/types/publication';
import { Translation } from '@/src/types/translation';

import { ConversationsSelectors } from '@/src/store/conversations/conversations.reducers';
import { useAppSelector } from '@/src/store/hooks';
import { PublicationSelectors } from '@/src/store/publication/publication.reducers';

import Loader from '../Common/Loader';
import { ConversationRow } from '../Common/ReplaceConfirmationModal/Components';
import { PublicVersionSelector } from './Publish/PublicVersionSelector';
import { ConversationCompareItem } from './ConversationCompareItem';

import { ConversationInfo } from '@epam/ai-dial-shared';

Expand All @@ -43,6 +43,9 @@ export const ChatCompareSelect = ({
const publicVersionGroups = useAppSelector(
PublicationSelectors.selectPublicVersionGroups,
);

const selectedConversation = selectedConversations[0];

const isLoading = !!useAppSelector(
ConversationsSelectors.selectIsCompareLoading,
);
Expand All @@ -55,24 +58,77 @@ export const ChatCompareSelect = ({
);

useEffect(() => {
if (selectedConversations.length === 1) {
const selectedConversation = selectedConversations[0];

if (selectedConversation) {
const comparableConversations = conversations.filter((conv) =>
isValidConversationForCompare(selectedConversation, conv, showAll),
);
setComparableConversations(sortByName(comparableConversations));
}
}, [conversations, selectedConversations, showAll]);
}, [conversations, selectedConversation, showAll]);

const isConversationMatchingSearch = (
conv: ConversationInfo,
searchValue: string,
) => {
return doesEntityContainSearchItem(conv, searchValue);
};

const isConversationVersionValid = (
conv: ConversationInfo,
publicVersionGroups: PublicVersionGroups,
selectedConversation: Conversation,
) => {
if (!conv.publicationInfo?.version) {
return true;
}

const currentVersionGroupId = getPublicItemIdWithoutVersion(
conv.publicationInfo.version,
conv.id,
);

const currentVersionGroup = currentVersionGroupId
? publicVersionGroups[currentVersionGroupId]
: null;

if (
currentVersionGroup &&
conv.publicationInfo?.version !==
currentVersionGroup.selectedVersion.version &&
(currentVersionGroup.selectedVersion.id !== selectedConversation.id ||
currentVersionGroup.allVersions.find(
(ver) => ver.id !== currentVersionGroup.selectedVersion.id,
)?.id !== conv.id)
) {
return false;
}

return true;
};

const filteredComparableConversations = useMemo(
() =>
comparableConversations.filter((conv) =>
doesEntityContainSearchItem(conv, searchValue),
comparableConversations.filter(
(conv) =>
isConversationMatchingSearch(conv, searchValue) &&
isConversationVersionValid(
conv,
publicVersionGroups,
selectedConversation,
),
),
[comparableConversations, searchValue],
[
comparableConversations,
publicVersionGroups,
searchValue,
selectedConversation,
],
);

if (selectedConversations.length !== 1) {
return null;
}

return (
<div
className="relative flex h-4/5 grow justify-center p-5 py-2"
Expand Down Expand Up @@ -119,79 +175,24 @@ export const ChatCompareSelect = ({
className="input-form peer"
data-qa="search-compare-conversation"
/>
<ul className="mt-4">
<div className="mt-4">
{filteredComparableConversations.length ? (
filteredComparableConversations.map((conv) => {
const currentVersionGroupId = conv.publicationInfo?.version
? getPublicItemIdWithoutVersion(
conv.publicationInfo.version,
conv.id,
)
: null;
const currentVersionGroup = currentVersionGroupId
? publicVersionGroups[currentVersionGroupId]
: null;

if (
currentVersionGroup &&
conv.publicationInfo?.version !==
currentVersionGroup.selectedVersion.version
) {
return null;
}

return (
<div
key={conv.id}
className="flex cursor-pointer items-center justify-between gap-4 rounded pr-[14px] hover:bg-accent-primary-alpha"
data-qa="conversation-row"
onClick={() => {
const selectedConversation =
comparableConversations.find(
(comparableConversation) =>
conv.id === comparableConversation.id,
);

if (selectedConversation) {
onConversationSelect(selectedConversation);
}
}}
>
<div className="w-full truncate">
<ConversationRow
featureContainerClassNames="!w-full"
itemComponentClassNames="group hover:bg-transparent !pl-3 !h-[34px]"
item={conv}
/>
</div>

{conv.publicationInfo?.version && (
<PublicVersionSelector
btnClassNames="cursor-pointer h-[34px] flex items-center"
publicVersionGroupId={getPublicItemIdWithoutVersion(
conv.publicationInfo.version,
conv.id,
)}
onChangeSelectedVersion={(_, newVersion) => {
const selectedConversation = conversations.find(
(conv) => conv.id === newVersion.id,
);

if (selectedConversation) {
onConversationSelect(selectedConversation);
}
}}
/>
)}
</div>
);
})
filteredComparableConversations.map((conv) => (
<ConversationCompareItem
key={conv.id}
conv={conv}
comparableConversations={comparableConversations}
selectedConversation={selectedConversation}
conversations={conversations}
onConversationSelect={onConversationSelect}
/>
))
) : (
<p className="mt-4 text-secondary">
{t('No conversations found')}
</p>
)}
</ul>
</div>
</>
) : (
<p
Expand Down
17 changes: 6 additions & 11 deletions apps/chat/src/components/Chat/ChatHeader/Header.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ import {
import { Conversation } from '@/src/types/chat';
import { EntityType, ScreenState } from '@/src/types/common';
import { DialAIEntityModel } from '@/src/types/models';
import { PublicVersionGroups } from '@/src/types/publication';
import { PublicVersionOption } from '@/src/types/publication';
import { Translation } from '@/src/types/translation';

import { AddonsSelectors } from '@/src/store/addons/addons.reducers';
Expand Down Expand Up @@ -141,26 +141,20 @@ export const ChatHeader = ({
}, [dispatch]);

const handleChangeSelectedVersion = useCallback(
(
versionGroupId: string,
newVersion: NonNullable<PublicVersionGroups[string]>['selectedVersion'],
oldVersion: NonNullable<PublicVersionGroups[string]>['selectedVersion'],
) => {
(versionGroupId: string, newVersion: PublicVersionOption) => {
dispatch(
PublicationActions.setNewVersionForPublicVersionGroup({
PublicationActions.setSelectedVersionForPublicVersionGroup({
versionGroupId,
newVersion,
}),
);
dispatch(
ConversationsActions.selectConversations({
conversationIds: selectedConversationIds.map((id) =>
id === oldVersion.id ? newVersion.id : id,
),
conversationIds: [newVersion.id],
}),
);
},
[dispatch, selectedConversationIds],
[dispatch],
);

const conversationSelectedAddons =
Expand Down Expand Up @@ -216,6 +210,7 @@ export const ChatHeader = ({
<PublicVersionSelector
publicVersionGroupId={publicVersionGroupId}
onChangeSelectedVersion={handleChangeSelectedVersion}
selectedEntityId={conversation.id}
/>
) : (
<p
Expand Down
79 changes: 79 additions & 0 deletions apps/chat/src/components/Chat/ConversationCompareItem.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
import React, { useCallback } from 'react';

import { getPublicItemIdWithoutVersion } from '@/src/utils/server/api';

import { Conversation } from '@/src/types/chat';
import { PublicVersionOption } from '@/src/types/publication';

import { ConversationRow } from '../Common/ReplaceConfirmationModal/Components';
import { PublicVersionSelector } from './Publish/PublicVersionSelector';

import { ConversationInfo } from '@epam/ai-dial-shared';

interface ConversationCompareItemProps {
conv: ConversationInfo;
comparableConversations: ConversationInfo[];
selectedConversation?: Conversation;
conversations: ConversationInfo[];
onConversationSelect: (conversation: ConversationInfo) => void;
}

export function ConversationCompareItem({
conv,
comparableConversations,
selectedConversation,
conversations,
onConversationSelect,
}: ConversationCompareItemProps) {
const handleConversationSelect = useCallback(() => {
const selectedConversation = comparableConversations.find(
(comparableConversation) => conv.id === comparableConversation.id,
);

if (selectedConversation) {
onConversationSelect(selectedConversation);
}
}, [comparableConversations, conv.id, onConversationSelect]);

const handleVersionChange = useCallback(
(_: string, newVersion: PublicVersionOption) => {
const selectedConversation = conversations.find(
(conv) => conv.id === newVersion.id,
);

if (selectedConversation) {
onConversationSelect(selectedConversation);
}
},
[conversations, onConversationSelect],
);

return (
<div
key={conv.id}
className="flex cursor-pointer items-center justify-between gap-4 rounded pr-[14px] hover:bg-accent-primary-alpha"
data-qa="conversation-row"
onClick={handleConversationSelect}
>
<div className="w-full truncate">
<ConversationRow
featureContainerClassNames="!w-full"
itemComponentClassNames="group hover:bg-transparent !pl-3 !h-[34px]"
item={conv}
/>
</div>

{conv.publicationInfo?.version && (
<PublicVersionSelector
btnClassNames="cursor-pointer h-[34px] flex items-center"
publicVersionGroupId={getPublicItemIdWithoutVersion(
conv.publicationInfo.version,
conv.id,
)}
excludeEntityId={selectedConversation?.id}
onChangeSelectedVersion={handleVersionChange}
/>
)}
</div>
);
}
Loading

0 comments on commit 5691525

Please sign in to comment.