entry edit, fix menu touch

This commit is contained in:
_Bastler 2021-11-21 16:43:36 +01:00
parent 2bd1e7a9d1
commit 185f28e262
18 changed files with 344 additions and 68 deletions

View File

@ -4,6 +4,7 @@ import { Routes, RouterModule } from '@angular/router';
import { AuthGuard, AuthUpdateGuard, AuthenticatedGuard, AnonymousGuard } from './auth/auth.guard'; import { AuthGuard, AuthUpdateGuard, AuthenticatedGuard, AnonymousGuard } from './auth/auth.guard';
import { PageBookmarks } from './pages/bookmarks/bookmarks.page'; import { PageBookmarks } from './pages/bookmarks/bookmarks.page';
import { PageComment } from './pages/comment/comment.page'; import { PageComment } from './pages/comment/comment.page';
import { PageEntryEdit } from './pages/entry/edit/edit.page';
import { PageEntry } from './pages/entry/entry.page'; import { PageEntry } from './pages/entry/entry.page';
import { PageHot } from './pages/hot/hot.page'; import { PageHot } from './pages/hot/hot.page';
import { PageLast } from './pages/last/last.page'; import { PageLast } from './pages/last/last.page';
@ -37,6 +38,7 @@ const routes: Routes = [
{ path: 'settings', component: PageSettings, canActivate: [ AuthenticatedGuard ] }, { path: 'settings', component: PageSettings, canActivate: [ AuthenticatedGuard ] },
{ path: 'submit', component: PageSubmission, canActivate: [ AuthenticatedGuard ] }, { path: 'submit', component: PageSubmission, canActivate: [ AuthenticatedGuard ] },
{ path: 'e/:id', component: PageEntry, canActivate: [ AuthenticatedGuard ] }, { path: 'e/:id', component: PageEntry, canActivate: [ AuthenticatedGuard ] },
{ path: 'e/:id/edit', component: PageEntryEdit, canActivate: [ AuthenticatedGuard ] },
{ path: 'c/:id', component: PageComment, canActivate: [ AuthenticatedGuard ] }, { path: 'c/:id', component: PageComment, canActivate: [ AuthenticatedGuard ] },
{ path: 'u/:username', component: PageUser, canActivate: [ AuthenticatedGuard ] }, { path: 'u/:username', component: PageUser, canActivate: [ AuthenticatedGuard ] },
{ path: 'u/c/:username', component: PageUserComments, canActivate: [ AuthenticatedGuard ] }, { path: 'u/c/:username', component: PageUserComments, canActivate: [ AuthenticatedGuard ] },

View File

@ -20,6 +20,7 @@ import { AppComponent } from './app.component';
import { PageBookmarks } from './pages/bookmarks/bookmarks.page'; import { PageBookmarks } from './pages/bookmarks/bookmarks.page';
import { PageComment } from './pages/comment/comment.page'; import { PageComment } from './pages/comment/comment.page';
import { PageEntry } from './pages/entry/entry.page'; import { PageEntry } from './pages/entry/entry.page';
import { PageEntryEdit } from './pages/entry/edit/edit.page';
import { PageEntries } from './pages/entries/entries.page'; import { PageEntries } from './pages/entries/entries.page';
import { PageHot } from './pages/hot/hot.page'; import { PageHot } from './pages/hot/hot.page';
import { PageLast } from './pages/last/last.page'; import { PageLast } from './pages/last/last.page';
@ -88,6 +89,7 @@ export class XhrInterceptor implements HttpInterceptor {
PageBookmarks, PageBookmarks,
PageComment, PageComment,
PageEntry, PageEntry,
PageEntryEdit,
PageEntries, PageEntries,
PageHot, PageHot,
PageLast, PageLast,

View File

@ -0,0 +1,41 @@
<div class="container">
<form [formGroup]="form" (ngSubmit)="update()" #formDirective="ngForm">
<mat-card>
<mat-card-content>
<p>{{'submission.edit' | i18n}}</p>
<mat-form-field>
<input matInput placeholder="{{'submission.entryType' | i18n}}" formControlName="entryType" disabled>
</mat-form-field>
<mat-form-field>
<input matInput placeholder="{{'submission.url' | i18n}}" formControlName="url" type="url"
[required]="entryType == 'LINK'" matAutofocus>
<mat-error *ngIf="hasError('url')">
{{'submission.url.error' | i18n}}
</mat-error>
</mat-form-field>
<mat-form-field>
<input matInput placeholder="{{'submission.title' | i18n}}" formControlName="title" type="text" required
(focus)="onTitleFocus($event)">
<mat-error>
{{'submission.title.error' | i18n}}
</mat-error>
</mat-form-field>
<mat-form-field>
<textarea [mat-autosize] [matAutosizeMinRows]="3" matInput placeholder="{{'submission.text' | i18n}}" [required]="entryType != 'LINK'"
formControlName="text"></textarea>
<mat-error>
{{'submission.text.error' | i18n}}
</mat-error>
</mat-form-field>
</mat-card-content>
<mat-card-actions>
<button *ngIf="!working" mat-raised-button color="primary" [disabled]="form.invalid">
{{'submission.update' | i18n}}
</button>
<a *ngIf="success" mat-button color="primary">{{'submission.success' | i18n}}</a>
</mat-card-actions>
</mat-card>
</form>
</div>

View File

@ -0,0 +1,20 @@
mat-form-field {
display: block;
}
form {
margin: 5px;
@media screen and (min-width: 576px) {
max-width: 100%;
}
@media screen and (min-width: 768px) {
max-width: 80%;
margin: 15px;
}
@media screen and (min-width: 992px) {
max-width: 50%;
}
}

View File

@ -0,0 +1,127 @@
import { Component, OnInit, ViewChild } from '@angular/core';
import { EntriesService } from '../../../services/entries.service';
import { ActivatedRoute, Router } from '@angular/router';
import { FormBuilder, FormGroup, Validators, NgForm } from '@angular/forms';
import { distinctUntilChanged, debounceTime } from 'rxjs/operators';
import { MatSnackBar } from '@angular/material/snack-bar';
@Component({
selector: 'page-entry-edit',
templateUrl: './edit.page.html',
styleUrls: [ './edit.page.scss' ]
})
export class PageEntryEdit implements OnInit {
id: number;
entry: any;
entryTypes: string[] = [ 'LINK', 'DISCUSSION', 'QUESTION', 'INTERN' ];
entryType: string = this.entryTypes[ 0 ];
notfound: boolean = false;
working: boolean = false;
success: boolean = false;
form: FormGroup;
@ViewChild('formDirective') private formDirective: NgForm;
constructor(private entriesService: EntriesService,
private formBuilder: FormBuilder,
private route: ActivatedRoute,
private snackBar: MatSnackBar) { }
ngOnInit(): void {
this.form = this.formBuilder.group({
entryType: [ '', Validators.required ],
url: [ '', Validators.required ],
title: [ '', Validators.required ],
text: [ '', Validators.nullValidator ],
});
this.form.get('entryType').disable();
this.form.get('entryType').valueChanges.subscribe((value) => {
this.entryType = value;
switch (value) {
case 'LINK':
this.form.get('url').setValidators([ Validators.required ]);
this.form.get('text').setValidators([ Validators.nullValidator ]);
break;
default:
this.form.get('url').setValidators([ Validators.nullValidator ]);
this.form.get('text').setValidators([ Validators.required ]);
break;
}
});
this.form.get('url').valueChanges.pipe(
debounceTime(800),
distinctUntilChanged()).subscribe((value) => {
if (value && !this.form.get('title').value) {
this.entriesService.titleHelper(value).subscribe((title: string) => {
this.form.get('title').setValue(title);
})
}
})
this.id = +this.route.snapshot.paramMap.get('id');
this.refresh();
}
refresh() {
this.entriesService.getEntry(this.id).subscribe((data) => {
this.entry = data;
this.entryType = this.entry.entryType;
this.form.get("entryType").setValue(this.entry.entryType);
this.form.get("url").setValue(this.entry.url);
this.form.get("title").setValue(this.entry.title);
this.form.get("text").setValue(this.entry.text);
}, (error) => {
if (error.status == 404) {
this.notfound = true;
}
})
}
hasError(controlName: string): boolean {
return this.form.controls[ controlName ].errors != null;
}
onTitleFocus(event): void {
}
update(): void {
if (this.working) {
return;
}
this.working = true;
this.entry.url = this.form.get("url").value;
this.entry.title = this.form.get("title").value;
this.entry.text = this.form.get("text").value;
this.entriesService.update(this.entry).subscribe((data) => {
this.entry = data;
this.working = false;
this.success = true;
}, (error) => {
this.working = false;
if (error.status == 403) {
this.snackBar.open("Error");
}
if (error.status == 422) {
let errors = {};
for (let code of error.error) {
errors[ code.field ] = errors[ code.field ] || {};
errors[ code.field ][ code.code ] = true;
}
for (let code in errors) {
this.form.get(code).setErrors(errors[ code ]);
}
}
})
}
}

View File

@ -1,51 +1,59 @@
<div class="container"> <div fxLayout="column" fxFlexFill>
<mat-card *ngIf="externals && externals.length > 0" class="box"> <div class="container">
<mat-card-content> <mat-card *ngIf="externals && externals.length > 0" class="box">
<h2>{{'login.external' | i18n}}</h2>
<mat-error *ngIf="externalLoginInvalid">
{{'login.external.invalid' | i18n}}
</mat-error>
</mat-card-content>
<mat-card-actions>
<a class="external-login" (click)="externalLogin(client)" *ngFor="let client of externals" mat-raised-button
color="accent">{{'login.external.client' | i18n:client.id}}</a>
<mat-slide-toggle [(ngModel)]="autologin">
{{'login.autologin' | i18n}}
</mat-slide-toggle>
</mat-card-actions>
</mat-card>
<form action="{{apiUrl}}/login" method="POST" #loginForm class="box">
<mat-card *ngIf="internalLogin || externals && externals.length < 1">
<mat-card-content> <mat-card-content>
<h2>{{'login.internal' | i18n}}</h2> <h2>{{'login.external' | i18n}}</h2>
<mat-error *ngIf="loginInvalid"> <mat-error *ngIf="externalLoginInvalid">
{{'login.invalid' | i18n}} {{'login.external.invalid' | i18n}}
</mat-error> </mat-error>
<mat-form-field>
<input id="username" name="username" matInput placeholder="{{'username' | i18n}}" required
matAutofocus>
<mat-error>
{{'username.missing' | i18n}}
</mat-error>
</mat-form-field>
<mat-form-field>
<input id="password" name="password" matInput type="password" placeholder="{{'password' | i18n}}"
required>
<mat-error>
{{'password.invalid.hint' | i18n}}
</mat-error>
</mat-form-field>
<mat-slide-toggle id="remember-me" name="remember-me">
{{'login.keepSession' | i18n}}
</mat-slide-toggle>
</mat-card-content> </mat-card-content>
<mat-card-actions> <mat-card-actions>
<button type="submit" (click)="loginForm.submit()" mat-raised-button color="primary" <a class="external-login" (click)="externalLogin(client)" *ngFor="let client of externals"
[disabled]="loginForm.invalid">{{'login' | mat-raised-button color="accent">{{'login.external.client' | i18n:client.id}}</a>
i18n}}<mat-icon style="font-size: 1em;">open_in_new <mat-slide-toggle [(ngModel)]="autologin">
</mat-icon></button> {{'login.autologin' | i18n}}
</mat-slide-toggle>
</mat-card-actions> </mat-card-actions>
</mat-card> </mat-card>
</form>
<form action="{{apiUrl}}/login" method="POST" #loginForm class="box">
<mat-card *ngIf="internalLogin || externals && externals.length < 1">
<mat-card-content>
<h2>{{'login.internal' | i18n}}</h2>
<mat-error *ngIf="loginInvalid">
{{'login.invalid' | i18n}}
</mat-error>
<mat-form-field>
<input id="username" name="username" matInput placeholder="{{'username' | i18n}}" required
matAutofocus>
<mat-error>
{{'username.missing' | i18n}}
</mat-error>
</mat-form-field>
<mat-form-field>
<input id="password" name="password" matInput type="password"
placeholder="{{'password' | i18n}}" required>
<mat-error>
{{'password.invalid.hint' | i18n}}
</mat-error>
</mat-form-field>
<mat-slide-toggle id="remember-me" name="remember-me">
{{'login.keepSession' | i18n}}
</mat-slide-toggle>
</mat-card-content>
<mat-card-actions>
<button type="submit" (click)="loginForm.submit()" mat-raised-button color="primary"
[disabled]="loginForm.invalid">{{'login' |
i18n}}<mat-icon style="font-size: 1em;">open_in_new
</mat-icon></button>
</mat-card-actions>
</mat-card>
</form>
</div>
<span fxFlexOffset="auto"></span>
<div class="container" *ngIf="!internalLogin">
<small>
<a href="/login?all">{{'login.local' | i18n}}</a>
</small>
</div>
</div> </div>

View File

@ -32,6 +32,21 @@
{{'settings.gravity.zero' | i18n}} {{'settings.gravity.zero' | i18n}}
</mat-hint> </mat-hint>
</mat-form-field> </mat-form-field>
<mat-form-field>
<button
*ngIf="user.settings.entryDelay || form.get('entryDelay').value != settings.defaultEntryDelay"
matPrefix mat-icon-button (click)="resetEntryDelay()">
<mat-icon>cancel</mat-icon>
</button>
<input type="number" min="0" max="15" step="1" matInput placeholder="{{'settings.entryDelay' | i18n}}"
formControlName="entryDelay">
<mat-hint *ngIf="form.get('entryDelay').value != 0">
{{'settings.entryDelay.hint' | i18n}}
</mat-hint>
<mat-hint *ngIf="form.get('entryDelay').value == 0">
{{'settings.entryDelay.zero' | i18n}}
</mat-hint>
</mat-form-field>
<mat-form-field> <mat-form-field>
<button <button
*ngIf="user.settings.commentDelay || form.get('commentDelay').value != settings.defaultCommentDelay" *ngIf="user.settings.commentDelay || form.get('commentDelay').value != settings.defaultCommentDelay"

View File

@ -30,6 +30,7 @@ export class PageSettings implements OnInit {
email: [ '', Validators.nullValidator ], email: [ '', Validators.nullValidator ],
about: [ '', Validators.nullValidator ], about: [ '', Validators.nullValidator ],
gravity: [ '', Validators.nullValidator ], gravity: [ '', Validators.nullValidator ],
entryDelay: [ '', Validators.nullValidator ],
commentDelay: [ '', Validators.nullValidator ], commentDelay: [ '', Validators.nullValidator ],
}); });
@ -47,6 +48,7 @@ export class PageSettings implements OnInit {
this.settingsService.settings.subscribe((settings) => { this.settingsService.settings.subscribe((settings) => {
this.settings = settings; this.settings = settings;
this.form.get('gravity').setValue(this.user.settings.gravity || this.settings.defaultGravity); this.form.get('gravity').setValue(this.user.settings.gravity || this.settings.defaultGravity);
this.form.get('entryDelay').setValue(this.user.settings.entryDelay || this.settings.defaultEntryDelay);
this.form.get('commentDelay').setValue(this.user.settings.commentDelay || this.settings.defaultCommentDelay); this.form.get('commentDelay').setValue(this.user.settings.commentDelay || this.settings.defaultCommentDelay);
}); });
}) })
@ -63,6 +65,11 @@ export class PageSettings implements OnInit {
this.form.get('gravity').setValue(this.settings.defaultGravity); this.form.get('gravity').setValue(this.settings.defaultGravity);
} }
resetEntryDelay(): void {
this.user.settings.entryDelay = null;
this.form.get('entryDelay').setValue(this.settings.defaultEntryDelay);
}
resetCommentDelay(): void { resetCommentDelay(): void {
this.user.settings.commentDelay = null; this.user.settings.commentDelay = null;
this.form.get('commentDelay').setValue(this.settings.defaultCommentDelay); this.form.get('commentDelay').setValue(this.settings.defaultCommentDelay);
@ -89,10 +96,16 @@ export class PageSettings implements OnInit {
this.user.settings.gravity = this.form.get('gravity').value; this.user.settings.gravity = this.form.get('gravity').value;
} }
if (this.form.get('entryDelay').value != this.settings.defaultEntryDelay && !this.user.settings.entryDelay) {
this.user.settings.entryDelay = this.form.get('entryDelay').value;
} else if (this.user.settings.entryDelay) {
this.user.settings.entryDelay = this.form.get('entryDelay').value;
}
if (this.form.get('commentDelay').value != this.settings.defaultCommentDelay && !this.user.settings.commentDelay) { if (this.form.get('commentDelay').value != this.settings.defaultCommentDelay && !this.user.settings.commentDelay) {
this.user.settings.commentDelay = this.form.get('commentDelay').value; this.user.settings.commentDelay = this.form.get('commentDelay').value;
} else if (this.user.settings.commentDelay) { } else if (this.user.settings.commentDelay) {
this.user.settings.commentDelay = this.form.get('gravity').value; this.user.settings.commentDelay = this.form.get('commentDelay').value;
} }
this.userService.update(this.user).subscribe((data) => { this.userService.update(this.user).subscribe((data) => {

View File

@ -39,6 +39,15 @@ export class EntriesService {
return this.http.post(environment.apiUrl + "/entries", entry); return this.http.post(environment.apiUrl + "/entries", entry);
} }
update(entry: any) {
entry.type = 'ENTRY';
return this.http.patch(environment.apiUrl + "/entries", entry);
}
delete(id: number) {
return this.http.delete(environment.apiUrl + "/entries/" + id);
}
titleHelper(url: string) { titleHelper(url: string) {
return this.http.get(environment.apiUrl + "/entries/helper/title?url=" + encodeURIComponent(url)); return this.http.get(environment.apiUrl + "/entries/helper/title?url=" + encodeURIComponent(url));
} }

View File

@ -51,7 +51,7 @@
'comment.replyHide' : 'comment.reply') | i18n}}</a> 'comment.replyHide' : 'comment.reply') | i18n}}</a>
<span *ngIf="canEdit()"> | </span> <span *ngIf="canEdit()"> | </span>
<a *ngIf="canEdit()" href="javascript:" (click)="edit()">{{'comment.edit' | i18n}}</a> <a *ngIf="canEdit()" href="javascript:" (click)="edit()">{{'comment.edit' | i18n}}</a>
<ng-container *ngIf="moderator"> <span class="mod" *ngIf="moderator">
<span *ngIf="comment.metadata.flagged"> | </span> <span *ngIf="comment.metadata.flagged"> | </span>
<a *ngIf="comment.metadata.flagged" href="javascript:" <a *ngIf="comment.metadata.flagged" href="javascript:"
(click)="modUnflagComment()">{{'moderation.comment.unflag' | (click)="modUnflagComment()">{{'moderation.comment.unflag' |
@ -59,7 +59,7 @@
<span> | </span> <span> | </span>
<a href="javascript:" (click)="modDeleteComment(comment)">{{'moderation.comment.delete' | <a href="javascript:" (click)="modDeleteComment(comment)">{{'moderation.comment.delete' |
i18n}}</a> i18n}}</a>
</ng-container> </span>
</small> </small>
</div> </div>
</ng-container> </ng-container>

View File

@ -31,6 +31,10 @@ small .mat-icon {
margin-right: 0px; margin-right: 0px;
} }
span.mod {
font-style: italic;
opacity: 0.7;
}
mat-form-field { mat-form-field {
display: block; display: block;
@ -52,4 +56,4 @@ form {
@media screen and (min-width: 992px) { @media screen and (min-width: 992px) {
max-width: 50%; max-width: 50%;
} }
} }

View File

@ -95,8 +95,6 @@ export class UiComment implements OnInit {
this.comment.metadata.comments = (this.comment.metadata.comments || 0) + 1; this.comment.metadata.comments = (this.comment.metadata.comments || 0) + 1;
} }
canEdit(): boolean { canEdit(): boolean {
const canEdit = this.author && (new Date(this.comment.created).getTime() > new Date().getTime()); const canEdit = this.author && (new Date(this.comment.created).getTime() > new Date().getTime());

View File

@ -42,7 +42,6 @@ export class UiComments implements OnInit {
} }
} }
addComment(comment: any): void { addComment(comment: any): void {
if (!this.comments) { if (!this.comments) {
this.comments = { "content": [] }; this.comments = { "content": [] };

View File

@ -31,6 +31,8 @@
<span> | </span> <span> | </span>
<a routerLink="/e/{{entry.id}}">{{(entry.metadata && entry.metadata.comments == 1 ? 'entry.comment' : <a routerLink="/e/{{entry.id}}">{{(entry.metadata && entry.metadata.comments == 1 ? 'entry.comment' :
'entry.comments') | i18n:(entry.metadata && entry.metadata.comments)}}</a> 'entry.comments') | i18n:(entry.metadata && entry.metadata.comments)}}</a>
<span *ngIf="canEdit()"> | </span>
<a *ngIf="canEdit()" routerLink="/e/{{entry.id}}/edit">{{'entry.edit' | i18n}}</a>
<span *ngIf="entry.metadata && entry.metadata.bookmark"> | </span> <span *ngIf="entry.metadata && entry.metadata.bookmark"> | </span>
<a *ngIf="entry.metadata && entry.metadata.bookmark" href="javascript:" (click)="addBookmark()" <a *ngIf="entry.metadata && entry.metadata.bookmark" href="javascript:" (click)="addBookmark()"
matTooltip="{{'bookmarks.add' | i18n}}"> matTooltip="{{'bookmarks.add' | i18n}}">
@ -54,12 +56,14 @@
i18n}}"> i18n}}">
<mat-icon inline="true">flag</mat-icon> <mat-icon inline="true">flag</mat-icon>
</a> </a>
<ng-container *ngIf="moderator"> <span *ngIf="canEdit()"> | </span>
<a *ngIf="canEdit()" href="javascript:" (click)="deleteEntry()">{{'entry.delete' | i18n}}</a>
<span *ngIf="moderator" class="mod">
<span *ngIf="entry.metadata.flagged"> | </span> <span *ngIf="entry.metadata.flagged"> | </span>
<a *ngIf="entry.metadata.flagged" href="javascript:" <a *ngIf="entry.metadata.flagged" href="javascript:" (click)="modUnflagEntry()">{{'moderation.entry.unflag' |
(click)="modUnflagEntry()">{{'moderation.entry.unflag' | i18n}}</a> i18n}}</a>
<span> | </span> <span> | </span>
<a href="javascript:" (click)="modDeleteEntry()">{{'moderation.entry.delete' | i18n}}</a> <a href="javascript:" (click)="modDeleteEntry()">{{'moderation.entry.delete' | i18n}}</a>
</ng-container> </span>
</small> </small>
</div> </div>

View File

@ -47,3 +47,8 @@ small {
span.voted { span.voted {
opacity: 0.5; opacity: 0.5;
} }
span.mod {
font-style: italic;
opacity: 0.7;
}

View File

@ -7,6 +7,7 @@ import { FlagService } from '../../services/flag.service';
import { BookmarksService } from '../../services/bookmarks.service'; import { BookmarksService } from '../../services/bookmarks.service';
import { ModerationService } from '../../services/moderarion.service'; import { ModerationService } from '../../services/moderarion.service';
import { ConfirmDialog } from '../../ui/confirm/confirm.component'; import { ConfirmDialog } from '../../ui/confirm/confirm.component';
import { EntriesService } from 'src/app/services/entries.service';
@Component({ @Component({
selector: 'ui-entry', selector: 'ui-entry',
@ -15,17 +16,19 @@ import { ConfirmDialog } from '../../ui/confirm/confirm.component';
}) })
export class UiEntry implements OnInit { export class UiEntry implements OnInit {
author: boolean = false;
moderator: boolean = false; moderator: boolean = false;
@Input() entry: any; @Input() entry: any;
@Input() index: number; @Input() index: number;
@Input() change: Function; @Input() change: Function;
constructor(private authService: AuthService, private voteService: VoteService, private flagService: FlagService, constructor(private authService: AuthService, private entriesService: EntriesService, private voteService: VoteService, private flagService: FlagService,
private moderationService: ModerationService, private bookmarksService: BookmarksService, public dialog: MatDialog) { } private moderationService: ModerationService, private bookmarksService: BookmarksService, public dialog: MatDialog) { }
ngOnInit(): void { ngOnInit(): void {
this.authService.auth.subscribe((auth: any) => { this.authService.auth.subscribe((auth: any) => {
if (auth && auth.authorities) { if (auth && auth.authorities) {
this.author = auth.username == this.entry.author;
for (let role of auth.authorities) { for (let role of auth.authorities) {
if (role.authority == 'ROLE_ADMIN' || role.authority == 'ROLE_MOD') { if (role.authority == 'ROLE_ADMIN' || role.authority == 'ROLE_MOD') {
this.moderator = true; this.moderator = true;
@ -81,6 +84,29 @@ export class UiEntry implements OnInit {
}); });
} }
canEdit(): boolean {
const canEdit = this.author && (new Date(this.entry.created).getTime() > new Date().getTime());
return canEdit;
}
deleteEntry() {
const dialogRef = this.dialog.open(ConfirmDialog, {
data: {
'label': 'entry.confirmDelete',
'args': [ this.entry.title, this.entry.author ]
}
})
dialogRef.afterClosed().subscribe(result => {
if (result) {
this.entriesService.delete(this.entry.id).subscribe((result: any) => {
this.entry = null;
this.change && this.change();
})
}
});
}
modDeleteEntry() { modDeleteEntry() {
const dialogRef = this.dialog.open(ConfirmDialog, { const dialogRef = this.dialog.open(ConfirmDialog, {
data: { data: {

View File

@ -1,6 +1,6 @@
<mat-toolbar color="primary"> <mat-toolbar color="primary">
<a href="javascript:" mat-icon-button> <a href="javascript:" mat-icon-button (click)="sidenav.toggle()">
<mat-icon (click)="sidenav.toggle()">menu</mat-icon> <mat-icon>menu</mat-icon>
</a> </a>
<mat-icon svgIcon="logo"></mat-icon> <mat-icon svgIcon="logo"></mat-icon>
<span> <span>
@ -41,7 +41,6 @@
<mat-sidenav-container> <mat-sidenav-container>
<mat-sidenav #sidenav [mode]="isBiggerScreen() ? 'side' : 'over'" [(opened)]="opened" <mat-sidenav #sidenav [mode]="isBiggerScreen() ? 'side' : 'over'" [(opened)]="opened"
(click)="!isBiggerScreen() && opened=false"> (click)="!isBiggerScreen() && opened=false">
<mat-nav-list> <mat-nav-list>
<a *ngIf="authenticated" routerLink="/top" routerLinkActive="active" mat-list-item> <a *ngIf="authenticated" routerLink="/top" routerLinkActive="active" mat-list-item>
<mat-icon>trending_up</mat-icon> {{'page.top' | i18n}} <mat-icon>trending_up</mat-icon> {{'page.top' | i18n}}

View File

@ -1,4 +1,4 @@
import { Component, HostListener } from '@angular/core'; import { Component, HostListener, ViewChild } from '@angular/core';
import { Router } from '@angular/router'; import { Router } from '@angular/router';
import { DomSanitizer } from '@angular/platform-browser'; import { DomSanitizer } from '@angular/platform-browser';
import { MatIconRegistry } from '@angular/material/icon'; import { MatIconRegistry } from '@angular/material/icon';
@ -9,6 +9,7 @@ import { AuthService } from '../../services/auth.service';
import { UserService } from '../../services/user.service'; import { UserService } from '../../services/user.service';
import { I18nService } from '../../services/i18n.service'; import { I18nService } from '../../services/i18n.service';
import { SettingsService } from '../../services/settings.service'; import { SettingsService } from '../../services/settings.service';
import { MatSidenav } from '@angular/material/sidenav';
@Component({ @Component({
selector: 'ui-main', selector: 'ui-main',
@ -16,7 +17,8 @@ import { SettingsService } from '../../services/settings.service';
styleUrls: [ './main.ui.scss' ] styleUrls: [ './main.ui.scss' ]
}) })
export class UiMain { export class UiMain {
opened = true;
opened: boolean = true;
darkTheme: boolean = false; darkTheme: boolean = false;
title = 'bstlboard'; title = 'bstlboard';
currentLocale: String; currentLocale: String;
@ -143,7 +145,6 @@ export class UiMain {
fromEvent(document, 'touchstart').subscribe((event: TouchEvent) => { fromEvent(document, 'touchstart').subscribe((event: TouchEvent) => {
if (event.touches[ 0 ]) { if (event.touches[ 0 ]) {
this.touchStartX = event.touches[ 0 ].screenX; this.touchStartX = event.touches[ 0 ].screenX;
} }
}) })
@ -154,12 +155,15 @@ export class UiMain {
}) })
fromEvent(document, 'touchend').subscribe((event: TouchEvent) => { fromEvent(document, 'touchend').subscribe((event: TouchEvent) => {
const touchDiff = this.touchStartX - this.touchX; if (this.touchX != 0) {
const touchDiff = this.touchStartX - this.touchX;
if (touchDiff < 0 && touchDiff < (this.touchThresh * -1) && !this.opened) { this.touchStartX = 0;
this.opened = true; this.touchX = 0;
} else if (touchDiff > 0 && touchDiff > this.touchThresh && this.opened) { if (touchDiff < 0 && touchDiff < (this.touchThresh * -1) && !this.opened) {
this.opened = false; this.opened = true;
} else if (touchDiff > 0 && touchDiff > this.touchThresh && this.opened) {
this.opened = false;
}
} }
}) })
} }