diff --git a/src/app/app-routing.module.ts b/src/app/app-routing.module.ts
index 6635d3c..0791b6d 100644
--- a/src/app/app-routing.module.ts
+++ b/src/app/app-routing.module.ts
@@ -8,6 +8,8 @@ import { PageEntry } from './pages/entry/entry.page';
import { PageHot } from './pages/hot/hot.page';
import { PageLast } from './pages/last/last.page';
import { PageLogin } from './pages/login/login.page';
+import { PageModerationComments } from './pages/moderation/comments/moderation.comments.page';
+import { PageModerationEntries } from './pages/moderation/entries/moderation.entries.page';
import { PageNew } from './pages/new/new.page';
import { PageNotFound } from './pages/notfound/notfound.page';
import { PageSettings } from './pages/settings/settings.page';
@@ -28,6 +30,8 @@ const routes: Routes = [
{ path: 'top', component: PageTop, canActivate: [ AuthenticatedGuard ] },
{ path: 'hot', component: PageHot, canActivate: [ AuthenticatedGuard ] },
{ path: 'last', component: PageLast, canActivate: [ AuthenticatedGuard ] },
+ { path: 'moderation/comments', component: PageModerationComments, canActivate: [ AuthenticatedGuard ] },
+ { path: 'moderation/entries', component: PageModerationEntries, canActivate: [ AuthenticatedGuard ] },
{ path: 'new', component: PageNew, canActivate: [ AuthenticatedGuard ] },
{ path: 'bookmarks', component: PageBookmarks, canActivate: [ AuthenticatedGuard ] },
{ path: 'settings', component: PageSettings, canActivate: [ AuthenticatedGuard ] },
diff --git a/src/app/app.module.ts b/src/app/app.module.ts
index 44647d7..308a6f9 100644
--- a/src/app/app.module.ts
+++ b/src/app/app.module.ts
@@ -24,6 +24,8 @@ import { PageEntries } from './pages/entries/entries.page';
import { PageHot } from './pages/hot/hot.page';
import { PageLast } from './pages/last/last.page';
import { PageLogin } from './pages/login/login.page';
+import { PageModerationComments } from './pages/moderation/comments/moderation.comments.page';
+import { PageModerationEntries } from './pages/moderation/entries/moderation.entries.page';
import { PageNew } from './pages/new/new.page';
import { PageNotFound } from './pages/notfound/notfound.page'
import { PageSettings } from './pages/settings/settings.page';
@@ -90,6 +92,8 @@ export class XhrInterceptor implements HttpInterceptor {
PageHot,
PageLast,
PageLogin,
+ PageModerationComments,
+ PageModerationEntries,
PageNew,
PageNotFound,
PageSettings,
diff --git a/src/app/pages/moderation/comments/moderation.comments.page.html b/src/app/pages/moderation/comments/moderation.comments.page.html
new file mode 100644
index 0000000..bc385ca
--- /dev/null
+++ b/src/app/pages/moderation/comments/moderation.comments.page.html
@@ -0,0 +1,21 @@
+
+
+
+
+
\ No newline at end of file
diff --git a/src/app/pages/moderation/comments/moderation.comments.page.ts b/src/app/pages/moderation/comments/moderation.comments.page.ts
new file mode 100644
index 0000000..ec72f89
--- /dev/null
+++ b/src/app/pages/moderation/comments/moderation.comments.page.ts
@@ -0,0 +1,38 @@
+import { Component, OnInit, Input } from '@angular/core';
+
+import { Router, ActivatedRoute } from '@angular/router';
+import { ModerationService } from '../../../services/moderarion.service';
+
+@Component({
+ selector: 'page-moderation-comments',
+ templateUrl: './moderation.comments.page.html'
+})
+export class PageModerationComments implements OnInit {
+
+ comments: any = {};
+ boundRefresh: Function;
+
+ constructor(private moderationService: ModerationService,) { }
+
+ ngOnInit(): void {
+ this.boundRefresh = this.refresh.bind(this);
+ this.refresh();
+ }
+
+ refresh(): void {
+ this.moderationService.getFlaggedComments(this.comments.number || 0, this.comments.size || 30).subscribe((data: any) => {
+ this.comments = data;
+ }, (error) => { })
+ }
+
+ showMore() {
+ const oldContent: any[] = this.comments.content;
+ this.moderationService.getFlaggedComments(this.comments.number + 1, this.comments.size).subscribe((data) => {
+ this.comments = data;
+ for (let comment of this.comments.content) {
+ oldContent.push(comment);
+ }
+ this.comments.content = oldContent;
+ })
+ }
+}
diff --git a/src/app/pages/moderation/entries/moderation.entries.page.html b/src/app/pages/moderation/entries/moderation.entries.page.html
new file mode 100644
index 0000000..9d79ea7
--- /dev/null
+++ b/src/app/pages/moderation/entries/moderation.entries.page.html
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/src/app/pages/moderation/entries/moderation.entries.page.ts b/src/app/pages/moderation/entries/moderation.entries.page.ts
new file mode 100644
index 0000000..6a09839
--- /dev/null
+++ b/src/app/pages/moderation/entries/moderation.entries.page.ts
@@ -0,0 +1,23 @@
+import { Component, OnInit } from '@angular/core';
+
+import { ModerationService } from '../../../services/moderarion.service';
+
+@Component({
+ selector: 'page-moderation-entries',
+ templateUrl: './moderation.entries.page.html'
+})
+export class PageModerationEntries implements OnInit {
+
+ boundFetch: Function;
+
+ constructor(private moderationService: ModerationService) { }
+
+ ngOnInit(): void {
+ this.boundFetch = this.fetch.bind(this);
+ }
+
+ fetch(page: number, size: number) {
+ return this.moderationService.getFlaggedEntries(page, size);
+ }
+
+}
diff --git a/src/app/services/flag.service.ts b/src/app/services/flag.service.ts
new file mode 100644
index 0000000..76fd66d
--- /dev/null
+++ b/src/app/services/flag.service.ts
@@ -0,0 +1,28 @@
+import { Injectable } from '@angular/core';
+import { HttpClient } from '@angular/common/http';
+import { environment } from '../../environments/environment';
+
+@Injectable({
+ providedIn: 'root',
+})
+export class FlagService {
+
+ constructor(private http: HttpClient) {
+ }
+
+ flagEntry(id: number) {
+ return this.http.put(environment.apiUrl + "/flags/entry/" + id, {});
+ }
+
+ unflagEntry(id: number) {
+ return this.http.delete(environment.apiUrl + "/flags/entry/" + id, {});
+ }
+
+ flagComment(id: number) {
+ return this.http.put(environment.apiUrl + "/flags/comment/" + id, {});
+ }
+
+ unflagComment(id: number) {
+ return this.http.delete(environment.apiUrl + "/flags/comment/" + id, {});
+ }
+}
\ No newline at end of file
diff --git a/src/app/services/moderarion.service.ts b/src/app/services/moderarion.service.ts
index 69e3741..a819320 100644
--- a/src/app/services/moderarion.service.ts
+++ b/src/app/services/moderarion.service.ts
@@ -10,6 +10,22 @@ export class ModerationService {
constructor(private http: HttpClient) {
}
+ getFlaggedComments(page: number, size: number) {
+ return this.http.get(environment.apiUrl + "/moderation/flags/comments?page=" + page + "&size=" + size);
+ }
+
+ getFlaggedEntries(page: number, size: number) {
+ return this.http.get(environment.apiUrl + "/moderation/flags/entries?page=" + page + "&size=" + size);
+ }
+
+ unflagComment(id: number) {
+ return this.http.delete(environment.apiUrl + "/moderation/flags/comment/" + id);
+ }
+
+ unflagEntry(id: number) {
+ return this.http.delete(environment.apiUrl + "/moderation/flags/entry/" + id);
+ }
+
deleteComment(id: number) {
return this.http.delete(environment.apiUrl + "/moderation/comment/" + id);
}
diff --git a/src/app/ui/comment/comment.ui.html b/src/app/ui/comment/comment.ui.html
index 63b39f7..71a5db0 100644
--- a/src/app/ui/comment/comment.ui.html
+++ b/src/app/ui/comment/comment.ui.html
@@ -27,6 +27,16 @@
routerLink="/e/{{comment.target}}">{{comment.metadata.entry || 'entry'}}
|
{{'comment.unvote' | i18n}}
+ |
+
+ outlined_flag
+
+
+ flag
+
@@ -39,8 +49,14 @@
'comment.replyHide' : 'comment.reply') | i18n}}
|
{{'comment.edit' | i18n}}
- |
- {{'moderation.comment.delete' | i18n}}
+
+ |
+ {{'moderation.comment.unflag' |
+ i18n}}
+ |
+ {{'moderation.comment.delete' |
+ i18n}}
+
diff --git a/src/app/ui/comment/comment.ui.ts b/src/app/ui/comment/comment.ui.ts
index 64d61c9..268ee55 100644
--- a/src/app/ui/comment/comment.ui.ts
+++ b/src/app/ui/comment/comment.ui.ts
@@ -4,6 +4,7 @@ import { FormBuilder, FormGroup, Validators, NgForm } from '@angular/forms';
import { AuthService } from '../../services/auth.service';
import { VoteService } from '../../services/vote.service';
+import { FlagService } from '../../services/flag.service';
import { CommentService } from '../../services/comment.service';
import { ModerationService } from '../../services/moderarion.service';
import { ConfirmDialog } from '../../ui/confirm/confirm.component';
@@ -27,7 +28,7 @@ export class UiComment implements OnInit {
@ViewChild('subcomments') comments: UiComments;
form: FormGroup;
- constructor(private authService: AuthService, private commentService: CommentService, private voteService: VoteService, private formBuilder: FormBuilder, private moderationService: ModerationService, public dialog: MatDialog) { }
+ constructor(private authService: AuthService, private commentService: CommentService, private voteService: VoteService, private flagService: FlagService, private formBuilder: FormBuilder, private moderationService: ModerationService, public dialog: MatDialog) { }
ngOnInit(): void {
this.authService.auth.subscribe((auth: any) => {
@@ -72,6 +73,20 @@ export class UiComment implements OnInit {
});
}
+ flag() {
+ this.flagService.flagComment(this.comment.id).subscribe((result) => {
+ this.comment.metadata.flag = false;
+ this.comment.metadata.unflag = true;
+ });
+ }
+
+ unflag() {
+ this.flagService.unflagComment(this.comment.id).subscribe((result) => {
+ this.comment.metadata.flag = true;
+ this.comment.metadata.unflag = false;
+ });
+ }
+
replyCallback(comment): void {
if (this.subcomments) {
this.comments.addComment(comment);
@@ -145,4 +160,21 @@ export class UiComment implements OnInit {
}
});
}
+
+ modUnflagComment() {
+ const dialogRef = this.dialog.open(ConfirmDialog, {
+ data: {
+ 'label': 'moderation.comment.confirmUnflag',
+ 'args': [ this.comment.text, this.comment.author ]
+ }
+ })
+
+ dialogRef.afterClosed().subscribe(result => {
+ if (result) {
+ this.moderationService.unflagComment(this.comment.id).subscribe((result: any) => {
+ this.change && this.change();
+ })
+ }
+ });
+ }
}
diff --git a/src/app/ui/entry/entry.ui.html b/src/app/ui/entry/entry.ui.html
index bf7a71e..756bc9b 100644
--- a/src/app/ui/entry/entry.ui.html
+++ b/src/app/ui/entry/entry.ui.html
@@ -30,19 +30,35 @@
|
{{(entry.metadata && entry.metadata.comments == 1 ? 'entry.comment' :
'entry.comments') | i18n:(entry.metadata && entry.metadata.comments)}}
- |
- |
+
bookmark_border
- |
+
bookmark
|
{{'entry.unvote' |
i18n}}
- |
- {{'moderation.entry.delete' | i18n}}
+ |
+
+ outlined_flag
+
+ |
+
+ flag
+
+
+ |
+ {{'moderation.entry.unflag' | i18n}}
+ |
+ {{'moderation.entry.delete' | i18n}}
+
\ No newline at end of file
diff --git a/src/app/ui/entry/entry.ui.ts b/src/app/ui/entry/entry.ui.ts
index 8544a23..ac1f6c8 100644
--- a/src/app/ui/entry/entry.ui.ts
+++ b/src/app/ui/entry/entry.ui.ts
@@ -3,6 +3,7 @@ import { MatDialog } from '@angular/material/dialog';
import { AuthService } from '../../services/auth.service';
import { VoteService } from '../../services/vote.service';
+import { FlagService } from '../../services/flag.service';
import { BookmarksService } from '../../services/bookmarks.service';
import { ModerationService } from '../../services/moderarion.service';
import { ConfirmDialog } from '../../ui/confirm/confirm.component';
@@ -19,7 +20,7 @@ export class UiEntry implements OnInit {
@Input() index: number;
@Input() change: Function;
- constructor(private authService: AuthService, private voteService: VoteService,
+ constructor(private authService: AuthService, private voteService: VoteService, private flagService: FlagService,
private moderationService: ModerationService, private bookmarksService: BookmarksService, public dialog: MatDialog) { }
ngOnInit(): void {
@@ -48,13 +49,15 @@ export class UiEntry implements OnInit {
addBookmark() {
this.bookmarksService.addEntry(this.entry.id).subscribe((result) => {
- this.entry.metadata.bookmarked = true;
+ this.entry.metadata.bookmark = false;
+ this.entry.metadata.removeBookmark = true;
});
}
removeBookmark() {
this.bookmarksService.removeEntry(this.entry.id).subscribe((result) => {
- this.entry.metadata.bookmarked = false;
+ this.entry.metadata.bookmark = true;
+ this.entry.metadata.removeBookmark = false;
});
}
@@ -64,21 +67,52 @@ export class UiEntry implements OnInit {
});
}
- deleteEntry(entry: any) {
+ flag() {
+ this.flagService.flagEntry(this.entry.id).subscribe((result) => {
+ this.entry.metadata.flag = false;
+ this.entry.metadata.unflag = true;
+ });
+ }
+
+ unflag() {
+ this.flagService.unflagEntry(this.entry.id).subscribe((result) => {
+ this.entry.metadata.unflag = false;
+ this.entry.metadata.flag = true;
+ });
+ }
+
+ modDeleteEntry() {
const dialogRef = this.dialog.open(ConfirmDialog, {
data: {
'label': 'moderation.entry.confirmDelete',
- 'args': [ entry.title, entry.author ]
+ 'args': [ this.entry.title, this.entry.author ]
}
})
dialogRef.afterClosed().subscribe(result => {
if (result) {
- this.moderationService.deleteEntry(entry.id).subscribe((result: any) => {
+ this.moderationService.deleteEntry(this.entry.id).subscribe((result: any) => {
this.entry = null;
this.change && this.change();
})
}
});
}
+
+ modUnflagEntry() {
+ const dialogRef = this.dialog.open(ConfirmDialog, {
+ data: {
+ 'label': 'moderation.entry.confirmUnflag',
+ 'args': [ this.entry.title, this.entry.author ]
+ }
+ })
+
+ dialogRef.afterClosed().subscribe(result => {
+ if (result) {
+ this.moderationService.unflagEntry(this.entry.id).subscribe((result: any) => {
+ this.change && this.change();
+ })
+ }
+ });
+ }
}
\ No newline at end of file
diff --git a/src/app/ui/main/main.ui.html b/src/app/ui/main/main.ui.html
index 5bfaa92..0fdca4f 100644
--- a/src/app/ui/main/main.ui.html
+++ b/src/app/ui/main/main.ui.html
@@ -56,6 +56,13 @@
history {{'page.last' | i18n}}
+
+
+ assignment_late {{'moderation.entries' | i18n}}
+
+
+ feedback {{'moderation.comments' | i18n}}
+
diff --git a/src/app/ui/main/main.ui.ts b/src/app/ui/main/main.ui.ts
index cac84fa..9cfd225 100644
--- a/src/app/ui/main/main.ui.ts
+++ b/src/app/ui/main/main.ui.ts
@@ -23,6 +23,7 @@ export class UiMain {
datetimeformat: String;
locales;
authenticated: boolean = false;
+ moderator: boolean = false;
constructor(
private i18n: I18nService,
@@ -40,8 +41,13 @@ export class UiMain {
this.datetimeformat = this.i18n.get('format.datetime', []);
this.currentLocale = this.i18n.getLocale();
this.locales = this.i18n.getLocales();
- this.authService.auth.subscribe(data => {
+ this.authService.auth.subscribe(auth => {
this.authenticated = true;
+ for (let role of auth.authorities) {
+ if (role.authority == 'ROLE_ADMIN' || role.authority == 'ROLE_MOD') {
+ this.moderator = true;
+ }
+ }
}, (error) => {
this.authenticated = false;
})
{{'comments.nothing' | i18n}}
+