From a590e4c7d462ecca6798da3782e520d19bb8f3f8 Mon Sep 17 00:00:00 2001 From: topchetoeu <36534413+TopchetoEU@users.noreply.github.com> Date: Sat, 1 Jul 2023 01:48:24 +0300 Subject: [PATCH] feat: add likes page --- backend/routers/ImageRouter.ts | 16 +++++++- frontend/src/app/app-routing.module.ts | 2 + frontend/src/app/app.module.ts | 2 + .../app/page-likes/page-likes.component.html | 4 ++ .../app/page-likes/page-likes.component.scss | 0 .../app/page-likes/page-likes.component.ts | 40 +++++++++++++++++++ .../app/page-user/page-user.component.html | 3 +- frontend/src/app/services/images.service.ts | 5 +++ 8 files changed, 69 insertions(+), 3 deletions(-) create mode 100644 frontend/src/app/page-likes/page-likes.component.html create mode 100644 frontend/src/app/page-likes/page-likes.component.scss create mode 100644 frontend/src/app/page-likes/page-likes.component.ts diff --git a/backend/routers/ImageRouter.ts b/backend/routers/ImageRouter.ts index 4a55a30..bcd3156 100644 --- a/backend/routers/ImageRouter.ts +++ b/backend/routers/ImageRouter.ts @@ -71,6 +71,18 @@ export default class ImageRouter extends AppRouter { return (await page.apply(cursor.sort({ created: -1 })).toArray()).map(v => ImageRouter.deserialize(v, jwt?.name)); } + @rest('GET', '/likes/:username') + async likeFeed(username: string, @page() page: Page, @jwt('salt', false) @auth() jwt?: JWTPayload) { + const user = await this.db.users.findOne({ username }); + if (user === undefined) throw new HttpError("User not found."); + + const cursor = this.db.images.find({ $or: [ + { _id: { $in: user.likes }, visibility: Visibility.Public, }, + { _id: { $in: user.likes }, author: user.username, } + ] }); + + return (await page.apply(cursor.sort({ created: -1 })).toArray()).map(v => ImageRouter.deserialize(v, jwt?.name)); + } @rest('POST', '/upload') async upload(@body() body: Blob, @headers() headers: Headers, @jwt(v => v.salt, true) @auth() jwt: JWTPayload) { @@ -172,7 +184,7 @@ export default class ImageRouter extends AppRouter { if (!user) throw new HttpError("You don't exist."); const res = await this.db.images.updateOne( - { _id: id }, + { _id: id, visibility: { $not: { $eq: Visibility.Private } } }, { $addToSet: { likes: jwt.name } } ); if (res.matchedCount === 0) throw new HttpError("Image doesn't exist."); @@ -190,7 +202,7 @@ export default class ImageRouter extends AppRouter { if (!user) throw new HttpError("You don't exist."); const res = await this.db.images.updateOne( - { _id: id }, + { _id: id, visibility: { $not: { $eq: Visibility.Private } } }, { $pull: { likes: jwt.name } } ); if (res.matchedCount === 0) throw new HttpError("Image doesn't exist."); diff --git a/frontend/src/app/app-routing.module.ts b/frontend/src/app/app-routing.module.ts index 84860c8..d54e83c 100644 --- a/frontend/src/app/app-routing.module.ts +++ b/frontend/src/app/app-routing.module.ts @@ -6,6 +6,7 @@ import { PageSignupComponent } from './page-signup/page-signup.component'; import { PageUploadComponent } from './page-upload/page-upload.component'; import { PageUserComponent } from './page-user/page-user.component'; import { PageImageComponent } from './page-image/page-image.component'; +import { PageLikesComponent } from './page-likes/page-likes.component'; const routes: Routes = [ { path: '', component: PageHomeComponent }, @@ -13,6 +14,7 @@ const routes: Routes = [ { path: 'signup', component: PageSignupComponent }, { path: 'upload', component: PageUploadComponent }, { path: 'user/:name', component: PageUserComponent }, + { path: 'likes/:name', component: PageLikesComponent }, { path: 'image/:id', component: PageImageComponent }, ]; diff --git a/frontend/src/app/app.module.ts b/frontend/src/app/app.module.ts index c98f792..6cee781 100644 --- a/frontend/src/app/app.module.ts +++ b/frontend/src/app/app.module.ts @@ -16,6 +16,7 @@ import { MessageComponent } from './message/message.component'; import { PageImageComponent } from './page-image/page-image.component'; import { SecurePipe } from './secure.pipe'; import { AuthorizerInterceptor } from './authorizer.interceptor'; +import { PageLikesComponent } from './page-likes/page-likes.component'; @NgModule({ declarations: [ @@ -25,6 +26,7 @@ import { AuthorizerInterceptor } from './authorizer.interceptor'; PageSignupComponent, PageUploadComponent, PageUserComponent, + PageLikesComponent, ImagesComponent, ImageComponent, MessageComponent, diff --git a/frontend/src/app/page-likes/page-likes.component.html b/frontend/src/app/page-likes/page-likes.component.html new file mode 100644 index 0000000..9a228d7 --- /dev/null +++ b/frontend/src/app/page-likes/page-likes.component.html @@ -0,0 +1,4 @@ +

User {{user.username}}'s likes:

+Go to posts + + diff --git a/frontend/src/app/page-likes/page-likes.component.scss b/frontend/src/app/page-likes/page-likes.component.scss new file mode 100644 index 0000000..e69de29 diff --git a/frontend/src/app/page-likes/page-likes.component.ts b/frontend/src/app/page-likes/page-likes.component.ts new file mode 100644 index 0000000..c9fdda5 --- /dev/null +++ b/frontend/src/app/page-likes/page-likes.component.ts @@ -0,0 +1,40 @@ +import { AfterViewInit, Component, ViewChild } from '@angular/core'; +import { ActivatedRoute } from '@angular/router'; +import { User, UsersService } from '../services/users.service'; +import { Image, ImagesService } from '../services/images.service'; +import { ImagesComponent } from '../images/images.component'; +import { ScrollService } from '../services/scroll.service'; +import { Observable } from 'rxjs'; +import { MessagesService } from '../services/messages.service'; + +@Component({ + selector: 'app-page-likes', + templateUrl: './page-likes.component.html', + styleUrls: ['./page-likes.component.scss'] +}) +export class PageLikesComponent { + @ViewChild("imgs") + public imagesEl!: ImagesComponent; + public images!: Observable; + public user: User = { username: 'Loading...' }; + + public feed(n: number, i: number) { + return this._images.likesFeed(this.user.username, { n, i }); + } + + public constructor( + route: ActivatedRoute, + users: UsersService, + private _images: ImagesService, + private _scroll: ScrollService, + private msgs: MessagesService, + ) { + route.paramMap.subscribe(async v => { + try { + this.user = await users.get(v.get('name')!); + this.images = ImagesComponent.fromFeed(this._scroll.scrollHost!, 10, this.feed.bind(this)); + } + catch (e: any) { msgs.error(e); } + }); + } +} diff --git a/frontend/src/app/page-user/page-user.component.html b/frontend/src/app/page-user/page-user.component.html index ce66b99..064cb64 100644 --- a/frontend/src/app/page-user/page-user.component.html +++ b/frontend/src/app/page-user/page-user.component.html @@ -1,3 +1,4 @@ -

User {{user.username}}

+

User {{user.username}}'s posts:

+Go to likes diff --git a/frontend/src/app/services/images.service.ts b/frontend/src/app/services/images.service.ts index 1016a80..b59e529 100644 --- a/frontend/src/app/services/images.service.ts +++ b/frontend/src/app/services/images.service.ts @@ -47,6 +47,11 @@ export class ImagesService { this.users.httpOptions({ params: page }) )); } + public async likesFeed(username: string, page: Page = {}) { + return await firstValueFrom(this.http.get(`${this.url}/likes/${username}`, + this.users.httpOptions({ params: page }) + )); + } public async upload(proto: CreateImageBody, file: File) { const data = new FormData();