fixes+improvements

This commit is contained in:
_Bastler 2021-10-03 20:22:58 +02:00
parent 7477527f24
commit a94647d549
10 changed files with 190 additions and 49 deletions

View File

@ -4,7 +4,9 @@
<p>{{entry.text}}</p>
<ui-commentform [target]="entry.id" [change]="boundRefresh"></ui-commentform>
<ui-commentform [target]="entry.id" [change]="boundReplyCallback"></ui-commentform>
<ui-comments [target]="entry.id"></ui-comments>
<ng-container *ngIf="entry.metadata.comments">
<ui-comments [target]="entry.id"></ui-comments>
</ng-container>
</ng-container>

View File

@ -3,6 +3,7 @@ import { Component, OnInit } from '@angular/core';
import { ActivatedRoute } from '@angular/router';
import { EntriesService } from '../../services/entries.service';
import { CommentService } from '../../services/comment.service';
@Component({
selector: 'page-entry',
@ -14,13 +15,15 @@ export class PageEntry implements OnInit {
entry: any;
notfound: boolean = false;
boundRefresh: Function;
boundReplyCallback: Function;
constructor(private entriesService: EntriesService,
constructor(private commentService: CommentService, private entriesService: EntriesService,
private route: ActivatedRoute) { }
ngOnInit(): void {
this.id = +this.route.snapshot.paramMap.get('id');
this.boundRefresh = this.refresh.bind(this);
this.boundReplyCallback = this.replyCallback.bind(this);
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;
});
}
}

View 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);
}
}

View File

@ -1,16 +1,17 @@
<div mat-line>
<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">&nbsp;</mat-icon>
{{'comment.author' | i18n}}<a routerLink="/u/{{comment.author}}">{{comment.author}}</a>&nbsp;
<a routerLink="/c/{{comment.id}}" matTooltip="{{comment.created | datef:'LLLL'}}">{{comment.created
| datef}}</a>
{{'comment.author' | i18n}}<a routerLink="/u/{{comment.author}}">{{comment.author}}</a>
&nbsp;
<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">&nbsp;</span>
<a *ngIf="comment.metadata && comment.metadata.downvote" href="javascript:" (click)="voteDown(comment.id)"
matTooltip="{{'vote.down' | i18n}}">
<mat-icon inline="true">remove</mat-icon>
<mat-icon inline="true">thumb_down</mat-icon>
</a>
</small>
</div>
@ -27,6 +28,10 @@
<a *ngIf="comment.metadata.unvote" href="javascript:" (click)="voteDown()">
{{'comment.unvote' | i18n}}
</a>
<span *ngIf="moderator">|</span>
<a *ngIf="moderator" href="javascript:" (click)="deleteComment(comment)">
{{'comment.delete' | i18n}}
</a>
</small>
</div>

View File

@ -1,6 +1,11 @@
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 { CommentService } from '../../services/comment.service';
import { ModerationService } from '../../services/moderarion.service';
import { ConfirmDialog } from '../../ui/confirm/confirm.component';
@Component({
selector: 'ui-comment',
@ -9,14 +14,26 @@ import { CommentService } from '../../services/comment.service';
})
export class UiComment implements OnInit {
moderator: boolean = false;
@Input() comment: any;
@Input() change: 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 {
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.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>';
}
@ -47,4 +64,21 @@ export class UiComment implements OnInit {
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()
})
}
});
}
}

View File

@ -36,7 +36,7 @@ export class UiCommentForm implements OnInit {
comment.text = this.form.get("text").value;
this.commentService.create(comment).subscribe((data) => {
this.form.reset();
this.formDirective.resetForm();
this.change && this.change();
});
}

View File

@ -1,11 +1,10 @@
<div mat-line>
<span *ngIf="index">{{index}}.&nbsp;</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">&nbsp;</mat-icon>
<mat-icon>{{'entryType.' + entry.entryType + '.icon' | i18n}}</mat-icon>&nbsp;
<span *ngIf="entry.metadata && entry.metadata.vote" (click)="voteUp(entry.id)" matTooltip="{{'vote.up' | i18n}}">
<mat-icon inline="true">thumb_up</mat-icon>
</span>
&nbsp;
<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>
</div>
@ -21,5 +20,9 @@
<a routerLink="/e/{{entry.id}}">
{{'entry.comments' | i18n:(entry.metadata && entry.metadata.comments)}}
</a>
<span *ngIf="moderator">|</span>
<a *ngIf="moderator" href="javascript:" (click)="deleteEntry(entry)">
{{'entry.delete' | i18n}}
</a>
</small>
</div>

View File

@ -1,3 +1,6 @@
@import '../../../variables.scss';
small a {
color: inherit !important;
text-decoration: none;
@ -6,4 +9,8 @@ small a {
small a:hover {
color: inherit !important;
text-decoration: underline;
}
a.vote {
color: $light-primary-text;
}

View File

@ -1,5 +1,11 @@
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 { CommentService } from '../../services/comment.service';
import { ModerationService } from '../../services/moderarion.service';
import { ConfirmDialog } from '../../ui/confirm/confirm.component';
@Component({
selector: 'ui-entry',
@ -8,14 +14,24 @@ import { VoteService } from '../../services/vote.service';
})
export class UiEntry implements OnInit {
moderator: boolean = false;
@Input() entry: any;
@Input() index : number;
@Input() change : Function;
@Input() index: number;
@Input() change: Function;
constructor(private voteService: VoteService) { }
constructor(private authService: AuthService, private voteService: VoteService,
private moderationService: ModerationService, public dialog: MatDialog) { }
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() {
@ -26,7 +42,25 @@ export class UiEntry implements OnInit {
voteDown() {
this.voteService.voteEntryDown(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',
'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();
})
}
});
}
}

View File

@ -1,43 +1,67 @@
<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>
<span>
{{'bstlboard' | i18n}}
</span>
<div *ngIf="auth && auth.authenticated">
<a mat-button routerLink="/">{{'top' | i18n}}</a>
<a mat-button routerLink="/new">{{'new' | i18n}}</a>
<span class="spacer"></span>
<ng-container *ngIf="auth && auth.authenticated">
<a routerLink="/submit" mat-raised-button color="accent">{{'submission' |
i18n}}</a>
</div>
<span class="spacer"></span>
<ng-container>
<button mat-button [matMenuTriggerFor]="menu">
<mat-icon>settings</mat-icon>
<mat-icon>arrow_drop_down</mat-icon>
</button>
<mat-menu #menu="matMenu">
<a *ngIf="!auth || auth && !auth.authenticated" routerLink="/login" routerLinkActive="active" mat-menu-item>
</ng-container>
</mat-toolbar>
<mat-sidenav-container>
<mat-sidenav #sidenav [mode]="isBiggerScreen() ? 'side' : 'over'" [(opened)]="opened"
(click)="!isBiggerScreen() && opened=false">
<mat-nav-list>
<a *ngIf="!auth || auth && !auth.authenticated" routerLink="/login" routerLinkActive="active" mat-list-item>
<mat-icon>login</mat-icon> {{'login' | i18n}}
</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}}
</a>
<mat-divider></mat-divider>
<a *ngFor="let locale of locales" mat-menu-item (click)="setLocale(locale)">{{'locale.' + locale + '.long' |
i18n}} <mat-icon inline=true *ngIf="locale == currentLocale">done</mat-icon></a>
<a mat-menu-item>
<a *ngIf="auth && auth.authenticated" (click)="logout()" mat-list-item>
<mat-icon>exit_to_app</mat-icon> {{'logout' | i18n}}
</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'">
{{'darkTheme' | i18n}}
</mat-slide-toggle>
</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>
<router-outlet></router-outlet>
</div>
</mat-nav-list>
</mat-sidenav>
<!-- Main content -->
<mat-sidenav-content>
<div class="container">
<router-outlet></router-outlet>
</div>
</mat-sidenav-content>
</mat-sidenav-container>