✨ Shared with me UI (#72)
This commit is contained in:
@@ -132,11 +132,12 @@ export class DriveApiClient {
|
||||
);
|
||||
}
|
||||
|
||||
static async search(searchString: string, options?: BaseSearchOptions) {
|
||||
static async search(searchString: string, view?: string,options?: BaseSearchOptions) {
|
||||
const companyId = options?.company_id ? options.company_id : Workspace.currentGroupId;
|
||||
const query = `/internal/services/documents/v1/companies/${companyId}/search`;
|
||||
const searchData = {
|
||||
search: searchString,
|
||||
view: view
|
||||
};
|
||||
const res = await Api.post<SearchDocumentsBody, { entities: DriveItem[] }>(query, searchData);
|
||||
this.logger.debug(
|
||||
@@ -147,4 +148,18 @@ export class DriveApiClient {
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
static async sharedWithMe(options?: BaseSearchOptions) {
|
||||
const companyId = options?.company_id ? options.company_id : Workspace.currentGroupId;
|
||||
const query = `/internal/services/documents/v1/companies/${companyId}/shared-with-me`;
|
||||
const filterData = {};
|
||||
const res = await Api.post<SearchDocumentsBody, { entities: DriveItem[] }>(query, filterData);
|
||||
this.logger.debug(
|
||||
`Drive shared with me by filter "${JSON.stringify(filterData)}". Found`,
|
||||
res.entities.length,
|
||||
'drive item(s)',
|
||||
);
|
||||
|
||||
return res;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,7 +4,7 @@ import { useCallback } from 'react';
|
||||
import { useRecoilCallback } from 'recoil';
|
||||
import { DriveApiClient } from '../api-client/api-client';
|
||||
import { DriveItemAtom, DriveItemChildrenAtom } from '../state/store';
|
||||
import { DriveItem, DriveItemVersion } from '../types';
|
||||
import { DriveItem, DriveItemDetails, DriveItemVersion } from '../types';
|
||||
|
||||
/**
|
||||
* Returns the children of a drive item
|
||||
@@ -18,20 +18,59 @@ export const useDriveActions = () => {
|
||||
({ set, snapshot }) =>
|
||||
async (parentId: string) => {
|
||||
if (parentId) {
|
||||
try {
|
||||
const details = await DriveApiClient.get(companyId, parentId);
|
||||
if (parentId == "shared-with-me") {
|
||||
const details = {
|
||||
path: [
|
||||
{
|
||||
id: "shared-with-me",
|
||||
name: "Shared with me"
|
||||
}
|
||||
],
|
||||
item: {
|
||||
id: "root",
|
||||
parent_id: "",
|
||||
company_id: "",
|
||||
workspace_id: "",
|
||||
name: "Shared with me",
|
||||
size: 0,
|
||||
description: "",
|
||||
tags: [],
|
||||
in_trash: false,
|
||||
is_directory: true,
|
||||
extension: "",
|
||||
added: "",
|
||||
last_modified: "",
|
||||
last_version_cache: {},
|
||||
access_info: {},
|
||||
},
|
||||
versions: [],
|
||||
children: [],
|
||||
access: "manage",
|
||||
websockets: [
|
||||
{
|
||||
room: "/companies/aa7ffdd0-fadb-11ed-b891-510fe3501b2b/documents/item/root",
|
||||
token: "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiJhYTU0Y2YyMC1mYWRiLTExZWQtYjg5MS01MTBmZTM1MDFiMmIiLCJuYW1lIjoiL2NvbXBhbmllcy9hYTdmZmRkMC1mYWRiLTExZWQtYjg5MS01MTBmZTM1MDFiMmIvZG9jdW1lbnRzL2l0ZW0vcm9vdCIsImlhdCI6MTY4ODk1MDk2OCwibmJmIjoxNjg2MjcyNTA4fQ.H6BFRcLG3Op32sqKi45Pf1s2YKcVbMxGZGPJal06l1g"
|
||||
}
|
||||
]
|
||||
};
|
||||
set(DriveItemChildrenAtom(parentId), details.children);
|
||||
set(DriveItemAtom(parentId), details);
|
||||
for (const child of details.children) {
|
||||
const currentValue = snapshot.getLoadable(DriveItemAtom(child.id)).contents;
|
||||
if (!currentValue) {
|
||||
//only update if not already in cache to avoid concurrent updates
|
||||
set(DriveItemAtom(child.id), { item: child });
|
||||
}
|
||||
}
|
||||
return details;
|
||||
} catch (e) {
|
||||
ToasterService.error('Unable to load your files.');
|
||||
} else {
|
||||
try {
|
||||
const details = await DriveApiClient.get(companyId, parentId);
|
||||
set(DriveItemChildrenAtom(parentId), details.children);
|
||||
set(DriveItemAtom(parentId), details);
|
||||
for (const child of details.children) {
|
||||
const currentValue = snapshot.getLoadable(DriveItemAtom(child.id)).contents;
|
||||
if (!currentValue) {
|
||||
//only update if not already in cache to avoid concurrent updates
|
||||
set(DriveItemAtom(child.id), { item: child });
|
||||
}
|
||||
}
|
||||
return details;
|
||||
} catch (e) {
|
||||
ToasterService.error('Unable to load your files.');
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
@@ -0,0 +1,80 @@
|
||||
import { DriveApiClient } from '@features/drive/api-client/api-client';
|
||||
import { useGlobalEffect } from '@features/global/hooks/use-global-effect';
|
||||
import { LoadingState } from '@features/global/state/atoms/Loading';
|
||||
import { delayRequest } from '@features/global/utils/managedSearchRequest';
|
||||
import useRouterCompany from '@features/router/hooks/use-router-company';
|
||||
import _ from 'lodash';
|
||||
import { useRecoilState, useRecoilValue } from 'recoil';
|
||||
import { SharedWithMeDriveItemsResultsState } from '../state/shared-with-me-drive-items-result';
|
||||
import { SearchInputState } from '../../search/state/search-input';
|
||||
|
||||
export const useSharedWithMeDriveItemsLoading = () => {
|
||||
return useRecoilValue(LoadingState('useSearchDriveItems'));
|
||||
};
|
||||
|
||||
let currentQuery = '';
|
||||
|
||||
export const useSharedWithMeDriveItems = () => {
|
||||
const companyId = useRouterCompany();
|
||||
const searchInput = useRecoilValue(SearchInputState);
|
||||
const [loading, setLoading] = useRecoilState(LoadingState('useSearchDriveItems'));
|
||||
|
||||
const [items, setItems] = useRecoilState(SharedWithMeDriveItemsResultsState(companyId));
|
||||
|
||||
const opt = _.omitBy(
|
||||
{
|
||||
limit: 25,
|
||||
workspace_id: searchInput.workspaceId,
|
||||
company_id: companyId,
|
||||
channel_id: searchInput.channelId,
|
||||
},
|
||||
_.isUndefined,
|
||||
);
|
||||
|
||||
const refresh = async () => {
|
||||
setLoading(true);
|
||||
|
||||
const query = searchInput.query;
|
||||
currentQuery = query;
|
||||
|
||||
const response = await DriveApiClient.sharedWithMe(opt);
|
||||
console.log("response is: ", response);
|
||||
const results = response.entities || [];
|
||||
|
||||
const update = {
|
||||
results,
|
||||
nextPage: '',
|
||||
// nextPage: response.next_page_token,
|
||||
};
|
||||
|
||||
if (currentQuery !== query) {
|
||||
return;
|
||||
}
|
||||
setItems(update);
|
||||
setLoading(false);
|
||||
};
|
||||
|
||||
const loadMore = async () => {
|
||||
//Not implemented
|
||||
console.error('Not implemented');
|
||||
};
|
||||
|
||||
useGlobalEffect(
|
||||
'useSearchDriveItems',
|
||||
() => {
|
||||
(async () => {
|
||||
setLoading(true);
|
||||
if (searchInput.query) {
|
||||
delayRequest('useSearchDriveItems', async () => {
|
||||
await refresh();
|
||||
});
|
||||
} else {
|
||||
refresh();
|
||||
}
|
||||
})();
|
||||
},
|
||||
[searchInput.channelId, searchInput.workspaceId],
|
||||
);
|
||||
|
||||
return { loading, driveItems: [...items.results], loadMore, refresh };
|
||||
};
|
||||
@@ -0,0 +1,22 @@
|
||||
import { DriveItem } from '@features/drive/types';
|
||||
import { atomFamily, selectorFamily } from 'recoil';
|
||||
|
||||
export type SharedWithMeDriveItemsResults = {
|
||||
results: DriveItem[];
|
||||
nextPage: string | null;
|
||||
};
|
||||
|
||||
export const SharedWithMeDriveItemsResultsState = atomFamily<SharedWithMeDriveItemsResults, string>({
|
||||
key: 'SharedWithMeDriveItemsResultsState',
|
||||
default: () => ({ results: [], nextPage: '' }),
|
||||
});
|
||||
|
||||
export const SearchFilesResultsNumberSelector = selectorFamily<number, string>({
|
||||
key: 'SharedWithMeDriveItemsResultsNumberSelector',
|
||||
get:
|
||||
(companyId: string) =>
|
||||
({ get }) => {
|
||||
const snapshot = get(SharedWithMeDriveItemsResultsState(companyId));
|
||||
return snapshot.results.length;
|
||||
},
|
||||
});
|
||||
@@ -0,0 +1,12 @@
|
||||
import { useRecoilValue, useSetRecoilState } from 'recoil';
|
||||
import RouterService from '@features/router/services/router-service';
|
||||
import { RouterState } from '@features/router/state/atoms/router';
|
||||
import { RouteViewSelector } from '@features/router/state/selectors/router-selector';
|
||||
|
||||
export default function useRouteView() {
|
||||
const setClientState = useSetRecoilState(RouterState);
|
||||
RouterService.setRecoilState = setClientState;
|
||||
const viewId = useRecoilValue(RouteViewSelector);
|
||||
|
||||
return viewId;
|
||||
}
|
||||
@@ -25,6 +25,7 @@ export type RouteType = {
|
||||
|
||||
export type ClientStateType = {
|
||||
companyId?: string;
|
||||
viewId?: string;
|
||||
workspaceId?: string;
|
||||
channelId?: string;
|
||||
messageId?: string;
|
||||
@@ -47,6 +48,7 @@ class RouterServices extends Observable {
|
||||
//List of client sub paths
|
||||
clientSubPathnames: Readonly<string[]> = [
|
||||
'/client/:companyId',
|
||||
'/client/:companyId/v/:viewId',
|
||||
'/client/:companyId/w/:workspaceId',
|
||||
'/client/:companyId/w/:workspaceId/c/:channelId',
|
||||
'/client/:companyId/w/:workspaceId/c/:channelId/t/:threadId',
|
||||
@@ -61,6 +63,7 @@ class RouterServices extends Observable {
|
||||
|
||||
pathnames: Readonly<Pathnames> = {
|
||||
CLIENT: '/client',
|
||||
SHARED_WITH_ME: '/client/:companyId/shared-with-me',
|
||||
SHARED: '/shared/:companyId/:appName/:documentId/t/:token',
|
||||
LOGIN: '/login',
|
||||
LOGOUT: '/logout',
|
||||
@@ -107,6 +110,15 @@ class RouterServices extends Observable {
|
||||
withErrorBoundary: true,
|
||||
},
|
||||
},
|
||||
{
|
||||
path: this.pathnames.SHARED_WITH_ME,
|
||||
key: 'client_shared',
|
||||
exact: false,
|
||||
component: App,
|
||||
options: {
|
||||
withErrorBoundary: true,
|
||||
},
|
||||
},
|
||||
{
|
||||
path: this.pathnames.SHARED,
|
||||
key: 'shared',
|
||||
@@ -167,6 +179,7 @@ class RouterServices extends Observable {
|
||||
|
||||
const reducedState: any = {
|
||||
companyId: match?.params?.companyId || '',
|
||||
viewId: match?.params?.viewId || '',
|
||||
workspaceId: match?.params?.workspaceId || '',
|
||||
channelId: match?.params?.channelId || '',
|
||||
messageId: match?.params?.messageId || '',
|
||||
@@ -177,6 +190,7 @@ class RouterServices extends Observable {
|
||||
token: match?.params?.token || '',
|
||||
appName: match?.params?.appName || '',
|
||||
shared: !!this.match(this.pathnames.SHARED),
|
||||
sharedWithMe: !!this.match(this.pathnames.SHARED_WITH_ME),
|
||||
};
|
||||
|
||||
const queryParameters = this.allowedQueryParameters[match?.path];
|
||||
@@ -270,6 +284,8 @@ class RouterServices extends Observable {
|
||||
return (
|
||||
`${this.pathnames.CLIENT}` +
|
||||
(state.companyId ? `/${state.companyId}` : '') +
|
||||
(state.viewId ? `/v/${state.viewId}` : '') +
|
||||
(state.sharedWithMe ? `/shared-with-me` : '') +
|
||||
(state.workspaceId ? `/w/${state.workspaceId}` : '') +
|
||||
(state.channelId ? `/c/${state.channelId}` : '') +
|
||||
(state.threadId ? `/t/${state.threadId}` : '') +
|
||||
|
||||
@@ -6,6 +6,11 @@ export const RouterCompanySelector = selector<string>({
|
||||
get: ({ get }) => get(RouterState)?.companyId || '',
|
||||
});
|
||||
|
||||
export const RouteViewSelector = selector<string>({
|
||||
key: 'RouterViewSelector',
|
||||
get: ({ get }) => get(RouterState)?.viewId || '',
|
||||
});
|
||||
|
||||
export const RouterWorkspaceSelector = selector<string>({
|
||||
key: 'RouterWorkspaceSelector',
|
||||
get: ({ get }) => get(RouterState)?.workspaceId || '',
|
||||
|
||||
@@ -42,7 +42,7 @@ export const useSearchDriveItems = () => {
|
||||
const query = searchInput.query;
|
||||
currentQuery = query;
|
||||
|
||||
const response = await DriveApiClient.search(searchInput.query, opt);
|
||||
const response = await DriveApiClient.search(searchInput.query, "", opt);
|
||||
let results = response.entities || [];
|
||||
if (isRecent)
|
||||
results = results.sort(
|
||||
|
||||
Reference in New Issue
Block a user