Skip to content

Commit

Permalink
feat(chat): add a 'Shared with me' section to the file manager modal …
Browse files Browse the repository at this point in the history
…(Issues #1283, #1982, #1987) (#1990)
  • Loading branch information
denys-kolomiitsev authored Aug 30, 2024
1 parent 98eb7a2 commit 83d0b5d
Show file tree
Hide file tree
Showing 10 changed files with 212 additions and 36 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@ import { useTranslation } from 'next-i18next';
import classNames from 'classnames';

import { constructPath } from '@/src/utils/app/file';
import { ApiUtils } from '@/src/utils/server/api';

import { ConversationInfo } from '@/src/types/chat';
import { Entity, FeatureType } from '@/src/types/common';
Expand Down Expand Up @@ -186,10 +185,7 @@ export function PublicationItemsList({
onSelect={handleSelect}
isChosen={chosenItemsIds.some((id) => id === f.id)}
/>
<a
download={f.name}
href={constructPath('api', ApiUtils.encodeApiUrl(f.id))}
>
<a download={f.name} href={constructPath('api', f.id)}>
<IconDownload
className="shrink-0 text-secondary hover:text-accent-primary"
size={18}
Expand Down
5 changes: 3 additions & 2 deletions apps/chat/src/components/Files/Download.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { constructPath } from '@/src/utils/app/file';
import { getDownloadPath } from '@/src/utils/app/file';
import { ApiUtils } from '@/src/utils/server/api';

import { DialFile } from '@/src/types/files';
Expand All @@ -12,10 +12,11 @@ export default function DownloadRenderer({
...props
}: CustomTriggerMenuRendererProps) {
const file = customTriggerData as DialFile;
const filePath = getDownloadPath(file);
return (
<a
download={file.name}
href={`api/${ApiUtils.encodeApiUrl(constructPath(file.absolutePath, file.name))}`}
href={`api/${ApiUtils.encodeApiUrl(filePath)}`}
onClick={onClick}
className={className}
>
Expand Down
93 changes: 92 additions & 1 deletion apps/chat/src/components/Files/FileManagerModal.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ import { getParentFolderIdsFromFolderId } from '@/src/utils/app/folders';
import { getFileRootId, isFolderId } from '@/src/utils/app/id';
import {
PublishedWithMeFilter,
SharedWithMeFilters,
defaultMyItemsFilters,
} from '@/src/utils/app/search';

Expand All @@ -36,6 +37,7 @@ import { Translation } from '@/src/types/translation';
import { ConversationsSelectors } from '@/src/store/conversations/conversations.reducers';
import { FilesActions, FilesSelectors } from '@/src/store/files/files.reducers';
import { useAppDispatch, useAppSelector } from '@/src/store/hooks';
import { ShareActions } from '@/src/store/share/share.reducers';

import Modal from '@/src/components/Common/Modal';

Expand Down Expand Up @@ -164,6 +166,19 @@ export const FileManagerModal = ({
searchQuery,
),
);

const sharedWithMeRootFolders = useAppSelector((state) =>
FilesSelectors.selectFilteredFolders(
state,
SharedWithMeFilters,
searchQuery,
),
);

const sharedWithMeRootFiles = useAppSelector((state) =>
FilesSelectors.selectFilteredFiles(state, SharedWithMeFilters, searchQuery),
);

const areFoldersLoading = useAppSelector(
FilesSelectors.selectAreFoldersLoading,
);
Expand Down Expand Up @@ -252,7 +267,9 @@ export const FileManagerModal = ({
!myRootFolders.length &&
!myRootFiles.length &&
!organizationRootFolders.length &&
!organizationRootFiles.length;
!organizationRootFiles.length &&
!sharedWithMeRootFolders.length &&
!sharedWithMeRootFiles.length;

const showNoResult = searchQuery !== '' && isNothingExists;

Expand Down Expand Up @@ -527,6 +544,19 @@ export const FileManagerModal = ({
[canAttachFiles, dispatch, forceShowSelectCheckBox],
);

const handleDeleteFolder = useCallback(
(folderId: string) => {
dispatch(
ShareActions.discardSharedWithMe({
resourceId: folderId,
featureType: FeatureType.File,
isFolder: true,
}),
);
},
[dispatch],
);

const handleDeleteMultipleFiles = useCallback(() => {
if (!deletingFileIds.length && !deletingFolderIds.length) {
return;
Expand Down Expand Up @@ -691,6 +721,67 @@ export const FileManagerModal = ({
})}
</div>
</FilesSectionWrapper>

<FilesSectionWrapper
name={t('Shared with me')}
dataQa="shared-with-me-files"
folders={sharedWithMeRootFolders}
files={sharedWithMeRootFiles}
>
<div className="flex flex-col gap-1 overflow-auto">
{sharedWithMeRootFolders.map((folder) => {
return (
<Folder
key={folder.id}
searchTerm={searchQuery}
currentFolder={folder}
allFolders={folders}
highlightedFolders={highlightFolderIds}
newAddedFolderId={newFolderId}
loadingFolderIds={loadingFolderIds}
openedFoldersIds={openedFoldersIds}
allItems={files}
additionalItemData={{
selectedFilesIds,
selectedFolderIds,
canAttachFiles:
canAttachFiles || forceShowSelectCheckBox,
}}
itemComponent={FileItem}
onClickFolder={handleFolderSelect}
onAddFolder={handleAddFolder}
onFileUpload={handleUploadFile}
onRenameFolder={handleRenameFolder}
skipFolderRenameValidation
onItemEvent={handleItemCallback}
withBorderHighlight={false}
featureType={FeatureType.File}
canSelectFolders={canAttachFolders}
showTooltip={showTooltip}
onSelectFolder={handleFolderToggle}
onDeleteFolder={handleDeleteFolder}
/>
);
})}
{sharedWithMeRootFiles.map((file) => {
return (
<FileItem
key={file.id}
item={file}
level={0}
additionalItemData={{
selectedFolderIds,
selectedFilesIds,
canAttachFiles:
canAttachFiles || forceShowSelectCheckBox,
}}
onEvent={handleItemCallback}
/>
);
})}
</div>
</FilesSectionWrapper>

<FilesSectionWrapper
name={t('All files')}
dataQa="all-files"
Expand Down
23 changes: 17 additions & 6 deletions apps/chat/src/store/files/files.epics.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,14 +16,15 @@ import {
import { combineEpics } from 'redux-observable';

import { FileService } from '@/src/utils/app/data/file-service';
import { triggerDownload } from '@/src/utils/app/file';
import { getDownloadPath, triggerDownload } from '@/src/utils/app/file';
import { translate } from '@/src/utils/app/translation';
import { ApiUtils } from '@/src/utils/server/api';

import { FeatureType, UploadStatus } from '@/src/types/common';
import { AppEpic } from '@/src/types/store';

import { PublicationActions } from '../publication/publication.reducers';
import { ShareActions } from '../share/share.reducers';
import { UIActions, UISelectors } from '../ui/ui.reducers';
import { FilesActions, FilesSelectors } from './files.reducers';

Expand Down Expand Up @@ -168,6 +169,15 @@ const deleteFileEpic: AppEpic = (action$, state$) =>
(file) => file.id === payload.fileId,
);

if (file && file.sharedWithMe) {
return of(
ShareActions.discardSharedWithMe({
resourceId: file.id,
featureType: FeatureType.File,
}),
);
}

if (!file?.serverSynced) {
return concat(
of(
Expand Down Expand Up @@ -258,12 +268,13 @@ const downloadFilesListEpic: AppEpic = (action$, state$) =>
files: FilesSelectors.selectFilesByIds(state$.value, payload.fileIds),
})),
tap(({ files }) => {
files.forEach((file) =>
triggerDownload(
`api/${ApiUtils.encodeApiUrl(`${file.absolutePath}/${file.name}`)}`,
files.forEach((file) => {
const filePath = getDownloadPath(file);
return triggerDownload(
`api/${ApiUtils.encodeApiUrl(filePath)}`,
file.name,
),
);
);
});
}),
ignoreElements(),
);
Expand Down
17 changes: 16 additions & 1 deletion apps/chat/src/store/files/files.reducers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ import { isEntityExternal } from '@/src/utils/app/share';

import { UploadStatus } from '@/src/types/common';
import { DialFile, FileFolderInterface } from '@/src/types/files';
import { FolderType } from '@/src/types/folder';
import { FolderInterface, FolderType } from '@/src/types/folder';
import { EntityFilters } from '@/src/types/search';

import { DEFAULT_FOLDER_NAME } from '@/src/constants/default-ui-settings';
Expand Down Expand Up @@ -260,6 +260,18 @@ export const filesSlice = createSlice({
);
state.newAddedFolderId = newAddedFolderId;
},
setFolders: (
state,
{ payload }: PayloadAction<{ folders: FolderInterface[] }>,
) => {
state.folders = payload.folders;
},
addFolders: (
state,
{ payload }: PayloadAction<{ folders: FolderInterface[] }>,
) => {
state.folders = combineEntities(state.folders, payload.folders);
},
renameFolder: (
state,
{
Expand Down Expand Up @@ -393,6 +405,9 @@ export const filesSlice = createSlice({
) => {
state.sharedFileIds = payload.ids;
},
addFiles: (state, { payload }: PayloadAction<{ files: DialFile[] }>) => {
state.files = combineEntities(payload.files, state.files);
},
},
});

Expand Down
10 changes: 6 additions & 4 deletions apps/chat/src/store/publication/publication.epics.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ import { combineEpics } from 'redux-observable';
import { ConversationService } from '@/src/utils/app/data/conversation-service';
import { PromptService } from '@/src/utils/app/data/prompt-service';
import { PublicationService } from '@/src/utils/app/data/publication-service';
import { constructPath } from '@/src/utils/app/file';
import {
getFolderFromId,
getFolderIdFromEntityId,
Expand Down Expand Up @@ -651,15 +652,16 @@ const uploadPublishedWithMeItemsEpic: AppEpic = (action$, state$) =>
FilesActions.getFilesSuccess({
files: (items as PublishedFileItem[]).map((item) => {
const decodedUrl = ApiUtils.decodeApiUrl(item.url);
const parsedApiKey = parsePromptApiKey(
splitEntityId(decodedUrl).name,
);
const { apiKey, bucket, parentPath, name } =
splitEntityId(decodedUrl);

return {
contentLength: item.contentLength,
contentType: item.contentType,
absolutePath: constructPath(apiKey, bucket, parentPath),
id: decodedUrl,
folderId: getFolderIdFromEntityId(decodedUrl),
name: parsedApiKey.name,
name,
publishedWithMe: true,
};
}),
Expand Down
Loading

0 comments on commit 83d0b5d

Please sign in to comment.