Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(chat)!: Implement the ability to access entity metadata. (Issue #3148) #3197

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ export class ConversationBuilder {
temperature: DEFAULT_TEMPERATURE,
replay: defaultReplay,
selectedAddons: model.selectedAddons ?? [],
lastActivityDate: Date.now(),
updatedAt: Date.now(),
folderId: '',
};
}
Expand Down Expand Up @@ -81,8 +81,8 @@ export class ConversationBuilder {
return this;
}

withLastActivityDate(lastActivityDate: number): ConversationBuilder {
this.conversation.lastActivityDate = lastActivityDate;
withUpdatedAt(updatedAt: number): ConversationBuilder {
this.conversation.updatedAt = updatedAt;
return this;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -447,13 +447,13 @@ export class ConversationData extends FolderData {
name?: string,
) {
const conversation = this.prepareDefaultConversation(model, name);
conversation.lastActivityDate = DateUtil.getYesterdayDate();
conversation.updatedAt = DateUtil.getYesterdayDate();
return conversation;
}

public prepareLastWeekConversation(model?: DialAIEntityModel, name?: string) {
const conversation = this.prepareDefaultConversation(model, name);
conversation.lastActivityDate = DateUtil.getLastWeekDate();
conversation.updatedAt = DateUtil.getLastWeekDate();
return conversation;
}

Expand All @@ -462,13 +462,13 @@ export class ConversationData extends FolderData {
name?: string,
) {
const conversation = this.prepareDefaultConversation(model, name);
conversation.lastActivityDate = DateUtil.getLastMonthDate();
conversation.updatedAt = DateUtil.getLastMonthDate();
return conversation;
}

public prepareOlderConversation(model?: DialAIEntityModel, name?: string) {
const conversation = this.prepareDefaultConversation(model, name);
conversation.lastActivityDate = DateUtil.getOlderDate();
conversation.updatedAt = DateUtil.getOlderDate();
return conversation;
}

Expand Down
1 change: 1 addition & 0 deletions apps/chat-e2e/src/testData/expectedConstants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -258,6 +258,7 @@ export enum MenuOptions {
select = 'Select',
view = 'View',
use = 'Use',
info = 'Info',
}

export enum FilterMenuOptions {
Expand Down
6 changes: 4 additions & 2 deletions apps/chat-e2e/src/tests/chatBarConversation.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -358,6 +358,7 @@ dialTest.skip(
MenuOptions.rename,
MenuOptions.compare,
MenuOptions.moveTo,
MenuOptions.info,
MenuOptions.delete,
]);
},
Expand Down Expand Up @@ -490,6 +491,7 @@ dialTest(
MenuOptions.moveTo,
MenuOptions.share,
MenuOptions.publish,
MenuOptions.info,
MenuOptions.delete,
]);
},
Expand Down Expand Up @@ -572,8 +574,8 @@ dialTest(
//TODO: enable when item modification date is implemented on backend
dialTest.skip(
'Chat sorting. Yesterday.\n' +
'Chat sorting. Last 7 days when chat with lastActivityDate is the day before yesterday.\n' +
'Chat sorting. Last 30 days when chat with lastActivityDate is the 8th day.\n' +
'Chat sorting. Last 7 days when chat with updatedAt is the day before yesterday.\n' +
'Chat sorting. Last 30 days when chat with updatedAt is the 8th day.\n' +
'Chat sorting. Yesterday chat is moved to Today section after regenerate response.\n' +
'Chat sorting. Last 7 Days chat is moved to Today section after editing already answered message',
async ({
Expand Down
8 changes: 4 additions & 4 deletions apps/chat-e2e/src/tests/overlay/events.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -142,7 +142,7 @@ dialOverlayTest(
isPlayback: newConversationData.request.isPlayback ?? false,
isReplay: newConversationData.request.isReplay ?? false,
id: newConversationData.request.id,
lastActivityDate: newConversationData.response.updatedAt,
updatedAt: newConversationData.response.updatedAt,
folderId: newConversationData.request.folderId,
bucket: newConversationData.response.bucket,
},
Expand Down Expand Up @@ -304,7 +304,7 @@ dialOverlayTest(
// id: conversation.id,
// folderId: conversation.folderId,
// publishedWithMe: !parentPath,
// lastActivityDate: actualPublishedConversation.updatedAt,
// updatedAt: actualPublishedConversation.updatedAt,
// bucket: actualPublishedConversation.bucket,
// ...(parentPath && { parentPath }),
// });
Expand All @@ -314,7 +314,7 @@ dialOverlayTest(
let actualConversationsList = await overlayItemApiHelper.listItems(
API.conversationsHost(),
);
//need to sort conversations by 'lastActivityDate' and 'name' in order to define the last conversation
//need to sort conversations by 'updatedAt' and 'name' in order to define the last conversation
actualConversationsList =
SortingUtil.sortBackendConversationsByDateAndName(
actualConversationsList,
Expand All @@ -338,7 +338,7 @@ dialOverlayTest(
isPlayback: isPlayback ?? false,
isReplay: isReplay ?? false,
id: conversation.id,
lastActivityDate: actualConversation.updatedAt,
updatedAt: actualConversation.updatedAt,
folderId: conversation.folderId,
};

Expand Down
1 change: 1 addition & 0 deletions apps/chat-e2e/src/tests/prompts.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -309,6 +309,7 @@ dialTest(
MenuOptions.moveTo,
MenuOptions.share,
MenuOptions.publish,
MenuOptions.info,
MenuOptions.delete,
]);
},
Expand Down
2 changes: 2 additions & 0 deletions apps/chat-e2e/src/tests/publishConversation.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -200,6 +200,7 @@ dialAdminTest(
MenuOptions.replay,
MenuOptions.playback,
MenuOptions.export,
MenuOptions.info,
],
);
},
Expand Down Expand Up @@ -365,6 +366,7 @@ dialAdminTest(
MenuOptions.playback,
MenuOptions.export,
MenuOptions.unpublish,
MenuOptions.info,
]);
},
);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -982,6 +982,7 @@ dialSharedWithMeTest(
.toEqual([
MenuOptions.duplicate,
MenuOptions.export,
MenuOptions.info,
MenuOptions.delete,
]);
},
Expand Down
2 changes: 2 additions & 0 deletions apps/chat/src/components/Chat/ChatModalsManager.jsx
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import { InfoModal } from '../Common/InfoModal';
import { ReplaceConfirmationModal } from '../Common/ReplaceConfirmationModal/ReplaceConfirmationModal';
import { UnshareDialog } from '../Common/UnshareDialog';
import { UserMobile } from '../Header/User/UserMobile';
Expand All @@ -8,6 +9,7 @@ import { ShareModal } from './ShareModal';
export function ChatModalsManager() {
return (
<>
<InfoModal />
<UserMobile />
<ShareModal />
<UnshareDialog />
Expand Down
12 changes: 12 additions & 0 deletions apps/chat/src/components/Chat/ConversationContextMenu.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ import { ContextMenuProps } from '@/src/types/menu';
import { SharingType } from '@/src/types/share';
import { Translation } from '@/src/types/translation';

import { ChatActions } from '@/src/store/chat/chat.reducer';
import {
ConversationsActions,
ConversationsSelectors,
Expand Down Expand Up @@ -354,6 +355,16 @@ export const ConversationContextMenu = ({
dispatch(ConversationsActions.setRenamingConversationId(conversation.id));
}, [conversation, dispatch]);

const handleOpenInfoModal = useCallback(() => {
const { id, updatedAt, createdAt, author, sharedWithMe } = conversation;

dispatch(
ChatActions.getEntityInfo({
entityInfo: { id, updatedAt, createdAt, author, sharedWithMe },
}),
);
}, [conversation, dispatch]);

return (
<>
<button
Expand Down Expand Up @@ -391,6 +402,7 @@ export const ConversationContextMenu = ({
isLoading={conversation.status !== UploadStatus.LOADED}
onSelect={isHeaderMenu ? undefined : handleSelect}
useStandardColor={isHeaderMenu}
onShowInfo={handleOpenInfoModal}
/>
</button>

Expand Down
3 changes: 2 additions & 1 deletion apps/chat/src/components/Chatbar/Conversations.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,8 @@ const _Conversations = ({ conversations }: Props) => {
other: [],
};
sortByDateAndName(conversationsToDisplay).forEach((conv) => {
const lastActivityDateNumber = conv.lastActivityDate;
const lastActivityDateNumber = conv.updatedAt;

if (
!lastActivityDateNumber ||
typeof lastActivityDateNumber !== 'number'
Expand Down
85 changes: 85 additions & 0 deletions apps/chat/src/components/Common/InfoModal.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
import { useTranslation } from '@/src/hooks/useTranslation';

import { ModalState } from '@/src/types/modal';
import { Translation } from '@/src/types/translation';

import { ChatActions } from '@/src/store/chat/chat.reducer';
import { ChatSelectors } from '@/src/store/chat/chat.selectors';
import { useAppDispatch, useAppSelector } from '@/src/store/hooks';

import { OUTSIDE_PRESS_AND_MOUSE_EVENT } from '@/src/constants/modal';

import { Modal } from './Modal';
import { withRenderWhen } from './RenderWhen';

interface infoRowProps {
dataQa: string;
infoLabel: string;
info: string;
}

function InfoRow({ dataQa, infoLabel, info }: infoRowProps) {
return (
<div className="grid grid-cols-3 gap-4" data-qa={dataQa}>
<span className="col-span-1 whitespace-pre-wrap break-words text-secondary">
{infoLabel}:
</span>
<span className="col-span-2 whitespace-pre-wrap break-words">{info}</span>
</div>
);
}

export function InfoModalView() {
const { t } = useTranslation(Translation.Chat);
const dispatch = useAppDispatch();

const modalState = useAppSelector(ChatSelectors.selectInfoModalState);
const entityInfo = useAppSelector(ChatSelectors.selectSelectedEntityInfo);

const handleClose = () => {
dispatch(ChatActions.setInfoModalState(ModalState.CLOSED));
};
return (
<Modal
portalId="theme-main"
state={modalState}
onClose={handleClose}
dataQa="info-modal"
containerClassName="inline-block w-full min-w-[90%] px-3 py-4 md:p-6 md:min-w-[300px] md:max-w-[400px]"
dismissProps={OUTSIDE_PRESS_AND_MOUSE_EVENT}
heading={t('Information')}
headingClassName="mb-4"
loaderClassName="min-h-[80px]"
>
<div className="flex flex-col justify-between gap-4">
{entityInfo?.updatedAt && (
<InfoRow
infoLabel={t('Last updated')}
info={entityInfo.updatedAt}
dataQa="updated-at"
/>
)}

{entityInfo?.createdAt && (
<InfoRow
infoLabel={t('Creation date')}
info={entityInfo.createdAt}
dataQa="created-at"
/>
)}

{(entityInfo?.isPublic || entityInfo?.sharedWithMe) && (
<InfoRow
infoLabel={t('Author')}
info={entityInfo.author ?? t('Unknown')}
dataQa="author"
/>
)}
</div>
</Modal>
);
}

export const InfoModal = withRenderWhen(ChatSelectors.selectInfoModalOpened)(
InfoModalView,
);
11 changes: 11 additions & 0 deletions apps/chat/src/components/Common/ItemContextMenu.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import {
IconFileArrowRight,
IconFolderPlus,
IconFolderShare,
IconInfoCircle,
IconPencilMinus,
IconPlayerPlay,
IconRefreshDot,
Expand Down Expand Up @@ -73,6 +74,7 @@ interface ItemContextMenuProps {
onUse?: MouseEventHandler<unknown>;
isLoading?: boolean;
TriggerIcon?: ContextMenuProps['TriggerIcon'];
onShowInfo?: () => void;
}

export default function ItemContextMenu({
Expand Down Expand Up @@ -103,6 +105,7 @@ export default function ItemContextMenu({
onSelect,
disableUse,
onUse,
onShowInfo,
TriggerIcon,
}: ItemContextMenuProps) {
const { t } = useTranslation(Translation.SideBar);
Expand Down Expand Up @@ -308,6 +311,13 @@ export default function ItemContextMenu({
onClick: onUnpublish,
disabled: disableAll,
},
{
name: t('Info'),
display: !!onShowInfo,
dataQa: 'info',
Icon: IconInfoCircle,
onClick: onShowInfo,
},
{
name: t('Delete'),
dataQa: 'delete',
Expand Down Expand Up @@ -341,6 +351,7 @@ export default function ItemContextMenu({
onReplay,
onSelect,
onShare,
onShowInfo,
onUnpublish,
onUnshare,
onUse,
Expand Down
9 changes: 8 additions & 1 deletion apps/chat/src/components/Common/Modal.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ export interface Props extends FormHTMLAttributes<HTMLFormElement> {
state?: ModalState | boolean;
heading?: string | ReactNode;
headingClassName?: string;
loaderClassName?: string;
dataQa: string;
initialFocus?: number | MutableRefObject<HTMLElement | null>;
overlayClassName?: string;
Expand All @@ -52,6 +53,7 @@ function ModalView({
state = ModalState.CLOSED,
heading,
headingClassName,
loaderClassName,
onClose,
children,
dataQa,
Expand Down Expand Up @@ -145,7 +147,12 @@ function ModalView({
)}

{state === ModalState.LOADING ? (
<div className="flex min-h-[200px] items-center justify-center">
<div
className={classNames(
'flex min-h-[200px] items-center justify-center',
loaderClassName,
)}
>
<Spinner size={60} />
</div>
) : (
Expand Down
Loading
Loading