Client: add ability for user to change nsfw settings
authorChocobozzz <florian.bigard@gmail.com>
Thu, 6 Apr 2017 19:21:03 +0000 (21:21 +0200)
committerChocobozzz <florian.bigard@gmail.com>
Thu, 6 Apr 2017 19:21:03 +0000 (21:21 +0200)
13 files changed:
client/src/app/account/account-change-password/account-change-password.component.html [new file with mode: 0644]
client/src/app/account/account-change-password/account-change-password.component.ts [new file with mode: 0644]
client/src/app/account/account-change-password/index.ts [new file with mode: 0644]
client/src/app/account/account-details/account-details.component.html [new file with mode: 0644]
client/src/app/account/account-details/account-details.component.ts [new file with mode: 0644]
client/src/app/account/account-details/index.ts [new file with mode: 0644]
client/src/app/account/account.component.html
client/src/app/account/account.component.scss [new file with mode: 0644]
client/src/app/account/account.component.ts
client/src/app/account/account.module.ts
client/src/app/core/auth/auth-user.model.ts
client/src/app/core/auth/auth.service.ts
client/src/app/shared/users/user.service.ts

diff --git a/client/src/app/account/account-change-password/account-change-password.component.html b/client/src/app/account/account-change-password/account-change-password.component.html
new file mode 100644 (file)
index 0000000..92d9f90
--- /dev/null
@@ -0,0 +1,24 @@
+<div *ngIf="error" class="alert alert-danger">{{ error }}</div>
+
+<form role="form" (ngSubmit)="changePassword()" [formGroup]="form">
+  <div class="form-group">
+    <label for="new-password">New password</label>
+    <input
+      type="password" class="form-control" id="new-password"
+      formControlName="new-password"
+    >
+    <div *ngIf="formErrors['new-password']" class="alert alert-danger">
+      {{ formErrors['new-password'] }}
+    </div>
+  </div>
+
+  <div class="form-group">
+    <label for="name">Confirm new password</label>
+    <input
+      type="password" class="form-control" id="new-confirmed-password"
+      formControlName="new-confirmed-password"
+    >
+  </div>
+
+  <input type="submit" value="Change password" class="btn btn-default" [disabled]="!form.valid">
+</form>
diff --git a/client/src/app/account/account-change-password/account-change-password.component.ts b/client/src/app/account/account-change-password/account-change-password.component.ts
new file mode 100644 (file)
index 0000000..15dc42d
--- /dev/null
@@ -0,0 +1,66 @@
+import { Component, OnInit } from '@angular/core';
+import { FormBuilder, FormGroup } from '@angular/forms';
+import { Router } from '@angular/router';
+
+import { NotificationsService } from 'angular2-notifications';
+
+import { FormReactive, UserService, USER_PASSWORD } from '../../shared';
+
+@Component({
+  selector: 'my-account-change-password',
+  templateUrl: './account-change-password.component.html'
+})
+
+export class AccountChangePasswordComponent extends FormReactive implements OnInit {
+  error: string = null;
+
+  form: FormGroup;
+  formErrors = {
+    'new-password': '',
+    'new-confirmed-password': ''
+  };
+  validationMessages = {
+    'new-password': USER_PASSWORD.MESSAGES,
+    'new-confirmed-password': USER_PASSWORD.MESSAGES
+  };
+
+  constructor(
+    private formBuilder: FormBuilder,
+    private router: Router,
+    private notificationsService: NotificationsService,
+    private userService: UserService
+  ) {
+    super();
+  }
+
+  buildForm() {
+    this.form = this.formBuilder.group({
+      'new-password': [ '', USER_PASSWORD.VALIDATORS ],
+      'new-confirmed-password': [ '', USER_PASSWORD.VALIDATORS ],
+    });
+
+    this.form.valueChanges.subscribe(data => this.onValueChanged(data));
+  }
+
+  ngOnInit() {
+    this.buildForm();
+  }
+
+  changePassword() {
+    const newPassword = this.form.value['new-password'];
+    const newConfirmedPassword = this.form.value['new-confirmed-password'];
+
+    this.error = null;
+
+    if (newPassword !== newConfirmedPassword) {
+      this.error = 'The new password and the confirmed password do not correspond.';
+      return;
+    }
+
+    this.userService.changePassword(newPassword).subscribe(
+      () => this.notificationsService.success('Success', 'Password updated.'),
+
+      err => this.error = err
+    );
+  }
+}
diff --git a/client/src/app/account/account-change-password/index.ts b/client/src/app/account/account-change-password/index.ts
new file mode 100644 (file)
index 0000000..72a63e4
--- /dev/null
@@ -0,0 +1 @@
+export * from './account-change-password.component';
diff --git a/client/src/app/account/account-details/account-details.component.html b/client/src/app/account/account-details/account-details.component.html
new file mode 100644 (file)
index 0000000..24b0750
--- /dev/null
@@ -0,0 +1,16 @@
+<div *ngIf="error" class="alert alert-danger">{{ error }}</div>
+
+<form role="form" (ngSubmit)="updateDetails()" [formGroup]="form">
+  <div class="form-group">
+    <label for="displayNSFW">Display NSFW videos</label>
+    <input
+      type="checkbox" id="displayNSFW"
+      formControlName="displayNSFW"
+    >
+    <div *ngIf="formErrors['displayNSFW']" class="alert alert-danger">
+      {{ formErrors['displayNSFW'] }}
+    </div>
+  </div>
+
+  <input type="submit" value="Update" class="btn btn-default" [disabled]="!form.valid">
+</form>
diff --git a/client/src/app/account/account-details/account-details.component.ts b/client/src/app/account/account-details/account-details.component.ts
new file mode 100644 (file)
index 0000000..30e5b14
--- /dev/null
@@ -0,0 +1,68 @@
+import { Component, OnInit, Input } from '@angular/core';
+import { FormBuilder, FormGroup } from '@angular/forms';
+import { Router } from '@angular/router';
+
+import { NotificationsService } from 'angular2-notifications';
+
+import { AuthService } from '../../core';
+import {
+  FormReactive,
+  User,
+  UserService,
+  USER_PASSWORD
+} from '../../shared';
+
+@Component({
+  selector: 'my-account-details',
+  templateUrl: './account-details.component.html'
+})
+
+export class AccountDetailsComponent extends FormReactive implements OnInit {
+  @Input() user: User = null;
+
+  error: string = null;
+
+  form: FormGroup;
+  formErrors = {};
+  validationMessages = {};
+
+  constructor(
+    private authService: AuthService,
+    private formBuilder: FormBuilder,
+    private router: Router,
+    private notificationsService: NotificationsService,
+    private userService: UserService
+  ) {
+    super();
+  }
+
+  buildForm() {
+    this.form = this.formBuilder.group({
+      displayNSFW: [ this.user.displayNSFW ],
+    });
+
+    this.form.valueChanges.subscribe(data => this.onValueChanged(data));
+  }
+
+  ngOnInit() {
+    this.buildForm();
+  }
+
+  updateDetails() {
+    const displayNSFW = this.form.value['displayNSFW'];
+    const details = {
+      displayNSFW
+    };
+
+    this.error = null;
+    this.userService.updateDetails(details).subscribe(
+      () => {
+        this.notificationsService.success('Success', 'Informations updated.');
+
+        this.authService.refreshUserInformations();
+      },
+
+      err => this.error = err
+    );
+  }
+}
diff --git a/client/src/app/account/account-details/index.ts b/client/src/app/account/account-details/index.ts
new file mode 100644 (file)
index 0000000..28f6447
--- /dev/null
@@ -0,0 +1 @@
+export * from './account-details.component';
index 2fbb5a90882171b5a7f825981feca32aa8b66c80..6f10e79cd212c79a61092d855256d7fc08cb1f5d 100644 (file)
@@ -1,26 +1,11 @@
 <h3>Account</h3>
 
-<div *ngIf="error" class="alert alert-danger">{{ error }}</div>
-
-<form role="form" (ngSubmit)="changePassword()" [formGroup]="form">
-  <div class="form-group">
-    <label for="new-password">New password</label>
-    <input
-      type="password" class="form-control" id="new-password"
-      formControlName="new-password"
-    >
-    <div *ngIf="formErrors['new-password']" class="alert alert-danger">
-      {{ formErrors['new-password'] }}
-    </div>
-  </div>
-
-  <div class="form-group">
-    <label for="name">Confirm new password</label>
-    <input
-      type="password" class="form-control" id="new-confirmed-password"
-      formControlName="new-confirmed-password"
-    >
-  </div>
-
-  <input type="submit" value="Change password" class="btn btn-default" [disabled]="!form.valid">
-</form>
+<div class="block">
+  <h4>Change password</h4>
+  <my-account-change-password></my-account-change-password>
+</div>
+
+<div class="block">
+  <h4>Update my informations</h4>
+  <my-account-details [user]="user"></my-account-details>
+</div>
diff --git a/client/src/app/account/account.component.scss b/client/src/app/account/account.component.scss
new file mode 100644 (file)
index 0000000..e0437e7
--- /dev/null
@@ -0,0 +1,3 @@
+.block {
+  margin-top: 40px;
+}
index 14452a73eccbdeacb406c1ab6eb87d7f667bc40d..57b3d4ccd4c052f1ab674bea3df4990c0514b9fa 100644 (file)
@@ -4,63 +4,25 @@ import { Router } from '@angular/router';
 
 import { NotificationsService } from 'angular2-notifications';
 
-import { FormReactive, UserService, USER_PASSWORD } from '../shared';
+import { AuthService } from '../core';
+import {
+  FormReactive,
+  User,
+  UserService,
+  USER_PASSWORD
+} from '../shared';
 
 @Component({
   selector: 'my-account',
-  templateUrl: './account.component.html'
+  templateUrl: './account.component.html',
+  styleUrls: [ './account.component.scss' ]
 })
+export class AccountComponent implements OnInit {
+  user: User = null;
 
-export class AccountComponent extends FormReactive implements OnInit {
-  error: string = null;
-
-  form: FormGroup;
-  formErrors = {
-    'new-password': '',
-    'new-confirmed-password': ''
-  };
-  validationMessages = {
-    'new-password': USER_PASSWORD.MESSAGES,
-    'new-confirmed-password': USER_PASSWORD.MESSAGES
-  };
-
-  constructor(
-    private formBuilder: FormBuilder,
-    private router: Router,
-    private notificationsService: NotificationsService,
-    private userService: UserService
-  ) {
-    super();
-  }
-
-  buildForm() {
-    this.form = this.formBuilder.group({
-      'new-password': [ '', USER_PASSWORD.VALIDATORS ],
-      'new-confirmed-password': [ '', USER_PASSWORD.VALIDATORS ],
-    });
-
-    this.form.valueChanges.subscribe(data => this.onValueChanged(data));
-  }
+  constructor(private authService: AuthService) {}
 
   ngOnInit() {
-    this.buildForm();
-  }
-
-  changePassword() {
-    const newPassword = this.form.value['new-password'];
-    const newConfirmedPassword = this.form.value['new-confirmed-password'];
-
-    this.error = null;
-
-    if (newPassword !== newConfirmedPassword) {
-      this.error = 'The new password and the confirmed password do not correspond.';
-      return;
-    }
-
-    this.userService.changePassword(newPassword).subscribe(
-      () => this.notificationsService.success('Success', 'Password updated.'),
-
-      err => this.error = err
-    );
+    this.user = this.authService.getUser();
   }
 }
index 75f2ee6f9b33d8ac7ecf230073d7306e7327fc48..f6c141ae6ae4f4590c566b1ef84989e12f1a2838 100644 (file)
@@ -2,6 +2,8 @@ import { NgModule } from '@angular/core';
 
 import { AccountRoutingModule } from './account-routing.module';
 import { AccountComponent } from './account.component';
+import { AccountChangePasswordComponent } from './account-change-password';
+import { AccountDetailsComponent } from './account-details';
 import { AccountService } from './account.service';
 import { SharedModule } from '../shared';
 
@@ -12,7 +14,9 @@ import { SharedModule } from '../shared';
   ],
 
   declarations: [
-    AccountComponent
+    AccountComponent,
+    AccountChangePasswordComponent,
+    AccountDetailsComponent
   ],
 
   exports: [
index cb7e88d19e1f248d94dd0b33077f37d0132c705d..7115b97817ca2118448d0d16675a9058dbfb3260 100644 (file)
@@ -67,7 +67,7 @@ export class AuthUser extends User {
     localStorage.setItem(AuthUser.KEYS.ID, this.id.toString());
     localStorage.setItem(AuthUser.KEYS.USERNAME, this.username);
     localStorage.setItem(AuthUser.KEYS.ROLE, this.role);
-    localStorage.setItem(AuthUser.KEYS.DISPLAY_NSFW, JSON.stringify(this.displayNSFW);
+    localStorage.setItem(AuthUser.KEYS.DISPLAY_NSFW, JSON.stringify(this.displayNSFW));
     this.tokens.save();
   }
 }
index 2e73281976c2e6626289701f08fe26913373b04d..00a4216ef202b8f066ac4d5bcfcc57e289ff3e5b 100644 (file)
@@ -125,7 +125,7 @@ export class AuthService {
                       res.username = username;
                       return res;
                     })
-                    .flatMap(res => this.fetchUserInformations(res))
+                    .flatMap(res => this.mergeUserInformations(res))
                     .map(res => this.handleLogin(res))
                     .catch((res) => this.restExtractor.handleError(res));
   }
@@ -178,7 +178,23 @@ export class AuthService {
                     });
   }
 
-  private fetchUserInformations (obj: any) {
+  refreshUserInformations() {
+    const obj = {
+      access_token: this.user.getAccessToken()
+    };
+
+    this.mergeUserInformations(obj)
+        .subscribe(
+          res => {
+            this.user.displayNSFW = res.displayNSFW;
+            this.user.role = res.role;
+
+            this.user.save();
+          }
+        );
+  }
+
+  private mergeUserInformations(obj: { access_token: string }) {
     // Do not call authHttp here to avoid circular dependencies headaches
 
     const headers = new Headers();
@@ -187,9 +203,13 @@ export class AuthService {
     return this.http.get(AuthService.BASE_USER_INFORMATIONS_URL, { headers })
              .map(res => res.json())
              .map(res => {
-               obj.id = res.id;
-               obj.role = res.role;
-               return obj;
+               const newProperties = {
+                 id: res.id,
+                 role: res.role,
+                 displayNSFW: res.displayNSFW
+               };
+
+               return Object.assign(obj, newProperties);
              }
     );
   }
@@ -198,13 +218,14 @@ export class AuthService {
     const id = obj.id;
     const username = obj.username;
     const role = obj.role;
+    const displayNSFW = obj.displayNSFW;
     const hashTokens = {
       access_token: obj.access_token,
       token_type: obj.token_type,
       refresh_token: obj.refresh_token
     };
 
-    this.user = new AuthUser({ id, username, role }, hashTokens);
+    this.user = new AuthUser({ id, username, role, displayNSFW }, hashTokens);
     this.user.save();
 
     this.setStatus(AuthStatus.LoggedIn);
index 865e04d485693795bcf287512f3cd2f45dc8c67b..0d41b900d329a45401f2119e3803a54d3be73824 100644 (file)
@@ -33,4 +33,12 @@ export class UserService {
                         .map(this.restExtractor.extractDataBool)
                         .catch((res) => this.restExtractor.handleError(res));
   }
+
+  updateDetails(details: { displayNSFW: boolean }) {
+    const url = UserService.BASE_USERS_URL + this.authService.getUser().id;
+
+    return this.authHttp.put(url, details)
+                        .map(this.restExtractor.extractDataBool)
+                        .catch((res) => this.restExtractor.handleError(res));
+  }
 }