feat(web): favorite an asset (#939)

* feat(web): favorite an asset

* fix: test and linting

* fix: asset dto type
This commit is contained in:
Jason Rasmussen
2022-11-08 11:20:36 -05:00
committed by GitHub
parent 8a9b0347bb
commit 99da181cfc
19 changed files with 453 additions and 12 deletions

View File

@@ -4,8 +4,8 @@ import { BadRequestException, NotFoundException, ForbiddenException } from '@nes
import { AlbumEntity } from '@app/database/entities/album.entity';
import { AlbumResponseDto } from './response-dto/album-response.dto';
import { IAssetRepository } from '../asset/asset-repository';
import {AddAssetsResponseDto} from "./response-dto/add-assets-response.dto";
import {IAlbumRepository} from "./album-repository";
import { AddAssetsResponseDto } from './response-dto/add-assets-response.dto';
import { IAlbumRepository } from './album-repository';
describe('Album service', () => {
let sut: AlbumService;
@@ -125,6 +125,7 @@ describe('Album service', () => {
assetRepositoryMock = {
create: jest.fn(),
update: jest.fn(),
getAllByUserId: jest.fn(),
getAllByDeviceId: jest.fn(),
getAssetCountByTimeBucket: jest.fn(),
@@ -333,7 +334,7 @@ describe('Album service', () => {
const albumResponse: AddAssetsResponseDto = {
alreadyInAlbum: [],
successfullyAdded: 1
successfullyAdded: 1,
};
const albumId = albumEntity.id;
@@ -341,13 +342,13 @@ describe('Album service', () => {
albumRepositoryMock.get.mockImplementation(() => Promise.resolve<AlbumEntity>(albumEntity));
albumRepositoryMock.addAssets.mockImplementation(() => Promise.resolve<AddAssetsResponseDto>(albumResponse));
const result = await sut.addAssetsToAlbum(
const result = (await sut.addAssetsToAlbum(
authUser,
{
assetIds: ['1'],
},
albumId,
) as AddAssetsResponseDto;
)) as AddAssetsResponseDto;
// TODO: stub and expect album rendered
expect(result.album?.id).toEqual(albumId);
@@ -358,7 +359,7 @@ describe('Album service', () => {
const albumResponse: AddAssetsResponseDto = {
alreadyInAlbum: [],
successfullyAdded: 1
successfullyAdded: 1,
};
const albumId = albumEntity.id;
@@ -366,13 +367,13 @@ describe('Album service', () => {
albumRepositoryMock.get.mockImplementation(() => Promise.resolve<AlbumEntity>(albumEntity));
albumRepositoryMock.addAssets.mockImplementation(() => Promise.resolve<AddAssetsResponseDto>(albumResponse));
const result = await sut.addAssetsToAlbum(
const result = (await sut.addAssetsToAlbum(
authUser,
{
assetIds: ['1'],
},
albumId,
) as AddAssetsResponseDto;
)) as AddAssetsResponseDto;
// TODO: stub and expect album rendered
expect(result.album?.id).toEqual(albumId);
@@ -383,7 +384,7 @@ describe('Album service', () => {
const albumResponse: AddAssetsResponseDto = {
alreadyInAlbum: [],
successfullyAdded: 1
successfullyAdded: 1,
};
const albumId = albumEntity.id;
@@ -447,7 +448,7 @@ describe('Album service', () => {
const albumResponse: AddAssetsResponseDto = {
alreadyInAlbum: [],
successfullyAdded: 1
successfullyAdded: 1,
};
const albumId = albumEntity.id;

View File

@@ -13,6 +13,7 @@ import { AssetCountByUserIdResponseDto } from './response-dto/asset-count-by-use
import { CheckExistingAssetsDto } from './dto/check-existing-assets.dto';
import { CheckExistingAssetsResponseDto } from './response-dto/check-existing-assets-response.dto';
import { In } from 'typeorm/find-options/operator/In';
import { UpdateAssetDto } from './dto/update-asset.dto';
export interface IAssetRepository {
create(
@@ -22,6 +23,7 @@ export interface IAssetRepository {
mimeType: string,
checksum?: Buffer,
): Promise<AssetEntity>;
update(asset: AssetEntity, dto: UpdateAssetDto): Promise<AssetEntity>;
getAllByUserId(userId: string): Promise<AssetEntity[]>;
getAllByDeviceId(userId: string, deviceId: string): Promise<string[]>;
getById(assetId: string): Promise<AssetEntity>;
@@ -252,6 +254,15 @@ export class AssetRepository implements IAssetRepository {
return createdAsset;
}
/**
* Update asset
*/
async update(asset: AssetEntity, dto: UpdateAssetDto): Promise<AssetEntity> {
asset.isFavorite = dto.isFavorite ?? asset.isFavorite;
return await this.assetRepository.save(asset);
}
/**
* Get assets by device's Id on the database
* @param userId

View File

@@ -15,6 +15,7 @@ import {
BadRequestException,
UploadedFile,
Header,
Put,
} from '@nestjs/common';
import { Authenticated } from '../../decorators/authenticated.decorator';
import { AssetService } from './asset.service';
@@ -50,6 +51,7 @@ import { QueryFailedError } from 'typeorm';
import { AssetCountByUserIdResponseDto } from './response-dto/asset-count-by-user-id-response.dto';
import { CheckExistingAssetsDto } from './dto/check-existing-assets.dto';
import { CheckExistingAssetsResponseDto } from './response-dto/check-existing-assets-response.dto';
import { UpdateAssetDto } from './dto/update-asset.dto';
@Authenticated()
@ApiBearerAuth()
@@ -222,6 +224,18 @@ export class AssetController {
return await this.assetService.getAssetById(authUser, assetId);
}
/**
* Update an asset
*/
@Put('/assetById/:assetId')
async updateAssetById(
@GetAuthUser() authUser: AuthUserDto,
@Param('assetId') assetId: string,
@Body() dto: UpdateAssetDto,
): Promise<AssetResponseDto> {
return await this.assetService.updateAssetById(authUser, assetId, dto);
}
@Delete('/')
async deleteAsset(
@GetAuthUser() authUser: AuthUserDto,

View File

@@ -97,6 +97,7 @@ describe('AssetService', () => {
beforeAll(() => {
assetRepositoryMock = {
create: jest.fn(),
update: jest.fn(),
getAllByUserId: jest.fn(),
getAllByDeviceId: jest.fn(),
getAssetCountByTimeBucket: jest.fn(),

View File

@@ -1,6 +1,7 @@
import { CuratedLocationsResponseDto } from './response-dto/curated-locations-response.dto';
import {
BadRequestException,
ForbiddenException,
Inject,
Injectable,
InternalServerErrorException,
@@ -39,6 +40,7 @@ import { AssetCountByUserIdResponseDto } from './response-dto/asset-count-by-use
import { timeUtils } from '@app/common/utils';
import { CheckExistingAssetsDto } from './dto/check-existing-assets.dto';
import { CheckExistingAssetsResponseDto } from './response-dto/check-existing-assets-response.dto';
import { UpdateAssetDto } from './dto/update-asset.dto';
const fileInfo = promisify(stat);
@@ -123,6 +125,21 @@ export class AssetService {
return mapAsset(asset);
}
public async updateAssetById(authUser: AuthUserDto, assetId: string, dto: UpdateAssetDto): Promise<AssetResponseDto> {
const asset = await this._assetRepository.getById(assetId);
if (!asset) {
throw new BadRequestException('Asset not found');
}
if (authUser.id !== asset.userId) {
throw new ForbiddenException('Not the owner');
}
const updatedAsset = await this._assetRepository.update(asset, dto);
return mapAsset(updatedAsset);
}
public async downloadFile(query: ServeFileDto, res: Res) {
try {
let fileReadStream = null;

View File

@@ -0,0 +1,6 @@
import { IsBoolean } from 'class-validator';
export class UpdateAssetDto {
@IsBoolean()
isFavorite!: boolean;
}