flagging
This commit is contained in:
parent
361e1b46c6
commit
da2ec818ac
@ -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 ] },
|
||||
|
@ -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,
|
||||
|
@ -0,0 +1,21 @@
|
||||
<div class="container">
|
||||
<mat-progress-bar *ngIf="!comments || !comments.content" mode="indeterminate"></mat-progress-bar>
|
||||
|
||||
<div *ngIf="comments && comments.content" fxLayout="column" fxFlexFill class="comments">
|
||||
<ng-container *ngFor="let comment of comments.content; let i = index">
|
||||
<mat-divider class="divider" *ngIf="i > 0"></mat-divider>
|
||||
<ui-comment class="comment" [comment]="comment" [subcomments]="false" [parentLink]="true" [change]="boundRefresh">
|
||||
</ui-comment>
|
||||
</ng-container>
|
||||
|
||||
<mat-list *ngIf="comments.totalElements == 0">
|
||||
<mat-list-item>
|
||||
<p>{{'comments.nothing' | i18n}}</p>
|
||||
</mat-list-item>
|
||||
</mat-list>
|
||||
|
||||
<small *ngIf="comments.totalElements > comments.content.length">
|
||||
<a mat-stroked-button color="primary" (click)="showMore()">{{'comments.showMore' | i18n}}</a>
|
||||
</small>
|
||||
</div>
|
||||
</div>
|
@ -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;
|
||||
})
|
||||
}
|
||||
}
|
@ -0,0 +1 @@
|
||||
<page-entries [fetch]="boundFetch"></page-entries>
|
23
src/app/pages/moderation/entries/moderation.entries.page.ts
Normal file
23
src/app/pages/moderation/entries/moderation.entries.page.ts
Normal file
@ -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);
|
||||
}
|
||||
|
||||
}
|
28
src/app/services/flag.service.ts
Normal file
28
src/app/services/flag.service.ts
Normal file
@ -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, {});
|
||||
}
|
||||
}
|
@ -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);
|
||||
}
|
||||
|
@ -27,6 +27,16 @@
|
||||
routerLink="/e/{{comment.target}}">{{comment.metadata.entry || 'entry'}}</a></span>
|
||||
<span *ngIf="comment.metadata && comment.metadata.unvote"> | </span>
|
||||
<a *ngIf="comment.metadata.unvote" href="javascript:" (click)="unvote()">{{'comment.unvote' | i18n}}</a>
|
||||
<span> | </span>
|
||||
<a *ngIf="comment.metadata && comment.metadata.flag" href="javascript:" (click)="flag(comment.id)" matTooltip="{{'comment.flag' |
|
||||
i18n}}">
|
||||
<mat-icon inline="true">outlined_flag</mat-icon>
|
||||
</a>
|
||||
<a *ngIf="comment.metadata && comment.metadata.unflag" href="javascript:" (click)="unflag(comment.id)"
|
||||
matTooletip="{{'comment.unflag' |
|
||||
i18n}}">
|
||||
<mat-icon inline="true">flag</mat-icon>
|
||||
</a>
|
||||
</small>
|
||||
</div>
|
||||
<ng-container *ngIf="!comment.metadata || !comment.metadata.edit">
|
||||
@ -39,8 +49,14 @@
|
||||
'comment.replyHide' : 'comment.reply') | i18n}}</a>
|
||||
<span *ngIf="canEdit()"> | </span>
|
||||
<a *ngIf="canEdit()" href="javascript:" (click)="edit()">{{'comment.edit' | i18n}}</a>
|
||||
<span *ngIf="moderator"> | </span>
|
||||
<a *ngIf="moderator" href="javascript:" (click)="modDeleteComment(comment)">{{'moderation.comment.delete' | i18n}}</a>
|
||||
<ng-container *ngIf="moderator">
|
||||
<span *ngIf="comment.flaggedStatus == 'FLAGGED'"> | </span>
|
||||
<a *ngIf="comment.flaggedStatus == 'FLAGGED'" href="javascript:" (click)="modUnflagComment()">{{'moderation.comment.unflag' |
|
||||
i18n}}</a>
|
||||
<span> | </span>
|
||||
<a href="javascript:" (click)="modDeleteComment(comment)">{{'moderation.comment.delete' |
|
||||
i18n}}</a>
|
||||
</ng-container>
|
||||
</small>
|
||||
</div>
|
||||
</ng-container>
|
||||
|
@ -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();
|
||||
})
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
@ -30,19 +30,35 @@
|
||||
<span> | </span>
|
||||
<a routerLink="/e/{{entry.id}}">{{(entry.metadata && entry.metadata.comments == 1 ? 'entry.comment' :
|
||||
'entry.comments') | i18n:(entry.metadata && entry.metadata.comments)}}</a>
|
||||
<span> | </span>
|
||||
<a *ngIf="entry.metadata && !entry.metadata.bookmarked" href="javascript:" (click)="addBookmark()"
|
||||
<span *ngIf="entry.metadata && entry.metadata.bookmark"> | </span>
|
||||
<a *ngIf="entry.metadata && entry.metadata.bookmark" href="javascript:" (click)="addBookmark()"
|
||||
matTooltip="{{'bookmarks.add' | i18n}}">
|
||||
<mat-icon inline="true">bookmark_border</mat-icon>
|
||||
</a>
|
||||
<a *ngIf="entry.metadata && entry.metadata.bookmarked" href="javascript:" (click)="removeBookmark()"
|
||||
<span *ngIf="entry.metadata && entry.metadata.removeBookmark"> | </span>
|
||||
<a *ngIf="entry.metadata && entry.metadata.removeBookmark" href="javascript:" (click)="removeBookmark()"
|
||||
matTooltip="{{'bookmarks.remove' | i18n}}">
|
||||
<mat-icon inline="true">bookmark</mat-icon>
|
||||
</a>
|
||||
<span *ngIf="entry.metadata && entry.metadata.unvote"> | </span>
|
||||
<a *ngIf="entry.metadata && entry.metadata.unvote" href="javascript:" (click)="unvote(entry.id)">{{'entry.unvote' |
|
||||
i18n}}</a>
|
||||
<span *ngIf="moderator"> | </span>
|
||||
<a *ngIf="moderator" href="javascript:" (click)="deleteEntry(entry)">{{'moderation.entry.delete' | i18n}}</a>
|
||||
<span *ngIf="entry.metadata && entry.metadata.flag"> | </span>
|
||||
<a *ngIf="entry.metadata && entry.metadata.flag" href="javascript:" (click)="flag(entry.id)" matTooltip="{{'entry.flag' |
|
||||
i18n}}">
|
||||
<mat-icon inline="true">outlined_flag</mat-icon>
|
||||
</a>
|
||||
<span *ngIf="entry.metadata && entry.metadata.unflag"> | </span>
|
||||
<a *ngIf="entry.metadata && entry.metadata.unflag" href="javascript:" (click)="unflag(entry.id)" matTooltip="{{'entry.unflag' |
|
||||
i18n}}">
|
||||
<mat-icon inline="true">flag</mat-icon>
|
||||
</a>
|
||||
<ng-container *ngIf="moderator">
|
||||
<span *ngIf="entry.flaggedStatus == 'FLAGGED'"> | </span>
|
||||
<a *ngIf="entry.flaggedStatus == 'FLAGGED'" href="javascript:"
|
||||
(click)="modUnflagEntry()">{{'moderation.entry.unflag' | i18n}}</a>
|
||||
<span> | </span>
|
||||
<a href="javascript:" (click)="modDeleteEntry()">{{'moderation.entry.delete' | i18n}}</a>
|
||||
</ng-container>
|
||||
</small>
|
||||
</div>
|
@ -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();
|
||||
})
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
@ -56,6 +56,13 @@
|
||||
<a *ngIf="authenticated" routerLink="/last" routerLinkActive="active" mat-list-item>
|
||||
<mat-icon>history</mat-icon> {{'page.last' | i18n}}
|
||||
</a>
|
||||
<mat-divider *ngIf="moderator"></mat-divider>
|
||||
<a *ngIf="moderator" routerLink="/moderation/entries" routerLinkActive="active" mat-list-item>
|
||||
<mat-icon>assignment_late</mat-icon> {{'moderation.entries' | i18n}}
|
||||
</a>
|
||||
<a *ngIf="moderator" routerLink="/moderation/comments" routerLinkActive="active" mat-list-item>
|
||||
<mat-icon>feedback</mat-icon> {{'moderation.comments' | i18n}}
|
||||
</a>
|
||||
<mat-divider *ngIf="authenticated"></mat-divider>
|
||||
<a (click)="openExternal('https://wiki.bstly.de/services/bstlboard#faq','_blank')" routerLinkActive="active"
|
||||
mat-list-item>
|
||||
|
@ -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;
|
||||
})
|
||||
|
Loading…
Reference in New Issue
Block a user