diff options
| author | Syndamia <kamen.d.mladenov@protonmail.com> | 2021-03-21 16:32:44 +0200 |
|---|---|---|
| committer | Syndamia <kamen.d.mladenov@protonmail.com> | 2021-03-21 16:32:44 +0200 |
| commit | 0a16705c40735e81afa1f3d58c7cba224f46dbcd (patch) | |
| tree | b34ce40ce9ec2070f3f60a46016ec73f1e3221a6 /src | |
| parent | 0133f3b5e9086fba5006314c183451974d50502c (diff) | |
| download | DevHive-Angular-0a16705c40735e81afa1f3d58c7cba224f46dbcd.tar DevHive-Angular-0a16705c40735e81afa1f3d58c7cba224f46dbcd.tar.gz DevHive-Angular-0a16705c40735e81afa1f3d58c7cba224f46dbcd.zip | |
Implemented (moved from post page) functionality for editing and deleting your posts into post component
Diffstat (limited to 'src')
| -rw-r--r-- | src/app/components/post-page/post-page.component.ts | 46 | ||||
| -rw-r--r-- | src/app/components/post/post.component.css | 21 | ||||
| -rw-r--r-- | src/app/components/post/post.component.html | 38 | ||||
| -rw-r--r-- | src/app/components/post/post.component.ts | 82 | ||||
| -rw-r--r-- | src/assets/icons/tabler-icon-edit.svg | 76 | ||||
| -rw-r--r-- | src/assets/icons/tabler-icon-trash.svg | 90 |
6 files changed, 304 insertions, 49 deletions
diff --git a/src/app/components/post-page/post-page.component.ts b/src/app/components/post-page/post-page.component.ts index e159c69..0babfdf 100644 --- a/src/app/components/post-page/post-page.component.ts +++ b/src/app/components/post-page/post-page.component.ts @@ -7,7 +7,6 @@ import { CommentService } from 'src/app/services/comment.service'; import { PostService } from 'src/app/services/post.service'; import { TokenService } from 'src/app/services/token.service'; import { Post } from 'src/models/post.model'; -import { CloudinaryService } from 'src/app/services/cloudinary.service'; @Component({ selector: 'app-post-page', @@ -18,22 +17,17 @@ export class PostPageComponent implements OnInit { private _title = 'Post'; public dataArrived = false; public loggedIn = false; - public editable = false; - public editingPost = false; public postId: Guid; public post: Post; - public files: File[]; - public editPostFormGroup: FormGroup; public addCommentFormGroup: FormGroup; - constructor(private _titleService: Title, private _router: Router, private _fb: FormBuilder, private _tokenService: TokenService, private _postService: PostService, private _commentService: CommentService, private _cloudinaryService: CloudinaryService){ + constructor(private _titleService: Title, private _router: Router, private _fb: FormBuilder, private _tokenService: TokenService, private _postService: PostService, private _commentService: CommentService) { this._titleService.setTitle(this._title); } ngOnInit(): void { this.loggedIn = this._tokenService.getTokenFromSessionStorage() !== ''; this.postId = Guid.parse(this._router.url.substring(6)); - this.files = []; // Gets the post and the logged in user and compares them, // to determine if the current post is made by the user @@ -41,52 +35,19 @@ export class PostPageComponent implements OnInit { next: (result: object) => { this.post = result as Post; this.post.fileURLs = Object.values(result)[7]; - if (this.loggedIn) { - this.editable = this.post.creatorUsername === this._tokenService.getUsernameFromSessionStorageToken(); - this.editPostFormGroup.get('newPostMessage')?.setValue(this.post.message); - } - if (this.post.fileURLs.length > 0) { - this.loadFiles(); - } - else { - this.dataArrived = true; - } + + this.dataArrived = true; }, error: () => { this._router.navigate(['/not-found']); } }); - this.editPostFormGroup = this._fb.group({ - newPostMessage: new FormControl(''), - fileUpload: new FormControl('') - }); - this.addCommentFormGroup = this._fb.group({ newComment: new FormControl('') }); } - private loadFiles(): void { - for (const fileURL of this.post.fileURLs) { - this._cloudinaryService.getFileRequest(fileURL).subscribe({ - next: (result: object) => { - const file = result as File; - const tmp = { - name: fileURL.match('(?<=\/)(?:.(?!\/))+$')?.pop() ?? 'Attachment' - }; - - Object.assign(file, tmp); - this.files.push(file); - - if (this.files.length === this.post.fileURLs.length) { - this.dataArrived = true; - } - } - }); - } - } - addComment(): void { if (!this.loggedIn) { this._router.navigate(['/login']); @@ -97,7 +58,6 @@ export class PostPageComponent implements OnInit { if (newComment !== '' && newComment !== null) { this._commentService.createCommentWithSessionStorageRequest(this.postId, newComment).subscribe({ next: () => { - this.editPostFormGroup.reset(); this.reloadPage(); } }); diff --git a/src/app/components/post/post.component.css b/src/app/components/post/post.component.css index c5919fd..1015564 100644 --- a/src/app/components/post/post.component.css +++ b/src/app/components/post/post.component.css @@ -32,3 +32,24 @@ height: 1.2em; width: 1.2em; } + +/* Edit */ + +#attachments-btns img, .file-button > input { + height: 1.4em; + width: 1.4em; +} + +.file-button { + position: relative; +} + +.file-button > img { + position: absolute; + pointer-events: none; +} + +.file-button > input { + font-size: inherit; + color: transparent; +} diff --git a/src/app/components/post/post.component.html b/src/app/components/post/post.component.html index 133b747..1831c5e 100644 --- a/src/app/components/post/post.component.html +++ b/src/app/components/post/post.component.html @@ -13,14 +13,36 @@ @{{ user.userName }} </span> </summary> - <article class="message margin-top-bot-small"> + <article class="message margin-top-bot-small" *ngIf="!editingPost"> {{ post.message }} </article> - <section class="flex-row flexible-children"> + <section class="flex-row flexible-children" *ngIf="!editingPost"> <figure *ngFor="let fileURL of post.fileURLs"> <app-post-attachment [paramURL]="fileURL"></app-post-attachment> </figure> </section> + <form [formGroup]="editPostFormGroup" *ngIf="editingPost"> + <textarea class="textarea-new-msg full-width faded-slim-border border-bottom-only padding-small" rows="1" formControlName="newPostMessage" placeholder="What's on your mind?"></textarea> + <section class="flex-row flex-justify-start flex-center-align-children top-bot-padding-bigger"> + <div class="file-button hover-half-opacity click-effect"> + <img src="/assets/icons/tabler-icon-paperclip.svg"> + <input type="file" formControlName="fileUpload" (change)="onFileUpload($event)" multiple> + </div> + </section> + </form> + <section class="flex-row bot-padding-bigger" *ngIf="editingPost"> + <div *ngFor="let file of files" class="form-attachment faded-slim-border flexible flex-row flex-no-wrap flex-center-align-items padding-small margin-top-bot-small"> + <div class="flexible"> + {{ file.name ? file.name : 'Attachment' }} + </div> + <div class="flex-col hover-half-opacity border-radius-small click-effect" (click)="removeAttachment(file.name)"> + <img src="/assets/icons/tabler-icon-x.svg"> + </div> + </div> + </section> + <button class="faded-slim-border full-width padding-small lighter-hover click-effect border-radius-smaller margin-bot-bigger" *ngIf="editingPost" (click)="editPost()"> + Update Post + </button> <section class="post-details flex-row flex-justify-end font-size-dot7 faded-slim-border border-bottom-only"> <time class="flex-row flex-center-align-items"> <img class="img-height-font-size" src="/assets/icons/tabler-icon-calendar-time.svg"> @@ -35,15 +57,21 @@ </span> </summary> </section> - <section class="flex-row flexible-children justify-children-center flex-center-align-children"> - <button class="padding-small lighter-hover click-effect border-radius-smaller" (click)="goToPostPage()"> + <section class="flex-row justify-children-center flex-center-align-children"> + <button class="padding-small lighter-hover click-effect border-radius-smaller" (click)="toggleEditing()"> + <img src="/assets/icons/tabler-icon-edit.svg"> + </button> + <button class="flexible padding-small lighter-hover click-effect border-radius-smaller" (click)="goToPostPage()"> <img src="/assets/icons/tabler-icon-message-2.svg"> Comment </button> - <button class="padding-small lighter-hover click-effect border-radius-smaller" (click)="goToPostPage()"> + <button class="flexible padding-small lighter-hover click-effect border-radius-smaller" (click)="goToPostPage()"> <img src="/assets/icons/tabler-icon-link.svg"> Share </button> + <button class="padding-small lighter-hover click-effect border-radius-smaller" (click)="deletePost()"> + <img src="/assets/icons/tabler-icon-trash.svg"> + </button> </section> </main> <aside class="rating flex-col flex-center-align-items"> diff --git a/src/app/components/post/post.component.ts b/src/app/components/post/post.component.ts index 58dad4f..5c79658 100644 --- a/src/app/components/post/post.component.ts +++ b/src/app/components/post/post.component.ts @@ -1,6 +1,8 @@ import { Component, Input, OnInit } from '@angular/core'; +import { FormBuilder, FormControl, FormGroup } from '@angular/forms'; import { Router } from '@angular/router'; import { Guid } from 'guid-typescript'; +import { CloudinaryService } from 'src/app/services/cloudinary.service'; import { PostService } from 'src/app/services/post.service'; import { RatingService } from 'src/app/services/rating.service'; import { UserService } from 'src/app/services/user.service'; @@ -22,10 +24,14 @@ export class PostComponent implements OnInit { @Input() paramId: string; @Input() index: number; public loggedIn = false; + public loggedInAuthor = false; + public editingPost = false; + public files: File[]; + public editPostFormGroup: FormGroup; private upvoteBtns: HTMLCollectionOf<HTMLElement>; private downvoteBtns: HTMLCollectionOf<HTMLElement>; - constructor(private _postService: PostService, private _ratingServe: RatingService, private _userService: UserService, private _router: Router, private _tokenService: TokenService) + constructor(private _postService: PostService, private _ratingServe: RatingService, private _userService: UserService, private _router: Router, private _tokenService: TokenService, private _cloudinaryService: CloudinaryService, private _fb: FormBuilder) { } ngOnInit(): void { @@ -33,6 +39,7 @@ export class PostComponent implements OnInit { this.post = this._postService.getDefaultPost(); this.user = this._userService.getDefaultUser(); + this.files = []; this._postService.getPostRequest(Guid.parse(this.paramId)).subscribe({ next: (result: object) => { @@ -49,6 +56,11 @@ export class PostComponent implements OnInit { this.loadUser(); } }); + + this.editPostFormGroup = this._fb.group({ + newPostMessage: new FormControl(''), + fileUpload: new FormControl('') + }); } private loadUser(): void { @@ -58,6 +70,14 @@ export class PostComponent implements OnInit { if (this.loggedIn) { this.highlightButtonsOnInit(); + + this.loggedInAuthor = this._tokenService.getUsernameFromSessionStorageToken() === this.post.creatorUsername; + this.editPostFormGroup.get('newPostMessage')?.setValue(this.post.message); + + if (this.post.fileURLs.length > 0) { + this.loadFiles(); + return; + } } this.loaded = true; @@ -65,6 +85,26 @@ export class PostComponent implements OnInit { }); } + private loadFiles(): void { + for (const fileURL of this.post.fileURLs) { + this._cloudinaryService.getFileRequest(fileURL).subscribe({ + next: (result: object) => { + const file = result as File; + const tmp = { + name: fileURL.match('(?<=\/)(?:.(?!\/))+$')?.pop() ?? 'Attachment' + }; + + Object.assign(file, tmp); + this.files.push(file); + + if (this.files.length === this.post.fileURLs.length) { + this.loaded = true; + } + } + }); + } + } + goToAuthorProfile(): void { this._router.navigate(['/profile/' + this.user.userName]); } @@ -73,6 +113,46 @@ export class PostComponent implements OnInit { this._router.navigate(['/post/' + this.post.postId]); } + toggleEditing(): void { + this.editingPost = !this.editingPost; + } + + onFileUpload(event: any): void { + this.files.push(...event.target.files); + this.editPostFormGroup.get('fileUpload')?.reset(); + } + + removeAttachment(fileName: string): void { + this.files = this.files.filter(x => x.name !== fileName); + } + + editPost(): void { + const newMessage = this.editPostFormGroup.get('newPostMessage')?.value; + + if (newMessage !== '') { + this._postService.putPostWithSessionStorageRequest(Guid.parse(this.paramId), newMessage, this.files).subscribe({ + next: () => { + this.reloadPage(); + } + }); + this.loaded = false; + } + } + + deletePost(): void { + this._postService.deletePostWithSessionStorage(Guid.parse(this.paramId)).subscribe({ + next: () => { + this._router.navigate(['/profile/' + this._tokenService.getUsernameFromSessionStorageToken()]); + } + }); + } + + private reloadPage(): void { + this._router.routeReuseStrategy.shouldReuseRoute = () => false; + this._router.onSameUrlNavigation = 'reload'; + this._router.navigate([this._router.url]); + } + votePost(isLike: boolean): void { if (!this.loggedIn) { this._router.navigate(['/login']); diff --git a/src/assets/icons/tabler-icon-edit.svg b/src/assets/icons/tabler-icon-edit.svg new file mode 100644 index 0000000..e12e396 --- /dev/null +++ b/src/assets/icons/tabler-icon-edit.svg @@ -0,0 +1,76 @@ +<?xml version="1.0" encoding="UTF-8" standalone="no"?> +<svg + xmlns:dc="http://purl.org/dc/elements/1.1/" + xmlns:cc="http://creativecommons.org/ns#" + xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" + xmlns:svg="http://www.w3.org/2000/svg" + xmlns="http://www.w3.org/2000/svg" + xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" + xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" + class="icon icon-tabler icon-tabler-edit" + width="24" + height="24" + viewBox="0 0 24 24" + stroke-width="2" + stroke="currentColor" + fill="none" + stroke-linecap="round" + stroke-linejoin="round" + version="1.1" + id="svg10" + sodipodi:docname="tabler-icon-edit.svg" + inkscape:version="1.0.2 (e86c870879, 2021-01-15)"> + <metadata + id="metadata16"> + <rdf:RDF> + <cc:Work + rdf:about=""> + <dc:format>image/svg+xml</dc:format> + <dc:type + rdf:resource="http://purl.org/dc/dcmitype/StillImage" /> + </cc:Work> + </rdf:RDF> + </metadata> + <defs + id="defs14" /> + <sodipodi:namedview + pagecolor="#ffffff" + bordercolor="#666666" + borderopacity="1" + objecttolerance="10" + gridtolerance="10" + guidetolerance="10" + inkscape:pageopacity="0" + inkscape:pageshadow="2" + inkscape:window-width="1920" + inkscape:window-height="1053" + id="namedview12" + showgrid="false" + inkscape:zoom="37.541667" + inkscape:cx="12" + inkscape:cy="12" + inkscape:window-x="0" + inkscape:window-y="0" + inkscape:window-maximized="1" + inkscape:current-layer="svg10" /> + <path + stroke="none" + d="M0 0h24v24H0z" + fill="none" + id="path2" /> + <path + d="M 9,7 H 6 A 2,2 0 0 0 4,9 v 9 a 2,2 0 0 0 2,2 h 9 a 2,2 0 0 0 2,-2 v -3" + id="path4" + style="stroke:#ffeede" /> + <path + d="m 9,15 h 3 l 8.5,-8.5 a 2.1213203,2.1213203 0 0 0 -3,-3 L 9,12 v 3" + id="path6" + style="stroke:#ffeede" /> + <line + x1="16" + y1="5" + x2="19" + y2="8" + id="line8" + style="stroke:#ffeede" /> +</svg> diff --git a/src/assets/icons/tabler-icon-trash.svg b/src/assets/icons/tabler-icon-trash.svg new file mode 100644 index 0000000..eee68f7 --- /dev/null +++ b/src/assets/icons/tabler-icon-trash.svg @@ -0,0 +1,90 @@ +<?xml version="1.0" encoding="UTF-8" standalone="no"?> +<svg + xmlns:dc="http://purl.org/dc/elements/1.1/" + xmlns:cc="http://creativecommons.org/ns#" + xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" + xmlns:svg="http://www.w3.org/2000/svg" + xmlns="http://www.w3.org/2000/svg" + xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" + xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" + class="icon icon-tabler icon-tabler-trash" + width="24" + height="24" + viewBox="0 0 24 24" + stroke-width="2" + stroke="currentColor" + fill="none" + stroke-linecap="round" + stroke-linejoin="round" + version="1.1" + id="svg14" + sodipodi:docname="tabler-icon-trash.svg" + inkscape:version="1.0.2 (e86c870879, 2021-01-15)"> + <metadata + id="metadata20"> + <rdf:RDF> + <cc:Work + rdf:about=""> + <dc:format>image/svg+xml</dc:format> + <dc:type + rdf:resource="http://purl.org/dc/dcmitype/StillImage" /> + </cc:Work> + </rdf:RDF> + </metadata> + <defs + id="defs18" /> + <sodipodi:namedview + pagecolor="#ffffff" + bordercolor="#666666" + borderopacity="1" + objecttolerance="10" + gridtolerance="10" + guidetolerance="10" + inkscape:pageopacity="0" + inkscape:pageshadow="2" + inkscape:window-width="1920" + inkscape:window-height="1053" + id="namedview16" + showgrid="false" + inkscape:zoom="37.541667" + inkscape:cx="12" + inkscape:cy="12" + inkscape:window-x="0" + inkscape:window-y="0" + inkscape:window-maximized="1" + inkscape:current-layer="svg14" /> + <path + stroke="none" + d="M0 0h24v24H0z" + fill="none" + id="path2" /> + <line + x1="4" + y1="7" + x2="20" + y2="7" + id="line4" + style="stroke:#ffeede" /> + <line + x1="10" + y1="11" + x2="10" + y2="17" + id="line6" + style="stroke:#ffeede" /> + <line + x1="14" + y1="11" + x2="14" + y2="17" + id="line8" + style="stroke:#ffeede" /> + <path + d="m 5,7 1,12 a 2,2 0 0 0 2,2 h 8 a 2,2 0 0 0 2,-2 L 19,7" + id="path10" + style="stroke:#ffeede" /> + <path + d="M 9,7 V 4 a 1,1 0 0 1 1,-1 h 4 a 1,1 0 0 1 1,1 v 3" + id="path12" + style="stroke:#ffeede" /> +</svg> |
