fixes+improvements
This commit is contained in:
parent
7477527f24
commit
a94647d549
@ -4,7 +4,9 @@
|
|||||||
|
|
||||||
<p>{{entry.text}}</p>
|
<p>{{entry.text}}</p>
|
||||||
|
|
||||||
<ui-commentform [target]="entry.id" [change]="boundRefresh"></ui-commentform>
|
<ui-commentform [target]="entry.id" [change]="boundReplyCallback"></ui-commentform>
|
||||||
|
|
||||||
|
<ng-container *ngIf="entry.metadata.comments">
|
||||||
<ui-comments [target]="entry.id"></ui-comments>
|
<ui-comments [target]="entry.id"></ui-comments>
|
||||||
|
</ng-container>
|
||||||
</ng-container>
|
</ng-container>
|
@ -3,6 +3,7 @@ import { Component, OnInit } from '@angular/core';
|
|||||||
import { ActivatedRoute } from '@angular/router';
|
import { ActivatedRoute } from '@angular/router';
|
||||||
|
|
||||||
import { EntriesService } from '../../services/entries.service';
|
import { EntriesService } from '../../services/entries.service';
|
||||||
|
import { CommentService } from '../../services/comment.service';
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'page-entry',
|
selector: 'page-entry',
|
||||||
@ -14,13 +15,15 @@ export class PageEntry implements OnInit {
|
|||||||
entry: any;
|
entry: any;
|
||||||
notfound: boolean = false;
|
notfound: boolean = false;
|
||||||
boundRefresh: Function;
|
boundRefresh: Function;
|
||||||
|
boundReplyCallback: Function;
|
||||||
|
|
||||||
constructor(private entriesService: EntriesService,
|
constructor(private commentService: CommentService, private entriesService: EntriesService,
|
||||||
private route: ActivatedRoute) { }
|
private route: ActivatedRoute) { }
|
||||||
|
|
||||||
ngOnInit(): void {
|
ngOnInit(): void {
|
||||||
this.id = +this.route.snapshot.paramMap.get('id');
|
this.id = +this.route.snapshot.paramMap.get('id');
|
||||||
this.boundRefresh = this.refresh.bind(this);
|
this.boundRefresh = this.refresh.bind(this);
|
||||||
|
this.boundReplyCallback = this.replyCallback.bind(this);
|
||||||
this.refresh();
|
this.refresh();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -34,4 +37,12 @@ export class PageEntry implements OnInit {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
replyCallback(): void {
|
||||||
|
this.entry.metadata.reply = false;
|
||||||
|
this.entry.metadata.comments = 0;
|
||||||
|
this.commentService.count(this.entry.id).subscribe((data) => {
|
||||||
|
this.entry.metadata.comments = +data;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
21
src/app/services/moderarion.service.ts
Normal file
21
src/app/services/moderarion.service.ts
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
import { Injectable } from '@angular/core';
|
||||||
|
import { HttpClient } from '@angular/common/http';
|
||||||
|
import { environment } from '../../environments/environment';
|
||||||
|
|
||||||
|
@Injectable({
|
||||||
|
providedIn: 'root',
|
||||||
|
})
|
||||||
|
export class ModerationService {
|
||||||
|
|
||||||
|
constructor(private http: HttpClient) {
|
||||||
|
}
|
||||||
|
|
||||||
|
deleteComment(id: number) {
|
||||||
|
return this.http.delete(environment.apiUrl + "/m/c/" + id);
|
||||||
|
}
|
||||||
|
|
||||||
|
deleteEntry(id: number) {
|
||||||
|
return this.http.delete(environment.apiUrl + "/m/e/" + id);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -1,16 +1,17 @@
|
|||||||
<div mat-line>
|
<div mat-line>
|
||||||
<small>
|
<small>
|
||||||
<a *ngIf="comment.metadata && comment.metadata.vote" href="javascript:" (click)="voteUp(comment.id)"
|
|
||||||
matTooltip="{{'vote.up' | i18n}}">
|
|
||||||
<mat-icon inline="true">expand_less</mat-icon>
|
|
||||||
</a>
|
|
||||||
<mat-icon *ngIf="!comment.metadata || !comment.metadata.vote" inline="true"> </mat-icon>
|
|
||||||
{{'comment.author' | i18n}}<a routerLink="/u/{{comment.author}}">{{comment.author}}</a>
|
|
||||||
<a routerLink="/c/{{comment.id}}" matTooltip="{{comment.created | datef:'LLLL'}}">{{comment.created
|
<a routerLink="/c/{{comment.id}}" matTooltip="{{comment.created | datef:'LLLL'}}">{{comment.created
|
||||||
| datef}}</a>
|
| datef}}</a>
|
||||||
|
{{'comment.author' | i18n}}<a routerLink="/u/{{comment.author}}">{{comment.author}}</a>
|
||||||
|
|
||||||
|
<a *ngIf="comment.metadata && comment.metadata.vote" href="javascript:" (click)="voteUp(comment.id)"
|
||||||
|
matTooltip="{{'vote.up' | i18n}}">
|
||||||
|
<mat-icon inline="true">thumb_up</mat-icon>
|
||||||
|
</a>
|
||||||
|
<span *ngIf="comment.metadata && comment.metadata.vote"> </span>
|
||||||
<a *ngIf="comment.metadata && comment.metadata.downvote" href="javascript:" (click)="voteDown(comment.id)"
|
<a *ngIf="comment.metadata && comment.metadata.downvote" href="javascript:" (click)="voteDown(comment.id)"
|
||||||
matTooltip="{{'vote.down' | i18n}}">
|
matTooltip="{{'vote.down' | i18n}}">
|
||||||
<mat-icon inline="true">remove</mat-icon>
|
<mat-icon inline="true">thumb_down</mat-icon>
|
||||||
</a>
|
</a>
|
||||||
</small>
|
</small>
|
||||||
</div>
|
</div>
|
||||||
@ -27,6 +28,10 @@
|
|||||||
<a *ngIf="comment.metadata.unvote" href="javascript:" (click)="voteDown()">
|
<a *ngIf="comment.metadata.unvote" href="javascript:" (click)="voteDown()">
|
||||||
{{'comment.unvote' | i18n}}
|
{{'comment.unvote' | i18n}}
|
||||||
</a>
|
</a>
|
||||||
|
<span *ngIf="moderator">|</span>
|
||||||
|
<a *ngIf="moderator" href="javascript:" (click)="deleteComment(comment)">
|
||||||
|
{{'comment.delete' | i18n}}
|
||||||
|
</a>
|
||||||
</small>
|
</small>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
@ -1,6 +1,11 @@
|
|||||||
import { Component, OnInit, Input } from '@angular/core';
|
import { Component, OnInit, Input } from '@angular/core';
|
||||||
|
import { MatDialog } from '@angular/material/dialog';
|
||||||
|
|
||||||
|
import { AuthService } from '../../services/auth.service';
|
||||||
import { VoteService } from '../../services/vote.service';
|
import { VoteService } from '../../services/vote.service';
|
||||||
import { CommentService } from '../../services/comment.service';
|
import { CommentService } from '../../services/comment.service';
|
||||||
|
import { ModerationService } from '../../services/moderarion.service';
|
||||||
|
import { ConfirmDialog } from '../../ui/confirm/confirm.component';
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'ui-comment',
|
selector: 'ui-comment',
|
||||||
@ -9,14 +14,26 @@ import { CommentService } from '../../services/comment.service';
|
|||||||
})
|
})
|
||||||
export class UiComment implements OnInit {
|
export class UiComment implements OnInit {
|
||||||
|
|
||||||
|
moderator: boolean = false;
|
||||||
@Input() comment: any;
|
@Input() comment: any;
|
||||||
@Input() change: Function;
|
@Input() change: Function;
|
||||||
|
|
||||||
boundReplyCallback: Function;
|
boundReplyCallback: Function;
|
||||||
|
|
||||||
constructor(private commentService: CommentService, private voteService: VoteService) { }
|
constructor(private authService: AuthService, private commentService: CommentService, private voteService: VoteService,
|
||||||
|
private moderationService: ModerationService, public dialog: MatDialog) { }
|
||||||
|
|
||||||
ngOnInit(): void {
|
ngOnInit(): void {
|
||||||
|
this.authService.auth.subscribe((auth: any) => {
|
||||||
|
if (auth && auth.authorities) {
|
||||||
|
for (let role of auth.authorities) {
|
||||||
|
if (role.authority == 'ROLE_ADMIN' || role.authority == 'ROLE_MOD') {
|
||||||
|
this.moderator = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
this.commentService.countParent(this.comment.target, this.comment.id).subscribe((data) => {
|
this.commentService.countParent(this.comment.target, this.comment.id).subscribe((data) => {
|
||||||
this.comment.metadata.comments = +data;
|
this.comment.metadata.comments = +data;
|
||||||
});
|
});
|
||||||
@ -36,7 +53,7 @@ export class UiComment implements OnInit {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
author(author : string) {
|
author(author: string) {
|
||||||
return '<a href="/u/' + author + '">' + author + '</a>';
|
return '<a href="/u/' + author + '">' + author + '</a>';
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -47,4 +64,21 @@ export class UiComment implements OnInit {
|
|||||||
this.comment.metadata.comments = +data;
|
this.comment.metadata.comments = +data;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
deleteComment(comment: any) {
|
||||||
|
const dialogRef = this.dialog.open(ConfirmDialog, {
|
||||||
|
data: {
|
||||||
|
'label': 'comment.confirmDelete',
|
||||||
|
'args': [ comment.text, comment.author ]
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
dialogRef.afterClosed().subscribe(result => {
|
||||||
|
if (result) {
|
||||||
|
this.moderationService.deleteComment(comment.id).subscribe((result: any) => {
|
||||||
|
this.change && this.change()
|
||||||
|
})
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -36,7 +36,7 @@ export class UiCommentForm implements OnInit {
|
|||||||
comment.text = this.form.get("text").value;
|
comment.text = this.form.get("text").value;
|
||||||
|
|
||||||
this.commentService.create(comment).subscribe((data) => {
|
this.commentService.create(comment).subscribe((data) => {
|
||||||
this.form.reset();
|
this.formDirective.resetForm();
|
||||||
this.change && this.change();
|
this.change && this.change();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -1,11 +1,10 @@
|
|||||||
<div mat-line>
|
<div mat-line>
|
||||||
<span *ngIf="index">{{index}}. </span>
|
<span *ngIf="index">{{index}}. </span>
|
||||||
<a *ngIf="entry.metadata && entry.metadata.vote" href="javascript:" (click)="voteUp(entry.id)"
|
|
||||||
matTooltip="{{'vote.up' | i18n}}">
|
|
||||||
<mat-icon inline="true">expand_less</mat-icon>
|
|
||||||
</a>
|
|
||||||
<mat-icon *ngIf="!entry.metadata || !entry.metadata.vote" inline="true"> </mat-icon>
|
|
||||||
<mat-icon>{{'entryType.' + entry.entryType + '.icon' | i18n}}</mat-icon>
|
<mat-icon>{{'entryType.' + entry.entryType + '.icon' | i18n}}</mat-icon>
|
||||||
|
<span *ngIf="entry.metadata && entry.metadata.vote" (click)="voteUp(entry.id)" matTooltip="{{'vote.up' | i18n}}">
|
||||||
|
<mat-icon inline="true">thumb_up</mat-icon>
|
||||||
|
</span>
|
||||||
|
|
||||||
<a class="title" *ngIf="entry.url" [href]="entry.url" target="_blank">{{entry.title}}</a>
|
<a class="title" *ngIf="entry.url" [href]="entry.url" target="_blank">{{entry.title}}</a>
|
||||||
<a class="title" *ngIf="!entry.url" routerLink="/e/{{entry.id}}">{{entry.title}}</a>
|
<a class="title" *ngIf="!entry.url" routerLink="/e/{{entry.id}}">{{entry.title}}</a>
|
||||||
</div>
|
</div>
|
||||||
@ -21,5 +20,9 @@
|
|||||||
<a routerLink="/e/{{entry.id}}">
|
<a routerLink="/e/{{entry.id}}">
|
||||||
{{'entry.comments' | i18n:(entry.metadata && entry.metadata.comments)}}
|
{{'entry.comments' | i18n:(entry.metadata && entry.metadata.comments)}}
|
||||||
</a>
|
</a>
|
||||||
|
<span *ngIf="moderator">|</span>
|
||||||
|
<a *ngIf="moderator" href="javascript:" (click)="deleteEntry(entry)">
|
||||||
|
{{'entry.delete' | i18n}}
|
||||||
|
</a>
|
||||||
</small>
|
</small>
|
||||||
</div>
|
</div>
|
@ -1,3 +1,6 @@
|
|||||||
|
@import '../../../variables.scss';
|
||||||
|
|
||||||
|
|
||||||
small a {
|
small a {
|
||||||
color: inherit !important;
|
color: inherit !important;
|
||||||
text-decoration: none;
|
text-decoration: none;
|
||||||
@ -7,3 +10,7 @@ small a:hover {
|
|||||||
color: inherit !important;
|
color: inherit !important;
|
||||||
text-decoration: underline;
|
text-decoration: underline;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
a.vote {
|
||||||
|
color: $light-primary-text;
|
||||||
|
}
|
@ -1,5 +1,11 @@
|
|||||||
import { Component, OnInit, Input } from '@angular/core';
|
import { Component, OnInit, Input } from '@angular/core';
|
||||||
|
import { MatDialog } from '@angular/material/dialog';
|
||||||
|
|
||||||
|
import { AuthService } from '../../services/auth.service';
|
||||||
import { VoteService } from '../../services/vote.service';
|
import { VoteService } from '../../services/vote.service';
|
||||||
|
import { CommentService } from '../../services/comment.service';
|
||||||
|
import { ModerationService } from '../../services/moderarion.service';
|
||||||
|
import { ConfirmDialog } from '../../ui/confirm/confirm.component';
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'ui-entry',
|
selector: 'ui-entry',
|
||||||
@ -8,14 +14,24 @@ import { VoteService } from '../../services/vote.service';
|
|||||||
})
|
})
|
||||||
export class UiEntry implements OnInit {
|
export class UiEntry implements OnInit {
|
||||||
|
|
||||||
|
moderator: boolean = false;
|
||||||
@Input() entry: any;
|
@Input() entry: any;
|
||||||
@Input() index : number;
|
@Input() index: number;
|
||||||
@Input() change : Function;
|
@Input() change: Function;
|
||||||
|
|
||||||
constructor(private voteService: VoteService) { }
|
constructor(private authService: AuthService, private voteService: VoteService,
|
||||||
|
private moderationService: ModerationService, public dialog: MatDialog) { }
|
||||||
|
|
||||||
ngOnInit(): void {
|
ngOnInit(): void {
|
||||||
|
this.authService.auth.subscribe((auth: any) => {
|
||||||
|
if (auth && auth.authorities) {
|
||||||
|
for (let role of auth.authorities) {
|
||||||
|
if (role.authority == 'ROLE_ADMIN' || role.authority == 'ROLE_MOD') {
|
||||||
|
this.moderator = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
voteUp() {
|
voteUp() {
|
||||||
@ -29,4 +45,22 @@ export class UiEntry implements OnInit {
|
|||||||
this.change && this.change()
|
this.change && this.change()
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
deleteEntry(entry: any) {
|
||||||
|
const dialogRef = this.dialog.open(ConfirmDialog, {
|
||||||
|
data: {
|
||||||
|
'label': 'comment.confirmDelete',
|
||||||
|
'args': [ entry.title, entry.author ]
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
dialogRef.afterClosed().subscribe(result => {
|
||||||
|
if (result) {
|
||||||
|
this.moderationService.deleteEntry(entry.id).subscribe((result: any) => {
|
||||||
|
this.entry = null;
|
||||||
|
this.change && this.change();
|
||||||
|
})
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
@ -1,43 +1,67 @@
|
|||||||
<mat-toolbar color="primary">
|
<mat-toolbar color="primary">
|
||||||
|
<a href="javascript:" mat-icon-button>
|
||||||
|
<mat-icon (click)="sidenav.toggle()">menu</mat-icon>
|
||||||
|
</a>
|
||||||
<mat-icon svgIcon="logo"></mat-icon>
|
<mat-icon svgIcon="logo"></mat-icon>
|
||||||
<span>
|
<span>
|
||||||
{{'bstlboard' | i18n}}
|
{{'bstlboard' | i18n}}
|
||||||
</span>
|
</span>
|
||||||
<div *ngIf="auth && auth.authenticated">
|
<span class="spacer"></span>
|
||||||
<a mat-button routerLink="/">{{'top' | i18n}}</a>
|
<ng-container *ngIf="auth && auth.authenticated">
|
||||||
<a mat-button routerLink="/new">{{'new' | i18n}}</a>
|
|
||||||
<a routerLink="/submit" mat-raised-button color="accent">{{'submission' |
|
<a routerLink="/submit" mat-raised-button color="accent">{{'submission' |
|
||||||
i18n}}</a>
|
i18n}}</a>
|
||||||
</div>
|
</ng-container>
|
||||||
<span class="spacer"></span>
|
|
||||||
<ng-container>
|
</mat-toolbar>
|
||||||
<button mat-button [matMenuTriggerFor]="menu">
|
|
||||||
<mat-icon>settings</mat-icon>
|
<mat-sidenav-container>
|
||||||
<mat-icon>arrow_drop_down</mat-icon>
|
<mat-sidenav #sidenav [mode]="isBiggerScreen() ? 'side' : 'over'" [(opened)]="opened"
|
||||||
</button>
|
(click)="!isBiggerScreen() && opened=false">
|
||||||
<mat-menu #menu="matMenu">
|
|
||||||
<a *ngIf="!auth || auth && !auth.authenticated" routerLink="/login" routerLinkActive="active" mat-menu-item>
|
<mat-nav-list>
|
||||||
|
<a *ngIf="!auth || auth && !auth.authenticated" routerLink="/login" routerLinkActive="active" mat-list-item>
|
||||||
<mat-icon>login</mat-icon> {{'login' | i18n}}
|
<mat-icon>login</mat-icon> {{'login' | i18n}}
|
||||||
</a>
|
</a>
|
||||||
<a *ngIf="auth && auth.authenticated" routerLink="/settings" routerLinkActive="active" mat-menu-item>
|
<a *ngIf="auth && auth.authenticated" routerLink="/" routerLinkActive="active" mat-list-item>
|
||||||
|
<mat-icon>trending_up</mat-icon> {{'top' | i18n}}
|
||||||
|
</a>
|
||||||
|
<a *ngIf="auth && auth.authenticated" routerLink="/new" routerLinkActive="active" mat-list-item>
|
||||||
|
<mat-icon>history</mat-icon> {{'new' | i18n}}
|
||||||
|
</a>
|
||||||
|
<mat-divider></mat-divider>
|
||||||
|
<a *ngIf="auth && auth.authenticated" routerLink="/settings" routerLinkActive="active" mat-list-item>
|
||||||
<mat-icon>tune</mat-icon> {{'settings' | i18n}}
|
<mat-icon>tune</mat-icon> {{'settings' | i18n}}
|
||||||
</a>
|
</a>
|
||||||
<mat-divider></mat-divider>
|
<mat-divider></mat-divider>
|
||||||
<a *ngFor="let locale of locales" mat-menu-item (click)="setLocale(locale)">{{'locale.' + locale + '.long' |
|
<a *ngIf="auth && auth.authenticated" (click)="logout()" mat-list-item>
|
||||||
i18n}} <mat-icon inline=true *ngIf="locale == currentLocale">done</mat-icon></a>
|
<mat-icon>exit_to_app</mat-icon> {{'logout' | i18n}}
|
||||||
<a mat-menu-item>
|
</a>
|
||||||
|
<a *ngIf="!auth || auth && !auth.authenticated" routerLink="/login" routerLinkActive="active" mat-list-item>
|
||||||
|
<mat-icon>login</mat-icon> {{'login' | i18n}}
|
||||||
|
</a>
|
||||||
|
</mat-nav-list>
|
||||||
|
|
||||||
|
<span class="spacer"></span>
|
||||||
|
|
||||||
|
|
||||||
|
<mat-nav-list>
|
||||||
|
<a *ngFor="let locale of locales" mat-list-item (click)="setLocale(locale)">
|
||||||
|
<mat-icon *ngIf="locale == currentLocale">done</mat-icon>{{'locale.' + locale + '.long' |
|
||||||
|
i18n}}
|
||||||
|
</a>
|
||||||
|
<a mat-list-item>
|
||||||
<mat-slide-toggle (change)="darkThemeChange($event)" [checked]="darkTheme == 'true'">
|
<mat-slide-toggle (change)="darkThemeChange($event)" [checked]="darkTheme == 'true'">
|
||||||
{{'darkTheme' | i18n}}
|
{{'darkTheme' | i18n}}
|
||||||
</mat-slide-toggle>
|
</mat-slide-toggle>
|
||||||
</a>
|
</a>
|
||||||
<mat-divider *ngIf="auth && auth.authenticated"></mat-divider>
|
|
||||||
<a *ngIf="auth && auth.authenticated" (click)="logout()" mat-menu-item>
|
|
||||||
<mat-icon>exit_to_app</mat-icon> {{'logout' | i18n}}
|
|
||||||
</a>
|
|
||||||
</mat-menu>
|
|
||||||
</ng-container>
|
|
||||||
</mat-toolbar>
|
|
||||||
|
|
||||||
<div class="container" fxFlex>
|
</mat-nav-list>
|
||||||
|
</mat-sidenav>
|
||||||
|
|
||||||
|
<!-- Main content -->
|
||||||
|
<mat-sidenav-content>
|
||||||
|
<div class="container">
|
||||||
<router-outlet></router-outlet>
|
<router-outlet></router-outlet>
|
||||||
</div>
|
</div>
|
||||||
|
</mat-sidenav-content>
|
||||||
|
</mat-sidenav-container>
|
Loading…
Reference in New Issue
Block a user