From b4fa60d4fdd6e70cb5f21e7b4a05cfc194d2020a Mon Sep 17 00:00:00 2001 From: Maarten Rijke Date: Wed, 6 Sep 2023 05:14:44 +0200 Subject: [PATCH] feat(web): show original uploader in shared album photo details (#3977) * feat(web): show original uploader in shared album photo details * feat: send owner in asset by id response * chore: open api * fix: linting * fix: change to Shared By * openapi * openapi * api * styling --------- Co-authored-by: Jason Rasmussen Co-authored-by: Alex --- cli/src/api/open-api/api.ts | 6 +++ mobile/openapi/doc/AssetResponseDto.md | Bin 1444 -> 1515 bytes .../openapi/lib/model/asset_response_dto.dart | Bin 9330 -> 9981 bytes .../openapi/test/asset_response_dto_test.dart | Bin 2819 -> 2923 bytes server/immich-openapi-specs.json | 5 ++- .../asset/response-dto/asset-response.dto.ts | 37 +++++---------- .../immich/api-v1/asset/asset-repository.ts | 1 + .../src/immich/api-v1/asset/asset.service.ts | 4 ++ server/test/fixtures/shared-link.stub.ts | 4 +- web/src/api/open-api/api.ts | 6 +++ .../asset-viewer/detail-panel.svelte | 42 ++++++++++++------ 11 files changed, 63 insertions(+), 42 deletions(-) diff --git a/cli/src/api/open-api/api.ts b/cli/src/api/open-api/api.ts index 2301c02e1c..35a769d283 100644 --- a/cli/src/api/open-api/api.ts +++ b/cli/src/api/open-api/api.ts @@ -645,6 +645,12 @@ export interface AssetResponseDto { * @memberof AssetResponseDto */ 'originalPath': string; + /** + * + * @type {UserResponseDto} + * @memberof AssetResponseDto + */ + 'owner'?: UserResponseDto; /** * * @type {string} diff --git a/mobile/openapi/doc/AssetResponseDto.md b/mobile/openapi/doc/AssetResponseDto.md index b122147ff18984d25ccdd93715733b274ca6c854..929031a3a3620475086c783baa0c2340b0b815cf 100644 GIT binary patch delta 59 zcmZ3&{hE6NFSERsmO_m}w3b$AacWUeYH>k+UU8~RNxqg=tOiJE@_a^Rw*2zE)FRKx M227Hh)tPIV06c^e+W-In delta 12 TcmaFOy@Y!MFZ1RQ=IKlT9!UfV diff --git a/mobile/openapi/lib/model/asset_response_dto.dart b/mobile/openapi/lib/model/asset_response_dto.dart index 02bb376cc2be63a36fed0a7f10abb47cc9a1d09d..078389c549af1ba88d78e6fc867d44c93d6e0637 100644 GIT binary patch delta 201 zcmez5@z-|&GgnDQX0cv=d0uMKWJ6|=&3w#d%$vPgVj0Cki&Kk&Qi}`n^NLelO7iU$ zz=}54vz=q%RIs&$axJ+zm_vl0+-0<)14Aq2A}7sdv&Bp%ra DgwPM~ diff --git a/mobile/openapi/test/asset_response_dto_test.dart b/mobile/openapi/test/asset_response_dto_test.dart index f89eacf986dc53f0e58fa20c5055be3dcd2e9e33..d0985f429bb73714fa9eb0268f16a1b1b49c83d8 100644 GIT binary patch delta 41 wcmZn`do8vhiCr|bIJGD!wYVTZuQ=7EBwr!FJTJ9qasj*ABxaM%ne4Ne0Yv5w;s5{u delta 16 XcmaDY)-1LmiG6Yd8^`8L>@%4GHlzjp diff --git a/server/immich-openapi-specs.json b/server/immich-openapi-specs.json index 2856819c58..0aa62f43c5 100644 --- a/server/immich-openapi-specs.json +++ b/server/immich-openapi-specs.json @@ -5208,6 +5208,9 @@ "originalPath": { "type": "string" }, + "owner": { + "$ref": "#/components/schemas/UserResponseDto" + }, "ownerId": { "type": "string" }, @@ -5246,8 +5249,8 @@ "type", "id", "deviceAssetId", - "ownerId", "deviceId", + "ownerId", "originalPath", "originalFileName", "resized", diff --git a/server/src/domain/asset/response-dto/asset-response.dto.ts b/server/src/domain/asset/response-dto/asset-response.dto.ts index 8079d9fd18..41e7f20522 100644 --- a/server/src/domain/asset/response-dto/asset-response.dto.ts +++ b/server/src/domain/asset/response-dto/asset-response.dto.ts @@ -2,14 +2,16 @@ import { AssetEntity, AssetType } from '@app/infra/entities'; import { ApiProperty } from '@nestjs/swagger'; import { PersonResponseDto, mapFace } from '../../person/person.dto'; import { TagResponseDto, mapTag } from '../../tag'; +import { UserResponseDto, mapUser } from '../../user/response-dto/user-response.dto'; import { ExifResponseDto, mapExif } from './exif-response.dto'; import { SmartInfoResponseDto, mapSmartInfo } from './smart-info-response.dto'; export class AssetResponseDto { id!: string; deviceAssetId!: string; - ownerId!: string; deviceId!: string; + ownerId!: string; + owner?: UserResponseDto; @ApiProperty({ enumName: 'AssetTypeEnum', enum: AssetType }) type!: AssetType; @@ -33,11 +35,12 @@ export class AssetResponseDto { checksum!: string; } -export function mapAsset(entity: AssetEntity): AssetResponseDto { +function _map(entity: AssetEntity, withExif: boolean): AssetResponseDto { return { id: entity.id, deviceAssetId: entity.deviceAssetId, ownerId: entity.ownerId, + owner: entity.owner ? mapUser(entity.owner) : undefined, deviceId: entity.deviceId, type: entity.type, originalPath: entity.originalPath, @@ -50,7 +53,7 @@ export function mapAsset(entity: AssetEntity): AssetResponseDto { isFavorite: entity.isFavorite, isArchived: entity.isArchived, duration: entity.duration ?? '0:00:00.00000', - exifInfo: entity.exifInfo ? mapExif(entity.exifInfo) : undefined, + exifInfo: withExif ? (entity.exifInfo ? mapExif(entity.exifInfo) : undefined) : undefined, smartInfo: entity.smartInfo ? mapSmartInfo(entity.smartInfo) : undefined, livePhotoVideoId: entity.livePhotoVideoId, tags: entity.tags?.map(mapTag), @@ -59,30 +62,12 @@ export function mapAsset(entity: AssetEntity): AssetResponseDto { }; } +export function mapAsset(entity: AssetEntity): AssetResponseDto { + return _map(entity, true); +} + export function mapAssetWithoutExif(entity: AssetEntity): AssetResponseDto { - return { - id: entity.id, - deviceAssetId: entity.deviceAssetId, - ownerId: entity.ownerId, - deviceId: entity.deviceId, - type: entity.type, - originalPath: entity.originalPath, - originalFileName: entity.originalFileName, - resized: !!entity.resizePath, - thumbhash: entity.thumbhash?.toString('base64') || null, - fileCreatedAt: entity.fileCreatedAt, - fileModifiedAt: entity.fileModifiedAt, - updatedAt: entity.updatedAt, - isFavorite: entity.isFavorite, - isArchived: entity.isArchived, - duration: entity.duration ?? '0:00:00.00000', - exifInfo: undefined, - smartInfo: entity.smartInfo ? mapSmartInfo(entity.smartInfo) : undefined, - livePhotoVideoId: entity.livePhotoVideoId, - tags: entity.tags?.map(mapTag), - people: entity.faces?.map(mapFace), - checksum: entity.checksum.toString('base64'), - }; + return _map(entity, false); } export class MemoryLaneResponseDto { diff --git a/server/src/immich/api-v1/asset/asset-repository.ts b/server/src/immich/api-v1/asset/asset-repository.ts index 0466b3668c..c666e88bdf 100644 --- a/server/src/immich/api-v1/asset/asset-repository.ts +++ b/server/src/immich/api-v1/asset/asset-repository.ts @@ -107,6 +107,7 @@ export class AssetRepository implements IAssetRepository { tags: true, sharedLinks: true, smartInfo: true, + owner: true, faces: { person: true, }, diff --git a/server/src/immich/api-v1/asset/asset.service.ts b/server/src/immich/api-v1/asset/asset.service.ts index 77b3f73e09..c6013e2f7e 100644 --- a/server/src/immich/api-v1/asset/asset.service.ts +++ b/server/src/immich/api-v1/asset/asset.service.ts @@ -199,6 +199,10 @@ export class AssetService { data.people = []; } + if (authUser.isPublicUser) { + delete data.owner; + } + return data; } diff --git a/server/test/fixtures/shared-link.stub.ts b/server/test/fixtures/shared-link.stub.ts index e85b000ce1..31a9459850 100644 --- a/server/test/fixtures/shared-link.stub.ts +++ b/server/test/fixtures/shared-link.stub.ts @@ -1,5 +1,5 @@ import { AlbumResponseDto, AssetResponseDto, ExifResponseDto, mapUser, SharedLinkResponseDto } from '@app/domain'; -import { AssetType, SharedLinkEntity, SharedLinkType } from '@app/infra/entities'; +import { AssetType, SharedLinkEntity, SharedLinkType, UserEntity } from '@app/infra/entities'; import { assetStub } from './asset.stub'; import { authStub } from './auth.stub'; import { userStub } from './user.stub'; @@ -158,7 +158,7 @@ export const sharedLinkStub = { assets: [ { id: 'id_1', - owner: userStub.user1, + owner: undefined as unknown as UserEntity, ownerId: 'user_id_1', deviceAssetId: 'device_asset_id_1', deviceId: 'device_id_1', diff --git a/web/src/api/open-api/api.ts b/web/src/api/open-api/api.ts index 2301c02e1c..35a769d283 100644 --- a/web/src/api/open-api/api.ts +++ b/web/src/api/open-api/api.ts @@ -645,6 +645,12 @@ export interface AssetResponseDto { * @memberof AssetResponseDto */ 'originalPath': string; + /** + * + * @type {UserResponseDto} + * @memberof AssetResponseDto + */ + 'owner'?: UserResponseDto; /** * * @type {string} diff --git a/web/src/lib/components/asset-viewer/detail-panel.svelte b/web/src/lib/components/asset-viewer/detail-panel.svelte index fc4526a465..53bff125fb 100644 --- a/web/src/lib/components/asset-viewer/detail-panel.svelte +++ b/web/src/lib/components/asset-viewer/detail-panel.svelte @@ -13,6 +13,7 @@ import { asByteUnitString } from '../../utils/byte-units'; import ImageThumbnail from '../assets/thumbnail/image-thumbnail.svelte'; import { getAssetFilename } from '$lib/utils/asset-utils'; + import UserAvatar from '../shared-components/user-avatar.svelte'; export let asset: AssetResponseDto; export let albums: AlbumResponseDto[] = []; @@ -20,6 +21,8 @@ let textarea: HTMLTextAreaElement; let description: string; + $: isOwner = $page?.data?.user?.id === asset.ownerId; + $: { // Get latest description from server if (asset.id && !api.isSharedLink) { @@ -93,20 +96,17 @@

Info

-
+