diff --git a/mobile/openapi/README.md b/mobile/openapi/README.md index 341b88421..891c64cc9 100644 --- a/mobile/openapi/README.md +++ b/mobile/openapi/README.md @@ -3,7 +3,7 @@ Immich API This Dart package is automatically generated by the [OpenAPI Generator](https://openapi-generator.tech) project: -- API version: 1.43.1 +- API version: 1.45.0 - Build package: org.openapitools.codegen.languages.DartClientCodegen ## Requirements diff --git a/mobile/openapi/doc/AlbumResponseDto.md b/mobile/openapi/doc/AlbumResponseDto.md index 6a987df43..9bc1957c4 100644 --- a/mobile/openapi/doc/AlbumResponseDto.md +++ b/mobile/openapi/doc/AlbumResponseDto.md @@ -13,6 +13,7 @@ Name | Type | Description | Notes **ownerId** | **String** | | **albumName** | **String** | | **createdAt** | **String** | | +**updatedAt** | **String** | | **albumThumbnailAssetId** | **String** | | **shared** | **bool** | | **sharedUsers** | [**List**](UserResponseDto.md) | | [default to const []] diff --git a/mobile/openapi/doc/AssetResponseDto.md b/mobile/openapi/doc/AssetResponseDto.md index aa7d5494c..bcb0120cd 100644 --- a/mobile/openapi/doc/AssetResponseDto.md +++ b/mobile/openapi/doc/AssetResponseDto.md @@ -17,6 +17,7 @@ Name | Type | Description | Notes **resizePath** | **String** | | **createdAt** | **String** | | **modifiedAt** | **String** | | +**updatedAt** | **String** | | **isFavorite** | **bool** | | **mimeType** | **String** | | **duration** | **String** | | diff --git a/mobile/openapi/lib/model/album_response_dto.dart b/mobile/openapi/lib/model/album_response_dto.dart index 7858e857d..b2264f0d3 100644 --- a/mobile/openapi/lib/model/album_response_dto.dart +++ b/mobile/openapi/lib/model/album_response_dto.dart @@ -18,6 +18,7 @@ class AlbumResponseDto { required this.ownerId, required this.albumName, required this.createdAt, + required this.updatedAt, required this.albumThumbnailAssetId, required this.shared, this.sharedUsers = const [], @@ -34,6 +35,8 @@ class AlbumResponseDto { String createdAt; + String updatedAt; + String? albumThumbnailAssetId; bool shared; @@ -43,51 +46,51 @@ class AlbumResponseDto { List assets; @override - bool operator ==(Object other) => - identical(this, other) || - other is AlbumResponseDto && - other.assetCount == assetCount && - other.id == id && - other.ownerId == ownerId && - other.albumName == albumName && - other.createdAt == createdAt && - other.albumThumbnailAssetId == albumThumbnailAssetId && - other.shared == shared && - other.sharedUsers == sharedUsers && - other.assets == assets; + bool operator ==(Object other) => identical(this, other) || other is AlbumResponseDto && + other.assetCount == assetCount && + other.id == id && + other.ownerId == ownerId && + other.albumName == albumName && + other.createdAt == createdAt && + other.updatedAt == updatedAt && + other.albumThumbnailAssetId == albumThumbnailAssetId && + other.shared == shared && + other.sharedUsers == sharedUsers && + other.assets == assets; @override int get hashCode => - // ignore: unnecessary_parenthesis - (assetCount.hashCode) + - (id.hashCode) + - (ownerId.hashCode) + - (albumName.hashCode) + - (createdAt.hashCode) + - (albumThumbnailAssetId == null ? 0 : albumThumbnailAssetId!.hashCode) + - (shared.hashCode) + - (sharedUsers.hashCode) + - (assets.hashCode); + // ignore: unnecessary_parenthesis + (assetCount.hashCode) + + (id.hashCode) + + (ownerId.hashCode) + + (albumName.hashCode) + + (createdAt.hashCode) + + (updatedAt.hashCode) + + (albumThumbnailAssetId == null ? 0 : albumThumbnailAssetId!.hashCode) + + (shared.hashCode) + + (sharedUsers.hashCode) + + (assets.hashCode); @override - String toString() => - 'AlbumResponseDto[assetCount=$assetCount, id=$id, ownerId=$ownerId, albumName=$albumName, createdAt=$createdAt, albumThumbnailAssetId=$albumThumbnailAssetId, shared=$shared, sharedUsers=$sharedUsers, assets=$assets]'; + String toString() => 'AlbumResponseDto[assetCount=$assetCount, id=$id, ownerId=$ownerId, albumName=$albumName, createdAt=$createdAt, updatedAt=$updatedAt, albumThumbnailAssetId=$albumThumbnailAssetId, shared=$shared, sharedUsers=$sharedUsers, assets=$assets]'; Map toJson() { final json = {}; - json[r'assetCount'] = this.assetCount; - json[r'id'] = this.id; - json[r'ownerId'] = this.ownerId; - json[r'albumName'] = this.albumName; - json[r'createdAt'] = this.createdAt; + json[r'assetCount'] = this.assetCount; + json[r'id'] = this.id; + json[r'ownerId'] = this.ownerId; + json[r'albumName'] = this.albumName; + json[r'createdAt'] = this.createdAt; + json[r'updatedAt'] = this.updatedAt; if (this.albumThumbnailAssetId != null) { json[r'albumThumbnailAssetId'] = this.albumThumbnailAssetId; } else { // json[r'albumThumbnailAssetId'] = null; } - json[r'shared'] = this.shared; - json[r'sharedUsers'] = this.sharedUsers; - json[r'assets'] = this.assets; + json[r'shared'] = this.shared; + json[r'sharedUsers'] = this.sharedUsers; + json[r'assets'] = this.assets; return json; } @@ -101,13 +104,13 @@ class AlbumResponseDto { // Ensure that the map contains the required keys. // Note 1: the values aren't checked for validity beyond being non-null. // Note 2: this code is stripped in release mode! - // assert(() { - // requiredKeys.forEach((key) { - // assert(json.containsKey(key), 'Required key "AlbumResponseDto[$key]" is missing from JSON.'); - // assert(json[key] != null, 'Required key "AlbumResponseDto[$key]" has a null value in JSON.'); - // }); - // return true; - // }()); + assert(() { + requiredKeys.forEach((key) { + assert(json.containsKey(key), 'Required key "AlbumResponseDto[$key]" is missing from JSON.'); + assert(json[key] != null, 'Required key "AlbumResponseDto[$key]" has a null value in JSON.'); + }); + return true; + }()); return AlbumResponseDto( assetCount: mapValueOfType(json, r'assetCount')!, @@ -115,8 +118,8 @@ class AlbumResponseDto { ownerId: mapValueOfType(json, r'ownerId')!, albumName: mapValueOfType(json, r'albumName')!, createdAt: mapValueOfType(json, r'createdAt')!, - albumThumbnailAssetId: - mapValueOfType(json, r'albumThumbnailAssetId'), + updatedAt: mapValueOfType(json, r'updatedAt')!, + albumThumbnailAssetId: mapValueOfType(json, r'albumThumbnailAssetId'), shared: mapValueOfType(json, r'shared')!, sharedUsers: UserResponseDto.listFromJson(json[r'sharedUsers'])!, assets: AssetResponseDto.listFromJson(json[r'assets'])!, @@ -125,10 +128,7 @@ class AlbumResponseDto { return null; } - static List? listFromJson( - dynamic json, { - bool growable = false, - }) { + static List? listFromJson(dynamic json, {bool growable = false,}) { final result = []; if (json is List && json.isNotEmpty) { for (final row in json) { @@ -156,18 +156,12 @@ class AlbumResponseDto { } // maps a json object with a list of AlbumResponseDto-objects as value to a dart map - static Map> mapListFromJson( - dynamic json, { - bool growable = false, - }) { + static Map> mapListFromJson(dynamic json, {bool growable = false,}) { final map = >{}; if (json is Map && json.isNotEmpty) { json = json.cast(); // ignore: parameter_assignments for (final entry in json.entries) { - final value = AlbumResponseDto.listFromJson( - entry.value, - growable: growable, - ); + final value = AlbumResponseDto.listFromJson(entry.value, growable: growable,); if (value != null) { map[entry.key] = value; } @@ -183,9 +177,11 @@ class AlbumResponseDto { 'ownerId', 'albumName', 'createdAt', + 'updatedAt', 'albumThumbnailAssetId', 'shared', 'sharedUsers', 'assets', }; } + diff --git a/mobile/openapi/lib/model/asset_response_dto.dart b/mobile/openapi/lib/model/asset_response_dto.dart index 2f516e2bd..3842f5ab9 100644 --- a/mobile/openapi/lib/model/asset_response_dto.dart +++ b/mobile/openapi/lib/model/asset_response_dto.dart @@ -22,6 +22,7 @@ class AssetResponseDto { required this.resizePath, required this.createdAt, required this.modifiedAt, + required this.updatedAt, required this.isFavorite, required this.mimeType, required this.duration, @@ -51,6 +52,8 @@ class AssetResponseDto { String modifiedAt; + String updatedAt; + bool isFavorite; String? mimeType; @@ -92,6 +95,7 @@ class AssetResponseDto { other.resizePath == resizePath && other.createdAt == createdAt && other.modifiedAt == modifiedAt && + other.updatedAt == updatedAt && other.isFavorite == isFavorite && other.mimeType == mimeType && other.duration == duration && @@ -114,6 +118,7 @@ class AssetResponseDto { (resizePath == null ? 0 : resizePath!.hashCode) + (createdAt.hashCode) + (modifiedAt.hashCode) + + (updatedAt.hashCode) + (isFavorite.hashCode) + (mimeType == null ? 0 : mimeType!.hashCode) + (duration.hashCode) + @@ -125,7 +130,7 @@ class AssetResponseDto { (tags.hashCode); @override - String toString() => 'AssetResponseDto[type=$type, id=$id, deviceAssetId=$deviceAssetId, ownerId=$ownerId, deviceId=$deviceId, originalPath=$originalPath, resizePath=$resizePath, createdAt=$createdAt, modifiedAt=$modifiedAt, isFavorite=$isFavorite, mimeType=$mimeType, duration=$duration, webpPath=$webpPath, encodedVideoPath=$encodedVideoPath, exifInfo=$exifInfo, smartInfo=$smartInfo, livePhotoVideoId=$livePhotoVideoId, tags=$tags]'; + String toString() => 'AssetResponseDto[type=$type, id=$id, deviceAssetId=$deviceAssetId, ownerId=$ownerId, deviceId=$deviceId, originalPath=$originalPath, resizePath=$resizePath, createdAt=$createdAt, modifiedAt=$modifiedAt, updatedAt=$updatedAt, isFavorite=$isFavorite, mimeType=$mimeType, duration=$duration, webpPath=$webpPath, encodedVideoPath=$encodedVideoPath, exifInfo=$exifInfo, smartInfo=$smartInfo, livePhotoVideoId=$livePhotoVideoId, tags=$tags]'; Map toJson() { final json = {}; @@ -142,6 +147,7 @@ class AssetResponseDto { } json[r'createdAt'] = this.createdAt; json[r'modifiedAt'] = this.modifiedAt; + json[r'updatedAt'] = this.updatedAt; json[r'isFavorite'] = this.isFavorite; if (this.mimeType != null) { json[r'mimeType'] = this.mimeType; @@ -206,6 +212,7 @@ class AssetResponseDto { resizePath: mapValueOfType(json, r'resizePath'), createdAt: mapValueOfType(json, r'createdAt')!, modifiedAt: mapValueOfType(json, r'modifiedAt')!, + updatedAt: mapValueOfType(json, r'updatedAt')!, isFavorite: mapValueOfType(json, r'isFavorite')!, mimeType: mapValueOfType(json, r'mimeType'), duration: mapValueOfType(json, r'duration')!, @@ -273,6 +280,7 @@ class AssetResponseDto { 'resizePath', 'createdAt', 'modifiedAt', + 'updatedAt', 'isFavorite', 'mimeType', 'duration', diff --git a/mobile/openapi/test/album_response_dto_test.dart b/mobile/openapi/test/album_response_dto_test.dart index 1f16d754f..a91dcf877 100644 --- a/mobile/openapi/test/album_response_dto_test.dart +++ b/mobile/openapi/test/album_response_dto_test.dart @@ -41,6 +41,11 @@ void main() { // TODO }); + // String updatedAt + test('to test the property `updatedAt`', () async { + // TODO + }); + // String albumThumbnailAssetId test('to test the property `albumThumbnailAssetId`', () async { // TODO diff --git a/mobile/openapi/test/asset_response_dto_test.dart b/mobile/openapi/test/asset_response_dto_test.dart index 523fc5281..f4cce051e 100644 --- a/mobile/openapi/test/asset_response_dto_test.dart +++ b/mobile/openapi/test/asset_response_dto_test.dart @@ -61,6 +61,11 @@ void main() { // TODO }); + // String updatedAt + test('to test the property `updatedAt`', () async { + // TODO + }); + // bool isFavorite test('to test the property `isFavorite`', () async { // TODO diff --git a/server/apps/immich/src/api-v1/album/album-repository.ts b/server/apps/immich/src/api-v1/album/album-repository.ts index f9392fa16..07f05c03a 100644 --- a/server/apps/immich/src/api-v1/album/album-repository.ts +++ b/server/apps/immich/src/api-v1/album/album-repository.ts @@ -213,18 +213,27 @@ export class AlbumRepository implements IAlbumRepository { } async get(albumId: string): Promise { - const query = this.albumRepository.createQueryBuilder('album'); - - const album = await query - .where('album.id = :albumId', { albumId }) - .leftJoinAndSelect('album.sharedUsers', 'sharedUser') - .leftJoinAndSelect('sharedUser.userInfo', 'userInfo') - .leftJoinAndSelect('album.assets', 'assets') - .leftJoinAndSelect('assets.assetInfo', 'assetInfo') - .leftJoinAndSelect('assetInfo.exifInfo', 'exifInfo') - .leftJoinAndSelect('album.sharedLinks', 'sharedLinks') - .orderBy('"assetInfo"."createdAt"::timestamptz', 'ASC') - .getOne(); + const album = await this.albumRepository.findOne({ + where: { id: albumId }, + relations: { + sharedUsers: { + userInfo: true, + }, + assets: { + assetInfo: { + exifInfo: true, + }, + }, + sharedLinks: true, + }, + order: { + assets: { + assetInfo: { + createdAt: 'ASC', + }, + }, + }, + }); if (!album) { return; @@ -249,11 +258,14 @@ export class AlbumRepository implements IAlbumRepository { } await this.userAlbumRepository.save([...newRecords]); + await this.albumRepository.update({ id: album.id }, { updatedAt: new Date().toISOString() }); + return this.get(album.id) as Promise; // There is an album for sure } async removeUser(album: AlbumEntity, userId: string): Promise { await this.userAlbumRepository.delete({ albumId: album.id, sharedUserId: userId }); + await this.albumRepository.update({ id: album.id }, { updatedAt: new Date().toISOString() }); } async removeAssets(album: AlbumEntity, removeAssetsDto: RemoveAssetsDto): Promise { @@ -262,6 +274,8 @@ export class AlbumRepository implements IAlbumRepository { assetId: In(removeAssetsDto.assetIds), }); + await this.albumRepository.update({ id: album.id }, { updatedAt: new Date().toISOString() }); + return res.affected || 0; } @@ -290,6 +304,8 @@ export class AlbumRepository implements IAlbumRepository { await this.assetAlbumRepository.save([...newRecords]); + await this.albumRepository.update({ id: album.id }, { updatedAt: new Date().toISOString() }); + return { successfullyAdded: newRecords.length, alreadyInAlbum: alreadyExisting, diff --git a/server/apps/immich/src/api-v1/album/album.service.spec.ts b/server/apps/immich/src/api-v1/album/album.service.spec.ts index eb00f5ac3..6733db560 100644 --- a/server/apps/immich/src/api-v1/album/album.service.spec.ts +++ b/server/apps/immich/src/api-v1/album/album.service.spec.ts @@ -32,6 +32,7 @@ describe('Album service', () => { albumEntity.id = albumId; albumEntity.albumName = 'name'; albumEntity.createdAt = 'date'; + albumEntity.updatedAt = 'date'; albumEntity.sharedUsers = []; albumEntity.assets = []; albumEntity.albumThumbnailAssetId = null; @@ -183,6 +184,7 @@ describe('Album service', () => { albumName: 'name', albumThumbnailAssetId: null, createdAt: 'date', + updatedAt: 'date', id: 'f19ab956-4761-41ea-a5d6-bae948308d58', ownerId, shared: false, diff --git a/server/apps/immich/src/api-v1/asset/asset.core.ts b/server/apps/immich/src/api-v1/asset/asset.core.ts index 5ad47c70a..5fbe9c881 100644 --- a/server/apps/immich/src/api-v1/asset/asset.core.ts +++ b/server/apps/immich/src/api-v1/asset/asset.core.ts @@ -27,6 +27,7 @@ export class AssetCore { createdAt: timeUtils.checkValidTimestamp(dto.createdAt) ? dto.createdAt : new Date().toISOString(), modifiedAt: timeUtils.checkValidTimestamp(dto.modifiedAt) ? dto.modifiedAt : new Date().toISOString(), + updatedAt: new Date().toISOString(), deviceAssetId: dto.deviceAssetId, deviceId: dto.deviceId, diff --git a/server/apps/immich/src/api-v1/tag/tag.service.spec.ts b/server/apps/immich/src/api-v1/tag/tag.service.spec.ts index 7a906012a..395a37573 100644 --- a/server/apps/immich/src/api-v1/tag/tag.service.spec.ts +++ b/server/apps/immich/src/api-v1/tag/tag.service.spec.ts @@ -23,6 +23,7 @@ describe('TagService', () => { shouldChangePassword: true, createdAt: '2022-12-02T19:29:23.603Z', deletedAt: undefined, + updatedAt: '2022-12-02T19:29:23.603Z', tags: [], oauthId: 'oauth-id-1', }); diff --git a/server/immich-openapi-specs.json b/server/immich-openapi-specs.json index f786c4693..5a7b3380b 100644 --- a/server/immich-openapi-specs.json +++ b/server/immich-openapi-specs.json @@ -3291,6 +3291,9 @@ "modifiedAt": { "type": "string" }, + "updatedAt": { + "type": "string" + }, "isFavorite": { "type": "boolean" }, @@ -3336,6 +3339,7 @@ "resizePath", "createdAt", "modifiedAt", + "updatedAt", "isFavorite", "mimeType", "duration", @@ -3361,6 +3365,9 @@ "createdAt": { "type": "string" }, + "updatedAt": { + "type": "string" + }, "albumThumbnailAssetId": { "type": "string", "nullable": true @@ -3387,6 +3394,7 @@ "ownerId", "albumName", "createdAt", + "updatedAt", "albumThumbnailAssetId", "shared", "sharedUsers", diff --git a/server/libs/domain/src/album/response-dto/album-response.dto.ts b/server/libs/domain/src/album/response-dto/album-response.dto.ts index 0be9173f4..651e18ed2 100644 --- a/server/libs/domain/src/album/response-dto/album-response.dto.ts +++ b/server/libs/domain/src/album/response-dto/album-response.dto.ts @@ -8,6 +8,7 @@ export class AlbumResponseDto { ownerId!: string; albumName!: string; createdAt!: string; + updatedAt!: string; albumThumbnailAssetId!: string | null; shared!: boolean; sharedUsers!: UserResponseDto[]; @@ -30,6 +31,7 @@ export function mapAlbum(entity: AlbumEntity): AlbumResponseDto { albumName: entity.albumName, albumThumbnailAssetId: entity.albumThumbnailAssetId, createdAt: entity.createdAt, + updatedAt: entity.updatedAt, id: entity.id, ownerId: entity.ownerId, sharedUsers, @@ -52,6 +54,7 @@ export function mapAlbumExcludeAssetInfo(entity: AlbumEntity): AlbumResponseDto albumName: entity.albumName, albumThumbnailAssetId: entity.albumThumbnailAssetId, createdAt: entity.createdAt, + updatedAt: entity.updatedAt, id: entity.id, ownerId: entity.ownerId, sharedUsers, diff --git a/server/libs/domain/src/asset/response-dto/asset-response.dto.ts b/server/libs/domain/src/asset/response-dto/asset-response.dto.ts index dc09f6d8c..d72967723 100644 --- a/server/libs/domain/src/asset/response-dto/asset-response.dto.ts +++ b/server/libs/domain/src/asset/response-dto/asset-response.dto.ts @@ -16,6 +16,7 @@ export class AssetResponseDto { resizePath!: string | null; createdAt!: string; modifiedAt!: string; + updatedAt!: string; isFavorite!: boolean; mimeType!: string | null; duration!: string; @@ -38,6 +39,7 @@ export function mapAsset(entity: AssetEntity): AssetResponseDto { resizePath: entity.resizePath, createdAt: entity.createdAt, modifiedAt: entity.modifiedAt, + updatedAt: entity.updatedAt, isFavorite: entity.isFavorite, mimeType: entity.mimeType, webpPath: entity.webpPath, @@ -61,6 +63,7 @@ export function mapAssetWithoutExif(entity: AssetEntity): AssetResponseDto { resizePath: entity.resizePath, createdAt: entity.createdAt, modifiedAt: entity.modifiedAt, + updatedAt: entity.updatedAt, isFavorite: entity.isFavorite, mimeType: entity.mimeType, webpPath: entity.webpPath, diff --git a/server/libs/domain/src/user/user.service.spec.ts b/server/libs/domain/src/user/user.service.spec.ts index 9235c3258..938e324f5 100644 --- a/server/libs/domain/src/user/user.service.spec.ts +++ b/server/libs/domain/src/user/user.service.spec.ts @@ -31,6 +31,7 @@ const adminUser: UserEntity = Object.freeze({ shouldChangePassword: false, profileImagePath: '', createdAt: '2021-01-01', + updatedAt: '2021-01-01', tags: [], }); @@ -45,6 +46,7 @@ const immichUser: UserEntity = Object.freeze({ shouldChangePassword: false, profileImagePath: '', createdAt: '2021-01-01', + updatedAt: '2021-01-01', tags: [], }); @@ -59,6 +61,7 @@ const updatedImmichUser: UserEntity = Object.freeze({ shouldChangePassword: true, profileImagePath: '', createdAt: '2021-01-01', + updatedAt: '2021-01-01', tags: [], }); diff --git a/server/libs/domain/test/fixtures.ts b/server/libs/domain/test/fixtures.ts index 3cc9a17f3..e25fab90a 100644 --- a/server/libs/domain/test/fixtures.ts +++ b/server/libs/domain/test/fixtures.ts @@ -48,6 +48,7 @@ const assetResponse: AssetResponseDto = { resizePath: '', createdAt: today.toISOString(), modifiedAt: today.toISOString(), + updatedAt: today.toISOString(), isFavorite: false, mimeType: 'image/jpeg', smartInfo: { @@ -67,6 +68,7 @@ const albumResponse: AlbumResponseDto = { albumName: 'Test Album', albumThumbnailAssetId: null, createdAt: today.toISOString(), + updatedAt: today.toISOString(), id: 'album-123', ownerId: 'admin_id', sharedUsers: [], @@ -126,6 +128,7 @@ export const userEntityStub = { shouldChangePassword: false, profileImagePath: '', createdAt: '2021-01-01', + updatedAt: '2021-01-01', tags: [], }), user1: Object.freeze({ @@ -137,6 +140,7 @@ export const userEntityStub = { shouldChangePassword: false, profileImagePath: '', createdAt: '2021-01-01', + updatedAt: '2021-01-01', tags: [], }), }; @@ -329,6 +333,7 @@ export const sharedLinkStub = { ownerId: authStub.admin.id, albumName: 'Test Album', createdAt: today.toISOString(), + updatedAt: today.toISOString(), albumThumbnailAssetId: null, sharedUsers: [], sharedLinks: [], @@ -348,6 +353,7 @@ export const sharedLinkStub = { resizePath: '', createdAt: today.toISOString(), modifiedAt: today.toISOString(), + updatedAt: today.toISOString(), isFavorite: false, mimeType: 'image/jpeg', smartInfo: { diff --git a/server/libs/infra/src/db/entities/album.entity.ts b/server/libs/infra/src/db/entities/album.entity.ts index 53c06a53f..a62c0c552 100644 --- a/server/libs/infra/src/db/entities/album.entity.ts +++ b/server/libs/infra/src/db/entities/album.entity.ts @@ -1,4 +1,4 @@ -import { Column, CreateDateColumn, Entity, OneToMany, PrimaryGeneratedColumn } from 'typeorm'; +import { Column, CreateDateColumn, Entity, OneToMany, PrimaryGeneratedColumn, UpdateDateColumn } from 'typeorm'; import { AssetAlbumEntity } from './asset-album.entity'; import { SharedLinkEntity } from './shared-link.entity'; import { UserAlbumEntity } from './user-album.entity'; @@ -17,6 +17,9 @@ export class AlbumEntity { @CreateDateColumn({ type: 'timestamptz' }) createdAt!: string; + @UpdateDateColumn({ type: 'timestamptz' }) + updatedAt!: string; + @Column({ comment: 'Asset ID to be used as thumbnail', type: 'varchar', nullable: true }) albumThumbnailAssetId!: string | null; diff --git a/server/libs/infra/src/db/entities/asset.entity.ts b/server/libs/infra/src/db/entities/asset.entity.ts index 532793e1c..5f716da34 100644 --- a/server/libs/infra/src/db/entities/asset.entity.ts +++ b/server/libs/infra/src/db/entities/asset.entity.ts @@ -1,4 +1,14 @@ -import { Column, Entity, Index, JoinTable, ManyToMany, OneToOne, PrimaryGeneratedColumn, Unique } from 'typeorm'; +import { + Column, + Entity, + Index, + JoinTable, + ManyToMany, + OneToOne, + PrimaryGeneratedColumn, + Unique, + UpdateDateColumn, +} from 'typeorm'; import { ExifEntity } from './exif.entity'; import { SharedLinkEntity } from './shared-link.entity'; import { SmartInfoEntity } from './smart-info.entity'; @@ -40,6 +50,9 @@ export class AssetEntity { @Column({ type: 'timestamptz' }) modifiedAt!: string; + @UpdateDateColumn({ type: 'timestamptz' }) + updatedAt!: string; + @Column({ type: 'boolean', default: false }) isFavorite!: boolean; diff --git a/server/libs/infra/src/db/entities/user.entity.ts b/server/libs/infra/src/db/entities/user.entity.ts index 325c36db8..d8724aab9 100644 --- a/server/libs/infra/src/db/entities/user.entity.ts +++ b/server/libs/infra/src/db/entities/user.entity.ts @@ -1,4 +1,12 @@ -import { Column, CreateDateColumn, DeleteDateColumn, Entity, OneToMany, PrimaryGeneratedColumn } from 'typeorm'; +import { + Column, + CreateDateColumn, + DeleteDateColumn, + Entity, + OneToMany, + PrimaryGeneratedColumn, + UpdateDateColumn, +} from 'typeorm'; import { TagEntity } from './tag.entity'; @Entity('users') @@ -36,6 +44,9 @@ export class UserEntity { @DeleteDateColumn() deletedAt?: Date; + @UpdateDateColumn({ type: 'timestamptz' }) + updatedAt!: string; + @OneToMany(() => TagEntity, (tag) => tag.user) tags!: TagEntity[]; } diff --git a/server/libs/infra/src/db/migrations/1675667878312-AddUpdatedAtColumnToAlbumsUsersAssets.ts b/server/libs/infra/src/db/migrations/1675667878312-AddUpdatedAtColumnToAlbumsUsersAssets.ts new file mode 100644 index 000000000..90c00b38e --- /dev/null +++ b/server/libs/infra/src/db/migrations/1675667878312-AddUpdatedAtColumnToAlbumsUsersAssets.ts @@ -0,0 +1,17 @@ +import { MigrationInterface, QueryRunner } from 'typeorm'; + +export class AddUpdatedAtColumnToAlbumsUsersAssets1675667878312 implements MigrationInterface { + name = 'AddUpdatedAtColumnToAlbumsUsersAssets1675667878312'; + + public async up(queryRunner: QueryRunner): Promise { + await queryRunner.query(`ALTER TABLE "albums" ADD "updatedAt" TIMESTAMP WITH TIME ZONE NOT NULL DEFAULT now()`); + await queryRunner.query(`ALTER TABLE "users" ADD "updatedAt" TIMESTAMP WITH TIME ZONE NOT NULL DEFAULT now()`); + await queryRunner.query(`ALTER TABLE "assets" ADD "updatedAt" TIMESTAMP WITH TIME ZONE NOT NULL DEFAULT now()`); + } + + public async down(queryRunner: QueryRunner): Promise { + await queryRunner.query(`ALTER TABLE "albums" DROP COLUMN "updatedAt"`); + await queryRunner.query(`ALTER TABLE "assets" DROP COLUMN "updatedAt"`); + await queryRunner.query(`ALTER TABLE "users" DROP COLUMN "updatedAt"`); + } +} diff --git a/web/src/api/open-api/api.ts b/web/src/api/open-api/api.ts index 6d0ac7036..e741d516d 100644 --- a/web/src/api/open-api/api.ts +++ b/web/src/api/open-api/api.ts @@ -4,7 +4,7 @@ * Immich * Immich API * - * The version of the OpenAPI document: 1.43.1 + * The version of the OpenAPI document: 1.45.0 * * * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). @@ -246,6 +246,12 @@ export interface AlbumResponseDto { * @memberof AlbumResponseDto */ 'createdAt': string; + /** + * + * @type {string} + * @memberof AlbumResponseDto + */ + 'updatedAt': string; /** * * @type {string} @@ -462,6 +468,12 @@ export interface AssetResponseDto { * @memberof AssetResponseDto */ 'modifiedAt': string; + /** + * + * @type {string} + * @memberof AssetResponseDto + */ + 'updatedAt': string; /** * * @type {boolean} diff --git a/web/src/api/open-api/base.ts b/web/src/api/open-api/base.ts index f022bd6e3..eb55f2cd7 100644 --- a/web/src/api/open-api/base.ts +++ b/web/src/api/open-api/base.ts @@ -4,7 +4,7 @@ * Immich * Immich API * - * The version of the OpenAPI document: 1.43.1 + * The version of the OpenAPI document: 1.45.0 * * * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). diff --git a/web/src/api/open-api/common.ts b/web/src/api/open-api/common.ts index d41e01f32..974b67d37 100644 --- a/web/src/api/open-api/common.ts +++ b/web/src/api/open-api/common.ts @@ -4,7 +4,7 @@ * Immich * Immich API * - * The version of the OpenAPI document: 1.43.1 + * The version of the OpenAPI document: 1.45.0 * * * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). diff --git a/web/src/api/open-api/configuration.ts b/web/src/api/open-api/configuration.ts index b12628461..7223695d8 100644 --- a/web/src/api/open-api/configuration.ts +++ b/web/src/api/open-api/configuration.ts @@ -4,7 +4,7 @@ * Immich * Immich API * - * The version of the OpenAPI document: 1.43.1 + * The version of the OpenAPI document: 1.45.0 * * * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). diff --git a/web/src/api/open-api/index.ts b/web/src/api/open-api/index.ts index 052d483f1..382b9a0b8 100644 --- a/web/src/api/open-api/index.ts +++ b/web/src/api/open-api/index.ts @@ -4,7 +4,7 @@ * Immich * Immich API * - * The version of the OpenAPI document: 1.43.1 + * The version of the OpenAPI document: 1.45.0 * * * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).