diff --git a/server/src/queries/asset.repository.sql b/server/src/queries/asset.repository.sql index ceb73e0e7b..e812b33f78 100644 --- a/server/src/queries/asset.repository.sql +++ b/server/src/queries/asset.repository.sql @@ -1,5 +1,12 @@ -- NOTE: This file is auto generated by ./sql-generator +-- AssetRepository.updateAllExif +update "exif" +set + "model" = $1 +where + "assetId" in ($2) + -- AssetRepository.getByDayOfYear with "res" as ( diff --git a/server/src/repositories/asset.repository.ts b/server/src/repositories/asset.repository.ts index 59df871ba8..94af400d05 100644 --- a/server/src/repositories/asset.repository.ts +++ b/server/src/repositories/asset.repository.ts @@ -201,6 +201,16 @@ export class AssetRepository { .execute(); } + @GenerateSql({ params: [[DummyValue.UUID], { model: DummyValue.STRING }] }) + @Chunked() + async updateAllExif(ids: string[], options: Updateable): Promise { + if (ids.length === 0) { + return; + } + + await this.db.updateTable('exif').set(options).where('assetId', 'in', ids).execute(); + } + async upsertJobStatus(...jobStatus: Insertable[]): Promise { if (jobStatus.length === 0) { return; diff --git a/server/src/services/asset.service.spec.ts b/server/src/services/asset.service.spec.ts index 5e7e2d79d0..b977dd6d70 100755 --- a/server/src/services/asset.service.spec.ts +++ b/server/src/services/asset.service.spec.ts @@ -460,6 +460,34 @@ describe(AssetService.name, () => { rating: undefined, }); expect(mocks.asset.updateAll).toHaveBeenCalled(); + expect(mocks.asset.updateAllExif).toHaveBeenCalledWith(['asset-1'], { latitude: 0, longitude: 0 }); + expect(mocks.job.queueAll).toHaveBeenCalledWith([ + { name: JobName.SIDECAR_WRITE, data: { id: 'asset-1', latitude: 0, longitude: 0 } }, + ]); + }); + + it('should update exif table if latitude field is provided', async () => { + mocks.access.asset.checkOwnerAccess.mockResolvedValue(new Set(['asset-1'])); + const dateTimeOriginal = new Date().toISOString(); + await sut.updateAll(authStub.admin, { + ids: ['asset-1'], + latitude: 30, + longitude: 50, + dateTimeOriginal, + isArchived: undefined, + isFavorite: false, + duplicateId: undefined, + rating: undefined, + }); + expect(mocks.asset.updateAll).toHaveBeenCalled(); + expect(mocks.asset.updateAllExif).toHaveBeenCalledWith(['asset-1'], { + dateTimeOriginal, + latitude: 30, + longitude: 50, + }); + expect(mocks.job.queueAll).toHaveBeenCalledWith([ + { name: JobName.SIDECAR_WRITE, data: { id: 'asset-1', dateTimeOriginal, latitude: 30, longitude: 50 } }, + ]); }); }); diff --git a/server/src/services/asset.service.ts b/server/src/services/asset.service.ts index 56b7f7743c..37ec00b0bb 100644 --- a/server/src/services/asset.service.ts +++ b/server/src/services/asset.service.ts @@ -134,8 +134,11 @@ export class AssetService extends BaseService { const { ids, dateTimeOriginal, latitude, longitude, ...options } = dto; await this.requireAccess({ auth, permission: Permission.ASSET_UPDATE, ids }); - for (const id of ids) { - await this.updateMetadata({ id, dateTimeOriginal, latitude, longitude }); + if (dateTimeOriginal !== undefined || latitude !== undefined || longitude !== undefined) { + await this.assetRepository.updateAllExif(ids, { dateTimeOriginal, latitude, longitude }); + await this.jobRepository.queueAll( + ids.map((id) => ({ name: JobName.SIDECAR_WRITE, data: { id, dateTimeOriginal, latitude, longitude } })), + ); } if ( diff --git a/server/test/repositories/asset.repository.mock.ts b/server/test/repositories/asset.repository.mock.ts index 19464f7ff2..531f8d56f1 100644 --- a/server/test/repositories/asset.repository.mock.ts +++ b/server/test/repositories/asset.repository.mock.ts @@ -7,6 +7,7 @@ export const newAssetRepositoryMock = (): Mocked