diff --git a/src/app/app-routing.module.ts b/src/app/app-routing.module.ts index 7fc01ea..2a390dc 100644 --- a/src/app/app-routing.module.ts +++ b/src/app/app-routing.module.ts @@ -2,6 +2,7 @@ import { NgModule } from '@angular/core'; import { Routes, RouterModule } from '@angular/router'; import { AuthGuard, AuthUpdateGuard, AuthenticatedGuard, AnonymousGuard } from './auth/auth.guard'; +import { PageBookmarks } from './pages/bookmarks/bookmarks.page'; import { PageEntry } from './pages/entry/entry.page'; import { PageLogin } from './pages/login/login.page'; import { PageNew } from './pages/new/new.page'; @@ -18,6 +19,7 @@ const routes: Routes = [ { path: '', component: PageTop, canActivate: [ AuthenticatedGuard ] }, { path: 'e/:id', component: PageEntry, canActivate: [ AuthenticatedGuard ] }, { path: 'new', component: PageNew, canActivate: [ AuthenticatedGuard ] }, + { path: 'bookmarks', component: PageBookmarks, canActivate: [ AuthenticatedGuard ] }, { path: 'submit', component: PageSubmission, canActivate: [ AuthenticatedGuard ] }, { path: 'login', component: PageLogin, canActivate: [ AnonymousGuard ] }, { path: 'settings', component: PageSettings, canActivate: [ AuthenticatedGuard ] }, diff --git a/src/app/app.module.ts b/src/app/app.module.ts index b441d76..4248ab9 100644 --- a/src/app/app.module.ts +++ b/src/app/app.module.ts @@ -17,6 +17,7 @@ import { AutofocusDirective } from './material/autofocus'; import { I18nPipe } from './utils/i18n.pipe'; import { MomentPipe } from './utils/moment.pipe'; import { AppComponent } from './app.component'; +import { PageBookmarks } from './pages/bookmarks/bookmarks.page'; import { PageEntry } from './pages/entry/entry.page'; import { PageLogin } from './pages/login/login.page'; import { PageNew } from './pages/new/new.page'; @@ -71,6 +72,7 @@ export class XhrInterceptor implements HttpInterceptor { I18nPipe, MomentPipe, AppComponent, + PageBookmarks, PageEntry, PageLogin, PageNew, diff --git a/src/app/pages/bookmarks/bookmarks.page.html b/src/app/pages/bookmarks/bookmarks.page.html new file mode 100644 index 0000000..24cc006 --- /dev/null +++ b/src/app/pages/bookmarks/bookmarks.page.html @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/app/pages/bookmarks/bookmarks.page.ts b/src/app/pages/bookmarks/bookmarks.page.ts new file mode 100644 index 0000000..1120ab8 --- /dev/null +++ b/src/app/pages/bookmarks/bookmarks.page.ts @@ -0,0 +1,81 @@ +import { Component, OnInit, Input } from '@angular/core'; +import { Router, ActivatedRoute } from '@angular/router'; +import { PageEvent } from '@angular/material/paginator'; + +import { BookmarksService } from '../../services/bookmarks.service'; + +@Component({ + selector: 'page-bookmarks', + templateUrl: './bookmarks.page.html' +}) +export class PageBookmarks implements OnInit { + + @Input() entries: any; + boundRefresh: Function; + boundUpdate: Function; + init: boolean = true; + + constructor(private bookmarksService: BookmarksService, private router: Router, private route: ActivatedRoute) { } + + ngOnInit(): void { + this.boundRefresh = this.refresh.bind(this); + this.boundUpdate = this.update.bind(this); + this.route.queryParams.subscribe(params => { + if (this.init) { + this.entries = {}; + if (params[ 'p' ]) { + this.entries.number = +params[ 'p' ] - 1; + if (this.entries.number < 0) { + this.entries.number = 0; + } + } + + if (params[ 's' ]) { + this.entries.size = +params[ 's' ]; + } + + this.refresh(); + this.init = false; + } + }); + } + + refresh(): void { + if (!this.entries) { + this.entries = {}; + } + + this.entries.content = null; + this.bookmarksService.getEntriesPages(this.entries.number || 0, this.entries.size || 30).subscribe((data: any) => { + this.entries = data; + this.entries.bookmarks = true; + }, (error) => { }) + + } + + update(event: PageEvent) { + this.entries.content = null; + const params: any = { p: null, s: null }; + + if (event.pageIndex != 0) { + params.p = event.pageIndex + 1; + } + + if (event.pageSize != 30) { + params.s = event.pageSize; + } + + this.router.navigate( + [], + { + relativeTo: this.route, + queryParams: params, + queryParamsHandling: 'merge' + }); + + this.bookmarksService.getEntriesPages(event.pageIndex, event.pageSize).subscribe((data: any) => { + this.entries = data; + }, (error) => { }) + } + +} diff --git a/src/app/services/bookmarks.service.ts b/src/app/services/bookmarks.service.ts new file mode 100644 index 0000000..7e023d3 --- /dev/null +++ b/src/app/services/bookmarks.service.ts @@ -0,0 +1,29 @@ +import { Injectable } from '@angular/core'; +import { HttpClient } from '@angular/common/http'; +import { environment } from '../../environments/environment'; + +@Injectable({ + providedIn: 'root', +}) +export class BookmarksService { + + constructor(private http: HttpClient) { + } + + getEntries() { + return this.http.get(environment.apiUrl + "/b"); + } + + getEntriesPages(page: number, size: number) { + return this.http.get(environment.apiUrl + "/b" + "?page=" + page + "&size=" + size); + } + + addEntry(id: number) { + return this.http.put(environment.apiUrl + "/b/" + id, {}); + } + + removeEntry(id: number) { + return this.http.delete(environment.apiUrl + "/b/" + id, {}); + } + +} \ No newline at end of file diff --git a/src/app/ui/comment/comment.ui.ts b/src/app/ui/comment/comment.ui.ts index 6ef7a51..877688a 100644 --- a/src/app/ui/comment/comment.ui.ts +++ b/src/app/ui/comment/comment.ui.ts @@ -43,19 +43,25 @@ export class UiComment implements OnInit { voteUp() { this.voteService.voteCommentUp(this.comment.id).subscribe((result) => { - this.change && this.change() + this.commentService.getComment(this.comment.id).subscribe((data) => { + this.comment = data; + }) }); } voteDown() { this.voteService.voteCommentDown(this.comment.id).subscribe((result) => { - this.change && this.change() + this.commentService.getComment(this.comment.id).subscribe((data) => { + this.comment = data; + }) }); } unvote() { this.voteService.unvoteComment(this.comment.id).subscribe((result) => { - this.change && this.change() + this.commentService.getComment(this.comment.id).subscribe((data) => { + this.comment = data; + }) }); } diff --git a/src/app/ui/comments/comments.ui.html b/src/app/ui/comments/comments.ui.html index 2b98bc4..bc18b5a 100644 --- a/src/app/ui/comments/comments.ui.html +++ b/src/app/ui/comments/comments.ui.html @@ -1,6 +1,6 @@
- +
\ No newline at end of file diff --git a/src/app/ui/comments/comments.ui.scss b/src/app/ui/comments/comments.ui.scss index d67975e..ce7688c 100644 --- a/src/app/ui/comments/comments.ui.scss +++ b/src/app/ui/comments/comments.ui.scss @@ -1,3 +1,7 @@ .comments { padding-left: 15px; } + +.divider { + margin: 10px 0px; +} \ No newline at end of file diff --git a/src/app/ui/entries/entries.ui.html b/src/app/ui/entries/entries.ui.html index e06801a..707951c 100644 --- a/src/app/ui/entries/entries.ui.html +++ b/src/app/ui/entries/entries.ui.html @@ -11,7 +11,11 @@ -

{{'entries.nothing' | i18n}}

+ + +

{{'entries.nothing' | i18n}}

+
+
diff --git a/src/app/ui/entry/entry.ui.html b/src/app/ui/entry/entry.ui.html index 0d704cb..a2de45d 100644 --- a/src/app/ui/entry/entry.ui.html +++ b/src/app/ui/entry/entry.ui.html @@ -19,18 +19,28 @@ --> - thumb_up - thumb_down + thumb_up + thumb_down   {{'points' | i18n:(entry.metadata && entry.metadata.points)}} {{entry.created | datef}} {{'entry.author' | i18n}}{{entry.author}} - | + | {{'entry.comments' | i18n:(entry.metadata && entry.metadata.comments)}} + | + + bookmark_border + + + bookmark + | - {{'entry.unvote' | i18n}} + {{'entry.unvote' | + i18n}} | {{'entry.delete' | i18n}} diff --git a/src/app/ui/entry/entry.ui.ts b/src/app/ui/entry/entry.ui.ts index 8755e34..6a19440 100644 --- a/src/app/ui/entry/entry.ui.ts +++ b/src/app/ui/entry/entry.ui.ts @@ -3,7 +3,7 @@ import { MatDialog } from '@angular/material/dialog'; import { AuthService } from '../../services/auth.service'; import { VoteService } from '../../services/vote.service'; -import { CommentService } from '../../services/comment.service'; +import { BookmarksService } from '../../services/bookmarks.service'; import { ModerationService } from '../../services/moderarion.service'; import { ConfirmDialog } from '../../ui/confirm/confirm.component'; @@ -20,7 +20,7 @@ export class UiEntry implements OnInit { @Input() change: Function; constructor(private authService: AuthService, private voteService: VoteService, - private moderationService: ModerationService, public dialog: MatDialog) { } + private moderationService: ModerationService, private bookmarksService: BookmarksService, public dialog: MatDialog) { } ngOnInit(): void { this.authService.auth.subscribe((auth: any) => { @@ -36,26 +36,38 @@ export class UiEntry implements OnInit { voteUp() { this.voteService.voteEntryUp(this.entry.id).subscribe((result) => { - this.change && this.change() + this.change && this.change(); }); } voteDown() { this.voteService.voteEntryDown(this.entry.id).subscribe((result) => { - this.change && this.change() + this.change && this.change(); + }); + } + + addBookmark() { + this.bookmarksService.addEntry(this.entry.id).subscribe((result) => { + this.entry.metadata.bookmarked = true; + }); + } + + removeBookmark() { + this.bookmarksService.removeEntry(this.entry.id).subscribe((result) => { + this.entry.metadata.bookmarked = false; }); } unvote() { this.voteService.unvoteEntry(this.entry.id).subscribe((result) => { - this.change && this.change() + this.change && this.change(); }); } deleteEntry(entry: any) { const dialogRef = this.dialog.open(ConfirmDialog, { data: { - 'label': 'comment.confirmDelete', + 'label': 'entry.confirmDelete', 'args': [ entry.title, entry.author ] } }) diff --git a/src/app/ui/main/main.ui.html b/src/app/ui/main/main.ui.html index 7afbcfb..30b027f 100644 --- a/src/app/ui/main/main.ui.html +++ b/src/app/ui/main/main.ui.html @@ -28,6 +28,9 @@ history {{'new' | i18n}} + + bookmarks {{'bookmarks' | i18n}} + tune {{'settings' | i18n}}