[DEV] add basic interfaces to see users
This commit is contained in:
parent
0c5f524906
commit
80a9806bf4
@ -16,6 +16,7 @@ import {
|
||||
SignOutScene,
|
||||
SignUpScene,
|
||||
HomeUnregisteredScene,
|
||||
ManageAccountsScene,
|
||||
} from './scene';
|
||||
import { OnlyAdminGuard, OnlyUnregisteredGuardHome, OnlyUsersGuard, OnlyUsersGuardHome } from 'common/service/session';
|
||||
import { ForbiddenScene, NotFound404Scene } from 'common/scene';
|
||||
@ -66,6 +67,11 @@ const routes: Routes = [
|
||||
component: SettingsScene,
|
||||
canActivate: [OnlyAdminGuard],
|
||||
},
|
||||
{
|
||||
path: 'manage_accounts',
|
||||
component: ManageAccountsScene,
|
||||
canActivate: [OnlyAdminGuard],
|
||||
},
|
||||
{
|
||||
path: '**',
|
||||
component: NotFound404Scene,
|
||||
|
@ -102,9 +102,16 @@ export class AppComponent implements OnInit {
|
||||
position: MenuPosition.LEFT,
|
||||
hover: 'Admin configuration karso management',
|
||||
icon: 'settings',
|
||||
title: 'Settings',
|
||||
title: 'Admin Settings',
|
||||
navigateTo: 'settings',
|
||||
enable: this.sessionService.userAdmin === true,
|
||||
}, { // TODO move this in the setting environment system ?
|
||||
position: MenuPosition.LEFT,
|
||||
hover: 'Admin of users',
|
||||
icon: 'manage_accounts',
|
||||
title: 'Manage Accounts',
|
||||
navigateTo: 'manage_accounts',
|
||||
enable: this.sessionService.userAdmin === true,
|
||||
},
|
||||
],
|
||||
},
|
||||
|
@ -22,6 +22,7 @@ import {
|
||||
ChangePasswordScene,
|
||||
SettingsScene,
|
||||
HomeUnregisteredScene,
|
||||
ManageAccountsScene,
|
||||
} from 'app/scene';
|
||||
import {
|
||||
BddService,
|
||||
@ -69,6 +70,7 @@ import { PasswordEntryComponent } from './component';
|
||||
ForbiddenScene,
|
||||
ChangePasswordScene,
|
||||
HomeUnregisteredScene,
|
||||
ManageAccountsScene,
|
||||
],
|
||||
imports: [
|
||||
BrowserModule,
|
||||
|
@ -4,6 +4,7 @@ import { ForgotPasswordScene } from './forgot-password/forgot-password';
|
||||
import { HelpScene } from './help/help';
|
||||
import { HomeUnregisteredScene } from './home-unregistered/home-unregistered';
|
||||
import { HomeScene } from './home/home';
|
||||
import { ManageAccountsScene } from './manage-accounts/manage-accounts';
|
||||
import { SettingsScene } from './settings/settings';
|
||||
import { SignInScene } from './sign-in/sign-in';
|
||||
import { SignOutScene } from './sign-out/sign-out';
|
||||
@ -22,4 +23,5 @@ export {
|
||||
ChangePasswordScene,
|
||||
SettingsScene,
|
||||
HomeUnregisteredScene,
|
||||
ManageAccountsScene,
|
||||
};
|
||||
|
100
front/src/app/scene/manage-accounts/manage-accounts.html
Normal file
100
front/src/app/scene/manage-accounts/manage-accounts.html
Normal file
@ -0,0 +1,100 @@
|
||||
<div class="generic-page">
|
||||
<div class="title">Manage User Accounts</div>
|
||||
<div class="fill-all">
|
||||
<div>
|
||||
<div class="settings-title">
|
||||
<div class="group-title">Current users</div>
|
||||
<div class="group-description">List of all users</div>
|
||||
</div>
|
||||
<div class="settings-elements">
|
||||
<table style="width:100%;">
|
||||
<tr>
|
||||
<th>id</th>
|
||||
<th>login</th>
|
||||
<th>e-mail</th>
|
||||
<th>admin</th>
|
||||
<th>blocked</th>
|
||||
<th>avatar</th>
|
||||
<th>lastConnection</th>
|
||||
</tr>
|
||||
<tr *ngFor="let user of users">
|
||||
<th>{{user.id}}</th>
|
||||
<th>{{user.login}}</th>
|
||||
<th>{{user.email}}</th>
|
||||
<th>{{user.admin}}</th>
|
||||
<th>{{user.blocked}}</th>
|
||||
<th>{{user.avatar}}</th>
|
||||
<th>{{user.lastConnection}}</th>
|
||||
</tr>
|
||||
</table>
|
||||
</div>
|
||||
<div class="settings-validation">
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="clear"><br/></div>
|
||||
<div style="padding-top:15px;">
|
||||
<div class="settings-title">
|
||||
<div class="group-title">Create new user</div>
|
||||
<div class="group-description">Add a new user on the server</div>
|
||||
</div>
|
||||
<div class="settings-elements">
|
||||
<table style="width:100%;">
|
||||
<tr>
|
||||
<td width="25%"><b>Login:</b></td>
|
||||
<td width="75%">
|
||||
<input
|
||||
id="username"
|
||||
name="username"
|
||||
class="{{loginIcon}}"
|
||||
type="text"
|
||||
required=""
|
||||
placeholder="Pick a Username"
|
||||
[value]="login"
|
||||
(input)="checkLogin($event.target.value)" />
|
||||
<div class="error color-shadow-black" *ngIf="loginHelp">{{loginHelp}}</div>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><b>email:</b></td>
|
||||
<td>
|
||||
<input
|
||||
id="email"
|
||||
name="e-mail"
|
||||
class="{{emailIcon}}"
|
||||
type="text"
|
||||
required=""
|
||||
placeholder="you@example.com"
|
||||
[value]="email"
|
||||
(input)="checkEmail($event.target.value)" />
|
||||
<div class="error color-shadow-black" *ngIf="emailHelp">{{emailHelp}}</div>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><b>Password:</b></td>
|
||||
<td>
|
||||
<app-password-entry
|
||||
[value]="password"
|
||||
placeholder="Enter new password (verify)"
|
||||
[hasError]="passwordState !== true"
|
||||
(changeValue)="checkPassword($event)"></app-password-entry>
|
||||
<div class="error color-shadow-black" *ngIf="passwordState !== true && passwordState !== false">{{passwordState}}</div>
|
||||
</td>
|
||||
<tr>
|
||||
</table>
|
||||
<button
|
||||
class="button login color-button-validate color-shadow-black"
|
||||
id="login-button"
|
||||
[disabled]="validateButtonCreateUserDisabled"
|
||||
(click)="onCreateUser()"
|
||||
type="submit">
|
||||
Create user
|
||||
</button>
|
||||
</div>
|
||||
<div class="settings-validation">
|
||||
|
||||
</div>
|
||||
</div>
|
||||
<div class="clear"></div>
|
||||
</div>
|
151
front/src/app/scene/manage-accounts/manage-accounts.less
Normal file
151
front/src/app/scene/manage-accounts/manage-accounts.less
Normal file
@ -0,0 +1,151 @@
|
||||
.settings-title {
|
||||
width: 80%;
|
||||
border: solid;
|
||||
border-width: 1px;
|
||||
margin: auto;
|
||||
padding: 10px 20px;
|
||||
|
||||
border-color: black;
|
||||
border-radius: 10px 10px 0px 0px;
|
||||
background-color: gray;
|
||||
|
||||
.group-title {
|
||||
font-size: 24px;
|
||||
font-weight: bold;
|
||||
line-height: 24px;
|
||||
vertical-align: middle;
|
||||
margin: 10px 0 10px 0;
|
||||
text-align: Left;
|
||||
}
|
||||
.group-description {
|
||||
font-size: 16px;
|
||||
line-height: 16px;
|
||||
vertical-align: middle;
|
||||
margin: 10px 0 10px 0;
|
||||
text-align: Left;
|
||||
}
|
||||
}
|
||||
|
||||
.settings-elements {
|
||||
width: 80%;
|
||||
border: solid;
|
||||
border-width: 0px 1px;
|
||||
margin: auto;
|
||||
padding: 10px 20px;
|
||||
|
||||
border-color: black;
|
||||
border-radius: 0px;
|
||||
background-color: lightgray;
|
||||
vertical-align: middle;
|
||||
text-align: Left;
|
||||
|
||||
.elem-hr {
|
||||
width: 100%;
|
||||
border-color: black;
|
||||
border: dashed;
|
||||
border-width: 1px 0 0 0;
|
||||
margin: 10px auto;
|
||||
}
|
||||
.elem-checkbox {
|
||||
font-size: 18px;
|
||||
font-weight: bold;
|
||||
margin: 0 10px 0 10px;
|
||||
}
|
||||
.elem-title {
|
||||
font-size: 18px;
|
||||
font-weight: bold;
|
||||
margin: 0 10px 0 36px;
|
||||
}
|
||||
.elem-description {
|
||||
font-size: 14px;
|
||||
margin: 0 20px 10px 50px;
|
||||
font-style: italic;
|
||||
}
|
||||
.elem-input {
|
||||
font-size: 14px;
|
||||
margin: 0 20px 10px 36px;
|
||||
input {
|
||||
width: 100%;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.settings-validation {
|
||||
width: 80%;
|
||||
border: solid;
|
||||
border-width: 1px;
|
||||
margin: auto;
|
||||
padding: 10px 20px;
|
||||
|
||||
border-color: black;
|
||||
border-radius: 0px 0px 10px 10px;
|
||||
background-color: gray;
|
||||
}
|
||||
|
||||
.title {
|
||||
//background-color: green;
|
||||
font-size: 45px;
|
||||
font-weight: bold;
|
||||
line-height: 60px;
|
||||
width: 100%;
|
||||
text-align: center;
|
||||
vertical-align: middle;
|
||||
margin: 10px 0 10px 0;
|
||||
text-shadow: 1px 1px 2px white, 0 0 1em white, 0 0 0.2em white;
|
||||
text-transform: uppercase;
|
||||
font-family: 'Roboto', 'Helvetica', 'Arial', sans-serif;
|
||||
}
|
||||
.item-home {
|
||||
background-color: rgba(200, 200, 200, 0.5);
|
||||
font-size: 20px;
|
||||
height: 190px;
|
||||
width: 200px;
|
||||
margin: 5px;
|
||||
padding: 0;
|
||||
overflow: hidden;
|
||||
// box-shadow: 0 1px 1.5px 0 rgba(0,0,0,.12),0 1px 1px 0 rgba(0,0,0,.24);
|
||||
box-shadow: 0px 2px 4px 0 rgba(0, 0, 0, 0.6);
|
||||
line-height: normal;
|
||||
border: none;
|
||||
font-family: 'Roboto', 'Helvetica', 'Arial', 'sans-serif';
|
||||
font-weight: 500;
|
||||
text-transform: uppercase;
|
||||
letter-spacing: 0;
|
||||
will-change: box-shadow;
|
||||
outline: none;
|
||||
cursor: pointer;
|
||||
text-decoration: none;
|
||||
text-align: center;
|
||||
transition-duration: 0.4s;
|
||||
float: left;
|
||||
display: block;
|
||||
|
||||
h1 {
|
||||
font-size: 24px;
|
||||
}
|
||||
|
||||
&:hover {
|
||||
background-color: rgba(200, 200, 200, 1);
|
||||
//box-shadow: 0px 2px 4px 0 rgba(255, 0, 0, 0.6);
|
||||
}
|
||||
|
||||
.material-icons {
|
||||
vertical-align: middle;
|
||||
}
|
||||
|
||||
.material-icons {
|
||||
position: absolute;
|
||||
top: 50%;
|
||||
left: 50%;
|
||||
transform: ~'translate(-12px,-12px)';
|
||||
line-height: 24px;
|
||||
width: 24px;
|
||||
}
|
||||
}
|
||||
|
||||
@media all and (min-width: 1310px) {
|
||||
.colomn_mutiple {
|
||||
width: ~'calc(210px * 5)';
|
||||
margin: auto;
|
||||
}
|
||||
}
|
285
front/src/app/scene/manage-accounts/manage-accounts.ts
Normal file
285
front/src/app/scene/manage-accounts/manage-accounts.ts
Normal file
@ -0,0 +1,285 @@
|
||||
/** @file
|
||||
* @author Edouard DUPIN
|
||||
* @copyright 2018, Edouard DUPIN, all right reserved
|
||||
* @license PROPRIETARY (see license file)
|
||||
*/
|
||||
|
||||
import { Component, OnInit } from '@angular/core';
|
||||
import { ActivatedRoute } from '@angular/router';
|
||||
import { AdminUserService, SettingsService } from 'app/service';
|
||||
import {
|
||||
checkEmailValidity,
|
||||
checkLoginValidity,
|
||||
createPasswordState,
|
||||
isArrayOf,
|
||||
isBoolean,
|
||||
isInArray,
|
||||
isNullOrUndefined,
|
||||
isNumber,
|
||||
isObject,
|
||||
isOptionalArrayOf,
|
||||
isOptionalOf,
|
||||
isString,
|
||||
isUndefined,
|
||||
} from 'common/utils';
|
||||
export enum SettingType {
|
||||
TITLE = 'TITLE',
|
||||
GROUP = 'GROUP',
|
||||
LINE = 'LINE',
|
||||
BOOLEAN = 'BOOLEAN',
|
||||
STRING = 'STRING',
|
||||
PASSWORD = 'PASSWORD',
|
||||
}
|
||||
export function isSettingType(data: any): data is SettingType {
|
||||
return isInArray(data, ['TITLE', 'GROUP', 'LINE', 'BOOLEAN', 'STRING', 'PASSWORD']);
|
||||
}
|
||||
|
||||
export interface SettingsItem {
|
||||
// Type of the menu Node
|
||||
type: SettingType;
|
||||
// Displayed Title
|
||||
title?: string;
|
||||
// Description of the parameter
|
||||
description?: string;
|
||||
// Image to dsplay that describe the parameter
|
||||
image?: string;
|
||||
// If true the parameter is applied directly to the backend
|
||||
directApply?: boolean;
|
||||
// Parameter key to SET/GET
|
||||
key?: string;
|
||||
// Parameter key to SET/GET or the sub-menu
|
||||
value?: SettingsItem[] | boolean | string | Number;
|
||||
// whendata is change the value is set here:
|
||||
newValue?: boolean | string | Number;
|
||||
}
|
||||
|
||||
export function isSettingsItem(data: any): data is SettingsItem {
|
||||
if (isNullOrUndefined(data)) {
|
||||
return false;
|
||||
}
|
||||
if (!isObject(data)) {
|
||||
return false;
|
||||
}
|
||||
if (!isSettingType(data.type)) {
|
||||
return false;
|
||||
}
|
||||
if (!isOptionalOf(data.title, isString)) {
|
||||
return false;
|
||||
}
|
||||
if (!isOptionalOf(data.description, isString)) {
|
||||
return false;
|
||||
}
|
||||
if (!isOptionalOf(data.image, isString)) {
|
||||
return false;
|
||||
}
|
||||
if (!isOptionalOf(data.directApply, isBoolean)) {
|
||||
return false;
|
||||
}
|
||||
if (!isOptionalOf(data.key, isString)) {
|
||||
return false;
|
||||
}
|
||||
if (
|
||||
!isOptionalOf(data.value, isBoolean) &&
|
||||
!isOptionalOf(data.value, isString) &&
|
||||
!isOptionalOf(data.value, isNumber) &&
|
||||
!isOptionalArrayOf(data.value, isSettingsItem)
|
||||
) {
|
||||
return false;
|
||||
}
|
||||
if (
|
||||
!isOptionalOf(data.newValue, isBoolean) &&
|
||||
!isOptionalOf(data.newValue, isString) &&
|
||||
!isOptionalOf(data.newValue, isNumber)
|
||||
) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@Component({
|
||||
selector: 'app-settings',
|
||||
templateUrl: './manage-accounts.html',
|
||||
styleUrls: ['./manage-accounts.less'],
|
||||
})
|
||||
export class ManageAccountsScene implements OnInit {
|
||||
users: any = [];
|
||||
|
||||
constructor(private adminUserService: AdminUserService) {
|
||||
}
|
||||
ngOnInit() {
|
||||
let self = this;
|
||||
this.adminUserService
|
||||
.getUsers()
|
||||
.then((response: any) => {
|
||||
console.log(`??? get full response: ${JSON.stringify(response, null, 4)}`);
|
||||
self.users = response;
|
||||
})
|
||||
.catch((error: any) => {
|
||||
console.log(`??? get ERROR response: ${JSON.stringify(error, null, 4)}`);
|
||||
});
|
||||
}
|
||||
|
||||
public passwordState: boolean|string = false;
|
||||
public password: string = '';
|
||||
public validateButtonCreateUserDisabled: boolean = true;
|
||||
/**
|
||||
* update the state of the validation button. if all is OK, the button will became clickable
|
||||
*/
|
||||
updateButtonVisibility(): void {
|
||||
if (this.passwordState === true && this.loginOK === true && this.emailOK === true) {
|
||||
this.validateButtonCreateUserDisabled = false;
|
||||
} else {
|
||||
this.validateButtonCreateUserDisabled = true;
|
||||
}
|
||||
}
|
||||
/**
|
||||
* Check if the current password is valid or not (update error message)
|
||||
* @param newValue New password value.
|
||||
*/
|
||||
checkPassword(newValue: string): void {
|
||||
this.password = newValue;
|
||||
this.passwordState = createPasswordState(this.password);
|
||||
this.checkPassword(this.password);
|
||||
this.updateButtonVisibility();
|
||||
}
|
||||
/**
|
||||
* Request the creation of a new user.
|
||||
*/
|
||||
onCreateUser(): void {
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
private signUpIconWrong: string = 'icon-right-not-validate';
|
||||
private signUpIconWait: string = 'icon-right-load';
|
||||
private signUpIconRight: string = 'icon-right-validate';
|
||||
|
||||
|
||||
public login: string = '';
|
||||
public loginOK: boolean = false;
|
||||
public loginHelp: string = '';
|
||||
public loginIcon: string = '';
|
||||
|
||||
public email: string = '';
|
||||
public emailOK: boolean = false;
|
||||
public emailHelp: string = '';
|
||||
public emailIcon: string = '';
|
||||
|
||||
|
||||
checkLogin(newValue: string): void {
|
||||
// this.userService.loginSha("loooogin", "ekljkj", true);
|
||||
this.login = newValue;
|
||||
if (this.login === null || this.login.length === 0) {
|
||||
this.loginOK = false;
|
||||
this.loginIcon = '';
|
||||
//this.loginIcon = this.signUpIconWrong;
|
||||
this.loginHelp = '';
|
||||
this.updateButtonVisibility();
|
||||
return;
|
||||
}
|
||||
if (this.login.length < 6) {
|
||||
this.loginOK = false;
|
||||
this.loginHelp = 'Need 6 characters';
|
||||
this.loginIcon = this.signUpIconWrong;
|
||||
this.updateButtonVisibility();
|
||||
return;
|
||||
}
|
||||
if (checkLoginValidity(this.login) === true) {
|
||||
this.loginOK = false;
|
||||
// this.loginHelp = "check in progress...";
|
||||
this.loginIcon = this.signUpIconWait;
|
||||
let self = this;
|
||||
this.adminUserService
|
||||
.checkLogin(this.login)
|
||||
.then((isNotUsed: boolean) => {
|
||||
// check if the answer is correct with the question
|
||||
if (newValue !== self.login) {
|
||||
return;
|
||||
}
|
||||
if (isNotUsed === false) {
|
||||
// the login exist ... ==> it is found...
|
||||
self.loginOK = false;
|
||||
self.loginHelp = 'Login already used ...';
|
||||
self.loginIcon = self.signUpIconWrong;
|
||||
self.updateButtonVisibility();
|
||||
} else {
|
||||
self.loginOK = true;
|
||||
self.loginHelp = '';
|
||||
self.loginIcon = self.signUpIconRight;
|
||||
self.updateButtonVisibility();
|
||||
return;
|
||||
}
|
||||
})
|
||||
.catch((error: number) => {
|
||||
console.log(`Status ${error}`);
|
||||
self.loginOK = false;
|
||||
self.loginHelp = 'ErrorOccured in fetching data ...';
|
||||
self.loginIcon = self.signUpIconWrong;
|
||||
self.updateButtonVisibility();
|
||||
});
|
||||
} else {
|
||||
this.loginOK = false;
|
||||
this.loginHelp = 'Not valid: characters, numbers and "_-."';
|
||||
}
|
||||
this.updateButtonVisibility();
|
||||
}
|
||||
|
||||
checkEmail(newValue: string): void {
|
||||
this.email = newValue;
|
||||
if (this.email === null || this.email.length === 0) {
|
||||
this.emailOK = false;
|
||||
this.updateButtonVisibility();
|
||||
this.emailIcon = '';
|
||||
this.emailHelp = '';
|
||||
return;
|
||||
}
|
||||
if (this.email.length < 6) {
|
||||
this.emailOK = false;
|
||||
this.emailHelp = 'Need 6 characters';
|
||||
this.updateButtonVisibility();
|
||||
this.emailIcon = this.signUpIconWrong;
|
||||
return;
|
||||
}
|
||||
if (checkEmailValidity(this.email) === true) {
|
||||
this.emailOK = false;
|
||||
this.emailHelp = '';
|
||||
// this.loginHelp = "check in progress...";
|
||||
this.emailIcon = this.signUpIconWait;
|
||||
let self = this;
|
||||
this.adminUserService.checkEMail(this.email).then(
|
||||
(isNotUsed: boolean) => {
|
||||
// check if the answer is correct with the question
|
||||
if (newValue !== self.email) {
|
||||
return;
|
||||
}
|
||||
if (isNotUsed === false) {
|
||||
// the email exist ... ==> it is found...
|
||||
self.emailOK = false;
|
||||
self.emailHelp = 'email already used ...';
|
||||
self.emailIcon = self.signUpIconWrong;
|
||||
self.updateButtonVisibility();
|
||||
} else {
|
||||
self.emailOK = true;
|
||||
self.emailHelp = '';
|
||||
self.emailIcon = self.signUpIconRight;
|
||||
self.updateButtonVisibility();
|
||||
return;
|
||||
}
|
||||
},
|
||||
(error: number) => {
|
||||
console.log(`Status ${error}`);
|
||||
self.emailOK = false;
|
||||
self.emailHelp = 'ErrorOccured in fetching data ...';
|
||||
self.emailIcon = self.signUpIconWrong;
|
||||
self.updateButtonVisibility();
|
||||
}
|
||||
);
|
||||
} else {
|
||||
this.emailOK = false;
|
||||
this.emailHelp = 'Not valid: characters, numbers, "_-." and email format: you@example.com';
|
||||
}
|
||||
this.updateButtonVisibility();
|
||||
}
|
||||
|
||||
}
|
@ -118,6 +118,24 @@ export class AdminUserService {
|
||||
});
|
||||
});
|
||||
}
|
||||
getUsers(): Promise<any> {
|
||||
return new Promise((resolve, reject) => {
|
||||
this.http
|
||||
.requestJson({
|
||||
server: 'karso',
|
||||
endPoint: 'users',
|
||||
requestType: HTTPRequestModel.GET,
|
||||
accept: HTTPMimeType.JSON,
|
||||
contentType: HTTPMimeType.JSON
|
||||
})
|
||||
.then((response: ModelResponseHttp) => {
|
||||
resolve(response.data);
|
||||
})
|
||||
.catch((error: any) => {
|
||||
reject(`return ERROR ${JSON.stringify(error, null, 2)}`);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
create(login: string, email: string, password: string) {
|
||||
return this.createSha(login, email, sha512(password));
|
||||
|
Loading…
Reference in New Issue
Block a user