Skip to content

Commit

Permalink
fix(chat): fix links sharing and playback with folders (Issue #1372, #…
Browse files Browse the repository at this point in the history
  • Loading branch information
IlyaBondar authored May 16, 2024
1 parent 256ce6a commit 206fa34
Show file tree
Hide file tree
Showing 8 changed files with 66 additions and 23 deletions.
8 changes: 4 additions & 4 deletions apps/chat/src/components/Chat/MessageAttachment.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ import {
import { useAppDispatch, useAppSelector } from '@/src/store/hooks';
import { SettingsSelectors } from '@/src/store/settings/settings.reducers';

import { chartType, stopBubbling } from '@/src/constants/chat';
import { PLOTLY_CONTENT_TYPE, stopBubbling } from '@/src/constants/chat';
import { FOLDER_ATTACHMENT_CONTENT_TYPE } from '@/src/constants/folders';

import { Spinner } from '@/src/components/Common/Spinner';
Expand Down Expand Up @@ -100,7 +100,7 @@ const AttachmentDataRenderer = ({
/>
);
}
if (attachment.type === chartType) {
if (attachment.type === PLOTLY_CONTENT_TYPE) {
return (
<PlotlyComponent plotlyData={attachment.data as unknown as PlotParams} />
);
Expand Down Expand Up @@ -214,7 +214,7 @@ const AttachmentUrlRendererComponent = ({
);
}

if (attachmentType === chartType) {
if (attachmentType === PLOTLY_CONTENT_TYPE) {
return <ChartAttachmentUrlRenderer attachmentUrl={mappedAttachmentUrl} />;
}

Expand Down Expand Up @@ -268,7 +268,7 @@ export const MessageAttachment = ({ attachment, isInner }: Props) => {
const isOpenable =
attachment.data ||
(attachment.url && imageTypes.has(attachment.type)) ||
attachment.type === chartType ||
attachment.type === PLOTLY_CONTENT_TYPE ||
isCustomAttachmentType;
const mappedAttachmentUrl = useMemo(
() => getMappedAttachmentUrl(attachment.url),
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import {
getDialFilesFromAttachments,
getDialFoldersFromAttachments,
getDialLinksFromAttachments,
} from '@/src/utils/app/file';

Expand All @@ -13,12 +14,13 @@ interface PlaybackAttachmentsProps {

export function PlaybackAttachments({ attachments }: PlaybackAttachmentsProps) {
const files = getDialFilesFromAttachments(attachments);
const folders = getDialFoldersFromAttachments(attachments);
const links = getDialLinksFromAttachments(attachments);

return (
<div className="relative rounded">
<div className="flex max-h-[100px] flex-col gap-1 overflow-auto pt-3 md:grid md:grid-cols-3">
<ChatInputAttachments files={files} links={links} />
<ChatInputAttachments files={files} folders={folders} links={links} />
</div>
</div>
);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ vi.mock('@/src/utils/app/file', () => {
});
return files;
}),
getDialFoldersFromAttachments: vi.fn().mockReturnValue([]),
getDialLinksFromAttachments: vi.fn().mockReturnValue([]),
};
});
Expand Down
3 changes: 2 additions & 1 deletion apps/chat/src/components/Files/AttachButton.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { Placement } from '@floating-ui/react';
import {
IconFileDescription,
IconFolder,
IconLink,
IconPaperclip,
IconUpload,
Expand Down Expand Up @@ -88,7 +89,7 @@ export const AttachButton = ({
),
dataQa: 'attach_uploaded',
display: canAttachFiles || canAttachFolders,
Icon: IconFileDescription,
Icon: !canAttachFiles ? IconFolder : IconFileDescription,
onClick: handleOpenAttachmentsModal,
},
{
Expand Down
2 changes: 1 addition & 1 deletion apps/chat/src/constants/chat.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,6 @@ export const resetShareEntity: ShareInterface = {
sharedWithMe: false,
};

export const chartType = 'application/vnd.plotly.v1+json';
export const PLOTLY_CONTENT_TYPE = 'application/vnd.plotly.v1+json';

export const ISOLATED_MODEL_QUERY_PARAM = 'isolated-model-id';
16 changes: 12 additions & 4 deletions apps/chat/src/store/share/share.epics.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ import { combineEpics } from 'redux-observable';

import { ConversationService } from '@/src/utils/app/data/conversation-service';
import { ShareService } from '@/src/utils/app/data/share-service';
import { constructPath } from '@/src/utils/app/file';
import { constructPath, isAttachmentLink } from '@/src/utils/app/file';
import { splitEntityId } from '@/src/utils/app/folders';
import { isConversationId, isFolderId, isPromptId } from '@/src/utils/app/id';
import { EnumMapper } from '@/src/utils/app/mappers';
Expand All @@ -36,6 +36,7 @@ import {
} from '@/src/types/share';
import { AppEpic } from '@/src/types/store';

import { PLOTLY_CONTENT_TYPE } from '@/src/constants/chat';
import { DEFAULT_CONVERSATION_NAME } from '@/src/constants/default-ui-settings';
import { errorsMessages } from '@/src/constants/errors';

Expand All @@ -55,8 +56,13 @@ const getInternalResourcesUrls = (
return (messages
?.map((message) =>
message.custom_content?.attachments
?.map((attachment) => attachment.url)
.filter(Boolean),
?.map((attachment) =>
attachment.url && attachment.type === PLOTLY_CONTENT_TYPE
? ApiUtils.encodeApiUrl(attachment.url)
: attachment.url,
)
.filter(Boolean)
.filter((url) => url && !isAttachmentLink(url)),
)
.filter(Boolean)
.flat() || []) as string[];
Expand Down Expand Up @@ -116,7 +122,9 @@ const shareConversationEpic: AppEpic = (action$) =>
{
url: ApiUtils.encodeApiUrl(payload.resourceId),
},
...internalResources.map((res) => ({ url: res })),
...internalResources.map((res) => ({
url: res,
})),
],
}).pipe(
map((response: ShareByLinkResponseModel) => {
Expand Down
47 changes: 39 additions & 8 deletions apps/chat/src/utils/app/file.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,15 @@ import { TFunction } from 'next-i18next';

import { Attachment, Conversation } from '@/src/types/chat';
import { UploadStatus } from '@/src/types/common';
import { DialFile, DialLink } from '@/src/types/files';
import { FolderInterface } from '@/src/types/folder';
import { DialFile, DialLink, FileFolderInterface } from '@/src/types/files';
import { FolderInterface, FolderType } from '@/src/types/folder';

import { FOLDER_ATTACHMENT_CONTENT_TYPE } from '@/src/constants/folders';

import { ApiUtils } from '../server/api';
import { doesHaveDotsInTheEnd } from './common';
import { getPathToFolderById } from './folders';
import { isFolderId } from './id';

import escapeRegExp from 'lodash-es/escapeRegExp';
import { extensions } from 'mime-types';
Expand Down Expand Up @@ -171,6 +172,9 @@ const parseAttachmentUrl = (url: string) => {
};
};

export const isAttachmentLink = (url: string): boolean =>
url.startsWith('http') || url.startsWith('//');

export const getDialFilesFromAttachments = (
attachments: Attachment[] | undefined,
): Omit<DialFile, 'contentLength'>[] => {
Expand All @@ -182,8 +186,8 @@ export const getDialFilesFromAttachments = (
.map((attachment): Omit<DialFile, 'contentLength'> | null => {
if (
!attachment.url ||
attachment.url.startsWith('http') ||
attachment.url.startsWith('//')
isAttachmentLink(attachment.url) ||
isFolderId(attachment.url)
) {
return null;
}
Expand All @@ -201,22 +205,49 @@ export const getDialFilesFromAttachments = (
.filter(Boolean) as Omit<DialFile, 'contentLength'>[];
};

export const getDialLinksFromAttachments = (
export const getDialFoldersFromAttachments = (
attachments: Attachment[] | undefined,
): DialLink[] => {
): FileFolderInterface[] => {
if (!attachments) {
return [];
}

return attachments
.map((attachment): DialLink | null => {
.map((attachment): FileFolderInterface | null => {
if (
!attachment.url ||
(!attachment.url.startsWith('http') && !attachment.url.startsWith('//'))
isAttachmentLink(attachment.url) ||
!isFolderId(attachment.url)
) {
return null;
}

const { absolutePath, name } = parseAttachmentUrl(attachment.url);

return {
id: attachment.url,
type: FolderType.File,
name,
folderId: absolutePath,
absolutePath,
};
})
.filter(Boolean) as FileFolderInterface[];
};

export const getDialLinksFromAttachments = (
attachments: Attachment[] | undefined,
): DialLink[] => {
if (!attachments) {
return [];
}

return attachments
.map((attachment): DialLink | null => {
if (!attachment.url || !isAttachmentLink(attachment.url)) {
return null;
}

return {
href: attachment.url,
title: attachment.title,
Expand Down
8 changes: 4 additions & 4 deletions apps/chat/src/utils/app/import-export.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ import { Prompt } from '@/src/types/prompt';

import { UploadedAttachment } from '@/src/store/import-export/importExport.reducers';

import { chartType } from '@/src/constants/chat';
import { PLOTLY_CONTENT_TYPE } from '@/src/constants/chat';

import { ApiUtils } from '../server/api';
import { cleanConversationHistory } from './clean';
Expand Down Expand Up @@ -425,19 +425,19 @@ export const updateAttachment = ({
// TODO: remove ApiUtils.encodeApiUrl from updateAttachment()
const newAttachmentUrl =
oldAttachment.url &&
(oldAttachment.type === chartType
(oldAttachment.type === PLOTLY_CONTENT_TYPE
? constructPath(newAttachmentFile.absolutePath, newAttachmentFile.name)
: ApiUtils.encodeApiUrl(
constructPath(newAttachmentFile.absolutePath, newAttachmentFile.name),
));

const newType =
oldAttachment.type === chartType
oldAttachment.type === PLOTLY_CONTENT_TYPE
? oldAttachment.type ?? newAttachmentFile.contentType
: newAttachmentFile.contentType ?? oldAttachment.type;

const newTitle =
oldAttachment.type === chartType
oldAttachment.type === PLOTLY_CONTENT_TYPE
? oldAttachment.title ?? newAttachmentFile.name
: newAttachmentFile.name ?? oldAttachment.title;

Expand Down

0 comments on commit 206fa34

Please sign in to comment.