diff --git a/packages/server/src/controllers/index/FileController.ts b/packages/server/src/controllers/index/FileController.ts index ecc2c7ba00..fd284e21ee 100644 --- a/packages/server/src/controllers/index/FileController.ts +++ b/packages/server/src/controllers/index/FileController.ts @@ -35,11 +35,12 @@ export default class FileController extends BaseController { const parent: File = await fileModel.load(parentTemp.id); const paginatedFiles = await fileModel.childrens(parent.id, pagination); const pageCount = Math.ceil((await fileModel.childrenCount(parent.id)) / pagination.limit); + const parentBaseUrl = await fileModel.fileUrl(parent.id); const paginationLinks = createPaginationLinks(pagination.page, pageCount, setQueryParameters(parentBaseUrl, { ...baseUrlQuery, 'page': 'PAGE_NUMBER' })); - async function fileToViewItem(file: File): Promise { - const filePath = await fileModel.itemFullPath(file); + async function fileToViewItem(file: File, fileFullPaths: Record): Promise { + const filePath = fileFullPaths[file.id]; let url = `${baseUrl()}/files/${filePath}`; if (!file.is_directory) { @@ -60,17 +61,19 @@ export default class FileController extends BaseController { const files: any[] = []; + const fileFullPaths = await fileModel.itemFullPaths(paginatedFiles.items); + if (parent.id !== root.id) { const p = await fileModel.load(parent.parent_id); files.push({ - ...await fileToViewItem(p), + ...await fileToViewItem(p, await fileModel.itemFullPaths([p])), icon: 'fas fa-arrow-left', name: '..', }); } for (const file of paginatedFiles.items) { - files.push(await fileToViewItem(file)); + files.push(await fileToViewItem(file, fileFullPaths)); } const view: View = defaultView('files', owner); @@ -80,6 +83,8 @@ export default class FileController extends BaseController { view.content.parentId = parent.id; view.cssFiles = ['index/files']; view.partials.push('pagination'); + + return view; } diff --git a/packages/server/src/models/FileModel.ts b/packages/server/src/models/FileModel.ts index 9add61fddf..b640d98545 100644 --- a/packages/server/src/models/FileModel.ts +++ b/packages/server/src/models/FileModel.ts @@ -62,6 +62,36 @@ export default class FileModel extends BaseModel { return null; // Not a special dir } + public async itemFullPaths(items: File[]): Promise> { + const output: Record = {}; + + const itemCache: Record = {}; + + await this.withTransaction(async () => { + for (const item of items) { + const segments: string[] = []; + let current: File = item; + + while (current) { + if (current.is_root) break; + segments.splice(0, 0, current.name); + + if (current.parent_id) { + const id = current.parent_id; + current = itemCache[id] ? itemCache[id] : await this.load(id); + itemCache[id] = current; + } else { + current = null; + } + } + + output[item.id] = segments.length ? (`root:/${segments.join('/')}:`) : 'root'; + } + }); + + return output; + } + public async itemFullPath(item: File): Promise { const segments: string[] = []; while (item) { @@ -348,8 +378,8 @@ export default class FileModel extends BaseModel { public async childrenCount(id: string): Promise { const parent = await this.load(id); await this.checkCanReadPermissions(parent); - const r = await this.db(this.tableName).where('parent_id', id).count('id', { as: 'total' }); - return Number(r); + const r: any = await this.db(this.tableName).where('parent_id', id).count('id', { as: 'total' }).first(); + return r.total; } public async childrens(id: string, pagination: Pagination): Promise { diff --git a/packages/server/src/models/utils/pagination.ts b/packages/server/src/models/utils/pagination.ts index 6da7f3c56d..4b4652140f 100644 --- a/packages/server/src/models/utils/pagination.ts +++ b/packages/server/src/models/utils/pagination.ts @@ -26,7 +26,7 @@ export interface PaginatedResults { cursor?: string; } -export const pageMaxSize = 1000; +export const pageMaxSize = 100; const defaultOrderField_ = 'updated_time'; const defaultOrderDir_ = PaginationOrderDir.DESC;