refactor: move asset stacks to their own entity (#6353)

* feat: auto-stack burst photos

* feat: move stacks to asset stack entity

* chore: pin node version with volta in server

* chore: update e2e cases

* chore: cleanup

* feat: migrate existing stacks

---------

Co-authored-by: Jason Rasmussen <jrasm91@gmail.com>
This commit is contained in:
Zack Pollard
2024-01-27 18:52:14 +00:00
committed by GitHub
parent c4b8c853bc
commit 25cad79657
29 changed files with 538 additions and 243 deletions
@@ -0,0 +1,47 @@
import { IAssetStackRepository } from '@app/domain';
import { Injectable } from '@nestjs/common';
import { InjectRepository } from '@nestjs/typeorm';
import { Repository } from 'typeorm';
import { AssetStackEntity } from '../entities';
@Injectable()
export class AssetStackRepository implements IAssetStackRepository {
constructor(@InjectRepository(AssetStackEntity) private repository: Repository<AssetStackEntity>) {}
create(entity: Partial<AssetStackEntity>) {
return this.save(entity);
}
async delete(id: string): Promise<void> {
await this.repository.delete(id);
}
update(entity: Partial<AssetStackEntity>) {
return this.save(entity);
}
async getById(id: string): Promise<AssetStackEntity | null> {
return this.repository.findOne({
where: {
id,
},
relations: {
primaryAsset: true,
assets: true,
},
});
}
private async save(entity: Partial<AssetStackEntity>) {
const { id } = await this.repository.save(entity);
return this.repository.findOneOrFail({
where: {
id,
},
relations: {
primaryAsset: true,
assets: true,
},
});
}
}
@@ -138,7 +138,7 @@ export class AssetRepository implements IAssetRepository {
const withExif = Object.keys(exifWhere).length > 0 || _withExif;
const where = _.omitBy(
const where: FindOptionsWhere<AssetEntity> = _.omitBy(
{
ownerId,
id,
@@ -182,10 +182,6 @@ export class AssetRepository implements IAssetRepository {
builder.leftJoinAndSelect('faces.person', 'person');
}
if (withStacked) {
builder.leftJoinAndSelect('asset.stack', 'stack');
}
if (withSmartInfo) {
builder.leftJoinAndSelect('asset.smartInfo', 'smartInfo');
}
@@ -194,13 +190,20 @@ export class AssetRepository implements IAssetRepository {
builder.withDeleted();
}
builder
.where(where)
builder.where(where);
if (withStacked) {
builder
.leftJoinAndSelect('asset.stack', 'stack')
.leftJoinAndSelect('stack.assets', 'stackedAssets')
.andWhere(new Brackets((qb) => qb.where('stack.primaryAssetId = asset.id').orWhere('asset.stackId IS NULL')));
}
return builder
.skip(size * (page - 1))
.take(size)
.orderBy('asset.fileCreatedAt', order ?? 'DESC');
return builder.getMany();
.orderBy('asset.fileCreatedAt', order ?? 'DESC')
.getMany();
}
create(asset: AssetCreate): Promise<AssetEntity> {
@@ -279,7 +282,9 @@ export class AssetRepository implements IAssetRepository {
faces: {
person: true,
},
stack: true,
stack: {
assets: true,
},
};
}
@@ -797,8 +802,14 @@ export class AssetRepository implements IAssetRepository {
builder = builder.andWhere('asset.type = :assetType', { assetType });
}
let stackJoined = false;
if (exifInfo !== false) {
builder = builder.leftJoinAndSelect('asset.exifInfo', 'exifInfo').leftJoinAndSelect('asset.stack', 'stack');
stackJoined = true;
builder = builder
.leftJoinAndSelect('asset.exifInfo', 'exifInfo')
.leftJoinAndSelect('asset.stack', 'stack')
.leftJoinAndSelect('stack.assets', 'stackedAssets');
}
if (albumId) {
@@ -829,7 +840,12 @@ export class AssetRepository implements IAssetRepository {
}
if (withStacked) {
builder = builder.andWhere('asset.stackParentId IS NULL');
if (!stackJoined) {
builder = builder.leftJoinAndSelect('asset.stack', 'stack').leftJoinAndSelect('stack.assets', 'stackedAssets');
}
builder = builder.andWhere(
new Brackets((qb) => qb.where('stack.primaryAssetId = asset.id').orWhere('asset.stackId IS NULL')),
);
}
return builder;
+1
View File
@@ -2,6 +2,7 @@ export * from './access.repository';
export * from './activity.repository';
export * from './album.repository';
export * from './api-key.repository';
export * from './asset-stack.repository';
export * from './asset.repository';
export * from './audit.repository';
export * from './communication.repository';