From fd0ff703b67466c5c492f2b77be46790619c295c Mon Sep 17 00:00:00 2001 From: Montassar Ghanmy Date: Wed, 8 Jan 2025 17:58:01 +0100 Subject: [PATCH] =?UTF-8?q?=F0=9F=90=9B=20Fixing=20pagination=20for=20"Sha?= =?UTF-8?q?red=20with=20me"/ES=20(#778)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../src/core/platform/services/search/api.ts | 2 ++ .../core/platform/services/search/index.ts | 27 +++++++++++++++++++ .../src/services/documents/services/index.ts | 3 +++ .../node/src/services/documents/types.ts | 6 +++++ .../documents/web/controllers/documents.ts | 1 + .../features/drive/api-client/api-client.ts | 26 +++++++++++------- .../drive/hooks/use-drive-actions.tsx | 15 ++++++++--- .../src/app/features/drive/state/store.ts | 4 +-- .../frontend/src/app/features/drive/types.ts | 9 +++++++ .../app/views/client/body/drive/browser.tsx | 1 - 10 files changed, 78 insertions(+), 16 deletions(-) diff --git a/tdrive/backend/node/src/core/platform/services/search/api.ts b/tdrive/backend/node/src/core/platform/services/search/api.ts index da7a33ef..bdbdc112 100644 --- a/tdrive/backend/node/src/core/platform/services/search/api.ts +++ b/tdrive/backend/node/src/core/platform/services/search/api.ts @@ -1,4 +1,5 @@ /* eslint-disable @typescript-eslint/no-explicit-any, @typescript-eslint/explicit-module-boundary-types */ +import { SearchDocumentsOptions } from "src/services/documents/types"; import { TdriveServiceProvider } from "../../framework"; import { ListResult } from "../../framework/api/crud-service"; import { @@ -62,6 +63,7 @@ export interface SearchServiceAPI extends TdriveServiceProvider { getRepository(table: string, entityType: EntityTarget): SearchRepository; upsert(entities: any[]): Promise; remove(entities: any[]): Promise; + handlePagination(options: SearchDocumentsOptions): void; type: SearchConfiguration["type"]; } diff --git a/tdrive/backend/node/src/core/platform/services/search/index.ts b/tdrive/backend/node/src/core/platform/services/search/index.ts index f3ccc201..bbdd01fc 100644 --- a/tdrive/backend/node/src/core/platform/services/search/index.ts +++ b/tdrive/backend/node/src/core/platform/services/search/index.ts @@ -15,6 +15,7 @@ import { DatabaseServiceAPI } from "../database/api"; import SearchRepository from "./repository"; import { Client as OpenClient } from "@opensearch-project/opensearch"; import { Client as ESClient } from "@elastic/elasticsearch"; +import { SearchDocumentsOptions } from "src/services/documents/types"; @ServiceName("search") @Consumes(["database"]) @@ -96,4 +97,30 @@ export default class Search extends TdriveService { api(): SearchServiceAPI { return this; } + + handlePagination(options: SearchDocumentsOptions): void { + if (this.type === "mongodb") { + // No custom pagination logic for MongoDB + return; + } + + if (this.type === "elasticsearch" || this.type === "opensearch") { + if (options.nextPage?.page_token) { + // Set the scroll ID as the page token + options.pagination = { + ...options.pagination, + page_token: options.nextPage.page_token, + }; + } else { + // Clear pagination if no nextPage token is provided + options.pagination = { + limitStr: options.pagination?.limitStr, + }; + } + return; + } + + // Handle unsupported platform types + throw new Error(`Pagination handling is not implemented for platform type: ${this.type}`); + } } diff --git a/tdrive/backend/node/src/services/documents/services/index.ts b/tdrive/backend/node/src/services/documents/services/index.ts index 294d4f8c..bf64ec71 100644 --- a/tdrive/backend/node/src/services/documents/services/index.ts +++ b/tdrive/backend/node/src/services/documents/services/index.ts @@ -133,6 +133,9 @@ export class DocumentsService { options.sort = this.getSortFieldMapping(options.sort); } + // Handle pagination differently for non-MongoDB platforms + globalResolver.platformServices.search.handlePagination(options); + const fileList: ListResult = await this.search(options, context); const result = fileList.getEntities(); diff --git a/tdrive/backend/node/src/services/documents/types.ts b/tdrive/backend/node/src/services/documents/types.ts index 78f45bc4..db3adb5b 100644 --- a/tdrive/backend/node/src/services/documents/types.ts +++ b/tdrive/backend/node/src/services/documents/types.ts @@ -57,12 +57,18 @@ export type SearchDocumentsOptions = { onlyDirectlyShared?: boolean; onlyUploadedNotByMe?: boolean; pagination?: Paginable; + nextPage?: { + page_token: string; + }; }; export type BrowseDocumentsOptions = { filter?: SearchDocumentsBody; sort?: SortType; paginate?: Paginable; + nextPage?: { + page_token: string; + }; }; export type SearchDocumentsBody = { diff --git a/tdrive/backend/node/src/services/documents/web/controllers/documents.ts b/tdrive/backend/node/src/services/documents/web/controllers/documents.ts index 145706aa..2811de95 100644 --- a/tdrive/backend/node/src/services/documents/web/controllers/documents.ts +++ b/tdrive/backend/node/src/services/documents/web/controllers/documents.ts @@ -213,6 +213,7 @@ export class DocumentsController { onlyUploadedNotByMe: true, sort: request.body.sort, pagination: request.body.paginate, + nextPage: request.body.nextPage, }; return { diff --git a/tdrive/frontend/src/app/features/drive/api-client/api-client.ts b/tdrive/frontend/src/app/features/drive/api-client/api-client.ts index e0f89757..247bf292 100644 --- a/tdrive/frontend/src/app/features/drive/api-client/api-client.ts +++ b/tdrive/frontend/src/app/features/drive/api-client/api-client.ts @@ -70,7 +70,13 @@ export class DriveApiClient { ); } - static async browse(companyId: string, id: string | 'trash' | '', filter: BrowseFilter, sort: BrowseSort, paginate: BrowsePaginate) { + static async browse( + companyId: string, + id: string | 'trash' | '', + filter: BrowseFilter, + sort: BrowseSort, + paginate: BrowsePaginate, + ) { return await Api.post( `/internal/services/documents/v1/companies/${companyId}/browse/${id}${appendTdriveToken()}`, { @@ -79,7 +85,10 @@ export class DriveApiClient { paginate: { page_token: paginate.page.toString(), limitStr: paginate.limit.toString(), - } + }, + nextPage: { + page_token: paginate.nextPage?.page_token || '', + }, }, ); } @@ -93,7 +102,7 @@ export class DriveApiClient { static async restore(companyId: string, id: string | 'trash' | '') { return await Api.post( `/internal/services/documents/v1/companies/${companyId}/item/${id}/restore${appendTdriveToken()}`, - {} + {}, ); } @@ -111,13 +120,10 @@ export class DriveApiClient { if (!data.version) data.version = {} as Partial; return new Promise((resolve, reject) => { - Api.post< - { item: Partial; version: Partial }, - DriveItem - >( + Api.post<{ item: Partial; version: Partial }, DriveItem>( `/internal/services/documents/v1/companies/${companyId}/item${appendTdriveToken()}`, data as { item: Partial; version: Partial }, - (res) => { + res => { if ((res as any)?.statusCode || (res as any)?.error) { reject(res); } @@ -151,7 +157,9 @@ export class DriveApiClient { static getDownloadUrl(companyId: string, id: string, versionId?: string) { if (versionId) - return Api.route(`/internal/services/documents/v1/companies/${companyId}/item/${id}/download?version_id=${versionId}`); + return Api.route( + `/internal/services/documents/v1/companies/${companyId}/item/${id}/download?version_id=${versionId}`, + ); return Api.route(`/internal/services/documents/v1/companies/${companyId}/item/${id}/download`); } diff --git a/tdrive/frontend/src/app/features/drive/hooks/use-drive-actions.tsx b/tdrive/frontend/src/app/features/drive/hooks/use-drive-actions.tsx index 5ad7e05b..f009250c 100644 --- a/tdrive/frontend/src/app/features/drive/hooks/use-drive-actions.tsx +++ b/tdrive/frontend/src/app/features/drive/hooks/use-drive-actions.tsx @@ -9,7 +9,7 @@ import { DriveItemPagination, DriveItemSort, } from '../state/store'; -import { BrowseFilter, DriveItem, DriveItemVersion } from '../types'; +import { BrowseFilter, DriveItem, DriveItemDetails, DriveItemVersion } from '../types'; import { SharedWithMeFilterState } from '../state/shared-with-me-filter'; import Languages from 'features/global/services/languages-service'; import { useUserQuota } from 'features/users/hooks/use-user-quota'; @@ -70,11 +70,12 @@ export const useDriveActions = (inPublicSharing?: boolean) => { let pagination = await snapshot.getPromise(DriveItemPagination); if (resetPagination) { - pagination = { page: 0, limit: pagination.limit }; + pagination = { page: 0, limit: pagination.limit, nextPage: pagination.nextPage }; set(DriveItemPagination, pagination); } + let details: DriveItemDetails | undefined; try { - const details = await DriveApiClient.browse( + details = await DriveApiClient.browse( companyId, parentId, filter, @@ -94,7 +95,13 @@ export const useDriveActions = (inPublicSharing?: boolean) => { } catch (e) { ToasterService.error(Languages.t('hooks.use-drive-actions.unable_load_file')); } finally { - set(DriveItemPagination, { page: pagination.limit, limit: pagination.limit }); + set(DriveItemPagination, { + page: pagination.limit, + limit: pagination.limit, + nextPage: { + page_token: details?.nextPage?.page_token || '', + }, + }); } } }, diff --git a/tdrive/frontend/src/app/features/drive/state/store.ts b/tdrive/frontend/src/app/features/drive/state/store.ts index 8c45b4fc..c429e677 100644 --- a/tdrive/frontend/src/app/features/drive/state/store.ts +++ b/tdrive/frontend/src/app/features/drive/state/store.ts @@ -11,9 +11,9 @@ export const DriveItemAtom = atomFamily | null, string default: () => null, }); -export const DriveItemSelectedList = atom<{[key: string]: boolean }>({ +export const DriveItemSelectedList = atom<{ [key: string]: boolean }>({ key: 'DriveItemSelectedList', - default: {} + default: {}, }); export const DriveItemSort = atom({ diff --git a/tdrive/frontend/src/app/features/drive/types.ts b/tdrive/frontend/src/app/features/drive/types.ts index 5e12d623..5bff99a8 100644 --- a/tdrive/frontend/src/app/features/drive/types.ts +++ b/tdrive/frontend/src/app/features/drive/types.ts @@ -5,6 +5,9 @@ export type BrowseQuery = { page_token: string; limitStr: string; }; + nextPage?: { + page_token: string; + }; } export type BrowseFilter = { @@ -21,6 +24,9 @@ export type BrowsePaginate = { page: number; limit: number; lastPage?: boolean; + nextPage?: { + page_token: string; + }; }; export type DriveItemDetails = { @@ -33,6 +39,9 @@ export type DriveItemDetails = { room: string; token?: string; }[]; + nextPage?: { + page_token: string; + } }; export type DriveItem = { diff --git a/tdrive/frontend/src/app/views/client/body/drive/browser.tsx b/tdrive/frontend/src/app/views/client/body/drive/browser.tsx index 2cb75b6a..403a4062 100644 --- a/tdrive/frontend/src/app/views/client/body/drive/browser.tsx +++ b/tdrive/frontend/src/app/views/client/body/drive/browser.tsx @@ -137,7 +137,6 @@ export default memo( useEffect(() => { setChecked({}); refresh(parentId); - if (!inPublicSharing) refresh('trash'); }, [parentId, refresh, filter]); const uploadItemModal = useCallback(() => {