From 8094a8980265a0a28e508dbd7cf7c7029e6d98b6 Mon Sep 17 00:00:00 2001 From: Chocobozzz Date: Tue, 5 Sep 2017 21:29:39 +0200 Subject: Add user update for admins --- client/src/app/+admin/admin.module.ts | 3 +- client/src/app/+admin/users/index.ts | 2 +- client/src/app/+admin/users/shared/user.service.ts | 14 ++- client/src/app/+admin/users/user-add/index.ts | 1 - .../+admin/users/user-add/user-add.component.html | 58 ----------- .../+admin/users/user-add/user-add.component.ts | 79 --------------- client/src/app/+admin/users/user-edit/index.ts | 2 + .../+admin/users/user-edit/user-add.component.ts | 87 +++++++++++++++++ .../users/user-edit/user-edit.component.html | 55 +++++++++++ client/src/app/+admin/users/user-edit/user-edit.ts | 16 ++++ .../users/user-edit/user-update.component.ts | 106 +++++++++++++++++++++ .../users/user-list/user-list.component.html | 2 +- .../+admin/users/user-list/user-list.component.ts | 17 +++- client/src/app/+admin/users/users.routes.ts | 11 ++- .../account-change-password.component.ts | 1 - .../account-details/account-details.component.ts | 9 +- client/src/app/shared/users/user.service.ts | 12 +-- client/src/app/shared/utils.ts | 4 + 18 files changed, 320 insertions(+), 159 deletions(-) delete mode 100644 client/src/app/+admin/users/user-add/index.ts delete mode 100644 client/src/app/+admin/users/user-add/user-add.component.html delete mode 100644 client/src/app/+admin/users/user-add/user-add.component.ts create mode 100644 client/src/app/+admin/users/user-edit/index.ts create mode 100644 client/src/app/+admin/users/user-edit/user-add.component.ts create mode 100644 client/src/app/+admin/users/user-edit/user-edit.component.html create mode 100644 client/src/app/+admin/users/user-edit/user-edit.ts create mode 100644 client/src/app/+admin/users/user-edit/user-update.component.ts (limited to 'client/src/app') diff --git a/client/src/app/+admin/admin.module.ts b/client/src/app/+admin/admin.module.ts index e4ba8e5b7..853085a83 100644 --- a/client/src/app/+admin/admin.module.ts +++ b/client/src/app/+admin/admin.module.ts @@ -4,7 +4,7 @@ import { AdminComponent } from './admin.component' import { AdminRoutingModule } from './admin-routing.module' import { FriendsComponent, FriendAddComponent, FriendListComponent, FriendService } from './friends' import { RequestSchedulersComponent, RequestSchedulersStatsComponent, RequestSchedulersService } from './request-schedulers' -import { UsersComponent, UserAddComponent, UserListComponent, UserService } from './users' +import { UsersComponent, UserAddComponent, UserUpdateComponent, UserListComponent, UserService } from './users' import { VideoAbusesComponent, VideoAbuseListComponent } from './video-abuses' import { SharedModule } from '../shared' @@ -26,6 +26,7 @@ import { SharedModule } from '../shared' UsersComponent, UserAddComponent, + UserUpdateComponent, UserListComponent, VideoAbusesComponent, diff --git a/client/src/app/+admin/users/index.ts b/client/src/app/+admin/users/index.ts index cef2c282c..efcd0d9cb 100644 --- a/client/src/app/+admin/users/index.ts +++ b/client/src/app/+admin/users/index.ts @@ -1,5 +1,5 @@ export * from './shared' -export * from './user-add' +export * from './user-edit' export * from './user-list' export * from './users.component' export * from './users.routes' diff --git a/client/src/app/+admin/users/shared/user.service.ts b/client/src/app/+admin/users/shared/user.service.ts index ffd7ba7da..999013bcc 100644 --- a/client/src/app/+admin/users/shared/user.service.ts +++ b/client/src/app/+admin/users/shared/user.service.ts @@ -5,7 +5,7 @@ import 'rxjs/add/operator/map' import { BytesPipe } from 'angular-pipes/src/math/bytes.pipe' import { AuthHttp, RestExtractor, RestDataSource, User } from '../../../shared' -import { UserCreate } from '../../../../../../shared' +import { UserCreate, UserUpdate } from '../../../../../../shared' @Injectable() export class UserService { @@ -23,6 +23,18 @@ export class UserService { .catch(this.restExtractor.handleError) } + updateUser (userId: number, userUpdate: UserUpdate) { + return this.authHttp.put(UserService.BASE_USERS_URL + userId, userUpdate) + .map(this.restExtractor.extractDataBool) + .catch(this.restExtractor.handleError) + } + + getUser (userId: number) { + return this.authHttp.get(UserService.BASE_USERS_URL + userId) + .map(this.restExtractor.extractDataGet) + .catch(this.restExtractor.handleError) + } + getDataSource () { return new RestDataSource(this.authHttp, UserService.BASE_USERS_URL, this.formatDataSource.bind(this)) } diff --git a/client/src/app/+admin/users/user-add/index.ts b/client/src/app/+admin/users/user-add/index.ts deleted file mode 100644 index 3a4654101..000000000 --- a/client/src/app/+admin/users/user-add/index.ts +++ /dev/null @@ -1 +0,0 @@ -export * from './user-add.component' diff --git a/client/src/app/+admin/users/user-add/user-add.component.html b/client/src/app/+admin/users/user-add/user-add.component.html deleted file mode 100644 index f84d72c7c..000000000 --- a/client/src/app/+admin/users/user-add/user-add.component.html +++ /dev/null @@ -1,58 +0,0 @@ -
-
- -

Add user

- -
{{ error }}
- -
-
- - -
- {{ formErrors.username }} -
-
- -
- - -
- {{ formErrors.email }} -
-
- -
- - -
- {{ formErrors.password }} -
-
- -
- - -
- - -
-
-
diff --git a/client/src/app/+admin/users/user-add/user-add.component.ts b/client/src/app/+admin/users/user-add/user-add.component.ts deleted file mode 100644 index 91377a933..000000000 --- a/client/src/app/+admin/users/user-add/user-add.component.ts +++ /dev/null @@ -1,79 +0,0 @@ -import { Component, OnInit } from '@angular/core' -import { FormBuilder, FormGroup } from '@angular/forms' -import { Router } from '@angular/router' - -import { NotificationsService } from 'angular2-notifications' - -import { UserService } from '../shared' -import { - FormReactive, - USER_USERNAME, - USER_EMAIL, - USER_PASSWORD, - USER_VIDEO_QUOTA -} from '../../../shared' -import { UserCreate } from '../../../../../../shared' - -@Component({ - selector: 'my-user-add', - templateUrl: './user-add.component.html' -}) -export class UserAddComponent extends FormReactive implements OnInit { - error: string = null - - form: FormGroup - formErrors = { - 'username': '', - 'email': '', - 'password': '', - 'videoQuota': '' - } - validationMessages = { - 'username': USER_USERNAME.MESSAGES, - 'email': USER_EMAIL.MESSAGES, - 'password': USER_PASSWORD.MESSAGES, - 'videoQuota': USER_VIDEO_QUOTA.MESSAGES - } - - constructor ( - private formBuilder: FormBuilder, - private router: Router, - private notificationsService: NotificationsService, - private userService: UserService - ) { - super() - } - - buildForm () { - this.form = this.formBuilder.group({ - username: [ '', USER_USERNAME.VALIDATORS ], - email: [ '', USER_EMAIL.VALIDATORS ], - password: [ '', USER_PASSWORD.VALIDATORS ], - videoQuota: [ '-1', USER_VIDEO_QUOTA.VALIDATORS ] - }) - - this.form.valueChanges.subscribe(data => this.onValueChanged(data)) - } - - ngOnInit () { - this.buildForm() - } - - addUser () { - this.error = null - - const userCreate: UserCreate = this.form.value - - // A select in HTML is always mapped as a string, we convert it to number - userCreate.videoQuota = parseInt(this.form.value['videoQuota'], 10) - - this.userService.addUser(userCreate).subscribe( - () => { - this.notificationsService.success('Success', `User ${userCreate.username} created.`) - this.router.navigate([ '/admin/users/list' ]) - }, - - err => this.error = err.text - ) - } -} diff --git a/client/src/app/+admin/users/user-edit/index.ts b/client/src/app/+admin/users/user-edit/index.ts new file mode 100644 index 000000000..edec02fbb --- /dev/null +++ b/client/src/app/+admin/users/user-edit/index.ts @@ -0,0 +1,2 @@ +export * from './user-add.component' +export * from './user-update.component' diff --git a/client/src/app/+admin/users/user-edit/user-add.component.ts b/client/src/app/+admin/users/user-edit/user-add.component.ts new file mode 100644 index 000000000..40f649cff --- /dev/null +++ b/client/src/app/+admin/users/user-edit/user-add.component.ts @@ -0,0 +1,87 @@ +import { Component, OnInit } from '@angular/core' +import { FormBuilder, FormGroup } from '@angular/forms' +import { Router } from '@angular/router' + +import { NotificationsService } from 'angular2-notifications' + +import { UserService } from '../shared' +import { + USER_USERNAME, + USER_EMAIL, + USER_PASSWORD, + USER_VIDEO_QUOTA +} from '../../../shared' +import { UserCreate } from '../../../../../../shared' +import { UserEdit } from './user-edit' + +@Component({ + selector: 'my-user-add', + templateUrl: './user-edit.component.html' +}) +export class UserAddComponent extends UserEdit implements OnInit { + error: string + + form: FormGroup + formErrors = { + 'username': '', + 'email': '', + 'password': '', + 'videoQuota': '' + } + validationMessages = { + 'username': USER_USERNAME.MESSAGES, + 'email': USER_EMAIL.MESSAGES, + 'password': USER_PASSWORD.MESSAGES, + 'videoQuota': USER_VIDEO_QUOTA.MESSAGES + } + + constructor ( + private formBuilder: FormBuilder, + private router: Router, + private notificationsService: NotificationsService, + private userService: UserService + ) { + super() + } + + buildForm () { + this.form = this.formBuilder.group({ + username: [ '', USER_USERNAME.VALIDATORS ], + email: [ '', USER_EMAIL.VALIDATORS ], + password: [ '', USER_PASSWORD.VALIDATORS ], + videoQuota: [ '-1', USER_VIDEO_QUOTA.VALIDATORS ] + }) + + this.form.valueChanges.subscribe(data => this.onValueChanged(data)) + } + + ngOnInit () { + this.buildForm() + } + + formValidated () { + this.error = undefined + + const userCreate: UserCreate = this.form.value + + // A select in HTML is always mapped as a string, we convert it to number + userCreate.videoQuota = parseInt(this.form.value['videoQuota'], 10) + + this.userService.addUser(userCreate).subscribe( + () => { + this.notificationsService.success('Success', `User ${userCreate.username} created.`) + this.router.navigate([ '/admin/users/list' ]) + }, + + err => this.error = err.text + ) + } + + isCreation () { + return true + } + + getFormButtonTitle () { + return 'Add user' + } +} diff --git a/client/src/app/+admin/users/user-edit/user-edit.component.html b/client/src/app/+admin/users/user-edit/user-edit.component.html new file mode 100644 index 000000000..0e23cb731 --- /dev/null +++ b/client/src/app/+admin/users/user-edit/user-edit.component.html @@ -0,0 +1,55 @@ +
+
+ +

Add user

+

Edit user {{ username }}

+ +
{{ error }}
+ +
+
+ + +
+ {{ formErrors.username }} +
+
+ +
+ + +
+ {{ formErrors.email }} +
+
+ +
+ + +
+ {{ formErrors.password }} +
+
+ +
+ + +
+ + +
+
+
diff --git a/client/src/app/+admin/users/user-edit/user-edit.ts b/client/src/app/+admin/users/user-edit/user-edit.ts new file mode 100644 index 000000000..61db8a906 --- /dev/null +++ b/client/src/app/+admin/users/user-edit/user-edit.ts @@ -0,0 +1,16 @@ +import { FormReactive } from '../../../shared' + +export abstract class UserEdit extends FormReactive { + videoQuotaOptions = [ + { value: -1, label: 'Unlimited' }, + { value: 100 * 1024 * 1024, label: '100MB' }, + { value: 5 * 1024 * 1024, label: '500MB' }, + { value: 1024 * 1024 * 1024, label: '1GB' }, + { value: 5 * 1024 * 1024 * 1024, label: '5GB' }, + { value: 20 * 1024 * 1024 * 1024, label: '20GB' }, + { value: 50 * 1024 * 1024 * 1024, label: '50GB' } + ] + + abstract isCreation (): boolean + abstract getFormButtonTitle (): string +} diff --git a/client/src/app/+admin/users/user-edit/user-update.component.ts b/client/src/app/+admin/users/user-edit/user-update.component.ts new file mode 100644 index 000000000..dbac5f974 --- /dev/null +++ b/client/src/app/+admin/users/user-edit/user-update.component.ts @@ -0,0 +1,106 @@ +import { Component, OnDestroy, OnInit } from '@angular/core' +import { FormBuilder, FormGroup } from '@angular/forms' +import { ActivatedRoute, Router } from '@angular/router' +import { Subscription } from 'rxjs/Subscription' + +import { NotificationsService } from 'angular2-notifications' + +import { UserService } from '../shared' +import { USER_EMAIL, USER_VIDEO_QUOTA } from '../../../shared' +import { UserUpdate } from '../../../../../../shared/models/users/user-update.model' +import { User } from '../../../shared/users/user.model' +import { UserEdit } from './user-edit' + +@Component({ + selector: 'my-user-update', + templateUrl: './user-edit.component.html' +}) +export class UserUpdateComponent extends UserEdit implements OnInit, OnDestroy { + error: string + userId: number + username: string + + form: FormGroup + formErrors = { + 'email': '', + 'videoQuota': '' + } + validationMessages = { + 'email': USER_EMAIL.MESSAGES, + 'videoQuota': USER_VIDEO_QUOTA.MESSAGES + } + + private paramsSub: Subscription + + constructor ( + private formBuilder: FormBuilder, + private route: ActivatedRoute, + private router: Router, + private notificationsService: NotificationsService, + private userService: UserService + ) { + super() + } + + buildForm () { + this.form = this.formBuilder.group({ + email: [ '', USER_EMAIL.VALIDATORS ], + videoQuota: [ '-1', USER_VIDEO_QUOTA.VALIDATORS ] + }) + + this.form.valueChanges.subscribe(data => this.onValueChanged(data)) + } + + ngOnInit () { + this.buildForm() + + this.paramsSub = this.route.params.subscribe(routeParams => { + const userId = routeParams['id'] + this.userService.getUser(userId).subscribe( + user => this.onUserFetched(user), + + err => this.error = err.text + ) + }) + } + + ngOnDestroy () { + this.paramsSub.unsubscribe() + } + + formValidated () { + this.error = undefined + + const userUpdate: UserUpdate = this.form.value + + // A select in HTML is always mapped as a string, we convert it to number + userUpdate.videoQuota = parseInt(this.form.value['videoQuota'], 10) + + this.userService.updateUser(this.userId, userUpdate).subscribe( + () => { + this.notificationsService.success('Success', `User ${this.username} updated.`) + this.router.navigate([ '/admin/users/list' ]) + }, + + err => this.error = err.text + ) + } + + isCreation () { + return false + } + + getFormButtonTitle () { + return 'Update user' + } + + private onUserFetched (userJson: User) { + this.userId = userJson.id + this.username = userJson.username + + this.form.patchValue({ + email: userJson.email, + videoQuota: userJson.videoQuota + }) + } +} diff --git a/client/src/app/+admin/users/user-list/user-list.component.html b/client/src/app/+admin/users/user-list/user-list.component.html index bb4c99a3f..eb5bc9d4a 100644 --- a/client/src/app/+admin/users/user-list/user-list.component.html +++ b/client/src/app/+admin/users/user-list/user-list.component.html @@ -5,7 +5,7 @@ diff --git a/client/src/app/+admin/users/user-list/user-list.component.ts b/client/src/app/+admin/users/user-list/user-list.component.ts index dbb85cedd..7187a2008 100644 --- a/client/src/app/+admin/users/user-list/user-list.component.ts +++ b/client/src/app/+admin/users/user-list/user-list.component.ts @@ -5,6 +5,7 @@ import { NotificationsService } from 'angular2-notifications' import { ConfirmService } from '../../../core' import { RestDataSource, User, Utils } from '../../../shared' import { UserService } from '../shared' +import { Router } from '@angular/router' @Component({ selector: 'my-user-list', @@ -22,15 +23,18 @@ export class UserListComponent { actions: { position: 'right', add: false, - edit: false, + edit: true, delete: true }, delete: { deleteButtonContent: Utils.getRowDeleteButton() }, + edit: { + editButtonContent: Utils.getRowEditButton() + }, pager: { display: true, - perPage: 1 + perPage: 10 }, columns: { id: { @@ -58,6 +62,7 @@ export class UserListComponent { } constructor ( + private router: Router, private notificationsService: NotificationsService, private confirmService: ConfirmService, private userService: UserService @@ -65,8 +70,12 @@ export class UserListComponent { this.usersSource = this.userService.getDataSource() } - removeUser ({ data }) { - const user: User = data + editUser ({ data }: { data: User }) { + this.router.navigate([ '/admin', 'users', data.id, 'update' ]) + } + + removeUser ({ data }: { data: User }) { + const user = data if (user.username === 'root') { this.notificationsService.error('Error', 'You cannot delete root.') diff --git a/client/src/app/+admin/users/users.routes.ts b/client/src/app/+admin/users/users.routes.ts index 723c5715d..a6a9c4c19 100644 --- a/client/src/app/+admin/users/users.routes.ts +++ b/client/src/app/+admin/users/users.routes.ts @@ -1,7 +1,7 @@ import { Routes } from '@angular/router' import { UsersComponent } from './users.component' -import { UserAddComponent } from './user-add' +import { UserAddComponent, UserUpdateComponent } from './user-edit' import { UserListComponent } from './user-list' export const UsersRoutes: Routes = [ @@ -31,6 +31,15 @@ export const UsersRoutes: Routes = [ title: 'Add a user' } } + }, + { + path: ':id/update', + component: UserUpdateComponent, + data: { + meta: { + title: 'Update a user' + } + } } ] } 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 index ce786cfa3..dba141296 100644 --- 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 @@ -26,7 +26,6 @@ export class AccountChangePasswordComponent extends FormReactive implements OnIn constructor ( private formBuilder: FormBuilder, - private router: Router, private notificationsService: NotificationsService, private userService: UserService ) { diff --git a/client/src/app/account/account-details/account-details.component.ts b/client/src/app/account/account-details/account-details.component.ts index 547f045c4..8cbed5009 100644 --- a/client/src/app/account/account-details/account-details.component.ts +++ b/client/src/app/account/account-details/account-details.component.ts @@ -11,7 +11,7 @@ import { UserService, USER_PASSWORD } from '../../shared' -import { UserUpdate } from '../../../../../shared' +import { UserUpdateMe } from '../../../../../shared' @Component({ selector: 'my-account-details', @@ -30,7 +30,6 @@ export class AccountDetailsComponent extends FormReactive implements OnInit { constructor ( private authService: AuthService, private formBuilder: FormBuilder, - private router: Router, private notificationsService: NotificationsService, private userService: UserService ) { @@ -51,14 +50,14 @@ export class AccountDetailsComponent extends FormReactive implements OnInit { updateDetails () { const displayNSFW = this.form.value['displayNSFW'] - const details: UserUpdate = { + const details: UserUpdateMe = { displayNSFW } this.error = null - this.userService.updateDetails(details).subscribe( + this.userService.updateMyDetails(details).subscribe( () => { - this.notificationsService.success('Success', 'Informations updated.') + this.notificationsService.success('Success', 'Information updated.') this.authService.refreshUserInformations() }, diff --git a/client/src/app/shared/users/user.service.ts b/client/src/app/shared/users/user.service.ts index b479ac034..35180be4d 100644 --- a/client/src/app/shared/users/user.service.ts +++ b/client/src/app/shared/users/user.service.ts @@ -6,7 +6,7 @@ import 'rxjs/add/operator/map' import { AuthService } from '../../core' import { AuthHttp } from '../auth' import { RestExtractor } from '../rest' -import { UserCreate, UserUpdate } from '../../../../../shared' +import { UserCreate, UserUpdateMe } from '../../../../../shared' @Injectable() export class UserService { @@ -22,13 +22,13 @@ export class UserService { checkTokenValidity () { const url = UserService.BASE_USERS_URL + 'me' - // AuthHttp will redirect us to the login page if the oken is not valid anymore + // AuthHttp will redirect us to the login page if the token is not valid anymore this.authHttp.get(url).subscribe() } changePassword (newPassword: string) { - const url = UserService.BASE_USERS_URL + this.authService.getUser().id - const body: UserUpdate = { + const url = UserService.BASE_USERS_URL + 'me' + const body: UserUpdateMe = { password: newPassword } @@ -37,8 +37,8 @@ export class UserService { .catch((res) => this.restExtractor.handleError(res)) } - updateDetails (details: UserUpdate) { - const url = UserService.BASE_USERS_URL + this.authService.getUser().id + updateMyDetails (details: UserUpdateMe) { + const url = UserService.BASE_USERS_URL + 'me' return this.authHttp.put(url, details) .map(this.restExtractor.extractDataBool) diff --git a/client/src/app/shared/utils.ts b/client/src/app/shared/utils.ts index 832311f89..c3189a570 100644 --- a/client/src/app/shared/utils.ts +++ b/client/src/app/shared/utils.ts @@ -9,4 +9,8 @@ export class Utils { static getRowDeleteButton () { return '' } + + static getRowEditButton () { + return '' + } } -- cgit v1.2.3