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

fix: fix shared with me display (Issue #704) #714

Merged
merged 4 commits into from
Feb 14, 2024
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
2 changes: 1 addition & 1 deletion apps/chat/src/hooks/useHandleFileFolders.ts
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,7 @@ export const useHandleFileFolders = (
* @param folderId - ID of the folder to toggle.
*/
const handleToggleFolder = useCallback(
(folderId: string | undefined) => {
(folderId: string) => {
if (!folderId) {
setIsAllFilesOpened((value) => !value);
setOpenedFoldersIds([]);
Expand Down
27 changes: 23 additions & 4 deletions apps/chat/src/store/conversations/conversations.epics.ts
Original file line number Diff line number Diff line change
Expand Up @@ -76,14 +76,15 @@ import { ApiKeys } from '@/src/utils/server/api';
import {
ChatBody,
Conversation,
ConversationInfo,
Message,
MessageSettings,
Playback,
RateBody,
Role,
} from '@/src/types/chat';
import { EntityType, FeatureType, UploadStatus } from '@/src/types/common';
import { FolderType } from '@/src/types/folder';
import { FolderInterface, FolderType } from '@/src/types/folder';
import { MigrationStorageKeys, StorageType } from '@/src/types/storage';
import { AppEpic } from '@/src/types/store';

Expand Down Expand Up @@ -2096,8 +2097,18 @@ const uploadConversationsWithFoldersEpic: AppEpic = (action$) =>
),
).pipe(
switchMap((foldersAndEntities) => {
const folders = foldersAndEntities.flatMap((f) => f.folders);
const conversations = foldersAndEntities.flatMap((f) => f.entities);
const folders = foldersAndEntities
.flatMap((f) => f.folders)
.map((item) => ({
...item,
...(payload.inheritedMetadata as Partial<FolderInterface>),
}));
const conversations = foldersAndEntities
.flatMap((f) => f.entities)
.map((item) => ({
...item,
...(payload.inheritedMetadata as Partial<ConversationInfo>),
}));
return concat(
of(
ConversationsActions.uploadFoldersSuccess({
Expand Down Expand Up @@ -2150,10 +2161,15 @@ const uploadConversationsWithFoldersRecursiveEpic: AppEpic = (action$) =>
of(
ConversationsActions.uploadFoldersSuccess({
paths: new Set(),
folders: getFoldersFromIds(paths, FolderType.Chat),
folders: getFoldersFromIds(
paths,
FolderType.Chat,
UploadStatus.LOADED,
),
allLoaded: true,
}),
),
of(ConversationsActions.initFoldersAndConversationsSuccess()),
);
}),
catchError(() => of(ConversationsActions.uploadConversationsFail())), // TODO: handle error it in https://github.com/epam/ai-dial-chat/issues/663
Expand Down Expand Up @@ -2198,6 +2214,9 @@ const openFolderEpic: AppEpic = (action$, state$) =>
of(
ConversationsActions.uploadConversationsWithFolders({
paths: [payload.id],
inheritedMetadata: {
sharedWithMe: true,
},
}),
),
);
Expand Down
3 changes: 3 additions & 0 deletions apps/chat/src/store/conversations/conversations.reducers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,7 @@ export const conversationsSlice = createSlice({
) => state,
initSelectedConversations: (state) => state,
initFoldersAndConversations: (state) => state,
initFoldersAndConversationsSuccess: (state) => state,
saveConversation: (state, _action: PayloadAction<Conversation>) => state,
recreateConversation: (
state,
Expand Down Expand Up @@ -595,6 +596,8 @@ export const conversationsSlice = createSlice({
payload,
}: PayloadAction<{
paths: (string | undefined)[];
// Needed for open shared with me folder and keep shared with me flag
inheritedMetadata?: unknown;
}>,
) => {
state.foldersStatus = UploadStatus.LOADING;
Expand Down
12 changes: 12 additions & 0 deletions apps/chat/src/store/conversations/conversations.selectors.ts
Original file line number Diff line number Diff line change
Expand Up @@ -168,6 +168,18 @@ export const selectChildAndCurrentFoldersIdsById = createSelector(
return new Set(getChildAndCurrentFoldersIdsById(folderId, folders));
},
);
export const selectFullTreeChildConversationsByFolderId = createSelector(
[selectConversations, selectChildAndCurrentFoldersIdsById],
(conversations, foldersIds) => {
return conversations.filter((conv) => foldersIds.has(conv.folderId));
},
);
export const selectFullTreeChildFoldersByFolderId = createSelector(
[selectFolders, selectChildAndCurrentFoldersIdsById],
(folders, foldersIds) => {
return folders.filter((folder) => foldersIds.has(folder.id));
},
);
export const selectFirstSelectedConversation = createSelector(
[selectSelectedConversations],
(conversations): Conversation | undefined => {
Expand Down
3 changes: 2 additions & 1 deletion apps/chat/src/store/files/files.epics.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ import { combineEpics } from 'redux-observable';
import { FileService } from '@/src/utils/app/data/file-service';
import { triggerDownload } from '@/src/utils/app/file';
import { translate } from '@/src/utils/app/translation';
import { encodeApiUrl } from '@/src/utils/server/api';

import { UploadStatus } from '@/src/types/common';
import { AppEpic } from '@/src/types/store';
Expand Down Expand Up @@ -229,7 +230,7 @@ const downloadFilesListEpic: AppEpic = (action$, state$) =>
tap(({ files }) => {
files.forEach((file) =>
triggerDownload(
`api/${encodeURI(`${file.absolutePath}/${file.name}`)}`,
`api/${encodeApiUrl(`${file.absolutePath}/${file.name}`)}`,
file.name,
),
);
Expand Down
12 changes: 12 additions & 0 deletions apps/chat/src/store/prompts/prompts.selectors.ts
Original file line number Diff line number Diff line change
Expand Up @@ -124,6 +124,18 @@ export const selectChildAndCurrentFoldersIdsById = createSelector(
return new Set(getChildAndCurrentFoldersIdsById(folderId, folders));
},
);
export const selectFullTreeChildPromptsByFolderId = createSelector(
[selectPrompts, selectChildAndCurrentFoldersIdsById],
(prompts, foldersIds) => {
return prompts.filter((conv) => foldersIds.has(conv.folderId));
},
);
export const selectFullTreeChildFoldersByFolderId = createSelector(
[selectFolders, selectChildAndCurrentFoldersIdsById],
(folders, foldersIds) => {
return folders.filter((folder) => foldersIds.has(folder.id));
},
);

export const selectSearchTerm = createSelector([rootSelector], (state) => {
return state.searchTerm;
Expand Down
87 changes: 67 additions & 20 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 { constructPath } from '@/src/utils/app/file';
import { splitEntityId } from '@/src/utils/app/folders';
import { translate } from '@/src/utils/app/translation';
import { parseConversationApiKey } from '@/src/utils/server/api';
import { encodeApiUrl, parseConversationApiKey } from '@/src/utils/server/api';

import { Conversation, Message } from '@/src/types/chat';
import {
Expand Down Expand Up @@ -111,7 +111,7 @@
invitationType: ShareRequestType.link,
resources: [
{
url: encodeURI(payload.resourceId),
url: encodeApiUrl(payload.resourceId),
},
...internalResources.map((res) => ({ url: res })),
],
Expand Down Expand Up @@ -159,7 +159,7 @@
invitationType: ShareRequestType.link,
resources: [
{
url: encodeURI(payload.resourceId + '/'),
url: encodeApiUrl(payload.resourceId) + '/',
},
...internalResourcesIds,
],
Expand Down Expand Up @@ -190,7 +190,7 @@
invitationType: ShareRequestType.link,
resources: [
{
url: encodeURI(payload.resourceId),
url: encodeApiUrl(payload.resourceId),
},
],
}).pipe(
Expand All @@ -215,7 +215,7 @@
invitationType: ShareRequestType.link,
resources: [
{
url: encodeURI(payload.resourceId + '/'),
url: encodeApiUrl(payload.resourceId) + '/',
},
],
}).pipe(
Expand Down Expand Up @@ -289,7 +289,7 @@
action$.pipe(
filter(
(action) =>
ConversationsActions.uploadConversationsSuccess.match(action) ||
ConversationsActions.initFoldersAndConversationsSuccess.match(action) ||
ShareActions.acceptShareInvitationSuccess.match(action),
),
filter(() =>
Expand Down Expand Up @@ -391,24 +391,48 @@
state$.value,
);
const folders = ConversationsSelectors.selectFolders(state$.value);

actions.push(
...(folders
.map((item) => {
.flatMap((item) => {
const isShared = payload.resources.folders.find(
(res) => res.id === item.id,
);

if (isShared) {
return ConversationsActions.updateFolder({
folderId: item.id,
values: {
isShared: true,
},
});
const childConversations =
ConversationsSelectors.selectFullTreeChildConversationsByFolderId(
state$.value,
item.id,
);
const childFolders =
ConversationsSelectors.selectFullTreeChildFoldersByFolderId(
state$.value,
item.id,
);

return [
...childFolders.map((folder) =>
ConversationsActions.updateFolder({
folderId: folder.id,
values: {
isShared: true,
},
}),
),
...childConversations.map((conv) =>
ConversationsActions.updateConversation({
id: conv.id,
values: {
isShared: true,
},
}),
),
];
}
return undefined;
})
.filter(Boolean) as any),

Check warning on line 435 in apps/chat/src/store/share/share.epics.ts

View workflow job for this annotation

GitHub Actions / run_tests / style_checks

Unexpected any. Specify a different type
);
actions.push(
...(conversations
Expand All @@ -427,7 +451,7 @@
}
return undefined;
})
.filter(Boolean) as any),

Check warning on line 454 in apps/chat/src/store/share/share.epics.ts

View workflow job for this annotation

GitHub Actions / run_tests / style_checks

Unexpected any. Specify a different type
);
} else {
actions.push(
Expand Down Expand Up @@ -468,27 +492,50 @@
}
return undefined;
})
.filter(Boolean) as any),

Check warning on line 495 in apps/chat/src/store/share/share.epics.ts

View workflow job for this annotation

GitHub Actions / run_tests / style_checks

Unexpected any. Specify a different type
);
const folders = PromptsSelectors.selectFolders(state$.value);
actions.push(
...(folders
.map((item) => {
.flatMap((item) => {
const isShared = payload.resources.folders.find(
(res) => res.id === item.id,
);

if (isShared) {
return PromptsActions.updateFolder({
folderId: item.id,
values: {
isShared: true,
},
});
const childPrompts =
PromptsSelectors.selectFullTreeChildPromptsByFolderId(
state$.value,
item.id,
);
const childFolders =
PromptsSelectors.selectFullTreeChildFoldersByFolderId(
state$.value,
item.id,
);

return [
...childFolders.map((folder) =>
PromptsActions.updateFolder({
folderId: folder.id,
values: {
isShared: true,
},
}),
),
...childPrompts.map((prompt) =>
PromptsActions.updatePrompt({
id: prompt.id,
values: {
isShared: true,
},
}),
),
];
}
return undefined;
})
.filter(Boolean) as any),

Check warning on line 538 in apps/chat/src/store/share/share.epics.ts

View workflow job for this annotation

GitHub Actions / run_tests / style_checks

Unexpected any. Specify a different type
);
} else {
actions.push(
Expand Down
26 changes: 14 additions & 12 deletions apps/chat/src/utils/app/data/share-service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ import {
import {
ApiKeys,
ApiUtils,
decodeApiUrl,
getFolderTypeByApiKey,
parseConversationApiKey,
parsePromptApiKey,
Expand Down Expand Up @@ -66,25 +67,26 @@ export class ShareService {

if (entity.nodeType === BackendDataNodeType.ITEM) {
const conversation = conversationResource as BackendChatEntity;
const id = decodeURI(
conversation.url.slice(0, conversation.url.length - 1),
);
const id = decodeApiUrl(conversation.url);

const { apiKey, bucket, parentPath } = splitEntityId(id);

entities.push({
...parseConversationApiKey(conversation.name),
id: decodeURI(conversation.url),
id,
lastActivityDate: conversation.updatedAt,
folderId: constructPath(apiKey, bucket, parentPath),
});
}
if (entity.nodeType === BackendDataNodeType.FOLDER) {
const folder = conversationResource as BackendChatFolder;
const id = decodeURI(folder.url.slice(0, folder.url.length - 1));
const id = decodeApiUrl(
folder.url.slice(0, folder.url.length - 1),
);
const { apiKey, bucket, parentPath } = splitEntityId(id);

folders.push({
id: decodeURI(folder.url.slice(0, folder.url.length - 1)),
id,
name: folder.name,
folderId: constructPath(apiKey, bucket, parentPath),
type: getFolderTypeByApiKey(ApiKeys.Conversations),
Expand All @@ -99,25 +101,25 @@ export class ShareService {

if (entity.nodeType === BackendDataNodeType.ITEM) {
const conversation = conversationResource as BackendChatEntity;
const id = decodeURI(
conversation.url.slice(0, conversation.url.length - 1),
);
const id = decodeApiUrl(conversation.url);
const { apiKey, bucket, parentPath } = splitEntityId(id);

entities.push({
...parsePromptApiKey(conversation.name),
id: decodeURI(conversation.url),
id,
lastActivityDate: conversation.updatedAt,
folderId: constructPath(apiKey, bucket, parentPath),
});
}
if (entity.nodeType === BackendDataNodeType.FOLDER) {
const folder = conversationResource as BackendChatFolder;
const id = decodeURI(folder.url.slice(0, folder.url.length - 1));
const id = decodeApiUrl(
folder.url.slice(0, folder.url.length - 1),
);
const { apiKey, bucket, parentPath } = splitEntityId(id);

folders.push({
id: decodeURI(folder.url.slice(0, folder.url.length - 1)),
id,
name: folder.name,
folderId: constructPath(apiKey, bucket, parentPath),
type: getFolderTypeByApiKey(ApiKeys.Prompts),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ export abstract class ApiEntityStorage<
name: folder.name,
folderId: constructPath(apiKey, bucket, parentPath),
type: getFolderTypeByApiKey(this.getStorageKey()),
isShared: false,
};
}

Expand All @@ -49,6 +50,7 @@ export abstract class ApiEntityStorage<
id,
lastActivityDate: entity.updatedAt,
folderId: constructPath(apiKey, bucket, parentPath),
isShared: false,
} as unknown as TEntityInfo;
}

Expand Down Expand Up @@ -150,7 +152,7 @@ export abstract class ApiEntityStorage<
'Content-Type': 'application/json',
},
body: JSON.stringify(this.cleanUpEntity(entity)),
}) // TODO: handle error it in https://github.com/epam/ai-dial-chat/issues/663
}); // TODO: handle error it in https://github.com/epam/ai-dial-chat/issues/663
}

updateEntity(entity: TEntity): Observable<void> {
Expand Down
Loading
Loading