diff --git a/src/app/app-routing.module.ts b/src/app/app-routing.module.ts
index 0791b6d..93d7604 100644
--- a/src/app/app-routing.module.ts
+++ b/src/app/app-routing.module.ts
@@ -4,6 +4,7 @@ import { Routes, RouterModule } from '@angular/router';
import { AuthGuard, AuthUpdateGuard, AuthenticatedGuard, AnonymousGuard } from './auth/auth.guard';
import { PageBookmarks } from './pages/bookmarks/bookmarks.page';
import { PageComment } from './pages/comment/comment.page';
+import { PageEntryEdit } from './pages/entry/edit/edit.page';
import { PageEntry } from './pages/entry/entry.page';
import { PageHot } from './pages/hot/hot.page';
import { PageLast } from './pages/last/last.page';
@@ -37,6 +38,7 @@ const routes: Routes = [
{ path: 'settings', component: PageSettings, canActivate: [ AuthenticatedGuard ] },
{ path: 'submit', component: PageSubmission, 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: 'u/:username', component: PageUser, canActivate: [ AuthenticatedGuard ] },
{ path: 'u/c/:username', component: PageUserComments, canActivate: [ AuthenticatedGuard ] },
diff --git a/src/app/app.module.ts b/src/app/app.module.ts
index 308a6f9..c67f05d 100644
--- a/src/app/app.module.ts
+++ b/src/app/app.module.ts
@@ -20,6 +20,7 @@ import { AppComponent } from './app.component';
import { PageBookmarks } from './pages/bookmarks/bookmarks.page';
import { PageComment } from './pages/comment/comment.page';
import { PageEntry } from './pages/entry/entry.page';
+import { PageEntryEdit } from './pages/entry/edit/edit.page';
import { PageEntries } from './pages/entries/entries.page';
import { PageHot } from './pages/hot/hot.page';
import { PageLast } from './pages/last/last.page';
@@ -88,6 +89,7 @@ export class XhrInterceptor implements HttpInterceptor {
PageBookmarks,
PageComment,
PageEntry,
+ PageEntryEdit,
PageEntries,
PageHot,
PageLast,
diff --git a/src/app/pages/entry/edit/edit.page.html b/src/app/pages/entry/edit/edit.page.html
new file mode 100644
index 0000000..3d24d62
--- /dev/null
+++ b/src/app/pages/entry/edit/edit.page.html
@@ -0,0 +1,41 @@
+
\ No newline at end of file
diff --git a/src/app/pages/entry/edit/edit.page.scss b/src/app/pages/entry/edit/edit.page.scss
new file mode 100644
index 0000000..db871a6
--- /dev/null
+++ b/src/app/pages/entry/edit/edit.page.scss
@@ -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%;
+ }
+}
\ No newline at end of file
diff --git a/src/app/pages/entry/edit/edit.page.ts b/src/app/pages/entry/edit/edit.page.ts
new file mode 100644
index 0000000..4b6ccb2
--- /dev/null
+++ b/src/app/pages/entry/edit/edit.page.ts
@@ -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 ]);
+ }
+ }
+ })
+
+ }
+
+}
diff --git a/src/app/pages/login/login.page.html b/src/app/pages/login/login.page.html
index 1494f5c..d6a859f 100644
--- a/src/app/pages/login/login.page.html
+++ b/src/app/pages/login/login.page.html
@@ -1,51 +1,59 @@
-
-
0" class="box">
-
- {{'login.external' | i18n}}
-
- {{'login.external.invalid' | i18n}}
-
-
-
- {{'login.external.client' | i18n:client.id}}
-
- {{'login.autologin' | i18n}}
-
-
-
-
-
diff --git a/src/app/ui/comment/comment.ui.scss b/src/app/ui/comment/comment.ui.scss
index bd8f7f3..befbb65 100644
--- a/src/app/ui/comment/comment.ui.scss
+++ b/src/app/ui/comment/comment.ui.scss
@@ -31,6 +31,10 @@ small .mat-icon {
margin-right: 0px;
}
+span.mod {
+ font-style: italic;
+ opacity: 0.7;
+}
mat-form-field {
display: block;
@@ -52,4 +56,4 @@ form {
@media screen and (min-width: 992px) {
max-width: 50%;
}
-}
+}
\ No newline at end of file
diff --git a/src/app/ui/comment/comment.ui.ts b/src/app/ui/comment/comment.ui.ts
index 268ee55..a9390cf 100644
--- a/src/app/ui/comment/comment.ui.ts
+++ b/src/app/ui/comment/comment.ui.ts
@@ -95,8 +95,6 @@ export class UiComment implements OnInit {
this.comment.metadata.comments = (this.comment.metadata.comments || 0) + 1;
}
-
-
canEdit(): boolean {
const canEdit = this.author && (new Date(this.comment.created).getTime() > new Date().getTime());
diff --git a/src/app/ui/comments/comments.ui.ts b/src/app/ui/comments/comments.ui.ts
index 7e388cc..2431164 100644
--- a/src/app/ui/comments/comments.ui.ts
+++ b/src/app/ui/comments/comments.ui.ts
@@ -42,7 +42,6 @@ export class UiComments implements OnInit {
}
}
-
addComment(comment: any): void {
if (!this.comments) {
this.comments = { "content": [] };
diff --git a/src/app/ui/entry/entry.ui.html b/src/app/ui/entry/entry.ui.html
index bce332d..fc14eef 100644
--- a/src/app/ui/entry/entry.ui.html
+++ b/src/app/ui/entry/entry.ui.html
@@ -31,6 +31,8 @@
|
{{(entry.metadata && entry.metadata.comments == 1 ? 'entry.comment' :
'entry.comments') | i18n:(entry.metadata && entry.metadata.comments)}}
+ |
+ {{'entry.edit' | i18n}}
|
@@ -54,12 +56,14 @@
i18n}}">
flag
-
+ |
+ {{'entry.delete' | i18n}}
+
|
- {{'moderation.entry.unflag' | i18n}}
+ {{'moderation.entry.unflag' |
+ i18n}}
|
{{'moderation.entry.delete' | i18n}}
-
+
\ No newline at end of file
diff --git a/src/app/ui/entry/entry.ui.scss b/src/app/ui/entry/entry.ui.scss
index ce436c1..0c57a91 100644
--- a/src/app/ui/entry/entry.ui.scss
+++ b/src/app/ui/entry/entry.ui.scss
@@ -47,3 +47,8 @@ small {
span.voted {
opacity: 0.5;
}
+
+span.mod {
+ font-style: italic;
+ opacity: 0.7;
+}
diff --git a/src/app/ui/entry/entry.ui.ts b/src/app/ui/entry/entry.ui.ts
index ac1f6c8..2a1d2f1 100644
--- a/src/app/ui/entry/entry.ui.ts
+++ b/src/app/ui/entry/entry.ui.ts
@@ -7,6 +7,7 @@ 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';
+import { EntriesService } from 'src/app/services/entries.service';
@Component({
selector: 'ui-entry',
@@ -15,17 +16,19 @@ import { ConfirmDialog } from '../../ui/confirm/confirm.component';
})
export class UiEntry implements OnInit {
+ author: boolean = false;
moderator: boolean = false;
@Input() entry: any;
@Input() index: number;
@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) { }
ngOnInit(): void {
this.authService.auth.subscribe((auth: any) => {
if (auth && auth.authorities) {
+ this.author = auth.username == this.entry.author;
for (let role of auth.authorities) {
if (role.authority == 'ROLE_ADMIN' || role.authority == 'ROLE_MOD') {
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() {
const dialogRef = this.dialog.open(ConfirmDialog, {
data: {
diff --git a/src/app/ui/main/main.ui.html b/src/app/ui/main/main.ui.html
index e7b40a6..f1f5b5a 100644
--- a/src/app/ui/main/main.ui.html
+++ b/src/app/ui/main/main.ui.html
@@ -1,6 +1,6 @@
-
- menu
+
+ menu
@@ -41,7 +41,6 @@
-
trending_up {{'page.top' | i18n}}
diff --git a/src/app/ui/main/main.ui.ts b/src/app/ui/main/main.ui.ts
index 56ecb95..626503f 100644
--- a/src/app/ui/main/main.ui.ts
+++ b/src/app/ui/main/main.ui.ts
@@ -1,4 +1,4 @@
-import { Component, HostListener } from '@angular/core';
+import { Component, HostListener, ViewChild } from '@angular/core';
import { Router } from '@angular/router';
import { DomSanitizer } from '@angular/platform-browser';
import { MatIconRegistry } from '@angular/material/icon';
@@ -9,6 +9,7 @@ import { AuthService } from '../../services/auth.service';
import { UserService } from '../../services/user.service';
import { I18nService } from '../../services/i18n.service';
import { SettingsService } from '../../services/settings.service';
+import { MatSidenav } from '@angular/material/sidenav';
@Component({
selector: 'ui-main',
@@ -16,7 +17,8 @@ import { SettingsService } from '../../services/settings.service';
styleUrls: [ './main.ui.scss' ]
})
export class UiMain {
- opened = true;
+
+ opened: boolean = true;
darkTheme: boolean = false;
title = 'bstlboard';
currentLocale: String;
@@ -143,7 +145,6 @@ export class UiMain {
fromEvent(document, 'touchstart').subscribe((event: TouchEvent) => {
if (event.touches[ 0 ]) {
this.touchStartX = event.touches[ 0 ].screenX;
-
}
})
@@ -154,12 +155,15 @@ export class UiMain {
})
fromEvent(document, 'touchend').subscribe((event: TouchEvent) => {
- const touchDiff = this.touchStartX - this.touchX;
-
- if (touchDiff < 0 && touchDiff < (this.touchThresh * -1) && !this.opened) {
- this.opened = true;
- } else if (touchDiff > 0 && touchDiff > this.touchThresh && this.opened) {
- this.opened = false;
+ if (this.touchX != 0) {
+ const touchDiff = this.touchStartX - this.touchX;
+ this.touchStartX = 0;
+ this.touchX = 0;
+ if (touchDiff < 0 && touchDiff < (this.touchThresh * -1) && !this.opened) {
+ this.opened = true;
+ } else if (touchDiff > 0 && touchDiff > this.touchThresh && this.opened) {
+ this.opened = false;
+ }
}
})
}