feat: batch change date and time relatively (#17717)

Co-authored-by: marcel.kuehne <>
Co-authored-by: Zack Pollard <zackpollard@ymail.com>
This commit is contained in:
mkuehne707
2025-08-07 15:42:33 +02:00
committed by GitHub
parent df2525ee08
commit 011a667314
19 changed files with 574 additions and 52 deletions
+27
View File
@@ -468,6 +468,33 @@ describe(AssetService.name, () => {
});
expect(mocks.asset.updateAll).toHaveBeenCalled();
});
it('should update exif table if dateTimeRelative and timeZone field is provided', async () => {
mocks.access.asset.checkOwnerAccess.mockResolvedValue(new Set(['asset-1']));
const dateTimeRelative = 35;
const timeZone = 'UTC+2';
mocks.asset.updateDateTimeOriginal.mockResolvedValue([
{ assetId: 'asset-1', dateTimeOriginal: new Date('2020-02-25T04:41:00'), timeZone },
]);
await sut.updateAll(authStub.admin, {
ids: ['asset-1'],
dateTimeRelative,
timeZone,
});
expect(mocks.asset.updateDateTimeOriginal).toHaveBeenCalledWith(['asset-1'], dateTimeRelative, timeZone);
expect(mocks.job.queueAll).toHaveBeenCalledWith([
{
name: JobName.SidecarWrite,
data: {
id: 'asset-1',
dateTimeOriginal: '2020-02-25T06:41:00.000+02:00',
description: undefined,
latitude: undefined,
longitude: undefined,
},
},
]);
});
});
describe('deleteAll', () => {
+39 -13
View File
@@ -113,22 +113,48 @@ export class AssetService extends BaseService {
}
async updateAll(auth: AuthDto, dto: AssetBulkUpdateDto): Promise<void> {
const { ids, description, dateTimeOriginal, latitude, longitude, ...options } = dto;
const { ids, description, dateTimeOriginal, dateTimeRelative, timeZone, latitude, longitude, ...options } = dto;
await this.requireAccess({ auth, permission: Permission.AssetUpdate, ids });
if (
description !== undefined ||
dateTimeOriginal !== undefined ||
latitude !== undefined ||
longitude !== undefined
) {
const staticValuesChanged =
description !== undefined || dateTimeOriginal !== undefined || latitude !== undefined || longitude !== undefined;
if (staticValuesChanged) {
await this.assetRepository.updateAllExif(ids, { description, dateTimeOriginal, latitude, longitude });
await this.jobRepository.queueAll(
ids.map((id) => ({
name: JobName.SidecarWrite,
data: { id, description, dateTimeOriginal, latitude, longitude },
})),
);
}
const assets =
(dateTimeRelative !== undefined && dateTimeRelative !== 0) || timeZone !== undefined
? await this.assetRepository.updateDateTimeOriginal(ids, dateTimeRelative, timeZone)
: null;
const dateTimesWithTimezone =
assets?.map((asset) => {
const isoString = asset.dateTimeOriginal?.toISOString();
let dateTime = isoString ? DateTime.fromISO(isoString) : null;
if (dateTime && asset.timeZone) {
dateTime = dateTime.setZone(asset.timeZone);
}
return {
assetId: asset.assetId,
dateTimeOriginal: dateTime?.toISO() ?? null,
};
}) ?? null;
if (staticValuesChanged || dateTimesWithTimezone) {
const entries: JobItem[] = (dateTimesWithTimezone ?? ids).map((entry: any) => ({
name: JobName.SidecarWrite,
data: {
id: entry.assetId ?? entry,
description,
dateTimeOriginal: entry.dateTimeOriginal ?? dateTimeOriginal,
latitude,
longitude,
},
}));
await this.jobRepository.queueAll(entries);
}
if (