feat(server, web): smart search filtering and pagination (#6525)

* initial pagination impl

* use limit + offset instead of take + skip

* wip web pagination

* working infinite scroll

* update api

* formatting

* fix rebase

* search refactor

* re-add runtime config for vector search

* fix rebase

* fixes

* useless omitBy

* unnecessary handling

* add sql decorator for `searchAssets`

* fixed search builder

* fixed sql

* remove mock method

* linting

* fixed pagination

* fixed unit tests

* formatting

* fix e2e tests

* re-flatten search builder

* refactor endpoints

* clean up dto

* refinements

* don't break everything just yet

* update openapi spec & sql

* update api

* linting

* update sql

* fixes

* optimize web code

* fix typing

* add page limit

* make limit based on asset count

* increase limit

* simpler import
This commit is contained in:
Mert
2024-02-12 20:50:47 -05:00
committed by GitHub
parent f1e4fdf175
commit e334443919
54 changed files with 3993 additions and 790 deletions
+1 -151
View File
@@ -1,20 +1,16 @@
import { AssetType } from '@app/infra/entities';
import { ApiProperty } from '@nestjs/swagger';
import { Type } from 'class-transformer';
import {
IsBoolean,
IsDateString,
IsEnum,
IsInt,
IsLatitude,
IsLongitude,
IsNotEmpty,
IsPositive,
IsString,
Min,
ValidateIf,
} from 'class-validator';
import { Optional, QueryBoolean, QueryDate, ValidateUUID } from '../../domain.util';
import { Optional, ValidateUUID } from '../../domain.util';
import { BulkIdsDto } from '../response-dto';
export class DeviceIdDto {
@@ -32,152 +28,6 @@ const hasGPS = (o: { latitude: undefined; longitude: undefined }) =>
o.latitude !== undefined || o.longitude !== undefined;
const ValidateGPS = () => ValidateIf(hasGPS);
export class AssetSearchDto {
@ValidateUUID({ optional: true })
id?: string;
@ValidateUUID({ optional: true })
libraryId?: string;
@IsString()
@Optional()
deviceAssetId?: string;
@IsString()
@Optional()
deviceId?: string;
@IsEnum(AssetType)
@Optional()
@ApiProperty({ enumName: 'AssetTypeEnum', enum: AssetType })
type?: AssetType;
@IsString()
@Optional()
checksum?: string;
@QueryBoolean({ optional: true })
isArchived?: boolean;
@QueryBoolean({ optional: true })
isEncoded?: boolean;
@QueryBoolean({ optional: true })
isExternal?: boolean;
@QueryBoolean({ optional: true })
isFavorite?: boolean;
@QueryBoolean({ optional: true })
isMotion?: boolean;
@QueryBoolean({ optional: true })
isOffline?: boolean;
@QueryBoolean({ optional: true })
isReadOnly?: boolean;
@QueryBoolean({ optional: true })
isVisible?: boolean;
@QueryBoolean({ optional: true })
withDeleted?: boolean;
@QueryBoolean({ optional: true })
withStacked?: boolean;
@QueryBoolean({ optional: true })
withExif?: boolean;
@QueryBoolean({ optional: true })
withPeople?: boolean;
@QueryDate({ optional: true })
createdBefore?: Date;
@QueryDate({ optional: true })
createdAfter?: Date;
@QueryDate({ optional: true })
updatedBefore?: Date;
@QueryDate({ optional: true })
updatedAfter?: Date;
@QueryDate({ optional: true })
trashedBefore?: Date;
@QueryDate({ optional: true })
trashedAfter?: Date;
@QueryDate({ optional: true })
takenBefore?: Date;
@QueryDate({ optional: true })
takenAfter?: Date;
@IsString()
@Optional()
originalFileName?: string;
@IsString()
@Optional()
originalPath?: string;
@IsString()
@Optional()
resizePath?: string;
@IsString()
@Optional()
webpPath?: string;
@IsString()
@Optional()
encodedVideoPath?: string;
@IsString()
@Optional()
city?: string;
@IsString()
@Optional()
state?: string;
@IsString()
@Optional()
country?: string;
@IsString()
@Optional()
make?: string;
@IsString()
@Optional()
model?: string;
@IsString()
@Optional()
lensModel?: string;
@IsEnum(AssetOrder)
@Optional()
@ApiProperty({ enumName: 'AssetOrder', enum: AssetOrder })
order?: AssetOrder;
@IsInt()
@Min(1)
@Type(() => Number)
@Optional()
page?: number;
@IsInt()
@Min(1)
@Type(() => Number)
@Optional()
size?: number;
}
export class AssetBulkUpdateDto extends BulkIdsDto {
@Optional()
@IsBoolean()