From 3f78ba1f3d44f9445be5dd5d7d733c0f6bc67235 Mon Sep 17 00:00:00 2001 From: FinnStutzenstein Date: Sat, 16 Jun 2018 18:05:46 +0200 Subject: [PATCH] Structural changes: - AuthenticationService->AuthService - removed underscore-directories - put site related stuff into site/ - same for projector - auth service went into a core/ directory, used by site and projector - the alert is now not global anymore. Every view can have its own alert - make the auth service query users/whoami for the current user - made a new OpenSlides service for managing the startup ... A lot todo ... --- client/proxy.conf.json | 10 ++- .../_directives/alert/alert.component.html | 4 - .../app/_directives/alert/alert.component.ts | 51 ------------ client/src/app/_services/alert.service.ts | 45 ----------- .../src/app/_services/auth-guard.service.ts | 34 -------- .../app/_services/authentication.service.ts | 69 ---------------- client/src/app/agenda/agenda.component.ts | 12 +-- client/src/app/app-routing.module.ts | 42 +++++----- client/src/app/app.component.html | 1 - client/src/app/app.component.ts | 13 +-- client/src/app/app.module.ts | 12 +-- client/src/app/base.component.ts | 13 --- .../auth.service.spec.ts} | 0 client/src/app/core/auth.service.ts | 81 +++++++++++++++++++ client/src/app/core/openslides.service.ts | 24 ++++++ .../src/app/core/router-auth-guard.service.ts | 40 +++++++++ client/src/app/core/title.service.ts | 16 ++++ client/src/app/login/login.component.ts | 68 ---------------- client/src/app/motions/motions.component.ts | 22 +++-- .../projector-container.component.css} | 0 .../projector-container.component.html | 4 + .../projector-container.component.spec.ts | 25 ++++++ .../projector-container.component.ts | 18 +++++ .../app/projector/projector.component.spec.ts | 32 ++++---- .../src/app/projector/projector.component.ts | 21 ++--- .../alert.component.css} | 0 client/src/app/site/alert.component.html | 4 + .../alert => site}/alert.component.spec.ts | 0 client/src/app/site/alert.component.ts | 34 ++++++++ .../{_services => site}/alert.service.spec.ts | 0 client/src/app/site/alert.service.ts | 33 ++++++++ client/src/app/{_models => site}/alert.ts | 0 client/src/app/site/site.component.html | 7 +- client/src/app/site/site.component.ts | 10 +-- client/src/app/site/start.component.css | 0 client/src/app/site/start.component.html | 7 ++ .../{start => site}/start.component.spec.ts | 0 client/src/app/site/start.component.ts | 22 +++++ client/src/app/start/start.component.html | 3 - client/src/app/start/start.component.ts | 20 ----- .../app/{login => users}/login.component.css | 0 .../app/{login => users}/login.component.html | 5 +- .../{login => users}/login.component.spec.ts | 0 client/src/app/users/login.component.ts | 58 +++++++++++++ 44 files changed, 461 insertions(+), 399 deletions(-) delete mode 100644 client/src/app/_directives/alert/alert.component.html delete mode 100644 client/src/app/_directives/alert/alert.component.ts delete mode 100644 client/src/app/_services/alert.service.ts delete mode 100644 client/src/app/_services/auth-guard.service.ts delete mode 100644 client/src/app/_services/authentication.service.ts delete mode 100644 client/src/app/base.component.ts rename client/src/app/{_services/authentication.service.spec.ts => core/auth.service.spec.ts} (100%) create mode 100644 client/src/app/core/auth.service.ts create mode 100644 client/src/app/core/openslides.service.ts create mode 100644 client/src/app/core/router-auth-guard.service.ts create mode 100644 client/src/app/core/title.service.ts delete mode 100644 client/src/app/login/login.component.ts rename client/src/app/{_directives/alert/alert.component.css => projector/projector-container.component.css} (100%) create mode 100644 client/src/app/projector/projector-container.component.html create mode 100644 client/src/app/projector/projector-container.component.spec.ts create mode 100644 client/src/app/projector/projector-container.component.ts rename client/src/app/{start/start.component.css => site/alert.component.css} (100%) create mode 100644 client/src/app/site/alert.component.html rename client/src/app/{_directives/alert => site}/alert.component.spec.ts (100%) create mode 100644 client/src/app/site/alert.component.ts rename client/src/app/{_services => site}/alert.service.spec.ts (100%) create mode 100644 client/src/app/site/alert.service.ts rename client/src/app/{_models => site}/alert.ts (100%) create mode 100644 client/src/app/site/start.component.css create mode 100644 client/src/app/site/start.component.html rename client/src/app/{start => site}/start.component.spec.ts (100%) create mode 100644 client/src/app/site/start.component.ts delete mode 100644 client/src/app/start/start.component.html delete mode 100644 client/src/app/start/start.component.ts rename client/src/app/{login => users}/login.component.css (100%) rename client/src/app/{login => users}/login.component.html (96%) rename client/src/app/{login => users}/login.component.spec.ts (100%) create mode 100644 client/src/app/users/login.component.ts diff --git a/client/proxy.conf.json b/client/proxy.conf.json index eb40147bc..bac003d55 100644 --- a/client/proxy.conf.json +++ b/client/proxy.conf.json @@ -3,8 +3,16 @@ "target": "http://localhost:8000", "secure": false }, + "/users/logout": { + "target": "http://localhost:8000", + "secure": false + }, + "/users/whoami": { + "target": "http://localhost:8000", + "secure": false + }, "/rest": { "target": "http://localhost:8000", "secure": false } -} \ No newline at end of file +} diff --git a/client/src/app/_directives/alert/alert.component.html b/client/src/app/_directives/alert/alert.component.html deleted file mode 100644 index 8a0c27e4e..000000000 --- a/client/src/app/_directives/alert/alert.component.html +++ /dev/null @@ -1,4 +0,0 @@ -
- {{alert.message}} - × -
\ No newline at end of file diff --git a/client/src/app/_directives/alert/alert.component.ts b/client/src/app/_directives/alert/alert.component.ts deleted file mode 100644 index 0e2e8ee86..000000000 --- a/client/src/app/_directives/alert/alert.component.ts +++ /dev/null @@ -1,51 +0,0 @@ -import { Component, OnInit } from '@angular/core'; - -import { Alert, AlertType } from '../../_models/alert'; -import { AlertService } from '../../_services/alert.service'; - -@Component({ - selector: 'alert', - templateUrl: './alert.component.html', - styleUrls: ['./alert.component.css'] -}) -export class AlertComponent implements OnInit { - alerts: Alert[] = []; - - constructor(private alertService: AlertService) { } - - ngOnInit() { - this.alertService.getAlert().subscribe((alert: Alert) => { - if (!alert) { - // clear alerts when an empty alert is received - this.alerts = []; - return; - } - - // add alert to array - this.alerts.push(alert); - }); - } - - removeAlert(alert: Alert) { - this.alerts = this.alerts.filter(x => x !== alert); - } - - cssClass(alert: Alert) { - if (!alert) { - return; - } - - // return css class based on alert type - switch (alert.type) { - case AlertType.Success: - return 'alert alert-success'; - case AlertType.Error: - return 'alert alert-danger'; - case AlertType.Info: - return 'alert alert-info'; - case AlertType.Warning: - return 'alert alert-warning'; - } - } - -} diff --git a/client/src/app/_services/alert.service.ts b/client/src/app/_services/alert.service.ts deleted file mode 100644 index 4b9464428..000000000 --- a/client/src/app/_services/alert.service.ts +++ /dev/null @@ -1,45 +0,0 @@ -import { Injectable } from '@angular/core'; -import { Observable, Subject } from 'rxjs'; - -import { Alert, AlertType } from '../_models/alert'; - - -@Injectable({ - providedIn: 'root' -}) -export class AlertService { - private subject = new Subject(); - - constructor() { } - - getAlert(): Observable { - return this.subject.asObservable(); - } - - success(message: string) { - this.alert(AlertType.Success, message); - } - - error(message: string) { - this.alert(AlertType.Error, message); - } - - info(message: string) { - this.alert(AlertType.Info, message); - } - - warn(message: string) { - this.alert(AlertType.Warning, message); - } - - alert(type: AlertType, message: string) { - this.subject.next({ type: type, message: message }); - } - - clear() { - // clear alerts - this.subject.next(); - } - - -} diff --git a/client/src/app/_services/auth-guard.service.ts b/client/src/app/_services/auth-guard.service.ts deleted file mode 100644 index e5001b05d..000000000 --- a/client/src/app/_services/auth-guard.service.ts +++ /dev/null @@ -1,34 +0,0 @@ -import { Injectable } from '@angular/core'; -import { - CanActivate, Router, - ActivatedRouteSnapshot, - RouterStateSnapshot -} from '@angular/router'; - -import { AuthenticationService } from "./authentication.service"; - -@Injectable({ - providedIn: 'root' -}) -export class AuthGuard implements CanActivate { - - constructor(private authenticationService: AuthenticationService, private router: Router) { } - - canActivate(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): boolean { - console.log('AuthGuard#canActivate called'); - let url: string = state.url; - - return this.checkLogin(url); - } - - checkLogin(url: string): boolean { - if (this.authenticationService.isLoggedIn) { return true; } - - // Store the attempted URL for redirecting - this.authenticationService.redirectUrl = url; - - // Navigate to the login page with extras - this.router.navigate(['/login']); - return false; - } -} \ No newline at end of file diff --git a/client/src/app/_services/authentication.service.ts b/client/src/app/_services/authentication.service.ts deleted file mode 100644 index 3da07c89d..000000000 --- a/client/src/app/_services/authentication.service.ts +++ /dev/null @@ -1,69 +0,0 @@ -import { Injectable } from '@angular/core'; -import { - HttpClient, HttpResponse, - HttpErrorResponse, HttpHeaders -} from '@angular/common/http'; -import { Observable, of, throwError } from 'rxjs'; -import { catchError, map, tap, delay } from 'rxjs/operators'; - -import { User } from '../users/user'; - -const httpOptions = { - withCredentials: true, - headers: new HttpHeaders({ - 'Content-Type': 'application/json' - }) -}; - -@Injectable({ - providedIn: 'root' -}) -export class AuthenticationService { - isLoggedIn: boolean; - loginURL: string = '/users/login/' - - // store the URL so we can redirect after logging in - redirectUrl: string; - - constructor(private http: HttpClient) { - - //check for the cookie in local storrage - //TODO checks for username now since django does not seem to return a cookie - if(localStorage.getItem("username")) { - this.isLoggedIn = true; - } else { - this.isLoggedIn = false; - } - - } - - //loggins a users. expects a user model - loginUser(user: User): Observable { - return this.http.post(this.loginURL, user, httpOptions) - .pipe( - tap(val => { - this.isLoggedIn = true; - //Set the session cookie in local storrage. - //TODO needs validation - }), - catchError(this.handleError()) - ); - } - - - //logout the user - //TODO not yet used - logoutUser(): void { - this.isLoggedIn = false; - localStorage.removeItem("username"); - } - - //very generic error handling function. - //implicitly returns an observable that will display an error message - private handleError() { - return (error: any): Observable => { - console.error(error); - return of(error); - } - }; -} diff --git a/client/src/app/agenda/agenda.component.ts b/client/src/app/agenda/agenda.component.ts index 466ccfbff..c2f7db1c3 100644 --- a/client/src/app/agenda/agenda.component.ts +++ b/client/src/app/agenda/agenda.component.ts @@ -1,21 +1,17 @@ import { Component, OnInit } from '@angular/core'; -import { BaseComponent } from '../base.component'; -import { Title } from '@angular/platform-browser'; +import { TitleService } from '../core/title.service'; @Component({ selector: 'app-agenda', templateUrl: './agenda.component.html', styleUrls: ['./agenda.component.css'] }) -export class AgendaComponent extends BaseComponent implements OnInit { +export class AgendaComponent implements OnInit { - constructor(titleService: Title) { - super(titleService) + constructor(private titleService: TitleService) { } ngOnInit() { - //TODO translate - super.setTitle("Agenda"); + this.titleService.setTitle("Agenda"); } - } diff --git a/client/src/app/app-routing.module.ts b/client/src/app/app-routing.module.ts index 6a204d2d9..b1471fd09 100644 --- a/client/src/app/app-routing.module.ts +++ b/client/src/app/app-routing.module.ts @@ -1,33 +1,37 @@ import { NgModule } from '@angular/core'; import { RouterModule, Routes } from '@angular/router'; -import { LoginComponent } from './login/login.component'; import { ProjectorComponent } from "./projector/projector.component"; -import { StartComponent } from "./start/start.component"; +import { ProjectorContainerComponent } from "./projector/projector-container.component"; +import { StartComponent } from "./site/start.component"; import { AgendaComponent } from "./agenda/agenda.component"; import { MotionsComponent } from "./motions/motions.component"; import { SiteComponent } from "./site/site.component"; +import { LoginComponent } from './users/login.component'; -import { AuthGuard } from "./_services/auth-guard.service"; +import { RouterAuthGuard } from "./core/router-auth-guard.service"; const routes: Routes = [ - { path: 'projector', component: ProjectorComponent }, - { path: 'login', component: LoginComponent }, - { - path: '', - component: SiteComponent, - canActivate: [AuthGuard], - children: [ - { path: '', component: StartComponent }, - { path: 'agenda', component: AgendaComponent }, - { path: 'motions', component: MotionsComponent }, - ] - }, - { path: '**', redirectTo: '' }, + { path: 'projector/:id', component: ProjectorComponent }, + //{ path: 'projector', redirect: 'projector/1' }, // Test this + { path: 'real-projector/:id', component: ProjectorContainerComponent }, + //{ path: 'real-projector', redirect: 'real-projector/1' }, // this too + { + path: '', + component: SiteComponent, + canActivate: [RouterAuthGuard], + children: [ + { path: '', component: StartComponent }, + { path: 'login', component: LoginComponent }, + { path: 'agenda', component: AgendaComponent }, + { path: 'motions', component: MotionsComponent }, + ] + }, + { path: '**', redirectTo: '' }, ]; @NgModule({ - imports: [RouterModule.forRoot(routes)], - exports: [RouterModule] + imports: [RouterModule.forRoot(routes)], + exports: [RouterModule] }) -export class AppRoutingModule { } \ No newline at end of file +export class AppRoutingModule { } diff --git a/client/src/app/app.component.html b/client/src/app/app.component.html index 6a164d697..0680b43f9 100644 --- a/client/src/app/app.component.html +++ b/client/src/app/app.component.html @@ -1,2 +1 @@ - diff --git a/client/src/app/app.component.ts b/client/src/app/app.component.ts index b3efa092a..4b91c049d 100644 --- a/client/src/app/app.component.ts +++ b/client/src/app/app.component.ts @@ -1,12 +1,15 @@ -import { Component } from '@angular/core'; +import { Component, OnInit } from '@angular/core'; +import { OpenSlidesService } from './core/openslides.service'; @Component({ selector: 'app-root', templateUrl: './app.component.html', styleUrls: ['./app.component.css'] }) -export class AppComponent { - title = 'OpenSlides 3'; - constructor() { } - +export class AppComponent implements OnInit { + constructor(private openSlides: OpenSlidesService) { } + + ngOnInit() { + this.openSlides.bootup(); + } } diff --git a/client/src/app/app.module.ts b/client/src/app/app.module.ts index bb80c4222..880143e94 100644 --- a/client/src/app/app.module.ts +++ b/client/src/app/app.module.ts @@ -7,16 +7,17 @@ import { library } from '@fortawesome/fontawesome-svg-core' import { fas } from '@fortawesome/free-solid-svg-icons'; import { AppComponent } from './app.component'; -import { LoginComponent } from './login/login.component'; +import { LoginComponent } from './users/login.component'; import { UsersComponent } from './users/users.component'; -import { AppRoutingModule } from './/app-routing.module'; +import { AppRoutingModule } from './app-routing.module'; import { ProjectorComponent } from './projector/projector.component'; +import { ProjectorContainerComponent } from './projector/projector-container.component'; import { MotionsComponent } from './motions/motions.component'; import { AgendaComponent } from './agenda/agenda.component'; import { SiteComponent } from './site/site.component'; -import { StartComponent } from './start/start.component'; -import { AlertComponent } from './_directives/alert/alert.component'; -import { AlertService } from './_services/alert.service'; +import { StartComponent } from './site/start.component'; +import { AlertComponent } from './site/alert.component'; +import { AlertService } from './site/alert.service'; //add font-awesome icons to library. //will blow up the code. @@ -28,6 +29,7 @@ library.add(fas); LoginComponent, UsersComponent, ProjectorComponent, + ProjectorContainerComponent, MotionsComponent, AgendaComponent, SiteComponent, diff --git a/client/src/app/base.component.ts b/client/src/app/base.component.ts deleted file mode 100644 index 9fae077ad..000000000 --- a/client/src/app/base.component.ts +++ /dev/null @@ -1,13 +0,0 @@ -import { Title } from '@angular/platform-browser'; - -//provides functions that might be used by a lot of components -export abstract class BaseComponent { - private titleSuffix: string = " - OpenSlides 3"; - - constructor(protected titleService: Title) { } - - setTitle(prefix: string) { - this.titleService.setTitle( prefix + this.titleSuffix ); - } - -} \ No newline at end of file diff --git a/client/src/app/_services/authentication.service.spec.ts b/client/src/app/core/auth.service.spec.ts similarity index 100% rename from client/src/app/_services/authentication.service.spec.ts rename to client/src/app/core/auth.service.spec.ts diff --git a/client/src/app/core/auth.service.ts b/client/src/app/core/auth.service.ts new file mode 100644 index 000000000..41eae7c8e --- /dev/null +++ b/client/src/app/core/auth.service.ts @@ -0,0 +1,81 @@ +import { Injectable } from '@angular/core'; +import { + HttpClient, + HttpResponse, + HttpErrorResponse, + HttpHeaders +} from '@angular/common/http'; +import { Observable, of, throwError } from 'rxjs'; +import { catchError, map, tap, delay } from 'rxjs/operators'; + +import { User } from '../users/user'; + +const httpOptions = { + withCredentials: true, + headers: new HttpHeaders({ + 'Content-Type': 'application/json' + }) +}; + +export interface LoginResponse { + user_id: number; + user: User; +} + +export interface WhoAmIResponse extends LoginResponse { + guest_enabled: boolean; +} + +@Injectable({ + providedIn: 'root' +}) +export class AuthService { + isLoggedIn: boolean = false; + + // store the URL so we can redirect after logging in + redirectUrl: string; + + constructor(private http: HttpClient) { } + + // Initialize the service by querying the server + init(): Observable { + return this.http.get('users/whoami', httpOptions) + .pipe( + catchError(this.handleError()) + ); + } + + loginUser(user: User): Observable { + return this.http.post('users/login', user, httpOptions) + .pipe( + tap(val => { + console.log(val) + }), + catchError(this.handleError()) + ); + } + + //logout the user + //TODO reboot openslides + logout(): any { + console.log("logout"); + // TODO Why isn't the request send?? + let t = this.http.post('users/logout', undefined, httpOptions); + /*.pipe( + tap(val => { + console.log(val) + }), + catchError(this.handleError()) + );*/ + console.log(t); + } + + //very generic error handling function. + //implicitly returns an observable that will display an error message + private handleError() { + return (error: any): Observable => { + console.error(error); + return of(error); + } + }; +} diff --git a/client/src/app/core/openslides.service.ts b/client/src/app/core/openslides.service.ts new file mode 100644 index 000000000..d802762e4 --- /dev/null +++ b/client/src/app/core/openslides.service.ts @@ -0,0 +1,24 @@ +import { Injectable } from '@angular/core'; +import { Router } from '@angular/router'; + +import { AuthService, WhoAmIResponse } from './auth.service'; + +@Injectable({ + providedIn: 'root' +}) +export class OpenSlidesService { + + constructor(private auth: AuthService, private router: Router) { } + + bootup () { + // TODO Lock the interface.. + this.auth.init().subscribe((whoami: WhoAmIResponse) => { + console.log(whoami); + if (!whoami.user && !whoami.guest_enabled) { + this.router.navigate(['/login']); + } else { + // It's ok! + } + }); + } +} diff --git a/client/src/app/core/router-auth-guard.service.ts b/client/src/app/core/router-auth-guard.service.ts new file mode 100644 index 000000000..1f8598e74 --- /dev/null +++ b/client/src/app/core/router-auth-guard.service.ts @@ -0,0 +1,40 @@ +import { Injectable } from '@angular/core'; +import { + CanActivate, + Router, + ActivatedRouteSnapshot, + RouterStateSnapshot +} from '@angular/router'; + +import { AuthService } from './auth.service'; + +@Injectable({ + providedIn: 'root' +}) +export class RouterAuthGuard implements CanActivate { + + constructor(private authService: AuthService, private router: Router) { } + + canActivate(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): boolean { + return this.checkAccess(state.url); + } + + checkAccess(url: string): boolean { + if (url === '/login') { + return true; + } + + // Check base permission for the current state + let hasBasePermission = true; // TODO: get this from the current state... + + if (!hasBasePermission) { + // Store the attempted URL for redirecting + this.authService.redirectUrl = url; + + // Navigate to the login page with extras + this.router.navigate(['/login']); + return false; + } + return true; + } +} diff --git a/client/src/app/core/title.service.ts b/client/src/app/core/title.service.ts new file mode 100644 index 000000000..1f068ae5f --- /dev/null +++ b/client/src/app/core/title.service.ts @@ -0,0 +1,16 @@ +import { Injectable } from '@angular/core'; +import { Title } from '@angular/platform-browser'; + +// Provides functionallity to set the webpage title +@Injectable({ + providedIn: 'root' +}) +export class TitleService { + private titleSuffix: string = " - OpenSlides 3"; + + constructor(protected titleService: Title) { } + + setTitle(prefix: string) { + this.titleService.setTitle(prefix + this.titleSuffix); + } +} diff --git a/client/src/app/login/login.component.ts b/client/src/app/login/login.component.ts deleted file mode 100644 index e31530a0b..000000000 --- a/client/src/app/login/login.component.ts +++ /dev/null @@ -1,68 +0,0 @@ -import { Component, OnInit } from '@angular/core'; -import { Router } from '@angular/router'; -import { Title } from '@angular/platform-browser'; - -import { BaseComponent } from '../base.component'; -import { User } from '../users/user'; -import { AuthenticationService } from '../_services/authentication.service'; -import { AlertService } from '../_services/alert.service'; - -@Component({ - selector: 'app-login', - templateUrl: './login.component.html', - styleUrls: ['./login.component.css'] -}) -export class LoginComponent extends BaseComponent implements OnInit { - user: User = { - username: '', - password: '' - }; - info: string; - - constructor( - titleService: Title, - private authenticationService: AuthenticationService, - private alertService: AlertService, - private router: Router, - ) { - super(titleService); - this.setInfo(); - } - - ngOnInit() { - //TODO translate - super.setTitle("Anmelden"); - } - - setInfo() { - this.info = 'Logged in? ' + (this.authenticationService.isLoggedIn ? 'in' : 'out'); - } - - //Todo: This serves as a prototype and need enhancement, - //like saving a "logged in state" and real checking the server - //if logIn was fine - onSubmit() { - this.authenticationService.loginUser(this.user).subscribe( - res => { - if (res.status === 400) { - //TODO, add more errors here, use translation - this.alertService.error("Benutzername oder Passwort war nicht korrekt."); - } else { - this.alertService.success("Logged in! :)"); - this.setInfo(); - if (this.authenticationService.isLoggedIn) { - localStorage.setItem("username", res.user.username); - - // Get the redirect URL from our auth service - // If no redirect has been set, use the default - let redirect = this.authenticationService.redirectUrl ? - this.authenticationService.redirectUrl : '/'; - - // Redirect the user - this.router.navigate([redirect]); - } - } - } - ); - } -} diff --git a/client/src/app/motions/motions.component.ts b/client/src/app/motions/motions.component.ts index 02cd98bc8..ed45a770a 100644 --- a/client/src/app/motions/motions.component.ts +++ b/client/src/app/motions/motions.component.ts @@ -1,20 +1,18 @@ import { Component, OnInit } from '@angular/core'; -import { BaseComponent } from '../base.component'; -import { Title } from '@angular/platform-browser'; +import { TitleService } from '../core/title.service'; @Component({ - selector: 'app-motions', - templateUrl: './motions.component.html', - styleUrls: ['./motions.component.css'] + selector: 'app-motions', + templateUrl: './motions.component.html', + styleUrls: ['./motions.component.css'] }) -export class MotionsComponent extends BaseComponent implements OnInit { +export class MotionsComponent implements OnInit { - constructor(titleService: Title) { - super(titleService) - } + constructor(private titleService: TitleService) { + } - ngOnInit() { - super.setTitle("Motions"); - } + ngOnInit() { + this.titleService.setTitle("Motions"); + } } diff --git a/client/src/app/_directives/alert/alert.component.css b/client/src/app/projector/projector-container.component.css similarity index 100% rename from client/src/app/_directives/alert/alert.component.css rename to client/src/app/projector/projector-container.component.css diff --git a/client/src/app/projector/projector-container.component.html b/client/src/app/projector/projector-container.component.html new file mode 100644 index 000000000..6b1d082bd --- /dev/null +++ b/client/src/app/projector/projector-container.component.html @@ -0,0 +1,4 @@ +

+ projector container works! + Here an iframe with the real-projector is needed +

diff --git a/client/src/app/projector/projector-container.component.spec.ts b/client/src/app/projector/projector-container.component.spec.ts new file mode 100644 index 000000000..748620bc3 --- /dev/null +++ b/client/src/app/projector/projector-container.component.spec.ts @@ -0,0 +1,25 @@ +import { async, ComponentFixture, TestBed } from '@angular/core/testing'; + +import { ProjectorContainerComponent } from './projector-container.component'; + +describe('ProjectorContainerComponent', () => { + let component: ProjectorContainerComponent; + let fixture: ComponentFixture; + + beforeEach(async(() => { + TestBed.configureTestingModule({ + declarations: [ ProjectorContainerComponent ] + }) + .compileComponents(); + })); + + beforeEach(() => { + fixture = TestBed.createComponent(ProjectorContainerComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/client/src/app/projector/projector-container.component.ts b/client/src/app/projector/projector-container.component.ts new file mode 100644 index 000000000..bc7095b18 --- /dev/null +++ b/client/src/app/projector/projector-container.component.ts @@ -0,0 +1,18 @@ +import { Component, OnInit } from '@angular/core'; +import { TitleService } from '../core/title.service'; + +@Component({ + selector: 'app-projector-container', + templateUrl: './projector-container.component.html', + styleUrls: ['./projector-container.component.css'] +}) +export class ProjectorContainerComponent implements OnInit { + + constructor(protected titleService: TitleService) { + } + + ngOnInit() { + this.titleService.setTitle('Projector'); + } + +} diff --git a/client/src/app/projector/projector.component.spec.ts b/client/src/app/projector/projector.component.spec.ts index 210497b72..587ab453a 100644 --- a/client/src/app/projector/projector.component.spec.ts +++ b/client/src/app/projector/projector.component.spec.ts @@ -3,23 +3,23 @@ import { async, ComponentFixture, TestBed } from '@angular/core/testing'; import { ProjectorComponent } from './projector.component'; describe('ProjectorComponent', () => { - let component: ProjectorComponent; - let fixture: ComponentFixture; + let component: ProjectorComponent; + let fixture: ComponentFixture; - beforeEach(async(() => { - TestBed.configureTestingModule({ - declarations: [ ProjectorComponent ] - }) - .compileComponents(); - })); + beforeEach(async(() => { + TestBed.configureTestingModule({ + declarations: [ ProjectorComponent ] + }) + .compileComponents(); + })); - beforeEach(() => { - fixture = TestBed.createComponent(ProjectorComponent); - component = fixture.componentInstance; - fixture.detectChanges(); - }); + beforeEach(() => { + fixture = TestBed.createComponent(ProjectorComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); - it('should create', () => { - expect(component).toBeTruthy(); - }); + it('should create', () => { + expect(component).toBeTruthy(); + }); }); diff --git a/client/src/app/projector/projector.component.ts b/client/src/app/projector/projector.component.ts index 4c05d3998..c7377195d 100644 --- a/client/src/app/projector/projector.component.ts +++ b/client/src/app/projector/projector.component.ts @@ -1,20 +1,15 @@ import { Component, OnInit } from '@angular/core'; -import { BaseComponent } from '../base.component'; -import { Title } from '@angular/platform-browser'; @Component({ - selector: 'app-projector', - templateUrl: './projector.component.html', - styleUrls: ['./projector.component.css'] + selector: 'app-projector', + templateUrl: './projector.component.html', + styleUrls: ['./projector.component.css'] }) -export class ProjectorComponent extends BaseComponent implements OnInit { +export class ProjectorComponent implements OnInit { - constructor(protected titleService: Title) { - super(titleService) - } - - ngOnInit() { - super.setTitle("Projector"); - } + constructor() { + } + ngOnInit() { + } } diff --git a/client/src/app/start/start.component.css b/client/src/app/site/alert.component.css similarity index 100% rename from client/src/app/start/start.component.css rename to client/src/app/site/alert.component.css diff --git a/client/src/app/site/alert.component.html b/client/src/app/site/alert.component.html new file mode 100644 index 000000000..bcc236e3b --- /dev/null +++ b/client/src/app/site/alert.component.html @@ -0,0 +1,4 @@ +
+ {{alert.message}} + × +
diff --git a/client/src/app/_directives/alert/alert.component.spec.ts b/client/src/app/site/alert.component.spec.ts similarity index 100% rename from client/src/app/_directives/alert/alert.component.spec.ts rename to client/src/app/site/alert.component.spec.ts diff --git a/client/src/app/site/alert.component.ts b/client/src/app/site/alert.component.ts new file mode 100644 index 000000000..1866c730a --- /dev/null +++ b/client/src/app/site/alert.component.ts @@ -0,0 +1,34 @@ +import { Component, OnInit, Input } from '@angular/core'; + +import { Alert, AlertType } from './alert'; + +@Component({ + selector: 'alert', + templateUrl: './alert.component.html', + styleUrls: ['./alert.component.css'] +}) +export class AlertComponent implements OnInit { + @Input() alert: Alert; + + constructor() { } + + ngOnInit() { } + + removeAlert(alert: Alert) { + this.alert = undefined; + } + + cssClass(alert: Alert) { + // return css class based on alert type + switch (alert.type) { + case AlertType.Success: + return 'alert alert-success'; + case AlertType.Error: + return 'alert alert-danger'; + case AlertType.Info: + return 'alert alert-info'; + case AlertType.Warning: + return 'alert alert-warning'; + } + } +} diff --git a/client/src/app/_services/alert.service.spec.ts b/client/src/app/site/alert.service.spec.ts similarity index 100% rename from client/src/app/_services/alert.service.spec.ts rename to client/src/app/site/alert.service.spec.ts diff --git a/client/src/app/site/alert.service.ts b/client/src/app/site/alert.service.ts new file mode 100644 index 000000000..a91e92634 --- /dev/null +++ b/client/src/app/site/alert.service.ts @@ -0,0 +1,33 @@ +import { Injectable } from '@angular/core'; + +import { Alert, AlertType } from './alert'; + + +@Injectable({ + providedIn: 'root' +}) +export class AlertService { + constructor() { } + + success(message: string): Alert { + return this.alert(AlertType.Success, message); + } + + error(message: string): Alert { + return this.alert(AlertType.Error, message); + } + + info(message: string): Alert { + return this.alert(AlertType.Info, message); + } + + warn(message: string): Alert { + return this.alert(AlertType.Warning, message); + } + + alert(type: AlertType, message: string): Alert { + return { type: type, message: message }; + } + + // TODO fromHttpError() to generate alerts form http errors +} diff --git a/client/src/app/_models/alert.ts b/client/src/app/site/alert.ts similarity index 100% rename from client/src/app/_models/alert.ts rename to client/src/app/site/alert.ts diff --git a/client/src/app/site/site.component.html b/client/src/app/site/site.component.html index 447cde845..c11cb8fba 100644 --- a/client/src/app/site/site.component.html +++ b/client/src/app/site/site.component.html @@ -1,3 +1,4 @@ -

The actual OpenSldies Content!

- -
Footer
\ No newline at end of file +

The actual OpenSldies Content!

+ + +
Footer
diff --git a/client/src/app/site/site.component.ts b/client/src/app/site/site.component.ts index ec09ea568..a68ba09d9 100644 --- a/client/src/app/site/site.component.ts +++ b/client/src/app/site/site.component.ts @@ -1,15 +1,13 @@ import { Component, OnInit } from '@angular/core'; @Component({ - selector: 'app-site', - templateUrl: './site.component.html', - styleUrls: ['./site.component.css'] + selector: 'app-site', + templateUrl: './site.component.html', + styleUrls: ['./site.component.css'] }) export class SiteComponent implements OnInit { constructor() { } - ngOnInit() { - } - + ngOnInit() { } } diff --git a/client/src/app/site/start.component.css b/client/src/app/site/start.component.css new file mode 100644 index 000000000..e69de29bb diff --git a/client/src/app/site/start.component.html b/client/src/app/site/start.component.html new file mode 100644 index 000000000..4f0120744 --- /dev/null +++ b/client/src/app/site/start.component.html @@ -0,0 +1,7 @@ +

+ start works! + Here the welcome text is displayed +

+ diff --git a/client/src/app/start/start.component.spec.ts b/client/src/app/site/start.component.spec.ts similarity index 100% rename from client/src/app/start/start.component.spec.ts rename to client/src/app/site/start.component.spec.ts diff --git a/client/src/app/site/start.component.ts b/client/src/app/site/start.component.ts new file mode 100644 index 000000000..16c2ed7d8 --- /dev/null +++ b/client/src/app/site/start.component.ts @@ -0,0 +1,22 @@ +import { Component, OnInit } from '@angular/core'; + +import { TitleService } from '../core/title.service'; +import {AuthService } from '../core/auth.service'; + +@Component({ + selector: 'app-start', + templateUrl: './start.component.html', + styleUrls: ['./start.component.css'] +}) +export class StartComponent implements OnInit { + + constructor(private titleService: TitleService, private auth: AuthService) { } + + ngOnInit() { + this.titleService.setTitle('Start page'); + } + + logout() { + this.auth.logout(); + } +} diff --git a/client/src/app/start/start.component.html b/client/src/app/start/start.component.html deleted file mode 100644 index 0c59dfcd7..000000000 --- a/client/src/app/start/start.component.html +++ /dev/null @@ -1,3 +0,0 @@ -

- start works! -

diff --git a/client/src/app/start/start.component.ts b/client/src/app/start/start.component.ts deleted file mode 100644 index 6935bf090..000000000 --- a/client/src/app/start/start.component.ts +++ /dev/null @@ -1,20 +0,0 @@ -import { Component, OnInit } from '@angular/core'; -import { BaseComponent } from '../base.component'; -import { Title } from '@angular/platform-browser'; - -@Component({ - selector: 'app-start', - templateUrl: './start.component.html', - styleUrls: ['./start.component.css'] -}) -export class StartComponent extends BaseComponent implements OnInit { - - constructor(titleService: Title) { - super(titleService) - } - - ngOnInit() { - super.setTitle("Start page"); - } - -} diff --git a/client/src/app/login/login.component.css b/client/src/app/users/login.component.css similarity index 100% rename from client/src/app/login/login.component.css rename to client/src/app/users/login.component.css diff --git a/client/src/app/login/login.component.html b/client/src/app/users/login.component.html similarity index 96% rename from client/src/app/login/login.component.html rename to client/src/app/users/login.component.html index 6fcd46c47..2e6499638 100644 --- a/client/src/app/login/login.component.html +++ b/client/src/app/users/login.component.html @@ -4,9 +4,8 @@ \ No newline at end of file + diff --git a/client/src/app/login/login.component.spec.ts b/client/src/app/users/login.component.spec.ts similarity index 100% rename from client/src/app/login/login.component.spec.ts rename to client/src/app/users/login.component.spec.ts diff --git a/client/src/app/users/login.component.ts b/client/src/app/users/login.component.ts new file mode 100644 index 000000000..293ab484b --- /dev/null +++ b/client/src/app/users/login.component.ts @@ -0,0 +1,58 @@ +import { Component, OnInit } from '@angular/core'; +import { Router } from '@angular/router'; + +import { User } from '../users/user'; +import { AuthService } from '../core/auth.service'; +import { AlertService } from '../site/alert.service'; +import { TitleService } from '../core/title.service'; + +@Component({ + selector: 'app-login', + templateUrl: './login.component.html', + styleUrls: ['./login.component.css'] +}) +export class LoginComponent implements OnInit { + user: User = { + username: '', + password: '' + }; + + constructor( + private titleService: TitleService, + private authService: AuthService, + private alertService: AlertService, + private router: Router, + ) { } + + ngOnInit() { + //TODO translate + this.titleService.setTitle('Anmelden'); + } + + //Todo: This serves as a prototype and need enhancement, + //like saving a "logged in state" and real checking the server + //if logIn was fine + onSubmit() { + this.authService.loginUser(this.user).subscribe( + res => { + // TODO an error is thrown here. Also all this stuff should the the auth service.. + /*if (res.status === 400) { + // TODO Use the error that comes from the server + //this.alertService.error("Benutzername oder Passwort war nicht korrekt."); + } else { + if (this.authService.isLoggedIn) { + // Get the redirect URL from our auth service + // If no redirect has been set, use the default + let redirect = this.authService.redirectUrl ? + this.authService.redirectUrl : '/'; + + // TODO check, if there is a redirect url. Else redirect to / + + // Redirect the user + this.router.navigate([redirect]); + } + }*/ + } + ); + } +}