diff --git a/backend/.gitignore b/backend/.gitignore index cbeb2f6..c7091f0 100644 --- a/backend/.gitignore +++ b/backend/.gitignore @@ -1,7 +1,7 @@ venv *.pyc staticfiles -media +media/feed-icons .env *.sqlite3 *.sqlite diff --git a/backend/app_be/media/default-icon.svg b/backend/app_be/media/default-icon.svg new file mode 100644 index 0000000..b1c7bbe Binary files /dev/null and b/backend/app_be/media/default-icon.svg differ diff --git a/backend/app_be/models.py b/backend/app_be/models.py index 1fa41f0..e407166 100644 --- a/backend/app_be/models.py +++ b/backend/app_be/models.py @@ -9,7 +9,7 @@ class User(models.Model): class Feed(models.Model): url = models.TextField(blank=False, null=False, validators=[URLValidator(['http', 'https'])]) active = models.BooleanField() - icon = models.FileField(upload_to='feed-icons', blank=True, null=True, + icon = models.FileField(upload_to='feed-icons', blank=True, null=False, default='default-icon.svg', validators=[FileExtensionValidator(['png', 'svg'])]) keywords = models.TextField(blank=False, null=False) match_all_keywords = models.BooleanField(blank=True, default=False) diff --git a/frontend/src/app/component/dialog/dialog.component.html b/frontend/src/app/component/dialog/dialog.component.html index 713c72a..ccab0f6 100644 --- a/frontend/src/app/component/dialog/dialog.component.html +++ b/frontend/src/app/component/dialog/dialog.component.html @@ -3,6 +3,6 @@

{{data.body}}

- + diff --git a/frontend/src/app/component/einstellungen/editieren/editieren.component.ts b/frontend/src/app/component/einstellungen/editieren/editieren.component.ts index 6e736b5..fa70bc9 100644 --- a/frontend/src/app/component/einstellungen/editieren/editieren.component.ts +++ b/frontend/src/app/component/einstellungen/editieren/editieren.component.ts @@ -35,7 +35,7 @@ export class EditierenComponent implements OnInit { private http: HttpClient, private _snackbar: MatSnackBar, private _logger: NGXLogger, - private _dialog: MatDialog) { + ) { this.route.paramMap.subscribe(paramMap => { this.id = paramMap.get('id'); if (this.id) { @@ -105,25 +105,4 @@ export class EditierenComponent implements OnInit { ); } } - - public saveDialog(feedData) { - const dialogRef = this._dialog.open(DialogComponent, { - data: { - title: 'Neuen Feed erstellen', - body: 'Neuen Feed erstellen?', - abort: 'Abbrechen', - confirm: 'OK', - hideAbort: false - } - }); - - dialogRef.afterClosed().subscribe( - data => { - if (data === true) { - // Confirm button was clicked - this.saveFeed(feedData); - } - } - ); - } } diff --git a/frontend/src/app/component/einstellungen/einstellungen.component.html b/frontend/src/app/component/einstellungen/einstellungen.component.html index c1038ba..90dabc7 100644 --- a/frontend/src/app/component/einstellungen/einstellungen.component.html +++ b/frontend/src/app/component/einstellungen/einstellungen.component.html @@ -15,13 +15,13 @@
-
-
+
diff --git a/frontend/src/app/component/einstellungen/einstellungen.component.ts b/frontend/src/app/component/einstellungen/einstellungen.component.ts index 44d2e8b..e1a08a5 100644 --- a/frontend/src/app/component/einstellungen/einstellungen.component.ts +++ b/frontend/src/app/component/einstellungen/einstellungen.component.ts @@ -1,11 +1,13 @@ import {Component, OnInit} from '@angular/core'; import {HttpClient} from '@angular/common/http'; -import {Observable, throwError} from 'rxjs'; +import {throwError} from 'rxjs'; import {MatSnackBar} from '@angular/material/snack-bar'; import {NGXLogger} from 'ngx-logger'; import {IFeed} from '../../interfaces/feed.interface'; import {FeedService} from '../../services/feed.service'; -import {ActivatedRoute, NavigationEnd, Router} from '@angular/router'; +import {ActivatedRoute} from '@angular/router'; +import {DialogComponent} from '../dialog/dialog.component'; +import {MatDialog} from '@angular/material/dialog'; @Component({ selector: 'app-einstellungen', @@ -16,29 +18,16 @@ export class EinstellungenComponent implements OnInit { icon; - feeds: Observable; - - mySubscription; + feeds: IFeed[] = []; constructor(private http: HttpClient, private _snackbar: MatSnackBar, private _logger: NGXLogger, private _feedService: FeedService, private _route: ActivatedRoute, - private _router: Router) { + private _dialog: MatDialog) { this.icon = 'assets/logo.svg'; - this._router.routeReuseStrategy.shouldReuseRoute = () => false; - this.mySubscription = this._router.events.subscribe((event) => { - if (event instanceof NavigationEnd) { - // Trick the Router into believing it's last link wasn't previously loaded - this._router.navigated = false; - } - }); - this._feedService.getFeeds().subscribe( - (data: any) => { - this.feeds = data; - } - ); + this._feedService.getFeeds().toPromise().then(data => this.feeds = data).catch(err => this._logger.error(err)); } ngOnInit(): void { @@ -48,12 +37,33 @@ export class EinstellungenComponent implements OnInit { this.http.delete('http://127.0.0.1:8000/feeds/' + id + '/').subscribe( () => { this._snackbar.open('Feed erfolgreich gelöscht!', 'Schließen', {duration: 3000}); + this.feeds = this.feeds.filter(feed => feed.id !== id); }, err => { this._logger.error(err); return throwError(err); } ); - this._router.navigate([this._router.url]); + } + + public deleteDialog(id: number) { + const dialogRef = this._dialog.open(DialogComponent, { + data: { + title: 'Feed löschen', + body: 'Feed wirklich löschen?', + abort: 'Abbrechen', + confirm: 'OK', + hideAbort: false + } + }); + + dialogRef.afterClosed().subscribe( + data => { + if (data === true) { + // Confirm button was clicked + this.deleteFeed(id); + } + } + ); } } diff --git a/frontend/src/app/component/tweets/tweets.component.html b/frontend/src/app/component/tweets/tweets.component.html index 7892d63..e9460ef 100644 --- a/frontend/src/app/component/tweets/tweets.component.html +++ b/frontend/src/app/component/tweets/tweets.component.html @@ -1,16 +1,16 @@
-
- Kein RSS_Feed vorhanden +
+ Kein RSS-Feed vorhanden
- RSS-Feed erstellen + RSS-Feed erstellen
-
- Kein Tweets vorhanden +
+ Keine Tweets vorhanden
Schau später noch einmal vorbei!
-
+
diff --git a/frontend/src/app/component/tweets/tweets.component.ts b/frontend/src/app/component/tweets/tweets.component.ts index e5d58e4..3ee55e2 100644 --- a/frontend/src/app/component/tweets/tweets.component.ts +++ b/frontend/src/app/component/tweets/tweets.component.ts @@ -1,6 +1,9 @@ import {Component, OnInit} from '@angular/core'; import {AuthService} from '../../services/auth.service'; import {HttpClient, HttpHeaders} from '@angular/common/http'; +import {FeedService} from '../../services/feed.service'; +import {IFeed} from '../../interfaces/feed.interface'; +import {Observable} from 'rxjs'; class Tweet { @@ -14,9 +17,16 @@ class Tweet { export class TweetsComponent implements OnInit { tweets: Tweet[] = []; + feeds: Observable[] = []; constructor(private http: HttpClient, - private authService: AuthService) { + private authService: AuthService, + private _feedService: FeedService) { + this._feedService.getFeeds().subscribe( + (data: any) => { + this.feeds = data; + } + ); } ngOnInit(): void { diff --git a/frontend/src/app/validators/keywords.validator.ts b/frontend/src/app/validators/keywords.validator.ts index 0166374..a86cfc3 100644 --- a/frontend/src/app/validators/keywords.validator.ts +++ b/frontend/src/app/validators/keywords.validator.ts @@ -1,6 +1,19 @@ import {AbstractControl} from '@angular/forms'; export function keywordsValidator(control: AbstractControl): { [key: string]: any } | null { - const valid = /^((\w){3,},?){1,2}(\w{3,})?$/.test(control.value); - return valid ? null : {'invalidKeywords': {value: control.value}}; + if (control.value == undefined) { + return null; + } + let split: string[]; + split = control.value.split(','); + if (split.length > 3) { + return {'invalidKeywords': {value: control.value}}; + } + for (let i = 0; i < split.length; i++) { + const word = split[i].trim(); + if (word.length < 3) { + return {'invalidKeywords': {value: control.value}}; + } + } + return null; }