✨ Sort files chronologically + infinite scroll (#535)
This commit is contained in:
+16
-2
@@ -264,12 +264,22 @@ export class MongoConnector extends AbstractConnector<MongoConnectionOptions> {
|
||||
options,
|
||||
);
|
||||
|
||||
const sort: any = {};
|
||||
let sort: any = {};
|
||||
for (const key of entityDefinition.options.primaryKey.slice(1)) {
|
||||
const defaultOrder =
|
||||
(columnsDefinition[key as string].options.order || "ASC") === "ASC" ? 1 : -1;
|
||||
sort[key as string] = (options?.pagination?.reversed ? -1 : 1) * defaultOrder;
|
||||
}
|
||||
if (options?.sort) {
|
||||
sort = options.sort
|
||||
? Object.fromEntries(
|
||||
Object.entries(options.sort).map(([field, direction]) => [
|
||||
field,
|
||||
direction === "asc" ? 1 : -1,
|
||||
]),
|
||||
)
|
||||
: {};
|
||||
}
|
||||
|
||||
logger.debug(`services.database.orm.mongodb.find - Query: ${JSON.stringify(query)}`);
|
||||
|
||||
@@ -277,7 +287,11 @@ export class MongoConnector extends AbstractConnector<MongoConnectionOptions> {
|
||||
.find(query)
|
||||
.sort(sort)
|
||||
.skip(Math.max(0, parseInt(options.pagination.page_token || "0")))
|
||||
.limit(Math.max(0, parseInt(options.pagination.limitStr || "100")));
|
||||
.limit(Math.max(0, parseInt(options.pagination.limitStr || "100")))
|
||||
.collation({
|
||||
locale: "en_US",
|
||||
numericOrdering: true,
|
||||
});
|
||||
|
||||
const entities: Table[] = [];
|
||||
while (await cursor.hasNext()) {
|
||||
|
||||
+8
-1
@@ -88,13 +88,20 @@ export class PostgresQueryBuilder {
|
||||
if (whereClause && whereClause.endsWith("AND ")) whereClause = whereClause.slice(0, -4);
|
||||
|
||||
// ==== ORDER BY =====
|
||||
const orderByClause = `${entityDefinition.options.primaryKey
|
||||
let orderByClause = `${entityDefinition.options.primaryKey
|
||||
.slice(1)
|
||||
.map(
|
||||
(key: string) =>
|
||||
`${key} ${(columnsDefinition[key].options.order || "ASC") === "ASC" ? "DESC" : "ASC"}`,
|
||||
)}`;
|
||||
|
||||
// ==== ORDER BY CUSTOM COLUMN =====
|
||||
if (options?.sort) {
|
||||
orderByClause = Object.keys(options.sort)
|
||||
.map(key => `${key} ${options.sort[key].toUpperCase()}`)
|
||||
.join(", ");
|
||||
}
|
||||
|
||||
// ==== PAGING =====
|
||||
let limit = 100;
|
||||
let offset = 0;
|
||||
|
||||
+7
@@ -22,6 +22,12 @@ export type inType = [string, Array<any>];
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
type likeType = [string, any];
|
||||
|
||||
type SortDirection = "asc" | "desc";
|
||||
|
||||
type SortOption = {
|
||||
[field: string]: SortDirection;
|
||||
};
|
||||
|
||||
export type FindOptions = {
|
||||
pagination?: Pagination;
|
||||
$lt?: comparisonType[];
|
||||
@@ -34,6 +40,7 @@ export type FindOptions = {
|
||||
$in?: inType[];
|
||||
$nin?: inType[];
|
||||
$like?: likeType[];
|
||||
sort?: SortOption;
|
||||
};
|
||||
|
||||
/**
|
||||
|
||||
@@ -35,14 +35,14 @@ export class ConsoleServiceImpl implements TdriveServiceProvider {
|
||||
|
||||
this.consoleOptions = {
|
||||
type: type,
|
||||
authority: s.authority,
|
||||
client_id: s.client_id,
|
||||
client_secret: s.client_secret,
|
||||
audience: s.audience,
|
||||
issuer: s.issuer,
|
||||
jwks_uri: s.jwks_uri,
|
||||
redirect_uris: s.redirect_uris,
|
||||
disable_account_creation: s.disable_account_creation,
|
||||
authority: s?.authority,
|
||||
client_id: s?.client_id,
|
||||
client_secret: s?.client_secret,
|
||||
audience: s?.audience,
|
||||
issuer: s?.issuer,
|
||||
jwks_uri: s?.jwks_uri,
|
||||
redirect_uris: s?.redirect_uris,
|
||||
disable_account_creation: s?.disable_account_creation,
|
||||
};
|
||||
|
||||
this.consoleOptions.type = type;
|
||||
|
||||
@@ -29,8 +29,10 @@ import {
|
||||
DriveFileAccessLevel,
|
||||
DriveItemDetails,
|
||||
DriveTdriveTab,
|
||||
PaginateDocumentBody,
|
||||
RootType,
|
||||
SearchDocumentsOptions,
|
||||
SortDocumentsBody,
|
||||
TrashType,
|
||||
} from "../types";
|
||||
import {
|
||||
@@ -105,6 +107,8 @@ export class DocumentsService {
|
||||
browse = async (
|
||||
id: string,
|
||||
options: SearchDocumentsOptions,
|
||||
sort: SortDocumentsBody,
|
||||
paginate: PaginateDocumentBody,
|
||||
context: DriveExecutionContext & { public_token?: string },
|
||||
): Promise<BrowseDetails> => {
|
||||
if (isSharedWithMeFolder(id)) {
|
||||
@@ -112,7 +116,7 @@ export class DocumentsService {
|
||||
} else {
|
||||
return {
|
||||
nextPage: null,
|
||||
...(await this.get(id, context)),
|
||||
...(await this.get(id, context, false, sort, paginate)),
|
||||
};
|
||||
}
|
||||
};
|
||||
@@ -154,6 +158,9 @@ export class DocumentsService {
|
||||
get = async (
|
||||
id: string,
|
||||
context: DriveExecutionContext & { public_token?: string },
|
||||
all?: boolean,
|
||||
sort?: SortDocumentsBody,
|
||||
paginate?: PaginateDocumentBody,
|
||||
): Promise<DriveItemDetails> => {
|
||||
if (!context) {
|
||||
this.logger.error("invalid context");
|
||||
@@ -206,7 +213,26 @@ export class DocumentsService {
|
||||
)
|
||||
).getEntities();
|
||||
|
||||
//Get children if it is a directory
|
||||
const sortFieldMapping = {
|
||||
name: "name",
|
||||
date: "last_modified",
|
||||
size: "size",
|
||||
};
|
||||
let sortField = {};
|
||||
sortField[sortFieldMapping[sort?.by] || "last_modified"] = sort?.order || "desc";
|
||||
|
||||
const dbType = await globalResolver.database.getConnector().getType();
|
||||
|
||||
// Initialize pagination
|
||||
let pagination;
|
||||
|
||||
if (paginate) {
|
||||
const { page, limit } = paginate;
|
||||
const pageNumber = dbType === "mongodb" ? page : page / limit + 1;
|
||||
|
||||
pagination = new Pagination(`${pageNumber}`, `${limit}`, false);
|
||||
}
|
||||
|
||||
let children = isDirectory
|
||||
? (
|
||||
await this.repository.find(
|
||||
@@ -229,7 +255,15 @@ export class DocumentsService {
|
||||
is_in_trash: false,
|
||||
}),
|
||||
},
|
||||
{},
|
||||
all
|
||||
? {}
|
||||
: {
|
||||
sort: {
|
||||
is_directory: "desc",
|
||||
...sortField,
|
||||
},
|
||||
pagination,
|
||||
},
|
||||
context,
|
||||
)
|
||||
).getEntities()
|
||||
|
||||
@@ -59,6 +59,12 @@ export type SearchDocumentsOptions = {
|
||||
pagination?: Paginable;
|
||||
};
|
||||
|
||||
export type BrowseDocumentsOptions = {
|
||||
filter?: SearchDocumentsBody;
|
||||
sort?: SortDocumentsBody;
|
||||
paginate?: PaginateDocumentBody;
|
||||
};
|
||||
|
||||
export type SearchDocumentsBody = {
|
||||
search?: string;
|
||||
company_id?: string;
|
||||
@@ -73,6 +79,16 @@ export type SearchDocumentsBody = {
|
||||
fields?: string[];
|
||||
};
|
||||
|
||||
export type SortDocumentsBody = {
|
||||
by: string;
|
||||
order: string;
|
||||
};
|
||||
|
||||
export type PaginateDocumentBody = {
|
||||
page: number;
|
||||
limit: number;
|
||||
};
|
||||
|
||||
export type DocumentsMessageQueueRequest = {
|
||||
item: DriveFile;
|
||||
version: FileVersion;
|
||||
|
||||
@@ -9,16 +9,19 @@ import { CompanyUserRole, PaginationQueryParameters } from "../../../../utils/ty
|
||||
import { DriveFile } from "../../entities/drive-file";
|
||||
import { FileVersion } from "../../entities/file-version";
|
||||
import {
|
||||
BrowseDocumentsOptions,
|
||||
CompanyExecutionContext,
|
||||
DriveExecutionContext,
|
||||
DriveFileAccessLevel,
|
||||
DriveItemDetails,
|
||||
DriveTdriveTab,
|
||||
ItemRequestParams,
|
||||
PaginateDocumentBody,
|
||||
ItemRequestByEditingSessionKeyParams,
|
||||
RequestParams,
|
||||
SearchDocumentsBody,
|
||||
SearchDocumentsOptions,
|
||||
SortDocumentsBody,
|
||||
} from "../../types";
|
||||
import { DriveFileDTO } from "../dto/drive-file-dto";
|
||||
import { DriveFileDTOBuilder } from "../../services/drive-file-dto-builder";
|
||||
@@ -196,7 +199,7 @@ export class DocumentsController {
|
||||
browse = async (
|
||||
request: FastifyRequest<{
|
||||
Params: ItemRequestParams;
|
||||
Body: SearchDocumentsBody;
|
||||
Body: BrowseDocumentsOptions;
|
||||
Querystring: PaginationQueryParameters & { public_token?: string };
|
||||
}>,
|
||||
): Promise<DriveItemDetails> => {
|
||||
@@ -204,15 +207,24 @@ export class DocumentsController {
|
||||
const { id } = request.params;
|
||||
|
||||
const options: SearchDocumentsOptions = {
|
||||
...request.body,
|
||||
company_id: request.body.company_id || context.company.id,
|
||||
...request.body.filter,
|
||||
company_id: request.body.filter?.company_id || context.company.id,
|
||||
view: DriveFileDTOBuilder.VIEW_SHARED_WITH_ME,
|
||||
onlyDirectlyShared: true,
|
||||
onlyUploadedNotByMe: true,
|
||||
};
|
||||
|
||||
const sortOptions: SortDocumentsBody = request.body.sort;
|
||||
const paginateOptions: PaginateDocumentBody = request.body.paginate;
|
||||
|
||||
return {
|
||||
...(await globalResolver.services.documents.documents.browse(id, options, context)),
|
||||
...(await globalResolver.services.documents.documents.browse(
|
||||
id,
|
||||
options,
|
||||
sortOptions,
|
||||
paginateOptions,
|
||||
context,
|
||||
)),
|
||||
};
|
||||
};
|
||||
|
||||
@@ -446,11 +458,12 @@ export class DocumentsController {
|
||||
downloadZip = async (
|
||||
request: FastifyRequest<{
|
||||
Params: RequestParams;
|
||||
Querystring: { token?: string; items: string; public_token?: string };
|
||||
Querystring: { token?: string; items: string; public_token?: string; is_directory?: boolean };
|
||||
}>,
|
||||
reply: FastifyReply,
|
||||
): Promise<void> => {
|
||||
const context = getDriveExecutionContext(request);
|
||||
const isDirectory = request.query.is_directory || false;
|
||||
let ids = (request.query.items || "").split(",");
|
||||
const token = request.query.token;
|
||||
|
||||
@@ -466,6 +479,11 @@ export class DocumentsController {
|
||||
ids = items.children.map(item => item.id);
|
||||
}
|
||||
|
||||
if (isDirectory) {
|
||||
const items = await globalResolver.services.documents.documents.get(ids[0], context, true);
|
||||
ids = items.children.map(item => item.id);
|
||||
}
|
||||
|
||||
try {
|
||||
const archive = await globalResolver.services.documents.documents.createZip(ids, context);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user