From ca2a76363635433efcd602ab34b6ac23a1969526 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Benedek=20L=C3=A1szl=C3=B3?= Date: Thu, 9 May 2024 23:02:55 +0200 Subject: [PATCH] likes --- src/app/services/data/post.service.ts | 129 +++++++++++++----- src/app/services/data/user.service.ts | 14 +- .../shared/side-menu/side-menu.component.scss | 9 ++ .../large-user/large-user.component.html | 5 +- .../large-user/large-user.component.scss | 1 + src/app/shared/views/post/post.component.html | 2 +- src/app/shared/views/post/post.component.ts | 10 +- .../small-user/small-user.component.html | 3 +- .../small-user/small-user.component.scss | 1 + 9 files changed, 133 insertions(+), 41 deletions(-) diff --git a/src/app/services/data/post.service.ts b/src/app/services/data/post.service.ts index 9cffea8..a5de58c 100644 --- a/src/app/services/data/post.service.ts +++ b/src/app/services/data/post.service.ts @@ -4,39 +4,49 @@ import { AuthService } from '../auth/auth.service'; import { AngularFirestore, Reference } from '@angular/fire/compat/firestore'; import { User } from '../../../model/User'; import { UserService } from './user.service'; -import { user } from '@angular/fire/auth'; +import { DocumentReference } from '@angular/fire/firestore'; @Injectable({ providedIn: 'root' }) export class PostService { - constructor(private auth: AuthService, private afs: AngularFirestore) { } + constructor(private auth: AuthService, private afs: AngularFirestore, private usersvc: UserService) { } getFeed(length: Number, start: Number): Promise> { return new Promise>((resolve, reject) => { - let posts = Array(); + let result = Array(); if (this.auth.checkAllowed()) { - this.afs.collection('post').valueChanges({idField: 'id'}).subscribe(data => { - data.forEach(i => { - this.afs.doc((i as any).user).valueChanges().subscribe(user => { - posts.push({ - user: { - username: (user as User).username, - email: (user as User).email, - picture: (user as User).picture, - followed: (user as User).followed - }, - content: i.content, - image: i.image, - likes: i.likes, - liked: i.liked, - id: i.id - }) + this.usersvc.getCurrentUser() + .then(currentUser => { + // get posts + this.afs.collection('post').valueChanges({ idField: 'id' }).subscribe(posts => { + posts.forEach(post => { + // get the user who made this post + this.afs.doc((post as any).user).valueChanges().subscribe(user => { + // get how many likes it has + this.afs.collection('like', ref => ref.where('post', '==', this.afs.doc('/post/' + post.id).ref)).valueChanges().subscribe(likes => { + // check if we liked this post + let liked: boolean = likes.filter(like => (like as any).user.id == currentUser.username).length != 0; + result.push({ + user: { + username: (user as User).username, + email: (user as User).email, + picture: (user as User).picture, + followed: (user as User).followed + }, + content: post.content, + image: post.image, + likes: likes.length, + liked: liked, + id: post.id + }) + }) + }); + }); + resolve(result); }); - }); - resolve(posts); - }); + }) } else { reject() } @@ -48,24 +58,42 @@ export class PostService { if (this.auth.checkAllowed()) { if (username == undefined) { this.auth.getUser().subscribe(cred => { + // get the user by id this.afs.collection('user', ref => ref.where('id', '==', cred?.uid)).valueChanges().subscribe(user => { - this.afs.collection('post', ref => ref.where('user', '==', this.afs.doc('/user/' + user[0].username).ref)).valueChanges({idField:'id'}).subscribe(data => { - data.forEach(i => { - i.user = user[0] as User; + // get their posts + this.afs.collection('post', ref => ref.where('user', '==', this.afs.doc('/user/' + user[0].username).ref)).valueChanges({ idField: 'id' }).subscribe(posts => { + posts.forEach(post => { + // get how many likes it has + this.afs.collection('like', ref => ref.where('post', '==', this.afs.doc('/post/' + post.id).ref)).valueChanges().subscribe(likes => { + // check if we liked this post + post.liked = likes.filter(like => (like as any).user.id == user[0].username).length != 0; + post.user = user[0] as User; + post.likes = likes.length; + }) + resolve(posts) }) - resolve(data) }); }) }); } else { - this.afs.collection('user').doc(username as string).valueChanges().subscribe(user => { - this.afs.collection('post', ref => ref.where('user', '==', this.afs.doc('/user/' + username).ref)).valueChanges({idField:'id'}).subscribe(data => { - data.forEach(i => { - i.user = user as User; - }) - resolve(data) - }); - }); + this.usersvc.getCurrentUser() + .then(currentUser => { + // get the user by username + this.afs.collection('user').doc(username as string).valueChanges().subscribe(user => { + // get their posts + this.afs.collection('post', ref => ref.where('user', '==', this.afs.doc('/user/' + username).ref)).valueChanges({ idField: 'id' }).subscribe(posts => { + posts.forEach(post => { + // get how many likes it has + this.afs.collection('like', ref => ref.where('post', '==', this.afs.doc('/post/' + post.id).ref)).valueChanges().subscribe(likes => { + post.liked = likes.filter(like => (like as any).user.id == currentUser.username).length != 0; + post.user = user as User; + post.likes = likes.length; + }) + resolve(posts) + }) + }); + }); + }) } } else { reject() @@ -96,6 +124,37 @@ export class PostService { } removePost(id: String) { - return this.afs.doc('/post/'+id).delete(); + return this.afs.doc('/post/' + id).delete(); + } + + toggleLike(postId: String): Promise { + return new Promise((resolve, reject) => { + if (this.auth.checkAllowed()) { + this.usersvc.getCurrentUser() + .then(user => { + let userRef = this.afs.doc('/user/' + user.username).ref; + let postRef = this.afs.doc('/post/' + postId).ref; + this.afs.collection('like', ref => ref.where('user', '==', userRef).where('post', '==', postRef)).get().subscribe(likes => { + if (likes.docs.length == 0) { + // like + this.afs.collection('like').add({ + user: userRef, + post: postRef + }) + resolve(true); + } else { + // dislike + likes.docs.forEach(likes => { + likes.ref.delete() + }) + resolve(false); + } + }) + }) + .catch(() => reject()) + } else { + reject(); + } + }); } } diff --git a/src/app/services/data/user.service.ts b/src/app/services/data/user.service.ts index f3ca9a8..46e54c4 100644 --- a/src/app/services/data/user.service.ts +++ b/src/app/services/data/user.service.ts @@ -2,7 +2,6 @@ import { Injectable } from '@angular/core'; import { User } from '../../../model/User'; import { AuthService } from '../auth/auth.service'; import { AngularFirestore } from '@angular/fire/compat/firestore'; -import { user } from '@angular/fire/auth'; @Injectable({ providedIn: 'root' @@ -26,6 +25,19 @@ export class UserService { }); } + getCurrentUser(): Promise { + return new Promise((resolve,reject)=>{ + this.auth.getUser().subscribe(user => { + this.afs.collection('user', ref => ref.where('id', '==', user?.uid)).valueChanges().subscribe(users=>{ + if (users.length != 0) + resolve(users[0]); + else + reject(); + }) + }); + }); + } + createUser(username: String, email: String, id: String) { return new Promise((resolve, reject) => { this.afs.collection('user').doc(username as string).set({ diff --git a/src/app/shared/side-menu/side-menu.component.scss b/src/app/shared/side-menu/side-menu.component.scss index 33671be..ff3680d 100644 --- a/src/app/shared/side-menu/side-menu.component.scss +++ b/src/app/shared/side-menu/side-menu.component.scss @@ -5,4 +5,13 @@ mat-sidenav { button { display: block; margin: 10px auto; +} + +app-side-menu { + height: 100%; + display: block; +} + +mat-sidenav-container { + height: 100%; } \ No newline at end of file diff --git a/src/app/shared/views/large-user/large-user.component.html b/src/app/shared/views/large-user/large-user.component.html index d414be0..7b881af 100644 --- a/src/app/shared/views/large-user/large-user.component.html +++ b/src/app/shared/views/large-user/large-user.component.html @@ -1,6 +1,7 @@
- {{user?.username}} + + {{user?.username}}
- +
\ No newline at end of file diff --git a/src/app/shared/views/large-user/large-user.component.scss b/src/app/shared/views/large-user/large-user.component.scss index afdbc93..985aa3b 100644 --- a/src/app/shared/views/large-user/large-user.component.scss +++ b/src/app/shared/views/large-user/large-user.component.scss @@ -16,6 +16,7 @@ } span { + margin: 20px auto; display: block; width: 100%; text-align: center; diff --git a/src/app/shared/views/post/post.component.html b/src/app/shared/views/post/post.component.html index 4c7faa9..ae21437 100644 --- a/src/app/shared/views/post/post.component.html +++ b/src/app/shared/views/post/post.component.html @@ -3,7 +3,7 @@
{{post?.content}}
- {{post?.likes}} + {{post?.likes}}
\ No newline at end of file diff --git a/src/app/shared/views/post/post.component.ts b/src/app/shared/views/post/post.component.ts index 5d0e787..fdd1ce0 100644 --- a/src/app/shared/views/post/post.component.ts +++ b/src/app/shared/views/post/post.component.ts @@ -14,7 +14,6 @@ import { PostService } from '../../../services/data/post.service'; styleUrl: './post.component.scss' }) export class PostComponent implements OnInit { - @Input() post: Post | undefined; isOwned: boolean = false; @@ -38,4 +37,13 @@ export class PostComponent implements OnInit { alert("failed to delete post"); }) } + + like() { + this.postSv.toggleLike(this.post?.id as String) + .then((result)=>{ + ((this.post as Post).likes as number) += result ? 1 : -1; + (this.post as Post).liked = result; + }) + .catch(()=>{alert('failed to toggle like on post')}) + } } diff --git a/src/app/shared/views/small-user/small-user.component.html b/src/app/shared/views/small-user/small-user.component.html index 542bc53..0366cda 100644 --- a/src/app/shared/views/small-user/small-user.component.html +++ b/src/app/shared/views/small-user/small-user.component.html @@ -1,3 +1,4 @@
- {{user?.username}} + + {{user?.username}}
\ No newline at end of file diff --git a/src/app/shared/views/small-user/small-user.component.scss b/src/app/shared/views/small-user/small-user.component.scss index 072df0e..1d0ad07 100644 --- a/src/app/shared/views/small-user/small-user.component.scss +++ b/src/app/shared/views/small-user/small-user.component.scss @@ -12,6 +12,7 @@ img { span { display: inline-block; + margin: 20px auto; padding-left: 10px; transform: translateY(-60%); }