1
0
Fork 0
mirror of https://github.com/immich-app/immich.git synced 2024-12-29 15:11:58 +00:00

fix(web+server): showing assets without thumbnail (#2652)

* fix(web+server): showing assets without thumbnail

* missed change
This commit is contained in:
Michel Heusschen 2023-06-04 04:41:27 +02:00 committed by GitHub
parent b8de668f5f
commit cab5477656
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
16 changed files with 98 additions and 38 deletions

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

View file

@ -6,7 +6,7 @@ import { InjectRepository } from '@nestjs/typeorm';
import { Repository } from 'typeorm/repository/Repository';
import { CuratedObjectsResponseDto } from './response-dto/curated-objects-response.dto';
import { AssetCountByTimeBucket } from './response-dto/asset-count-by-time-group-response.dto';
import { TimeGroupEnum } from './dto/get-asset-count-by-time-bucket.dto';
import { GetAssetCountByTimeBucketDto, TimeGroupEnum } from './dto/get-asset-count-by-time-bucket.dto';
import { GetAssetByTimeBucketDto } from './dto/get-asset-by-time-bucket.dto';
import { AssetCountByUserIdResponseDto } from './response-dto/asset-count-by-user-id-response.dto';
import { CheckExistingAssetsDto } from './dto/check-existing-assets.dto';
@ -37,7 +37,7 @@ export interface IAssetRepository {
getLocationsByUserId(userId: string): Promise<CuratedLocationsResponseDto[]>;
getDetectedObjectsByUserId(userId: string): Promise<CuratedObjectsResponseDto[]>;
getSearchPropertiesByUserId(userId: string): Promise<SearchPropertiesDto[]>;
getAssetCountByTimeBucket(userId: string, timeBucket: TimeGroupEnum): Promise<AssetCountByTimeBucket[]>;
getAssetCountByTimeBucket(userId: string, dto: GetAssetCountByTimeBucketDto): Promise<AssetCountByTimeBucket[]>;
getAssetCountByUserId(userId: string): Promise<AssetCountByUserIdResponseDto>;
getArchivedAssetCountByUserId(userId: string): Promise<AssetCountByUserIdResponseDto>;
getAssetByTimeBucket(userId: string, getAssetByTimeBucketDto: GetAssetByTimeBucketDto): Promise<AssetEntity[]>;
@ -119,36 +119,35 @@ export class AssetRepository implements IAssetRepository {
return builder.getMany();
}
async getAssetCountByTimeBucket(userId: string, timeBucket: TimeGroupEnum) {
let result: AssetCountByTimeBucket[] = [];
async getAssetCountByTimeBucket(
userId: string,
dto: GetAssetCountByTimeBucketDto,
): Promise<AssetCountByTimeBucket[]> {
const builder = this.assetRepository
.createQueryBuilder('asset')
.select(`COUNT(asset.id)::int`, 'count')
.where('"ownerId" = :userId', { userId: userId })
.andWhere('asset.isVisible = true')
.andWhere('asset.isArchived = false');
if (timeBucket === TimeGroupEnum.Month) {
result = await this.assetRepository
.createQueryBuilder('asset')
.select(`COUNT(asset.id)::int`, 'count')
// Using a parameter for this doesn't work https://github.com/typeorm/typeorm/issues/7308
if (dto.timeGroup === TimeGroupEnum.Month) {
builder
.addSelect(`date_trunc('month', "fileCreatedAt")`, 'timeBucket')
.where('"ownerId" = :userId', { userId: userId })
.andWhere('asset.resizePath is not NULL')
.andWhere('asset.isVisible = true')
.andWhere('asset.isArchived = false')
.groupBy(`date_trunc('month', "fileCreatedAt")`)
.orderBy(`date_trunc('month', "fileCreatedAt")`, 'DESC')
.getRawMany();
} else if (timeBucket === TimeGroupEnum.Day) {
result = await this.assetRepository
.createQueryBuilder('asset')
.select(`COUNT(asset.id)::int`, 'count')
.orderBy(`date_trunc('month', "fileCreatedAt")`, 'DESC');
} else if (dto.timeGroup === TimeGroupEnum.Day) {
builder
.addSelect(`date_trunc('day', "fileCreatedAt")`, 'timeBucket')
.where('"ownerId" = :userId', { userId: userId })
.andWhere('asset.resizePath is not NULL')
.andWhere('asset.isVisible = true')
.andWhere('asset.isArchived = false')
.groupBy(`date_trunc('day', "fileCreatedAt")`)
.orderBy(`date_trunc('day', "fileCreatedAt")`, 'DESC')
.getRawMany();
.orderBy(`date_trunc('day', "fileCreatedAt")`, 'DESC');
}
return result;
if (!dto.withoutThumbs) {
builder.andWhere('asset.resizePath is not NULL');
}
return builder.getRawMany();
}
async getSearchPropertiesByUserId(userId: string): Promise<SearchPropertiesDto[]> {
@ -231,7 +230,7 @@ export class AssetRepository implements IAssetRepository {
return this.assetRepository.find({
where: {
ownerId,
resizePath: Not(IsNull()),
resizePath: dto.withoutThumbs ? undefined : Not(IsNull()),
isVisible: true,
isFavorite: dto.isFavorite,
isArchived: dto.isArchived,

View file

@ -533,7 +533,7 @@ export class AssetService {
const result = await this._assetRepository.getAssetCountByTimeBucket(
getAssetCountByTimeBucketDto.userId || authUser.id,
getAssetCountByTimeBucketDto.timeGroup,
getAssetCountByTimeBucketDto,
);
return mapAssetCountByTimeBucket(result);

View file

@ -16,6 +16,14 @@ export class AssetSearchDto {
@Transform(toBoolean)
isArchived?: boolean;
/**
* Include assets without thumbnails
*/
@IsOptional()
@IsBoolean()
@Transform(toBoolean)
withoutThumbs?: boolean;
@IsOptional()
@IsNumber()
skip?: number;

View file

@ -1,5 +1,7 @@
import { ApiProperty } from '@nestjs/swagger';
import { IsNotEmpty, IsOptional, IsUUID } from 'class-validator';
import { Transform } from 'class-transformer';
import { IsBoolean, IsNotEmpty, IsOptional, IsUUID } from 'class-validator';
import { toBoolean } from '../../../utils/transform.util';
export enum TimeGroupEnum {
Day = 'day',
@ -19,4 +21,12 @@ export class GetAssetCountByTimeBucketDto {
@IsUUID('4')
@ApiProperty({ format: 'uuid' })
userId?: string;
/**
* Include assets without thumbnails
*/
@IsOptional()
@IsBoolean()
@Transform(toBoolean)
withoutThumbs?: boolean;
}

View file

@ -3380,6 +3380,15 @@
"type": "boolean"
}
},
{
"name": "withoutThumbs",
"required": false,
"in": "query",
"description": "Include assets without thumbnails",
"schema": {
"type": "boolean"
}
},
{
"name": "skip",
"required": false,
@ -6221,6 +6230,10 @@
"userId": {
"type": "string",
"format": "uuid"
},
"withoutThumbs": {
"type": "boolean",
"description": "Include assets without thumbnails"
}
},
"required": [

View file

@ -1396,6 +1396,12 @@ export interface GetAssetCountByTimeBucketDto {
* @memberof GetAssetCountByTimeBucketDto
*/
'userId'?: string;
/**
* Include assets without thumbnails
* @type {boolean}
* @memberof GetAssetCountByTimeBucketDto
*/
'withoutThumbs'?: boolean;
}
@ -4999,12 +5005,13 @@ export const AssetApiAxiosParamCreator = function (configuration?: Configuration
* @param {string} [userId]
* @param {boolean} [isFavorite]
* @param {boolean} [isArchived]
* @param {boolean} [withoutThumbs] Include assets without thumbnails
* @param {number} [skip]
* @param {string} [ifNoneMatch] ETag of data already cached on the client
* @param {*} [options] Override http request option.
* @throws {RequiredError}
*/
getAllAssets: async (userId?: string, isFavorite?: boolean, isArchived?: boolean, skip?: number, ifNoneMatch?: string, options: AxiosRequestConfig = {}): Promise<RequestArgs> => {
getAllAssets: async (userId?: string, isFavorite?: boolean, isArchived?: boolean, withoutThumbs?: boolean, skip?: number, ifNoneMatch?: string, options: AxiosRequestConfig = {}): Promise<RequestArgs> => {
const localVarPath = `/asset`;
// use dummy base URL string because the URL constructor only accepts absolute URLs.
const localVarUrlObj = new URL(localVarPath, DUMMY_BASE_URL);
@ -5038,6 +5045,10 @@ export const AssetApiAxiosParamCreator = function (configuration?: Configuration
localVarQueryParameter['isArchived'] = isArchived;
}
if (withoutThumbs !== undefined) {
localVarQueryParameter['withoutThumbs'] = withoutThumbs;
}
if (skip !== undefined) {
localVarQueryParameter['skip'] = skip;
}
@ -5970,13 +5981,14 @@ export const AssetApiFp = function(configuration?: Configuration) {
* @param {string} [userId]
* @param {boolean} [isFavorite]
* @param {boolean} [isArchived]
* @param {boolean} [withoutThumbs] Include assets without thumbnails
* @param {number} [skip]
* @param {string} [ifNoneMatch] ETag of data already cached on the client
* @param {*} [options] Override http request option.
* @throws {RequiredError}
*/
async getAllAssets(userId?: string, isFavorite?: boolean, isArchived?: boolean, skip?: number, ifNoneMatch?: string, options?: AxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise<Array<AssetResponseDto>>> {
const localVarAxiosArgs = await localVarAxiosParamCreator.getAllAssets(userId, isFavorite, isArchived, skip, ifNoneMatch, options);
async getAllAssets(userId?: string, isFavorite?: boolean, isArchived?: boolean, withoutThumbs?: boolean, skip?: number, ifNoneMatch?: string, options?: AxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise<Array<AssetResponseDto>>> {
const localVarAxiosArgs = await localVarAxiosParamCreator.getAllAssets(userId, isFavorite, isArchived, withoutThumbs, skip, ifNoneMatch, options);
return createRequestFunction(localVarAxiosArgs, globalAxios, BASE_PATH, configuration);
},
/**
@ -6259,13 +6271,14 @@ export const AssetApiFactory = function (configuration?: Configuration, basePath
* @param {string} [userId]
* @param {boolean} [isFavorite]
* @param {boolean} [isArchived]
* @param {boolean} [withoutThumbs] Include assets without thumbnails
* @param {number} [skip]
* @param {string} [ifNoneMatch] ETag of data already cached on the client
* @param {*} [options] Override http request option.
* @throws {RequiredError}
*/
getAllAssets(userId?: string, isFavorite?: boolean, isArchived?: boolean, skip?: number, ifNoneMatch?: string, options?: any): AxiosPromise<Array<AssetResponseDto>> {
return localVarFp.getAllAssets(userId, isFavorite, isArchived, skip, ifNoneMatch, options).then((request) => request(axios, basePath));
getAllAssets(userId?: string, isFavorite?: boolean, isArchived?: boolean, withoutThumbs?: boolean, skip?: number, ifNoneMatch?: string, options?: any): AxiosPromise<Array<AssetResponseDto>> {
return localVarFp.getAllAssets(userId, isFavorite, isArchived, withoutThumbs, skip, ifNoneMatch, options).then((request) => request(axios, basePath));
},
/**
*
@ -6627,6 +6640,13 @@ export interface AssetApiGetAllAssetsRequest {
*/
readonly isArchived?: boolean
/**
* Include assets without thumbnails
* @type {boolean}
* @memberof AssetApiGetAllAssets
*/
readonly withoutThumbs?: boolean
/**
*
* @type {number}
@ -7071,7 +7091,7 @@ export class AssetApi extends BaseAPI {
* @memberof AssetApi
*/
public getAllAssets(requestParameters: AssetApiGetAllAssetsRequest = {}, options?: AxiosRequestConfig) {
return AssetApiFp(this.configuration).getAllAssets(requestParameters.userId, requestParameters.isFavorite, requestParameters.isArchived, requestParameters.skip, requestParameters.ifNoneMatch, options).then((request) => request(this.axios, this.basePath));
return AssetApiFp(this.configuration).getAllAssets(requestParameters.userId, requestParameters.isFavorite, requestParameters.isArchived, requestParameters.withoutThumbs, requestParameters.skip, requestParameters.ifNoneMatch, options).then((request) => request(this.axios, this.basePath));
}
/**

View file

@ -29,7 +29,8 @@
const { data: assetCountByTimebucket } = await api.assetApi.getAssetCountByTimeBucket({
getAssetCountByTimeBucketDto: {
timeGroup: TimeGroupEnum.Month,
userId: user?.id
userId: user?.id,
withoutThumbs: true
}
});
bucketInfo = assetCountByTimebucket;

View file

@ -30,7 +30,10 @@
const getFavoriteCount = async () => {
try {
const { data: assets } = await api.assetApi.getAllAssets({ isFavorite: true });
const { data: assets } = await api.assetApi.getAllAssets({
isFavorite: true,
withoutThumbs: true
});
return {
favorites: assets.length

View file

@ -26,7 +26,10 @@
onMount(async () => {
try {
const { data: assets } = await api.assetApi.getAllAssets({ isArchived: true });
const { data: assets } = await api.assetApi.getAllAssets({
isArchived: true,
withoutThumbs: true
});
$archivedAsset = assets;
} catch {
handleError(Error, 'Unable to load archived assets');

View file

@ -28,7 +28,10 @@
onMount(async () => {
try {
const { data: assets } = await api.assetApi.getAllAssets({ isFavorite: true });
const { data: assets } = await api.assetApi.getAllAssets({
isFavorite: true,
withoutThumbs: true
});
favorites = assets;
} catch {
handleError(Error, 'Unable to load favorites');