entry edit, fix menu touch
This commit is contained in:
parent
2bd1e7a9d1
commit
185f28e262
@ -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 ] },
|
||||||
|
@ -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,
|
||||||
|
41
src/app/pages/entry/edit/edit.page.html
Normal file
41
src/app/pages/entry/edit/edit.page.html
Normal 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>
|
20
src/app/pages/entry/edit/edit.page.scss
Normal file
20
src/app/pages/entry/edit/edit.page.scss
Normal 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%;
|
||||||
|
}
|
||||||
|
}
|
127
src/app/pages/entry/edit/edit.page.ts
Normal file
127
src/app/pages/entry/edit/edit.page.ts
Normal 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 ]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -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>
|
@ -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"
|
||||||
|
@ -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) => {
|
||||||
|
@ -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));
|
||||||
}
|
}
|
||||||
|
@ -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>
|
||||||
|
@ -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%;
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -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());
|
||||||
|
|
||||||
|
@ -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": [] };
|
||||||
|
@ -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>
|
@ -47,3 +47,8 @@ small {
|
|||||||
span.voted {
|
span.voted {
|
||||||
opacity: 0.5;
|
opacity: 0.5;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
span.mod {
|
||||||
|
font-style: italic;
|
||||||
|
opacity: 0.7;
|
||||||
|
}
|
||||||
|
@ -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: {
|
||||||
|
@ -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}}
|
||||||
|
@ -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;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user