[DEV] remove common from repository
This commit is contained in:
parent
64fcd5e863
commit
f6c4f50291
@ -1,3 +0,0 @@
|
||||
<div>
|
||||
<img height="50px" [src]="getImage()"/>
|
||||
</div>
|
@ -1,68 +0,0 @@
|
||||
import { ComponentFixture, fakeAsync, TestBed, tick } from '@angular/core/testing';
|
||||
import { PasswordEntryComponent } from './async-status-component';
|
||||
|
||||
describe('PasswordEntryComponent global test', () => {
|
||||
let component: PasswordEntryComponent;
|
||||
let fixture: ComponentFixture<PasswordEntryComponent>;
|
||||
let input: HTMLInputElement;
|
||||
let button: HTMLButtonElement;
|
||||
|
||||
beforeEach(async () => {
|
||||
await TestBed.configureTestingModule({
|
||||
declarations: [PasswordEntryComponent],
|
||||
}).compileComponents();
|
||||
fixture = TestBed.createComponent(PasswordEntryComponent);
|
||||
component = fixture.componentInstance;
|
||||
input = fixture.nativeElement.querySelector('div').querySelector('input');
|
||||
button = fixture.nativeElement.querySelector('div').querySelector('button');
|
||||
});
|
||||
|
||||
it('Test mode password (default)', () => {
|
||||
fixture.detectChanges();
|
||||
expect(input.textContent).toEqual('');
|
||||
expect(button.textContent).toEqual('visibility_off');
|
||||
expect(input.type).toEqual('password');
|
||||
});
|
||||
|
||||
it('Test mode text', () => {
|
||||
component.passwordVisibility = true;
|
||||
fixture.detectChanges();
|
||||
expect(input.textContent).toEqual('');
|
||||
expect(button.textContent).toEqual('visibility');
|
||||
expect(input.type).toEqual('text');
|
||||
});
|
||||
|
||||
it('test click on hide button', fakeAsync(() => {
|
||||
fixture.detectChanges();
|
||||
expect(component.passwordVisibility).toEqual(false);
|
||||
button.click();
|
||||
tick();
|
||||
fixture.detectChanges();
|
||||
expect(component.passwordVisibility).toEqual(true);
|
||||
expect(button.textContent).toEqual('visibility');
|
||||
expect(input.type).toEqual('text');
|
||||
button.click();
|
||||
tick();
|
||||
fixture.detectChanges();
|
||||
expect(component.passwordVisibility).toEqual(false);
|
||||
expect(button.textContent).toEqual('visibility_off');
|
||||
expect(input.type).toEqual('password');
|
||||
}));
|
||||
|
||||
it('Set password', fakeAsync(() => {
|
||||
fixture.detectChanges();
|
||||
expect(component.passwordVisibility).toEqual(false);
|
||||
let tmpData = 'My beautifull Password';
|
||||
input.value = tmpData;
|
||||
input.dispatchEvent(new Event('input'));
|
||||
fixture.detectChanges();
|
||||
expect(input.textContent).toEqual(tmpData);
|
||||
expect(component.value).toEqual(tmpData);
|
||||
tmpData = '';
|
||||
input.value = tmpData;
|
||||
input.dispatchEvent(new Event('input'));
|
||||
fixture.detectChanges();
|
||||
expect(input.textContent).toEqual(tmpData);
|
||||
expect(component.value).toEqual(tmpData);
|
||||
}));
|
||||
});
|
@ -1,37 +0,0 @@
|
||||
/** @file
|
||||
* @author Edouard DUPIN
|
||||
* @copyright 2018, Edouard DUPIN, all right reserved
|
||||
* @license PROPRIETARY (see license file)
|
||||
*/
|
||||
import { Component, Input } from '@angular/core';
|
||||
|
||||
export enum AsyncActionState {
|
||||
IDLE = "idle",
|
||||
LOADING = "loading",
|
||||
DONE = "done",
|
||||
FAIL = "fail",
|
||||
}
|
||||
|
||||
@Component({
|
||||
selector: 'app-async-status-component',
|
||||
templateUrl: 'async-status-component.html',
|
||||
styleUrls: ['async-status-component.less'],
|
||||
})
|
||||
export class AsyncActionStatusComponent {
|
||||
/// Value of the password
|
||||
@Input() value: AsyncActionState = AsyncActionState.IDLE;
|
||||
|
||||
public getImage(): string {
|
||||
switch(this.value) {
|
||||
case AsyncActionState.IDLE:
|
||||
return '';
|
||||
case AsyncActionState.LOADING:
|
||||
return 'assets/images/load.svg';
|
||||
case AsyncActionState.DONE:
|
||||
return 'assets/images/validate.svg';
|
||||
case AsyncActionState.FAIL:
|
||||
return 'assets/images/validate-not.svg';
|
||||
|
||||
}
|
||||
}
|
||||
}
|
@ -1,13 +0,0 @@
|
||||
|
||||
<div>
|
||||
<div class="bmp-title">
|
||||
<div class="title"><ng-content select="name"></ng-content></div>
|
||||
<div class="description"><ng-content select="description"></ng-content></div>
|
||||
</div>
|
||||
<div class="bmp-elements">
|
||||
<ng-content select="body"></ng-content>
|
||||
</div>
|
||||
<div class="bmp-validation">
|
||||
<ng-content select="footer"></ng-content>
|
||||
</div>
|
||||
</div>
|
@ -1,78 +0,0 @@
|
||||
.bmp-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;
|
||||
|
||||
.title {
|
||||
font-size: 24px;
|
||||
font-weight: bold;
|
||||
line-height: 24px;
|
||||
vertical-align: middle;
|
||||
margin: 10px 0 10px 0;
|
||||
text-align: Left;
|
||||
}
|
||||
.description {
|
||||
font-size: 16px;
|
||||
line-height: 16px;
|
||||
vertical-align: middle;
|
||||
margin: 10px 0 10px 0;
|
||||
text-align: Left;
|
||||
}
|
||||
}
|
||||
|
||||
.bmp-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-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%;
|
||||
}
|
||||
}*/
|
||||
}
|
||||
|
||||
.bmp-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;
|
||||
}
|
@ -1,18 +0,0 @@
|
||||
/** @file
|
||||
* @author Edouard DUPIN
|
||||
* @copyright 2020, Edouard DUPIN, all right reserved
|
||||
* @license MPL-2 (see license file)
|
||||
*/
|
||||
|
||||
import { Component } from '@angular/core';
|
||||
|
||||
@Component({
|
||||
// moduleId: module.id.toString(),
|
||||
selector: 'burger-property',
|
||||
templateUrl: './burger-property.html',
|
||||
styleUrls: ['./burger-property.less'],
|
||||
})
|
||||
export class BurgerPropertyComponent {
|
||||
|
||||
constructor() {}
|
||||
}
|
@ -1,7 +0,0 @@
|
||||
<div class="elem-checkbox">
|
||||
<input
|
||||
type="checkbox"
|
||||
[checked]="value"
|
||||
(change)="onChange($event.target.checked)" />
|
||||
{{comment}}
|
||||
</div>
|
@ -1,6 +0,0 @@
|
||||
|
||||
.elem-checkbox {
|
||||
font-size: 18px;
|
||||
font-weight: bold;
|
||||
margin: 0 10px 0 10px;
|
||||
}
|
@ -1,29 +0,0 @@
|
||||
/** @file
|
||||
* @author Edouard DUPIN
|
||||
* @copyright 2018, Edouard DUPIN, all right reserved
|
||||
* @license PROPRIETARY (see license file)
|
||||
*/
|
||||
import { Component, EventEmitter, Input, Output } from '@angular/core';
|
||||
|
||||
@Component({
|
||||
selector: 'app-checkbox',
|
||||
templateUrl: 'checkbox.html',
|
||||
styleUrls: ['checkbox.less'],
|
||||
})
|
||||
export class CheckboxComponent {
|
||||
/// Checkbox value
|
||||
@Input() value: boolean = false;
|
||||
/// Description of the checkbox
|
||||
@Input() comment: string = "";
|
||||
/// event when change the value of the password
|
||||
@Output() changeValue: EventEmitter<boolean> = new EventEmitter();
|
||||
|
||||
/**
|
||||
* When input value change, need update the display and change the internal value.
|
||||
* @param newValue New value set on the password
|
||||
*/
|
||||
onChange(newValue: boolean): void {
|
||||
this.value = newValue;
|
||||
this.changeValue.emit(this.value);
|
||||
}
|
||||
}
|
@ -1,15 +0,0 @@
|
||||
<div class="top">
|
||||
<input
|
||||
type="text"
|
||||
[placeholder]="placeholder===undefined?'':placeholder"
|
||||
required=""
|
||||
[style.border]="hasError||notANumber? '2px dashed red' : ''"
|
||||
[(ngModel)]="value"
|
||||
(input)="onChangeValue($event.target.value)" />
|
||||
<button class="eye-button-2 unselectable" tabindex="-1" (click)="onDecrement()" type="submit">
|
||||
<i class="material-icons">arrow_back_ios</i>
|
||||
</button>
|
||||
<button class="eye-button unselectable" tabindex="-1" (click)="onIncrement()" type="submit">
|
||||
<i class="material-icons">arrow_forward_ios</i>
|
||||
</button>
|
||||
</div>
|
@ -1,39 +0,0 @@
|
||||
input {
|
||||
width: 100%;
|
||||
padding: 12px 20px;
|
||||
margin: 8px 0;
|
||||
display: inline-block;
|
||||
border: 1px solid #ccc;
|
||||
box-sizing: border-box;
|
||||
z-index: 5;
|
||||
}
|
||||
.eye-button {
|
||||
margin-left: -44px;
|
||||
margin-top: 15px;
|
||||
float: right;
|
||||
position: relative;
|
||||
display: block;
|
||||
border: none;
|
||||
z-index: 15;
|
||||
background: none;
|
||||
padding: 4 1 13 1;
|
||||
:hover {
|
||||
background: none;
|
||||
color: red;
|
||||
}
|
||||
}
|
||||
.eye-button-2 {
|
||||
margin-left: -70px;
|
||||
margin-top: 12px;
|
||||
float: right;
|
||||
position: relative;
|
||||
display: block;
|
||||
border: none;
|
||||
z-index: 15;
|
||||
background: none;
|
||||
padding: 4px 30px 4px 1px;
|
||||
:hover {
|
||||
background: none;
|
||||
color: red;
|
||||
}
|
||||
}
|
@ -1,70 +0,0 @@
|
||||
/** @file
|
||||
* @author Edouard DUPIN
|
||||
* @copyright 2018, Edouard DUPIN, all right reserved
|
||||
* @license PROPRIETARY (see license file)
|
||||
*/
|
||||
import { Component, EventEmitter, Input, OnInit, Output } from '@angular/core';
|
||||
import { isNumeric } from 'common/utils';
|
||||
|
||||
@Component({
|
||||
selector: 'app-entry-number',
|
||||
templateUrl: 'entry-number.html',
|
||||
styleUrls: ['entry-number.less'],
|
||||
})
|
||||
export class EntryNumberComponent implements OnInit {
|
||||
/// Value of the password
|
||||
@Input() value: string|undefined = '';
|
||||
/// Placeholder of the Value
|
||||
@Input() placeholder: string|undefined = '';
|
||||
/// The element has an error
|
||||
@Input() hasError: boolean = false;
|
||||
/// event when change the value of the password
|
||||
@Output() changeValue: EventEmitter<number|undefined> = new EventEmitter();
|
||||
|
||||
public notANumber: boolean = false;
|
||||
ngOnInit(): void {
|
||||
//if (value)
|
||||
}
|
||||
|
||||
/**
|
||||
* When input value change, need update the display and change the internal value.
|
||||
* @param newValue New value set on the password
|
||||
*/
|
||||
onChangeValue(newValue: string): void {
|
||||
if (newValue === "") {
|
||||
this.value = undefined;
|
||||
this.notANumber = false;
|
||||
this.changeValue.emit(undefined);
|
||||
return;
|
||||
}
|
||||
this.value = newValue;
|
||||
this.notANumber = false;
|
||||
if (!isNumeric(this.value)) {
|
||||
this.notANumber = true;
|
||||
}
|
||||
const numValue = Number(this.value);
|
||||
this.changeValue.emit(numValue);
|
||||
}
|
||||
onIncrement() {
|
||||
this.notANumber = false;
|
||||
let newValue = undefined;
|
||||
if (!isNumeric(this.value)) {
|
||||
newValue = 0;
|
||||
} else {
|
||||
newValue = Number(this.value) + 1;
|
||||
}
|
||||
this.value = "" + newValue;
|
||||
this.changeValue.emit(newValue);
|
||||
}
|
||||
onDecrement() {
|
||||
this.notANumber = false;
|
||||
let newValue = undefined;
|
||||
if (!isNumeric(this.value)) {
|
||||
newValue = 0;
|
||||
} else {
|
||||
newValue = Number(this.value) - 1;
|
||||
}
|
||||
this.value = "" + newValue;
|
||||
this.changeValue.emit(newValue);
|
||||
}
|
||||
}
|
@ -1,8 +0,0 @@
|
||||
<div>
|
||||
<app-entry
|
||||
[value]="value"
|
||||
[placeholder]="placeholder"
|
||||
[hasError]="state !== true"
|
||||
(changeValue)="check($event)"></app-entry>
|
||||
<app-error-message-state [value]="state"></app-error-message-state>
|
||||
</div>
|
@ -1,9 +0,0 @@
|
||||
input[type='text'] {
|
||||
width: 100%;
|
||||
padding: 12px 20px;
|
||||
margin: 8px 0;
|
||||
display: inline-block;
|
||||
border: 1px solid #ccc;
|
||||
box-sizing: border-box;
|
||||
z-index: 5;
|
||||
}
|
@ -1,59 +0,0 @@
|
||||
/** @file
|
||||
* @author Edouard DUPIN
|
||||
* @copyright 2018, Edouard DUPIN, all right reserved
|
||||
* @license PROPRIETARY (see license file)
|
||||
*/
|
||||
import { Component, EventEmitter, Input, OnInit, Output } from '@angular/core';
|
||||
import { isNullOrUndefined } from 'common/utils';
|
||||
|
||||
export type ReturnFunction = (a: boolean|string) => void;
|
||||
|
||||
export type CheckerParameter = {
|
||||
value: string,
|
||||
result: ReturnFunction
|
||||
}
|
||||
|
||||
@Component({
|
||||
selector: 'app-entry-validator',
|
||||
templateUrl: 'entry-validator.html',
|
||||
styleUrls: ['entry-validator.less'],
|
||||
})
|
||||
export class EntryValidatorComponent implements OnInit {
|
||||
/// Value of the password
|
||||
@Input() value: string = '';
|
||||
/// Placeholder of the Value
|
||||
@Input() placeholder: string = '';
|
||||
/// The element has an error
|
||||
@Output() checker: EventEmitter<CheckerParameter> = new EventEmitter();
|
||||
/// event when change the value of the password
|
||||
@Output() changeValue: EventEmitter<string> = new EventEmitter();
|
||||
|
||||
|
||||
public state: boolean|string = false;
|
||||
|
||||
ngOnInit(): void {
|
||||
//if (value)
|
||||
}
|
||||
|
||||
updateStatus(value: boolean|string): void {
|
||||
this.state = value
|
||||
if (this.state === true) {
|
||||
this.changeValue.emit(this.value);
|
||||
}
|
||||
}
|
||||
|
||||
check(newValue: string): void {
|
||||
let self = this;
|
||||
let lambdaCallBack = (value: boolean|string) => {self.updateStatus(value)};
|
||||
this.value = newValue;
|
||||
if (isNullOrUndefined(this.checker)) {
|
||||
this.changeValue.emit(this.value);
|
||||
return;
|
||||
}
|
||||
this.checker.emit({
|
||||
value: newValue,
|
||||
result: lambdaCallBack,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
@ -1,9 +0,0 @@
|
||||
<div class="top">
|
||||
<input
|
||||
type="text"
|
||||
[placeholder]="placeholder===undefined?'':placeholder"
|
||||
required=""
|
||||
[style.border]="hasError? '2px dashed red' : ''"
|
||||
[value]="value===undefined?'':value"
|
||||
(input)="onChangeValue($event.target.value)" />
|
||||
</div>
|
@ -1,9 +0,0 @@
|
||||
input[type='text'] {
|
||||
width: 100%;
|
||||
padding: 12px 20px;
|
||||
margin: 8px 0;
|
||||
display: inline-block;
|
||||
border: 1px solid #ccc;
|
||||
box-sizing: border-box;
|
||||
z-index: 5;
|
||||
}
|
@ -1,68 +0,0 @@
|
||||
import { ComponentFixture, fakeAsync, TestBed, tick } from '@angular/core/testing';
|
||||
import { PasswordEntryComponent } from './entry';
|
||||
|
||||
describe('PasswordEntryComponent global test', () => {
|
||||
let component: PasswordEntryComponent;
|
||||
let fixture: ComponentFixture<PasswordEntryComponent>;
|
||||
let input: HTMLInputElement;
|
||||
let button: HTMLButtonElement;
|
||||
|
||||
beforeEach(async () => {
|
||||
await TestBed.configureTestingModule({
|
||||
declarations: [PasswordEntryComponent],
|
||||
}).compileComponents();
|
||||
fixture = TestBed.createComponent(PasswordEntryComponent);
|
||||
component = fixture.componentInstance;
|
||||
input = fixture.nativeElement.querySelector('div').querySelector('input');
|
||||
button = fixture.nativeElement.querySelector('div').querySelector('button');
|
||||
});
|
||||
|
||||
it('Test mode password (default)', () => {
|
||||
fixture.detectChanges();
|
||||
expect(input.textContent).toEqual('');
|
||||
expect(button.textContent).toEqual('visibility_off');
|
||||
expect(input.type).toEqual('password');
|
||||
});
|
||||
|
||||
it('Test mode text', () => {
|
||||
component.passwordVisibility = true;
|
||||
fixture.detectChanges();
|
||||
expect(input.textContent).toEqual('');
|
||||
expect(button.textContent).toEqual('visibility');
|
||||
expect(input.type).toEqual('text');
|
||||
});
|
||||
|
||||
it('test click on hide button', fakeAsync(() => {
|
||||
fixture.detectChanges();
|
||||
expect(component.passwordVisibility).toEqual(false);
|
||||
button.click();
|
||||
tick();
|
||||
fixture.detectChanges();
|
||||
expect(component.passwordVisibility).toEqual(true);
|
||||
expect(button.textContent).toEqual('visibility');
|
||||
expect(input.type).toEqual('text');
|
||||
button.click();
|
||||
tick();
|
||||
fixture.detectChanges();
|
||||
expect(component.passwordVisibility).toEqual(false);
|
||||
expect(button.textContent).toEqual('visibility_off');
|
||||
expect(input.type).toEqual('password');
|
||||
}));
|
||||
|
||||
it('Set password', fakeAsync(() => {
|
||||
fixture.detectChanges();
|
||||
expect(component.passwordVisibility).toEqual(false);
|
||||
let tmpData = 'My beautifull Password';
|
||||
input.value = tmpData;
|
||||
input.dispatchEvent(new Event('input'));
|
||||
fixture.detectChanges();
|
||||
expect(input.textContent).toEqual(tmpData);
|
||||
expect(component.value).toEqual(tmpData);
|
||||
tmpData = '';
|
||||
input.value = tmpData;
|
||||
input.dispatchEvent(new Event('input'));
|
||||
fixture.detectChanges();
|
||||
expect(input.textContent).toEqual(tmpData);
|
||||
expect(component.value).toEqual(tmpData);
|
||||
}));
|
||||
});
|
@ -1,35 +0,0 @@
|
||||
/** @file
|
||||
* @author Edouard DUPIN
|
||||
* @copyright 2018, Edouard DUPIN, all right reserved
|
||||
* @license PROPRIETARY (see license file)
|
||||
*/
|
||||
import { Component, EventEmitter, Input, OnInit, Output } from '@angular/core';
|
||||
|
||||
@Component({
|
||||
selector: 'app-entry',
|
||||
templateUrl: 'entry.html',
|
||||
styleUrls: ['entry.less'],
|
||||
})
|
||||
export class EntryComponent implements OnInit {
|
||||
/// Value of the password
|
||||
@Input() value: string|undefined = '';
|
||||
/// Placeholder of the Value
|
||||
@Input() placeholder: string|undefined = '';
|
||||
/// The element has an error
|
||||
@Input() hasError: boolean = false;
|
||||
/// event when change the value of the password
|
||||
@Output() changeValue: EventEmitter<string> = new EventEmitter();
|
||||
|
||||
ngOnInit(): void {
|
||||
//if (value)
|
||||
}
|
||||
|
||||
/**
|
||||
* When input value change, need update the display and change the internal value.
|
||||
* @param newValue New value set on the password
|
||||
*/
|
||||
onChangeValue(newValue: string): void {
|
||||
this.value = newValue;
|
||||
this.changeValue.emit(this.value);
|
||||
}
|
||||
}
|
@ -1 +0,0 @@
|
||||
<div class="error color-shadow-black" *ngIf="value !== true && value !== false && value !== undefined">{{value}}</div>
|
@ -1,34 +0,0 @@
|
||||
|
||||
.error {
|
||||
background-color: #f44336;
|
||||
position: absolute;
|
||||
z-index: 10;
|
||||
display: block;
|
||||
max-width: 450px;
|
||||
padding: 5px 8px;
|
||||
margin: 2px 0 0;
|
||||
font-size: 16px;
|
||||
font-weight: 400;
|
||||
border-style: solid;
|
||||
border-width: 0px;
|
||||
box-sizing: border-box;
|
||||
|
||||
&:after,
|
||||
&:before {
|
||||
bottom: 100%;
|
||||
left: 25px;
|
||||
border: solid transparent;
|
||||
content: ' ';
|
||||
height: 0;
|
||||
width: 0;
|
||||
position: absolute;
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
&:after {
|
||||
border-bottom-color: #f44336;
|
||||
border-width: 10px;
|
||||
margin-left: -10px;
|
||||
}
|
||||
}
|
||||
|
@ -1,17 +0,0 @@
|
||||
/** @file
|
||||
* @author Edouard DUPIN
|
||||
* @copyright 2018, Edouard DUPIN, all right reserved
|
||||
* @license PROPRIETARY (see license file)
|
||||
*/
|
||||
import { Component, Input } from '@angular/core';
|
||||
|
||||
@Component({
|
||||
selector: 'app-error-message-state',
|
||||
templateUrl: 'error-message-state.html',
|
||||
styleUrls: ['error-message-state.less'],
|
||||
})
|
||||
export class ErrorMessageStateComponent {
|
||||
/// Value of the password
|
||||
@Input() value: boolean|string = false;
|
||||
|
||||
}
|
@ -1 +0,0 @@
|
||||
<p>error works!</p>
|
@ -1,18 +0,0 @@
|
||||
/** @file
|
||||
* @author Edouard DUPIN
|
||||
* @copyright 2018, Edouard DUPIN, all right reserved
|
||||
* @license PROPRIETARY (see license file)
|
||||
*/
|
||||
|
||||
import { Component, OnInit } from '@angular/core';
|
||||
|
||||
@Component({
|
||||
selector: 'app-error',
|
||||
templateUrl: './error.html',
|
||||
styleUrls: ['./error.less'],
|
||||
})
|
||||
export class ErrorComponent implements OnInit {
|
||||
constructor() {}
|
||||
|
||||
ngOnInit() {}
|
||||
}
|
@ -1,17 +0,0 @@
|
||||
import { AsyncActionState, AsyncActionStatusComponent } from './async-action-status/async-status-component';
|
||||
import { BurgerPropertyComponent } from './burger-property/burger-property';
|
||||
import { CheckboxComponent } from './checkbox/checkbox';
|
||||
import { EntryNumberComponent } from './entry-number/entry-number';
|
||||
import { EntryValidatorComponent } from './entry-validator/entry-validator';
|
||||
import { EntryComponent } from './entry/entry';
|
||||
import { ErrorMessageStateComponent } from './error-message-state/error-message-state';
|
||||
import { ErrorComponent } from './error/error';
|
||||
import { PasswordEntryComponent } from './password-entry/password-entry';
|
||||
import { PopInComponent } from './popin/popin';
|
||||
import { RenderFormComponent } from './render-settings/render-form';
|
||||
import { RenderSettingsComponent } from './render-settings/render-settings';
|
||||
import { SpinerComponent } from './spiner/spiner';
|
||||
import { TopMenuComponent } from './top-menu/top-menu';
|
||||
import { UploadFileComponent } from './upload-file/upload-file';
|
||||
|
||||
export { BurgerPropertyComponent, EntryNumberComponent, CheckboxComponent, RenderFormComponent, RenderSettingsComponent, ErrorMessageStateComponent, AsyncActionState, AsyncActionStatusComponent, EntryValidatorComponent, PopInComponent, TopMenuComponent, UploadFileComponent, ErrorComponent, SpinerComponent, PasswordEntryComponent, EntryComponent };
|
@ -1,12 +0,0 @@
|
||||
<div class="top">
|
||||
<input
|
||||
[type]="passwordVisibility?'text':'password'"
|
||||
[placeholder]="placeholder===undefined?'':placeholder"
|
||||
required=""
|
||||
[style.border]="hasError? '2px dashed red' : ''"
|
||||
[value]="value"
|
||||
(input)="onChangeValue($event.target.value)" />
|
||||
<button class="eye-button unselectable" tabindex="-1" (click)="onVisibility()" type="submit">
|
||||
<i class="material-icons">{{passwordVisibility?"visibility":"visibility_off"}}</i>
|
||||
</button>
|
||||
</div>
|
@ -1,25 +0,0 @@
|
||||
.eye-button {
|
||||
margin-left: -44px;
|
||||
margin-top: 15px;
|
||||
float: right;
|
||||
position: relative;
|
||||
display: block;
|
||||
border: none;
|
||||
z-index: 15;
|
||||
background: none;
|
||||
padding: 4 1 13 1;
|
||||
:hover {
|
||||
background: none;
|
||||
}
|
||||
}
|
||||
|
||||
input[type='text'],
|
||||
input[type='password'] {
|
||||
width: 100%;
|
||||
padding: 12px 20px;
|
||||
margin: 8px 0;
|
||||
display: inline-block;
|
||||
border: 1px solid #ccc;
|
||||
box-sizing: border-box;
|
||||
z-index: 5;
|
||||
}
|
@ -1,68 +0,0 @@
|
||||
import { ComponentFixture, fakeAsync, TestBed, tick } from '@angular/core/testing';
|
||||
import { PasswordEntryComponent } from './password-entry';
|
||||
|
||||
describe('PasswordEntryComponent global test', () => {
|
||||
let component: PasswordEntryComponent;
|
||||
let fixture: ComponentFixture<PasswordEntryComponent>;
|
||||
let input: HTMLInputElement;
|
||||
let button: HTMLButtonElement;
|
||||
|
||||
beforeEach(async () => {
|
||||
await TestBed.configureTestingModule({
|
||||
declarations: [PasswordEntryComponent],
|
||||
}).compileComponents();
|
||||
fixture = TestBed.createComponent(PasswordEntryComponent);
|
||||
component = fixture.componentInstance;
|
||||
input = fixture.nativeElement.querySelector('div').querySelector('input');
|
||||
button = fixture.nativeElement.querySelector('div').querySelector('button');
|
||||
});
|
||||
|
||||
it('Test mode password (default)', () => {
|
||||
fixture.detectChanges();
|
||||
expect(input.textContent).toEqual('');
|
||||
expect(button.textContent).toEqual('visibility_off');
|
||||
expect(input.type).toEqual('password');
|
||||
});
|
||||
|
||||
it('Test mode text', () => {
|
||||
component.passwordVisibility = true;
|
||||
fixture.detectChanges();
|
||||
expect(input.textContent).toEqual('');
|
||||
expect(button.textContent).toEqual('visibility');
|
||||
expect(input.type).toEqual('text');
|
||||
});
|
||||
|
||||
it('test click on hide button', fakeAsync(() => {
|
||||
fixture.detectChanges();
|
||||
expect(component.passwordVisibility).toEqual(false);
|
||||
button.click();
|
||||
tick();
|
||||
fixture.detectChanges();
|
||||
expect(component.passwordVisibility).toEqual(true);
|
||||
expect(button.textContent).toEqual('visibility');
|
||||
expect(input.type).toEqual('text');
|
||||
button.click();
|
||||
tick();
|
||||
fixture.detectChanges();
|
||||
expect(component.passwordVisibility).toEqual(false);
|
||||
expect(button.textContent).toEqual('visibility_off');
|
||||
expect(input.type).toEqual('password');
|
||||
}));
|
||||
|
||||
it('Set password', fakeAsync(() => {
|
||||
fixture.detectChanges();
|
||||
expect(component.passwordVisibility).toEqual(false);
|
||||
let tmpData = 'My beautifull Password';
|
||||
input.value = tmpData;
|
||||
input.dispatchEvent(new Event('input'));
|
||||
fixture.detectChanges();
|
||||
expect(input.textContent).toEqual(tmpData);
|
||||
expect(component.value).toEqual(tmpData);
|
||||
tmpData = '';
|
||||
input.value = tmpData;
|
||||
input.dispatchEvent(new Event('input'));
|
||||
fixture.detectChanges();
|
||||
expect(input.textContent).toEqual(tmpData);
|
||||
expect(component.value).toEqual(tmpData);
|
||||
}));
|
||||
});
|
@ -1,39 +0,0 @@
|
||||
/** @file
|
||||
* @author Edouard DUPIN
|
||||
* @copyright 2018, Edouard DUPIN, all right reserved
|
||||
* @license PROPRIETARY (see license file)
|
||||
*/
|
||||
import { Component, EventEmitter, Input, Output } from '@angular/core';
|
||||
|
||||
@Component({
|
||||
selector: 'app-password-entry',
|
||||
templateUrl: 'password-entry.html',
|
||||
styleUrls: ['password-entry.less'],
|
||||
})
|
||||
export class PasswordEntryComponent {
|
||||
/// Value of the password
|
||||
@Input() value: string = '';
|
||||
/// Placeholder of the Value
|
||||
@Input() placeholder: string = 'Write password.';
|
||||
/// The element has an error
|
||||
@Input() hasError: boolean = false;
|
||||
/// event when change the value of the password
|
||||
@Output() changeValue: EventEmitter<string> = new EventEmitter();
|
||||
/// Local value of the password viwibility
|
||||
public passwordVisibility: boolean = false;
|
||||
/**
|
||||
* Ov visibility request change (toggle the visibility)
|
||||
*/
|
||||
onVisibility(): void {
|
||||
this.passwordVisibility = !this.passwordVisibility;
|
||||
}
|
||||
|
||||
/**
|
||||
* When input value change, need update the display and change the internal value.
|
||||
* @param newValue New value set on the password
|
||||
*/
|
||||
onChangeValue(newValue: string): void {
|
||||
this.value = newValue;
|
||||
this.changeValue.emit(this.value);
|
||||
}
|
||||
}
|
@ -1,38 +0,0 @@
|
||||
<div class="popin" *ngIf="displayPopIn">
|
||||
<div class="element {{popSize}}">
|
||||
<div class="header">
|
||||
<label class="unselectable">{{popTitle}}</label>
|
||||
<div class="close" *ngIf="closeTopRight == true">
|
||||
<button class="button-close color-shadow-black" (click)="onCloseTop()" type="submit">
|
||||
<label class="unselectable"><i class="material-icons">close</i></label>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="body">
|
||||
<ng-content></ng-content>
|
||||
</div>
|
||||
<div class="footer">
|
||||
<div class="action" *ngIf="validateTitle != null">
|
||||
<button class="button color-shadow-black" (click)="onValidate()" type="submit">
|
||||
<label class="unselectable"><i class="material-icons">done</i> {{validateTitle}}</label>
|
||||
</button>
|
||||
</div>
|
||||
<div class="action" *ngIf="saveTitle != null">
|
||||
<button class="button color-shadow-black" (click)="onSave()" type="submit">
|
||||
<label class="unselectable"><i class="material-icons">save_alt</i> {{saveTitle}}</label>
|
||||
</button>
|
||||
</div>
|
||||
<div class="action" *ngIf="otherTitle != null">
|
||||
<button class="button color-shadow-black" (click)="onOther()" type="submit">
|
||||
<label class="unselectable"><i class="material-icons">star</i> {{otherTitle}}</label>
|
||||
</button>
|
||||
</div>
|
||||
<div class="action" *ngIf="closeTitle != null">
|
||||
<button class="button color-shadow-black" (click)="onClose()" type="submit">
|
||||
<label class="unselectable"><i class="material-icons">close</i> {{closeTitle}}</label>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="background"></div>
|
||||
</div>
|
@ -1,87 +0,0 @@
|
||||
/* popin STYLES
|
||||
-------------------------------*/
|
||||
|
||||
/* popins are hidden by default */
|
||||
.popin {
|
||||
position: fixed;
|
||||
top: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
z-index: 800;
|
||||
.small {
|
||||
top: 15%;
|
||||
right: 35%;
|
||||
bottom: 15%;
|
||||
left: 35%;
|
||||
}
|
||||
.medium {
|
||||
top: 15%;
|
||||
right: 25%;
|
||||
bottom: 15%;
|
||||
left: 25%;
|
||||
}
|
||||
.big {
|
||||
top: 15%;
|
||||
right: 15%;
|
||||
bottom: 15%;
|
||||
left: 15%;
|
||||
}
|
||||
.element {
|
||||
/* popin container fixed across whole screen */
|
||||
position: fixed;
|
||||
display: block;
|
||||
/* z-index must be higher than .popin-background */
|
||||
z-index: 1000;
|
||||
/* enables scrolling for tall popins */
|
||||
overflow: auto;
|
||||
|
||||
.header {
|
||||
padding: 10px;
|
||||
//display: block;
|
||||
background: #88f;
|
||||
//margin: 40px;
|
||||
//margin: auto;
|
||||
height: 40px;
|
||||
line-height: 36px;
|
||||
.close {
|
||||
display: block;
|
||||
float: right;
|
||||
}
|
||||
}
|
||||
|
||||
.body {
|
||||
//display: block;
|
||||
padding: 20px;
|
||||
background: #fff;
|
||||
/* margin exposes part of the popin background */
|
||||
//margin: 40px;
|
||||
//margin: auto;
|
||||
}
|
||||
.footer {
|
||||
padding: 10px;
|
||||
//display: block;
|
||||
background: #888;
|
||||
//margin: 40px;
|
||||
//margin: auto;
|
||||
height: 40px;
|
||||
line-height: 36px;
|
||||
.action {
|
||||
padding: 0 10px;
|
||||
display: block;
|
||||
float: right;
|
||||
}
|
||||
}
|
||||
}
|
||||
// Pop in mush have a background over all the windows ...
|
||||
.background {
|
||||
position: fixed;
|
||||
top: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
background-color: #000;
|
||||
opacity: 0.85;
|
||||
z-index: 900;
|
||||
}
|
||||
}
|
@ -1,78 +0,0 @@
|
||||
/** @file
|
||||
* @author Edouard DUPIN
|
||||
* @copyright 2020, Edouard DUPIN, all right reserved
|
||||
* @license MPL-2 (see license file)
|
||||
*/
|
||||
|
||||
import { Component, Input, Output, OnInit, OnDestroy, EventEmitter } from '@angular/core';
|
||||
import { PopInService } from 'common/service';
|
||||
|
||||
@Component({
|
||||
// moduleId: module.id.toString(),
|
||||
selector: 'app-popin',
|
||||
templateUrl: './popin.html',
|
||||
styleUrls: ['./popin.less'],
|
||||
})
|
||||
export class PopInComponent implements OnInit, OnDestroy {
|
||||
@Input() id: string;
|
||||
@Input() popTitle: string = 'No title';
|
||||
@Input() closeTopRight: any = 'false';
|
||||
@Input() popSize: string = 'medium';
|
||||
|
||||
@Output() callback: EventEmitter<any> = new EventEmitter();
|
||||
@Input() closeTitle: any = null;
|
||||
@Input() validateTitle: any = null;
|
||||
@Input() saveTitle: any = null;
|
||||
@Input() otherTitle: any = null;
|
||||
|
||||
public displayPopIn: boolean = false;
|
||||
|
||||
constructor(private popInService: PopInService) {}
|
||||
ngOnInit(): void {
|
||||
// ensure id attribute exists
|
||||
if (!this.id) {
|
||||
console.error('popin must have an id');
|
||||
return;
|
||||
}
|
||||
// move element to bottom of page (just before </body>) so it can be displayed above everything else
|
||||
// this.element.appendTo('body');
|
||||
this.popInService.add(this);
|
||||
// this.element.hide();
|
||||
}
|
||||
// remove self from popIn service when directive is destroyed
|
||||
ngOnDestroy(): void {
|
||||
this.popInService.remove(this.id);
|
||||
// this.element.remove();
|
||||
}
|
||||
// open popIn
|
||||
open(): void {
|
||||
//console.log(`open pop-in: ${this.id}`);
|
||||
this.displayPopIn = true;
|
||||
//this.element.show();
|
||||
}
|
||||
// close popin
|
||||
close(): void {
|
||||
this.displayPopIn = false;
|
||||
// this.element.hide();
|
||||
}
|
||||
|
||||
onCloseTop(): void {
|
||||
this.callback.emit(['close-top']);
|
||||
}
|
||||
|
||||
onValidate(): void {
|
||||
this.callback.emit(['validate']);
|
||||
}
|
||||
|
||||
onClose(): void {
|
||||
this.callback.emit(['close']);
|
||||
}
|
||||
|
||||
onOther(): void {
|
||||
this.callback.emit(['other']);
|
||||
}
|
||||
|
||||
onSave(): void {
|
||||
this.callback.emit(['save']);
|
||||
}
|
||||
}
|
@ -1,47 +0,0 @@
|
||||
<table width="100%">
|
||||
<tr *ngFor="let elem of values">
|
||||
<td width="15%" *ngIf="elem.type === 'STRING' || elem.type === 'PASSWORD' || elem.type === 'NUMBER'"
|
||||
[style.color]="getStyleRequireError(elem)"
|
||||
[style.font-weight]="elem.require === true ? 'bold' : ''"
|
||||
>{{elem.title}}</td>
|
||||
<td width="15%" *ngIf="elem.type === 'BOOLEAN'"
|
||||
[style.color]="getStyleRequireError(elem)"
|
||||
[style.font-weight]="elem.require === true ? 'bold' : ''"
|
||||
>{{elem.title}}</td>
|
||||
<td width="15%" *ngIf="elem.type === 'VALUE'"><b>{{elem.title}}</b></td>
|
||||
|
||||
<td width="85%" *ngIf="elem.type === 'VALUE'">{{elem.value}}</td>
|
||||
<td width="85%" *ngIf="elem.type === 'STRING'">
|
||||
<app-entry
|
||||
[value]="elem.value"
|
||||
[placeholder]="elem.placeholder"
|
||||
[hasError]="checkHasError(elem)"
|
||||
(changeValue)="checkParameter($event, elem)"></app-entry>
|
||||
<app-error-message-state [value]="elem.state"></app-error-message-state>
|
||||
</td>
|
||||
<td width="85%" *ngIf="elem.type === 'NUMBER'">
|
||||
<app-entry-number
|
||||
[value]="elem.value"
|
||||
[placeholder]="elem.placeholder"
|
||||
[hasError]="checkHasError(elem)"
|
||||
(changeValue)="checkParameter($event, elem)"></app-entry-number>
|
||||
<app-error-message-state [value]="elem.state"></app-error-message-state>
|
||||
</td>
|
||||
<td width="85%" *ngIf="elem.type === 'PASSWORD'">
|
||||
<app-password-entry
|
||||
[value]="elem.value"
|
||||
[placeholder]="elem.placeholder"
|
||||
[hasError]="checkHasError(elem)"
|
||||
(changeValue)="checkParameter($event, elem)"></app-password-entry>
|
||||
<app-error-message-state [value]="elem.state"></app-error-message-state>
|
||||
</td>
|
||||
<td width="85%" *ngIf="elem.type === 'BOOLEAN'">
|
||||
<app-checkbox
|
||||
[value]="elem.value"
|
||||
(changeValue)="checkParameter($event, elem)"></app-checkbox>
|
||||
<app-error-message-state [value]="elem.state"></app-error-message-state>
|
||||
</td>
|
||||
<td width="85%" *ngIf="elem.type === 'LINE'"></td>
|
||||
<td width="85%" *ngIf="elem.type === 'LINE'"></td>
|
||||
</tr>
|
||||
</table>
|
@ -1,17 +0,0 @@
|
||||
/** @file
|
||||
* @author Edouard DUPIN
|
||||
* @copyright 2018, Edouard DUPIN, all right reserved
|
||||
* @license PROPRIETARY (see license file)
|
||||
*/
|
||||
import { Component } from '@angular/core';
|
||||
import { RenderSettingsComponent } from './render-settings';
|
||||
|
||||
@Component({
|
||||
selector: 'app-render-form',
|
||||
templateUrl: 'render-form.html',
|
||||
styleUrls: ['render-form.less'],
|
||||
})
|
||||
export class RenderFormComponent extends RenderSettingsComponent {
|
||||
|
||||
}
|
||||
|
@ -1,39 +0,0 @@
|
||||
<div *ngFor="let elem of values" class="settings-elements">
|
||||
<div *ngIf="elem.type === 'LINE'">
|
||||
<div class="elem-hr"></div>
|
||||
</div>
|
||||
<div *ngIf="elem.type === 'BOOLEAN'">
|
||||
<div class="elem-checkbox">
|
||||
<app-checkbox
|
||||
[value]="elem.value"
|
||||
[comment]="elem.title"
|
||||
(changeValue)="checkParameter($event, elem)"></app-checkbox>
|
||||
</div>
|
||||
<div class="elem-description">{{elem.description}}</div>
|
||||
</div>
|
||||
<div *ngIf="elem.type === 'STRING'">
|
||||
<div class="elem-title">{{elem.title}}</div>
|
||||
<div class="elem-description">{{elem.description}}</div>
|
||||
<div class="elem-input">
|
||||
<app-entry
|
||||
[value]="elem.value"
|
||||
[placeholder]="elem.placeholder"
|
||||
[hasError]="elem.state !== undefined"
|
||||
(changeValue)="checkParameter($event, elem)"></app-entry>
|
||||
<app-error-message-state [value]="elem.state"></app-error-message-state>
|
||||
</div>
|
||||
</div>
|
||||
<div *ngIf="elem.type === 'PASSWORD'">
|
||||
<div class="elem-title">{{elem.title}}</div>
|
||||
<div class="elem-description">{{elem.description}}</div>
|
||||
<div class="elem-input">
|
||||
<input [value]="elem.value" />
|
||||
<app-password-entry
|
||||
[value]="elem.value"
|
||||
[placeholder]="elem.placeholder"
|
||||
[hasError]="elem.state !== true"
|
||||
(changeValue)="checkParameter($event, elem)"></app-password-entry>
|
||||
<app-error-message-state [value]="elem.state"></app-error-message-state>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
@ -1,32 +0,0 @@
|
||||
|
||||
.settings-elements {
|
||||
.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%;
|
||||
}
|
||||
}
|
||||
}
|
@ -1,204 +0,0 @@
|
||||
/** @file
|
||||
* @author Edouard DUPIN
|
||||
* @copyright 2018, Edouard DUPIN, all right reserved
|
||||
* @license PROPRIETARY (see license file)
|
||||
*/
|
||||
import { Component, EventEmitter, Input, Output } from '@angular/core';
|
||||
import { isBoolean, isInArray, isNullOrUndefined, isNumber, isObject, isOptionalOf, isString, isUndefined } from 'common/utils';
|
||||
|
||||
export type ReturnFunction = (a: boolean|string) => void;
|
||||
export type CheckerParameterType = string | number | boolean | undefined;
|
||||
// if string ==> the error, if undefined, it is OK
|
||||
export type CheckerParameter = (value: CheckerParameterType) => string | undefined;
|
||||
|
||||
|
||||
export enum SettingType {
|
||||
VALUE = 'VALUE',
|
||||
LINE = 'LINE',
|
||||
BOOLEAN = 'BOOLEAN',
|
||||
NUMBER = 'NUMBER',
|
||||
STRING = 'STRING',
|
||||
PASSWORD = 'PASSWORD',
|
||||
}
|
||||
export function isSettingType(data: any): data is SettingType {
|
||||
return isInArray(data, ['VALUE', 'LINE', 'NUMBER', 'BOOLEAN', 'STRING', 'PASSWORD']);
|
||||
}
|
||||
|
||||
export interface SettingsItem {
|
||||
// Type of the menu Node
|
||||
type: SettingType;
|
||||
// Unique key reference
|
||||
key?: string;
|
||||
// Displayed Title
|
||||
title?: string;
|
||||
// Description of the parameter
|
||||
description?: string;
|
||||
// placeholder of the parameter
|
||||
placeholder?: string;
|
||||
// Parameter key to SET/GET or the sub-menu
|
||||
value?: boolean | string | Number;
|
||||
// when data is change the value is set here undefined if not correct (must be set @ undefined):
|
||||
newValue?: boolean | string | Number;
|
||||
// checker to validate the data:
|
||||
checker?: CheckerParameter
|
||||
// result of the checker (must be set @ undefined):
|
||||
state?: boolean | string;
|
||||
// The element is require to have a valid form.
|
||||
require?: boolean
|
||||
}
|
||||
|
||||
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 (!isString(data.key)) {
|
||||
return false;
|
||||
}
|
||||
if (!isOptionalOf(data.title, isString)) {
|
||||
return false;
|
||||
}
|
||||
if (!isOptionalOf(data.description, isString)) {
|
||||
return false;
|
||||
}
|
||||
if (!isOptionalOf(data.placeholder, isString)) {
|
||||
return false;
|
||||
}
|
||||
if (
|
||||
!isOptionalOf(data.value, isBoolean) &&
|
||||
!isOptionalOf(data.value, isString) &&
|
||||
!isOptionalOf(data.value, isNumber)
|
||||
) {
|
||||
return false;
|
||||
}
|
||||
if (!isUndefined(data.newValue)) {
|
||||
return false;
|
||||
}
|
||||
if (!isOptionalOf(data.state, isString)) {
|
||||
return false;
|
||||
}
|
||||
if (!isOptionalOf(data.require, isBoolean)) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
@Component({
|
||||
selector: 'app-render-settings',
|
||||
templateUrl: 'render-settings.html',
|
||||
styleUrls: ['render-settings.less'],
|
||||
})
|
||||
export class RenderSettingsComponent {
|
||||
/// Value of the password
|
||||
@Input() values: SettingsItem[] = [];
|
||||
/// Number of error detected (undefined: No change or not ready, else the number of error)
|
||||
@Output() changeState: EventEmitter<Number> = new EventEmitter();
|
||||
/// event with the changed values
|
||||
@Output() deltaValues: EventEmitter<any> = new EventEmitter();
|
||||
|
||||
createOutputValues(): object {
|
||||
let out = {};
|
||||
//console.log(" Create values ... out ... ");
|
||||
this.values.forEach( (value) => {
|
||||
if (isNullOrUndefined(value.key)) {
|
||||
return;
|
||||
}
|
||||
//console.log(` key: ${value.key} : ${value.newValue}`);
|
||||
if (!isNullOrUndefined(value.newValue)) {
|
||||
//console.log(` ==> set`);
|
||||
out[value.key] = value.newValue;
|
||||
}
|
||||
});
|
||||
return out;
|
||||
}
|
||||
|
||||
countErrors(): number | undefined {
|
||||
let out = 0;
|
||||
this.values.forEach( (value) => {
|
||||
if (!isUndefined(value.state)) {
|
||||
out++;
|
||||
}
|
||||
});
|
||||
return out;
|
||||
}
|
||||
|
||||
checkMissing(): boolean | undefined {
|
||||
let error = 0;
|
||||
this.values.forEach( (elem) => {
|
||||
if (isNumber(elem.newValue)) {
|
||||
if ((isUndefined(elem.newValue) && elem.value === undefined) || elem.newValue === undefined) {
|
||||
error++;
|
||||
}
|
||||
} else {
|
||||
if ((isUndefined(elem.newValue) && elem.value === "") || elem.newValue === "") {
|
||||
error++;
|
||||
}
|
||||
}
|
||||
});
|
||||
return error !== 0;
|
||||
}
|
||||
|
||||
getStyleRequireError(elem): string {
|
||||
if (elem.require !== true) {
|
||||
return "";
|
||||
}
|
||||
if (isNumber(elem.newValue)) {
|
||||
//console.log(`>>>>>>>>>>>>>>>>>>>>>>>>>>>>><Is a number : ${elem.newValue} ${elem.value}`)
|
||||
if ((isUndefined(elem.newValue) && elem.value === undefined) || elem.newValue === undefined) {
|
||||
return "red";
|
||||
}
|
||||
} else {
|
||||
if ((isUndefined(elem.newValue) && elem.value === "") || elem.newValue === "") {
|
||||
return "red";
|
||||
}
|
||||
}
|
||||
return "";
|
||||
}
|
||||
|
||||
checkHasError(item: SettingsItem) {
|
||||
if (!isUndefined(item.state)) {
|
||||
return true;
|
||||
}
|
||||
if (item.require === true && item.value === "" && isUndefined(item.newValue)) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
checkParameter(newValue: string | number | boolean | undefined, item: SettingsItem): void {
|
||||
if (isNullOrUndefined(newValue) || newValue === "") {
|
||||
item.state = undefined
|
||||
} else if (!isNullOrUndefined(item.checker)) {
|
||||
item.state = item.checker(newValue);
|
||||
}
|
||||
if (item.value === newValue) {
|
||||
item.newValue = undefined;
|
||||
} else {
|
||||
item.newValue = newValue;
|
||||
}
|
||||
const missing = this.checkMissing();
|
||||
const outValue = this.createOutputValues();
|
||||
const nbError = this.countErrors();
|
||||
const nbValuesChanges = Object.keys(outValue).length;
|
||||
//console.log(`outValue=${JSON.stringify(outValue, null, 2)}`);
|
||||
//console.log(`nbError=${nbError} nbValuesChanges=${nbValuesChanges}`);
|
||||
if (nbValuesChanges === 0) {
|
||||
this.changeState.emit(undefined);
|
||||
return;
|
||||
}
|
||||
if (missing === true) {
|
||||
this.changeState.emit(undefined);
|
||||
return;
|
||||
}
|
||||
this.changeState.emit(nbError);
|
||||
if (nbError === 0) {
|
||||
this.deltaValues.emit(outValue);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,14 +0,0 @@
|
||||
/** @file
|
||||
* @author Edouard DUPIN
|
||||
* @copyright 2023, Edouard DUPIN, all right reserved
|
||||
* @license MPL-2 (see license file)
|
||||
*/
|
||||
|
||||
import { Component} from '@angular/core';
|
||||
|
||||
@Component({
|
||||
selector: 'spiner',
|
||||
template: '<img height="50px" src="assets/images/load.svg"/>',
|
||||
})
|
||||
export class SpinerComponent {
|
||||
}
|
@ -1,66 +0,0 @@
|
||||
<div class="top">
|
||||
<div id="main-menu" class="main-menu color-menu-background">
|
||||
<div *ngFor="let data of menu">
|
||||
<div
|
||||
class="inert_element unselectable"
|
||||
*ngIf="isNotButton(data)"
|
||||
[ngStyle]="{'float': data.position}"
|
||||
[ngClass]="getClassModel(data.model)">
|
||||
<div class="xdesktop" *ngIf="data.icon"><i class="material-icons">{{data.icon}}</i> {{data.title}}</div>
|
||||
<div class="xmobile" *ngIf="data.icon">
|
||||
<i class="material-icons">{{data.icon}}</i>
|
||||
</div>
|
||||
<div class="xdesktop" *ngIf="!data.icon">{{data.title}}</div>
|
||||
</div>
|
||||
<button
|
||||
class="item unselectable"
|
||||
*ngIf="!isNotButton(data)"
|
||||
(click)="onGeneric(data, $event)"
|
||||
(auxclick)="onGeneric(data, $event)"
|
||||
[ngStyle]="{'float': data.position}"
|
||||
[ngClass]="getClassModel(data.model)"
|
||||
[disable]="false">
|
||||
<div class="avatar unselectable" *ngIf="data.image"><img class="avatar" src="{{data.image}}" /> {{data.title}}</div>
|
||||
<div class="xdesktop" *ngIf="data.icon && !data.image">
|
||||
<i class="material-icons">{{data.icon}}</i> {{data.title}}
|
||||
</div>
|
||||
<div class="xmobile" *ngIf="data.icon && !data.image">
|
||||
<i class="material-icons">{{data.icon}}</i>
|
||||
</div>
|
||||
<div class="xdesktop" *ngIf="!data.icon && !data.image">{{data.title}}</div>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="fill-all" *ngIf="subMenu" (click)="onOutUserProperty()">
|
||||
<div class="sub-menu color-menu-background unselectable" [ngClass]="getClassMenuPosition()">
|
||||
<div *ngFor="let data of subMenu">
|
||||
<div
|
||||
class="inert_element unselectable"
|
||||
*ngIf="isNotButton(data)"
|
||||
[ngStyle]="{'float': data.position}"
|
||||
[ngClass]="getClassModel(data.model)">
|
||||
<div class="xdesktop" *ngIf="data.icon" [ngStyle]="{'float': data.position}">
|
||||
<i class="material-icons">{{data.icon}}</i> {{data.title}}
|
||||
</div>
|
||||
<div class="xmobile" *ngIf="data.icon" [ngStyle]="{'float': data.position}">
|
||||
<i class="material-icons">{{data.icon}}</i>
|
||||
</div>
|
||||
<div *ngIf="!data.icon" [ngStyle]="{'float': data.position}">{{data.title}}</div>
|
||||
</div>
|
||||
<button
|
||||
class="item"
|
||||
*ngIf="isEnable(data) && !isNotButton(data)"
|
||||
(click)="onGeneric(data, $event)"
|
||||
(auxclick)="onGeneric(data, $event)"
|
||||
[ngStyle]="{'float': data.position}"
|
||||
[ngClass]="getClassModel(data.model)"
|
||||
[disable]="false">
|
||||
<div *ngIf="data.icon" [ngStyle]="{'float': data.position}">
|
||||
<i class="material-icons">{{data.icon}}</i> {{data.title}}
|
||||
</div>
|
||||
<div *ngIf="!data.icon" [ngStyle]="{'float': data.position}">{{data.title}}</div>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
@ -1,182 +0,0 @@
|
||||
.element-pos-left {
|
||||
z-index: 5;
|
||||
float: left;
|
||||
}
|
||||
.element-pos-right {
|
||||
z-index: 5;
|
||||
float: right;
|
||||
}
|
||||
.element-pos-center {
|
||||
z-index: 5;
|
||||
float: none;
|
||||
}
|
||||
|
||||
.model_happy {
|
||||
color: yellow;
|
||||
}
|
||||
.model_disable {
|
||||
color: rgb(100, 100, 100);
|
||||
}
|
||||
.model_error {
|
||||
color: darkred;
|
||||
}
|
||||
.top {
|
||||
.sub-menu {
|
||||
position: fixed;
|
||||
|
||||
min-width: 150px;
|
||||
min-height: 70px;
|
||||
|
||||
display: block;
|
||||
overflow: visible;
|
||||
|
||||
box-shadow: none;
|
||||
flex-direction: column;
|
||||
flex-wrap: nowrap;
|
||||
justify-content: flex-start;
|
||||
box-sizing: border-box;
|
||||
flex-shrink: 0;
|
||||
margin: 0;
|
||||
padding: 0 3px 0 3px;
|
||||
border: none;
|
||||
z-index: 300;
|
||||
box-shadow: 0px 2px 4px 0 rgba(0, 0, 0, 0.6);
|
||||
|
||||
.item {
|
||||
display: block;
|
||||
float: top;
|
||||
line-height: 56px;
|
||||
z-index: 4;
|
||||
margin: 3px 0px 3px 0px;
|
||||
/*padding: 0px 3px 0px 3px;*/
|
||||
border: 0px; /*0px 3px 0px 3px solid transparent;*/
|
||||
/*text-transform: uppercase;*/
|
||||
font-weight: bold;
|
||||
font-size: 17px;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.material-icons {
|
||||
vertical-align: middle;
|
||||
}
|
||||
/* Create an Arraw on the top ob the box ... */
|
||||
&:after,
|
||||
&:before {
|
||||
bottom: 100%;
|
||||
right: 13px;
|
||||
border: solid transparent;
|
||||
content: ' ';
|
||||
height: 0;
|
||||
width: 0;
|
||||
position: absolute;
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
&:after {
|
||||
border-color: rgba(136, 183, 213, 0);
|
||||
border-bottom-color: #263238;
|
||||
border-width: 15px;
|
||||
margin-left: -15px;
|
||||
}
|
||||
}
|
||||
.menu-left {
|
||||
top: 75px;
|
||||
left: 15px;
|
||||
}
|
||||
.menu-right {
|
||||
top: 75px;
|
||||
right: 15px;
|
||||
}
|
||||
|
||||
.fill-all {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
/*
|
||||
background-color: #0F0;
|
||||
*/
|
||||
z-index: 400;
|
||||
}
|
||||
|
||||
.main-menu {
|
||||
position: fixed;
|
||||
top: 0px;
|
||||
left: 0px;
|
||||
|
||||
display: block;
|
||||
overflow: visible;
|
||||
|
||||
box-shadow: none;
|
||||
min-height: 56px;
|
||||
flex-direction: column;
|
||||
flex-wrap: nowrap;
|
||||
justify-content: flex-start;
|
||||
box-sizing: border-box;
|
||||
flex-shrink: 0;
|
||||
width: 100%;
|
||||
margin: 0;
|
||||
padding: 0 12px 0 12px;
|
||||
border: none;
|
||||
max-height: 1000px;
|
||||
z-index: 3;
|
||||
box-shadow: 0px 2px 4px 0 rgba(0, 0, 0, 0.6);
|
||||
|
||||
.item {
|
||||
display: block;
|
||||
float: left;
|
||||
line-height: 56px;
|
||||
z-index: 4;
|
||||
margin: 0 3px 0 3px;
|
||||
border: 0;
|
||||
text-transform: uppercase;
|
||||
font-weight: bold;
|
||||
font-size: 17px;
|
||||
.comment {
|
||||
visibility: 'hidden';
|
||||
}
|
||||
@media all and (min-width: 700px) {
|
||||
.comment {
|
||||
visibility: 'visible';
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.inert_element {
|
||||
display: block;
|
||||
float: left;
|
||||
line-height: 56px;
|
||||
z-index: 4;
|
||||
margin: 0 3px 0 3px;
|
||||
border: 0;
|
||||
//text-transform: uppercase;
|
||||
font-weight: bold;
|
||||
font-size: 17px;
|
||||
}
|
||||
|
||||
.ariane {
|
||||
display: block;
|
||||
float: left;
|
||||
line-height: 56px;
|
||||
z-index: 4;
|
||||
padding: 0 0 0 15px;
|
||||
margin: 0 3px 0 3px;
|
||||
border: 0;
|
||||
text-transform: uppercase;
|
||||
font-weight: bold;
|
||||
font-size: 15px;
|
||||
}
|
||||
|
||||
.material-icons {
|
||||
vertical-align: middle;
|
||||
}
|
||||
|
||||
.avatar {
|
||||
height: 42px;
|
||||
width: 42px;
|
||||
border-radius: 50%;
|
||||
vertical-align: middle;
|
||||
}
|
||||
}
|
||||
}
|
@ -1,104 +0,0 @@
|
||||
/** @file
|
||||
* @author Edouard DUPIN
|
||||
* @copyright 2018, Edouard DUPIN, all right reserved
|
||||
* @license PROPRIETARY (see license file)
|
||||
*/
|
||||
import { Component, OnInit, Input, EventEmitter, Output } from '@angular/core';
|
||||
|
||||
import { Router } from '@angular/router';
|
||||
import { isNullOrUndefined } from 'common/utils';
|
||||
import { MenuItem } from 'common/model/menu-item';
|
||||
|
||||
export interface EventOnMenu {
|
||||
menu: MenuItem;
|
||||
newWindows: boolean;
|
||||
ctrl: boolean;
|
||||
}
|
||||
|
||||
@Component({
|
||||
selector: 'app-top-menu',
|
||||
templateUrl: './top-menu.html',
|
||||
styleUrls: ['./top-menu.less'],
|
||||
})
|
||||
export class TopMenuComponent implements OnInit {
|
||||
@Input() menu: MenuItem[];
|
||||
subMenu: MenuItem[] = undefined;
|
||||
subMenuPosition: String = undefined;
|
||||
@Output() callback: EventEmitter<EventOnMenu> = new EventEmitter();
|
||||
|
||||
constructor(private router: Router) {}
|
||||
|
||||
isNotButton(data: MenuItem) {
|
||||
return (
|
||||
isNullOrUndefined(data.navigateTo) &&
|
||||
(isNullOrUndefined(data.callback) || data.callback === false) &&
|
||||
isNullOrUndefined(data.subMenu)
|
||||
);
|
||||
}
|
||||
isEnable(data: MenuItem) {
|
||||
if (!isNullOrUndefined(data) && !isNullOrUndefined(data.enable) && data.enable === false) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
getPosition(data: string): string {
|
||||
return `float: ${data}`;
|
||||
}
|
||||
|
||||
ngOnInit() {}
|
||||
onOutUserProperty(): void {
|
||||
//console.log('onOutUserProperty ==> event...');
|
||||
this.subMenu = undefined;
|
||||
}
|
||||
getClassMenuPosition(): string {
|
||||
if (isNullOrUndefined(this.subMenuPosition)) {
|
||||
return 'menu-left';
|
||||
}
|
||||
return 'menu-' + this.subMenuPosition;
|
||||
}
|
||||
getClassModel(data?: string): string {
|
||||
if (isNullOrUndefined(data)) {
|
||||
return '';
|
||||
}
|
||||
return 'model_' + data;
|
||||
}
|
||||
|
||||
onGeneric(data: MenuItem, event: any): void {
|
||||
//console.log(`onGeneric()`);
|
||||
// check if we need to navigate
|
||||
if (!isNullOrUndefined(data.navigateTo)) {
|
||||
// remove in every case the subMenu:
|
||||
this.subMenu = undefined;
|
||||
this.subMenuPosition = undefined;
|
||||
this.router.navigate([data.navigateTo]);
|
||||
return;
|
||||
}
|
||||
if (!isNullOrUndefined(data.callback) && data.callback === true) {
|
||||
//console.log(`Emit message on ${JSON.stringify(data)}`);
|
||||
this.callback.emit({
|
||||
menu: data,
|
||||
newWindows: event.which === 2,
|
||||
ctrl: event.ctrlKey,
|
||||
});
|
||||
return;
|
||||
}
|
||||
// check if we need to display a submenu
|
||||
if (isNullOrUndefined(data.subMenu)) {
|
||||
//just a toggle mode:
|
||||
data.subMenu = undefined;
|
||||
this.subMenuPosition = undefined;
|
||||
return;
|
||||
}
|
||||
if (this.subMenu === data.subMenu) {
|
||||
//just a toggle mode:
|
||||
this.subMenu = undefined;
|
||||
this.subMenuPosition = undefined;
|
||||
return;
|
||||
}
|
||||
//console.log(`Set Menu: ${JSON.stringify(data.subMenu)}`);
|
||||
// set the requested menu
|
||||
this.subMenu = data.subMenu;
|
||||
this.subMenuPosition = data.position;
|
||||
}
|
||||
}
|
@ -1,9 +0,0 @@
|
||||
<div>
|
||||
<div class="uploadfilecontainer" (click)="fileInput.click()" appDragDrop (onFileDropped)="uploadFile($event)">
|
||||
<input hidden type="file" #fileInput (change)="uploadFile($event.target.files)" />
|
||||
</div>
|
||||
<div class="files-list" *ngFor="let file of files;let i=index">
|
||||
<p>{{ file }}</p>
|
||||
<button class="delete-file" (click)="deleteAttachment(i)">// DELETE //</button>
|
||||
</div>
|
||||
</div>
|
@ -1,39 +0,0 @@
|
||||
.uploadfilecontainer {
|
||||
//background-image: url("../../../assets/cloud-2044823_960_720.png");
|
||||
background-repeat: no-repeat;
|
||||
background-size: 100px;
|
||||
background-position: center;
|
||||
height: 200px;
|
||||
width: 80%;
|
||||
margin: 20px auto;
|
||||
border: 2px dashed #1c8adb;
|
||||
border-radius: 10px;
|
||||
}
|
||||
|
||||
.uploadfilecontainer:hover {
|
||||
cursor: pointer;
|
||||
background-color: #9ecbec !important;
|
||||
opacity: 0.8;
|
||||
}
|
||||
|
||||
.files-list {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
width: 80%;
|
||||
margin: 10px auto;
|
||||
background: #ffffff;
|
||||
border: 1px dashed;
|
||||
border-radius: 12px;
|
||||
padding: 5px;
|
||||
color: #1c8adb;
|
||||
}
|
||||
|
||||
.files-list .delete-file {
|
||||
background: transparent;
|
||||
border: none;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.files-list .delete-file img {
|
||||
width: 30px;
|
||||
}
|
@ -1,25 +0,0 @@
|
||||
/** @file
|
||||
* @author Edouard DUPIN
|
||||
* @copyright 2018, Edouard DUPIN, all right reserved
|
||||
* @license PROPRIETARY (see license file)
|
||||
*/
|
||||
|
||||
import { Component } from '@angular/core';
|
||||
|
||||
@Component({
|
||||
selector: 'app-upload-file',
|
||||
templateUrl: './upload-file.html',
|
||||
styleUrls: ['./upload-file.less'],
|
||||
})
|
||||
export class UploadFileComponent {
|
||||
files: any = [];
|
||||
uploadFile(event) {
|
||||
for (let index = 0; index < event.length; index++) {
|
||||
const element = event[index];
|
||||
this.files.push(element.name);
|
||||
}
|
||||
}
|
||||
deleteAttachment(index) {
|
||||
this.files.splice(index, 1);
|
||||
}
|
||||
}
|
@ -1,4 +0,0 @@
|
||||
import { isMenuItem, isMenuPosition, MenuItem, MenuPosition } from './menu-item';
|
||||
import { NodeData, isNodeData } from './node';
|
||||
|
||||
export { NodeData, isNodeData, MenuPosition, isMenuPosition, MenuItem, isMenuItem };
|
@ -1,67 +0,0 @@
|
||||
import { isObject, isOptionalOf, isString, isNullOrUndefined, isOptionalArrayOf, isInArray } from 'common/utils';
|
||||
|
||||
export enum MenuPosition {
|
||||
LEFT = 'left',
|
||||
RIGHT = 'right',
|
||||
CENTER = 'none',
|
||||
}
|
||||
|
||||
export function isMenuPosition(data: any): data is MenuPosition {
|
||||
return isInArray(data, ['left', 'right', 'none']);
|
||||
}
|
||||
|
||||
export interface MenuItem {
|
||||
// Position of the menue element
|
||||
position: MenuPosition;
|
||||
// Hover help
|
||||
hover?: string;
|
||||
// Icon of the menue (need to be a meterial-icon name
|
||||
icon?: string;
|
||||
// Displayed Title
|
||||
image?: string;
|
||||
// Displayed Title
|
||||
title: string;
|
||||
// Model of the display:
|
||||
model?: string;
|
||||
// Jump Link (If undefined: it is considered as text and not a button)
|
||||
navigateTo?: string;
|
||||
// Menu model For a subList of elements
|
||||
callback?: boolean;
|
||||
// Other data that want to be set by the user
|
||||
otherData?: any;
|
||||
// Menu model For a subList of elements
|
||||
enable?: boolean;
|
||||
// Menu model For a subList of elements
|
||||
subMenu?: MenuItem[];
|
||||
}
|
||||
|
||||
export function isMenuItem(data: any): data is MenuItem {
|
||||
if (isNullOrUndefined(data)) {
|
||||
return false;
|
||||
}
|
||||
if (!isObject(data)) {
|
||||
return false;
|
||||
}
|
||||
if (!isMenuPosition(data.position)) {
|
||||
return false;
|
||||
}
|
||||
if (!isOptionalOf(data.hover, isString)) {
|
||||
return false;
|
||||
}
|
||||
if (!isOptionalOf(data.icon, isString)) {
|
||||
return false;
|
||||
}
|
||||
if (!isOptionalOf(data.image, isString)) {
|
||||
return false;
|
||||
}
|
||||
if (!isString(data.title)) {
|
||||
return false;
|
||||
}
|
||||
if (!isOptionalOf(data.navigateTo, isString)) {
|
||||
return false;
|
||||
}
|
||||
if (!isOptionalArrayOf(data.subMenu, isMenuItem)) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
@ -1,31 +0,0 @@
|
||||
import { isArrayOf, isNumberFinite, isObject, isOptionalOf, isOptionalArrayOf, isString } from 'common/utils';
|
||||
|
||||
export interface NodeData {
|
||||
id: number;
|
||||
name: string;
|
||||
description?: string;
|
||||
parentId?: number;
|
||||
covers?: number[];
|
||||
}
|
||||
|
||||
export function isNodeData(data: any): data is NodeData {
|
||||
if (!isObject(data)) {
|
||||
return false;
|
||||
}
|
||||
if (!isNumberFinite(data.id)) {
|
||||
return false;
|
||||
}
|
||||
if (!isString(data.name)) {
|
||||
return false;
|
||||
}
|
||||
if (!isOptionalOf(data.description, isString)) {
|
||||
return false;
|
||||
}
|
||||
if (!isOptionalOf(data.parentId, isNumberFinite)) {
|
||||
return false;
|
||||
}
|
||||
if (!isOptionalArrayOf(data.cover, isNumberFinite)) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
@ -1,17 +0,0 @@
|
||||
<div>
|
||||
<app-popin
|
||||
id="popin-delete-confirm"
|
||||
popSize="small"
|
||||
popTitle="Confirm Remove"
|
||||
[closeTitle]="closeButtonTitle"
|
||||
[validateTitle]="validateButtonTitle"
|
||||
closeTopRight="true"
|
||||
(callback)="eventPopUp($event[0])">
|
||||
<div class="expand" *ngIf="imageUrl != null">
|
||||
<img src="{{imageUrl}}" class="cover" />
|
||||
</div>
|
||||
<p class="expand">
|
||||
<label class="unselectable"><b>{{comment}}</b></label>
|
||||
</p>
|
||||
</app-popin>
|
||||
</div>
|
@ -1,13 +0,0 @@
|
||||
.expand {
|
||||
width: 100%;
|
||||
input {
|
||||
width: 100%;
|
||||
}
|
||||
div {
|
||||
width: 100%;
|
||||
}
|
||||
textarea {
|
||||
width: 100%;
|
||||
}
|
||||
text-align: center;
|
||||
}
|
@ -1,37 +0,0 @@
|
||||
/** @file
|
||||
* @author Edouard DUPIN
|
||||
* @copyright 2018, Edouard DUPIN, all right reserved
|
||||
* @license PROPRIETARY (see license file)
|
||||
*/
|
||||
|
||||
import { Component, OnInit, Input, Output, EventEmitter } from '@angular/core';
|
||||
|
||||
import { PopInService } from 'common/service';
|
||||
|
||||
@Component({
|
||||
selector: 'delete-confirm',
|
||||
templateUrl: './delete-confirm.html',
|
||||
styleUrls: ['./delete-confirm.less'],
|
||||
})
|
||||
export class PopInDeleteConfirm implements OnInit {
|
||||
@Input() comment: string = null;
|
||||
@Input() imageUrl: string = null;
|
||||
@Output() callback: EventEmitter<any> = new EventEmitter();
|
||||
|
||||
public closeButtonTitle: string = 'Cancel';
|
||||
public validateButtonTitle: string = 'Validate';
|
||||
|
||||
constructor(private popInService: PopInService) {}
|
||||
|
||||
OnDestroy() {}
|
||||
|
||||
ngOnInit() {}
|
||||
|
||||
eventPopUp(_event: string): void {
|
||||
console.log(`GET event: ${_event}`);
|
||||
this.popInService.close('popin-delete-confirm');
|
||||
if (_event === 'validate') {
|
||||
this.callback.emit(null);
|
||||
}
|
||||
}
|
||||
}
|
@ -1,4 +0,0 @@
|
||||
import { PopInDeleteConfirm } from './delete-confirm/delete-confirm';
|
||||
import { PopInUploadProgress } from './upload-progress/upload-progress';
|
||||
|
||||
export { PopInDeleteConfirm, PopInUploadProgress };
|
@ -1,34 +0,0 @@
|
||||
<div>
|
||||
<app-popin
|
||||
id="popin-upload-progress"
|
||||
popSize="medium"
|
||||
popTitle="Upload Media File"
|
||||
[closeTitle]="closeButtonTitle"
|
||||
[otherTitle]="otherButtonTitle"
|
||||
[validateTitle]="validateButtonTitle"
|
||||
(callback)="eventPopUp($event[0])">
|
||||
<p class="expand">
|
||||
<label class="unselectable"><b>{{mediaTitle}}</b></label>
|
||||
</p>
|
||||
<div *ngIf="progress != 100" class="progress-back">
|
||||
<div class="progress-bar" style="width:{{progress}}%"> {{progress}}%</div>
|
||||
</div>
|
||||
<div *ngIf="progress != 100">
|
||||
<label class="unselectable">Upload:</label><label style="text-align: right">{{uploadDisplay}}</label><br />
|
||||
<label class="unselectable">Size:</label><label style="text-align: right">{{sizeDisplay}}</label>
|
||||
</div>
|
||||
<div *ngIf="progress == 100 && error == null && result == null">
|
||||
<label class="unselectable">Upload done ... waiting server answer</label>
|
||||
</div>
|
||||
<div *ngIf="error != null">
|
||||
<label class="unselectable"><b>Get an error From the server:</b></label
|
||||
><br />
|
||||
<label class="unselectable">{{error}}</label>
|
||||
</div>
|
||||
<div *ngIf="result != null">
|
||||
<label class="unselectable"><b>Upload finished:</b></label
|
||||
><br />
|
||||
<label class="unselectable">{{result}}</label>
|
||||
</div>
|
||||
</app-popin>
|
||||
</div>
|
@ -1,21 +0,0 @@
|
||||
.expand {
|
||||
width: 100%;
|
||||
input {
|
||||
width: 100%;
|
||||
}
|
||||
textarea {
|
||||
width: 100%;
|
||||
}
|
||||
}
|
||||
|
||||
.progress-back {
|
||||
color: #000 !important;
|
||||
background-color: #f1f1f1 !important;
|
||||
border-radius: 3px;
|
||||
}
|
||||
|
||||
.progress-bar {
|
||||
color: #000000 !important;
|
||||
background-color: #4caf50 !important;
|
||||
border-radius: 3px;
|
||||
}
|
@ -1,113 +0,0 @@
|
||||
/** @file
|
||||
* @author Edouard DUPIN
|
||||
* @copyright 2018, Edouard DUPIN, all right reserved
|
||||
* @license PROPRIETARY (see license file)
|
||||
*/
|
||||
|
||||
import { Component, OnInit, Input, SimpleChanges } from '@angular/core';
|
||||
import { Router } from '@angular/router';
|
||||
|
||||
import { PopInService } from 'common/service';
|
||||
|
||||
@Component({
|
||||
selector: 'upload-progress',
|
||||
templateUrl: './upload-progress.html',
|
||||
styleUrls: ['./upload-progress.less'],
|
||||
})
|
||||
export class PopInUploadProgress implements OnInit {
|
||||
@Input() mediaTitle: string = '';
|
||||
@Input() mediaUploaded: number = 0;
|
||||
@Input() mediaSize: number = 999999999999;
|
||||
@Input() result: string = null;
|
||||
@Input() error: string = null;
|
||||
public closeButtonTitle: string = 'Abort';
|
||||
public otherButtonTitle: string = null;
|
||||
public validateButtonTitle: string = null;
|
||||
public uploadDisplay: string = '';
|
||||
public sizeDisplay: string = '';
|
||||
public progress: number = 0;
|
||||
constructor(private router: Router, private popInService: PopInService) {}
|
||||
OnDestroy() {}
|
||||
ngOnInit() {}
|
||||
eventPopUp(_event: string): void {
|
||||
console.log(`GET event: ${_event}`);
|
||||
this.popInService.close('popin-upload-progress');
|
||||
}
|
||||
updateNeedSend(): void {}
|
||||
|
||||
limit3(count: number): string {
|
||||
if (count >= 1000) {
|
||||
return `${count}`;
|
||||
}
|
||||
if (count >= 100) {
|
||||
return ` ${count}`;
|
||||
}
|
||||
if (count >= 10) {
|
||||
return ` ${count}`;
|
||||
}
|
||||
return ` ${count}`;
|
||||
}
|
||||
convertInHuman(countIn: number): string {
|
||||
let count = countIn;
|
||||
let tera = Math.trunc(count / (1024 * 1024 * 1024 * 1024));
|
||||
count = count - tera * 1024 * 1024 * 1024 * 1024;
|
||||
let giga = Math.trunc(count / (1024 * 1024 * 1024));
|
||||
count = count - giga * 1024 * 1024 * 1024;
|
||||
let mega = Math.trunc(count / (1024 * 1024));
|
||||
count = count - mega * 1024 * 1024;
|
||||
let kilo = Math.trunc(count / 1024);
|
||||
count = count - kilo * 1024;
|
||||
let out = '';
|
||||
if (out.length !== 0 || tera !== 0) {
|
||||
out = `${out} ${this.limit3(tera)}T`;
|
||||
}
|
||||
if (out.length !== 0 || giga !== 0) {
|
||||
out = `${out} ${this.limit3(giga)}G`;
|
||||
}
|
||||
if (out.length !== 0 || mega !== 0) {
|
||||
out = `${out} ${this.limit3(mega)}M`;
|
||||
}
|
||||
if (out.length !== 0 || kilo !== 0) {
|
||||
out = `${out} ${this.limit3(kilo)}k`;
|
||||
}
|
||||
if (out.length !== 0 || count !== 0) {
|
||||
out = `${out} ${this.limit3(count)}B`;
|
||||
}
|
||||
return out;
|
||||
}
|
||||
|
||||
ngOnChanges(changes: SimpleChanges) {
|
||||
//console.log(`Upload progress event : ${JSON.stringify(changes)}`);
|
||||
this.progress = Math.trunc((this.mediaUploaded * 100) / this.mediaSize);
|
||||
this.uploadDisplay = this.convertInHuman(this.mediaUploaded);
|
||||
this.sizeDisplay = this.convertInHuman(this.mediaSize);
|
||||
if (this.error === null && this.result === null) {
|
||||
this.closeButtonTitle = 'Abort';
|
||||
this.otherButtonTitle = null;
|
||||
this.validateButtonTitle = null;
|
||||
} else if (this.result === null) {
|
||||
this.closeButtonTitle = null;
|
||||
this.otherButtonTitle = 'Close';
|
||||
this.validateButtonTitle = null;
|
||||
} else {
|
||||
this.closeButtonTitle = null;
|
||||
this.otherButtonTitle = null;
|
||||
this.validateButtonTitle = 'Ok';
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export class UploadProgress {
|
||||
labelMediaTitle: string = '';
|
||||
mediaSendSize: number = 0;
|
||||
mediaSize: number = 99999999999999;
|
||||
result: string = null;
|
||||
error: string = null;
|
||||
clear() {
|
||||
this.labelMediaTitle = '';
|
||||
this.mediaSendSize = 0;
|
||||
this.mediaSize = 99999999999999;
|
||||
this.result = null;
|
||||
this.error = null;
|
||||
}
|
||||
}
|
@ -1,8 +0,0 @@
|
||||
<div class="full-mode">
|
||||
<div class="centered">
|
||||
<div class="error">
|
||||
<label class="unselectable"><i class="material-icons">report</i> 404 Not Found !</label>
|
||||
</div>
|
||||
<div class="comment"><label class="unselectable">Unknwn this page.</label></div>
|
||||
</div>
|
||||
</div>
|
@ -1,49 +0,0 @@
|
||||
.full-mode {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
top: 0;
|
||||
left: 0;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
border: 0;
|
||||
float: left;
|
||||
display: block;
|
||||
}
|
||||
|
||||
.centered {
|
||||
position: relative;
|
||||
max-width: 75%;
|
||||
padding: 16px 32px 16px 32px;
|
||||
|
||||
top: 50%;
|
||||
transform: ~'translate(0, -50%)';
|
||||
font-size: 30px;
|
||||
|
||||
font-weight: 600;
|
||||
text-align: center;
|
||||
line-height: 200%;
|
||||
}
|
||||
|
||||
.error {
|
||||
font-size: 55px;
|
||||
background-size: 45px;
|
||||
/*background-attachment: fixed;*/
|
||||
background-position: 0% 50%;
|
||||
padding: 0 0 0 58px;
|
||||
margin: 17px 0 17px 0;
|
||||
text-shadow: 0px 0px 4px #000000;
|
||||
color: rgb(160, 44, 44);
|
||||
i {
|
||||
font-size: 55px;
|
||||
}
|
||||
}
|
||||
|
||||
.comment {
|
||||
background-size: 45px;
|
||||
/*background-attachment: fixed;*/
|
||||
background-position: 0% 50%;
|
||||
padding: 0 0 0 58px;
|
||||
margin: 17px 0 17px 0;
|
||||
text-shadow: 0px 0px 4px #07213a;
|
||||
color: white;
|
||||
}
|
@ -1,16 +0,0 @@
|
||||
/** @file
|
||||
* @author Edouard DUPIN
|
||||
* @copyright 2018, Edouard DUPIN, all right reserved
|
||||
* @license PROPRIETARY (see license file)
|
||||
*/
|
||||
|
||||
import { Component } from '@angular/core';
|
||||
|
||||
@Component({
|
||||
selector: 'app-404-not-found',
|
||||
templateUrl: './404.html',
|
||||
styleUrls: ['./404.less'],
|
||||
})
|
||||
export class NotFound404Scene {
|
||||
constructor() {}
|
||||
}
|
@ -1 +0,0 @@
|
||||
<p>error-viewer works!</p>
|
@ -1,19 +0,0 @@
|
||||
/** @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';
|
||||
|
||||
@Component({
|
||||
selector: 'app-error-viewer',
|
||||
templateUrl: './error-viewer.html',
|
||||
styleUrls: ['./error-viewer.less'],
|
||||
})
|
||||
export class ErrorViewerScene implements OnInit {
|
||||
constructor(private route: ActivatedRoute) {}
|
||||
|
||||
ngOnInit() {}
|
||||
}
|
@ -1,10 +0,0 @@
|
||||
<div class="full-mode">
|
||||
<div class="centered">
|
||||
<div class="error">
|
||||
<label class="unselectable"><i class="material-icons">gpp_bad</i> 403 Forbidden</label>
|
||||
</div>
|
||||
<div class="comment">
|
||||
<label class="unselectable">You don't have permission to access this resource.</label>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
@ -1,50 +0,0 @@
|
||||
.full-mode {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
top: 0;
|
||||
left: 0;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
border: 0;
|
||||
float: left;
|
||||
display: block;
|
||||
}
|
||||
|
||||
.centered {
|
||||
position: relative;
|
||||
max-width: 500px;
|
||||
padding: 16px 32px 16px 32px;
|
||||
|
||||
top: 50%;
|
||||
left: 50%;
|
||||
transform: ~'translate(-50%, -50%)';
|
||||
font-size: 30px;
|
||||
|
||||
font-weight: 600;
|
||||
text-align: left;
|
||||
line-height: 200%;
|
||||
}
|
||||
|
||||
.error {
|
||||
font-size: 55px;
|
||||
background-size: 45px;
|
||||
/*background-attachment: fixed;*/
|
||||
background-position: 0% 50%;
|
||||
padding: 0 0 0 58px;
|
||||
margin: 17px 0 17px 0;
|
||||
text-shadow: 0px 0px 4px #000000;
|
||||
color: rgb(160, 44, 44);
|
||||
i {
|
||||
font-size: 55px;
|
||||
}
|
||||
}
|
||||
|
||||
.comment {
|
||||
background-size: 45px;
|
||||
/*background-attachment: fixed;*/
|
||||
background-position: 0% 50%;
|
||||
padding: 0 0 0 58px;
|
||||
margin: 17px 0 17px 0;
|
||||
text-shadow: 0px 0px 4px #07213a;
|
||||
color: white;
|
||||
}
|
@ -1,16 +0,0 @@
|
||||
/** @file
|
||||
* @author Edouard DUPIN
|
||||
* @copyright 2018, Edouard DUPIN, all right reserved
|
||||
* @license PROPRIETARY (see license file)
|
||||
*/
|
||||
|
||||
import { Component } from '@angular/core';
|
||||
|
||||
@Component({
|
||||
selector: 'app-forbidden',
|
||||
templateUrl: './forbidden.html',
|
||||
styleUrls: ['./forbidden.less'],
|
||||
})
|
||||
export class ForbiddenScene {
|
||||
constructor() {}
|
||||
}
|
@ -1,8 +0,0 @@
|
||||
<div class="full-mode">
|
||||
<div class="centered">
|
||||
<div class="error">
|
||||
<label class="unselectable"><i class="material-icons">login</i> Not registered!</label>
|
||||
</div>
|
||||
<div class="comment"><label class="unselectable">you must login to access to this website.</label></div>
|
||||
</div>
|
||||
</div>
|
@ -1,49 +0,0 @@
|
||||
.full-mode {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
top: 0;
|
||||
left: 0;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
border: 0;
|
||||
float: left;
|
||||
display: block;
|
||||
}
|
||||
|
||||
.centered {
|
||||
position: relative;
|
||||
max-width: 75%;
|
||||
padding: 16px 32px 16px 32px;
|
||||
|
||||
top: 50%;
|
||||
transform: ~'translate(0, -50%)';
|
||||
font-size: 30px;
|
||||
|
||||
font-weight: 600;
|
||||
text-align: center;
|
||||
line-height: 200%;
|
||||
}
|
||||
|
||||
.error {
|
||||
font-size: 55px;
|
||||
background-size: 45px;
|
||||
/*background-attachment: fixed;*/
|
||||
background-position: 0% 50%;
|
||||
padding: 0 0 0 58px;
|
||||
margin: 17px 0 17px 0;
|
||||
text-shadow: 0px 0px 4px #000000;
|
||||
color: rgb(160, 44, 44);
|
||||
i {
|
||||
font-size: 55px;
|
||||
}
|
||||
}
|
||||
|
||||
.comment {
|
||||
background-size: 45px;
|
||||
/*background-attachment: fixed;*/
|
||||
background-position: 0% 50%;
|
||||
padding: 0 0 0 58px;
|
||||
margin: 17px 0 17px 0;
|
||||
text-shadow: 0px 0px 4px #07213a;
|
||||
color: white;
|
||||
}
|
@ -1,16 +0,0 @@
|
||||
/** @file
|
||||
* @author Edouard DUPIN
|
||||
* @copyright 2018, Edouard DUPIN, all right reserved
|
||||
* @license PROPRIETARY (see license file)
|
||||
*/
|
||||
|
||||
import { Component } from '@angular/core';
|
||||
|
||||
@Component({
|
||||
selector: 'app-home-out',
|
||||
templateUrl: './home-out.html',
|
||||
styleUrls: ['./home-out.less'],
|
||||
})
|
||||
export class HomeOutScene {
|
||||
constructor() {}
|
||||
}
|
@ -1,8 +0,0 @@
|
||||
//import { ErrorViewerScene } from "./error-viewer/error-viewer";
|
||||
import { ErrorViewerScene } from './error-viewer/error-viewer';
|
||||
import { ForbiddenScene } from './forbidden/forbidden';
|
||||
import { SsoScene } from './sso/sso';
|
||||
import { HomeOutScene } from './home-out/home-out';
|
||||
import { NotFound404Scene } from './404/404';
|
||||
|
||||
export { ErrorViewerScene, SsoScene, ForbiddenScene, HomeOutScene, NotFound404Scene };
|
@ -1,32 +0,0 @@
|
||||
<div class="full">
|
||||
<div class="color-background-vignette container-global">
|
||||
<div class="containerCenter">
|
||||
<label for="login_field"><b>LOGIN (after SSO)</b></label>
|
||||
</div>
|
||||
<div class="imgContainer">
|
||||
<img src="assets/images/avatar_generic.svg" alt="Avatar" class="avatar" />
|
||||
</div>
|
||||
<div class="container" *ngIf="token === '__CANCEL__'">
|
||||
<label for="login_field"><b>ERROR: </b> Request cancel of connection !</label>
|
||||
</div>
|
||||
<div class="container" *ngIf="token === '__FAIL__'">
|
||||
<label for="login_field"><b>ERROR: </b> Connection FAIL !</label>
|
||||
</div>
|
||||
<div class="container" *ngIf="token === '__LOGOUT__'">
|
||||
<label for="login_field"><b>Dis-connected: </b> Redirect soon! </label>
|
||||
</div>
|
||||
<div class="container" *ngIf="token === 'ERROR_ME'">
|
||||
<label for="login_field"><b>ERROR: </b> can not retreive user local informations!</label>
|
||||
</div>
|
||||
<div
|
||||
class="container"
|
||||
*ngIf="token !== 'ERROR_ME' and token !== '__FAIL__' and token !== '__CANCEL__' and token === '__LOGOUT__'">
|
||||
<label for="login_field"><b>Connected: </b> Redirect soon!</label>
|
||||
</div>
|
||||
<div
|
||||
class="container"
|
||||
*ngIf="token !== 'ERROR_ME' and token !== '__FAIL__' and token !== '__CANCEL__' and token === '__LOGOUT__'">
|
||||
<label for="login_field"><b>Welcome back: </b> {{userName}}</label>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
@ -1,108 +0,0 @@
|
||||
.full {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
right: 0;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
border: 0;
|
||||
float: right;
|
||||
display: block;
|
||||
}
|
||||
|
||||
input[type='text'],
|
||||
input[type='password'] {
|
||||
width: 100%;
|
||||
padding: 12px 20px;
|
||||
margin: 8px 0;
|
||||
display: inline-block;
|
||||
border: 1px solid #ccc;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.login {
|
||||
margin: 2% 2%;
|
||||
width: 45%;
|
||||
}
|
||||
|
||||
.cancel {
|
||||
margin: 2% 2%;
|
||||
width: 45%;
|
||||
}
|
||||
.containerCenter {
|
||||
text-align: center;
|
||||
margin: 15px 0 0 0;
|
||||
}
|
||||
|
||||
.imgContainer {
|
||||
text-align: center;
|
||||
margin: 15px 0 0 0;
|
||||
}
|
||||
|
||||
img.avatar {
|
||||
width: 150px;
|
||||
border-radius: 50%;
|
||||
}
|
||||
|
||||
.container-global {
|
||||
padding: 16px 32px 16px 32px;
|
||||
}
|
||||
|
||||
.container {
|
||||
padding: 16px 0 0 0;
|
||||
}
|
||||
|
||||
span.psw {
|
||||
float: right;
|
||||
padding-top: 16px;
|
||||
}
|
||||
|
||||
.forgot {
|
||||
color: #00b;
|
||||
font-size: 14px;
|
||||
float: right;
|
||||
buttum: 0;
|
||||
line-height: 24px;
|
||||
}
|
||||
.error {
|
||||
background-color: #f44336;
|
||||
position: absolute;
|
||||
z-index: 10;
|
||||
display: block;
|
||||
max-width: 450px;
|
||||
padding: 5px 8px;
|
||||
margin: 2px 0 0;
|
||||
font-size: 16px;
|
||||
font-weight: 400;
|
||||
border-style: solid;
|
||||
border-width: 0px;
|
||||
box-sizing: border-box;
|
||||
|
||||
&:after,
|
||||
&:before {
|
||||
bottom: 100%;
|
||||
left: 25px;
|
||||
border: solid transparent;
|
||||
content: ' ';
|
||||
height: 0;
|
||||
width: 0;
|
||||
position: absolute;
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
&:after {
|
||||
border-bottom-color: #f44336;
|
||||
border-width: 10px;
|
||||
margin-left: -10px;
|
||||
}
|
||||
}
|
||||
|
||||
.container-global {
|
||||
position: relative;
|
||||
max-width: 400px;
|
||||
padding: 16px 32px 16px 32px;
|
||||
|
||||
top: 50%;
|
||||
left: 50%;
|
||||
transform: ~'translate(-50%, -50%)';
|
||||
box-shadow: 0px 8px 20px 0 rgba(0, 0, 0, 0.9);
|
||||
}
|
@ -1,85 +0,0 @@
|
||||
/** @file
|
||||
* @author Edouard DUPIN
|
||||
* @copyright 2018, Edouard DUPIN, all right reserved
|
||||
* @license PROPRIETARY (see license file)
|
||||
*/
|
||||
|
||||
import { Component, OnInit } from '@angular/core';
|
||||
import { ActivatedRoute, Router } from '@angular/router';
|
||||
import { SSOService, UserService } from 'common/service';
|
||||
|
||||
@Component({
|
||||
selector: 'app-sso',
|
||||
templateUrl: './sso.html',
|
||||
styleUrls: ['./sso.less'],
|
||||
})
|
||||
export class SsoScene implements OnInit {
|
||||
ssoData: string;
|
||||
token: string;
|
||||
keepConnected: boolean;
|
||||
userName: string;
|
||||
|
||||
constructor(
|
||||
private router: Router,
|
||||
private route: ActivatedRoute,
|
||||
private ssoService: SSOService,
|
||||
private userService: UserService
|
||||
) {
|
||||
console.error('retreive data after SSO');
|
||||
}
|
||||
|
||||
ngOnInit() {
|
||||
let self = this;
|
||||
console.log(`call after SSO back: ${window.location.href}`);
|
||||
const ssoData = this.route.snapshot.paramMap.get('data');
|
||||
if (ssoData == null) {
|
||||
this.ssoData = undefined;
|
||||
} else {
|
||||
this.ssoData = ssoData;
|
||||
}
|
||||
const token = this.route.snapshot.paramMap.get('token');
|
||||
if (token == null) {
|
||||
this.token = undefined;
|
||||
} else {
|
||||
this.token = token;
|
||||
}
|
||||
const keepConnected = this.route.snapshot.paramMap.get('keepConnected');
|
||||
if (keepConnected == null) {
|
||||
this.keepConnected = undefined;
|
||||
} else {
|
||||
this.keepConnected = keepConnected === 'true';
|
||||
}
|
||||
console.log(`ssoData: '${ssoData}'`);
|
||||
console.log(`token: '${token}'`);
|
||||
console.log(`keepConnected: '${keepConnected}'`);
|
||||
if (this.token !== '__CANCEL__' && this.token !== '__FAIL__' && this.token !== '__LOGOUT__') {
|
||||
const destination = this.ssoData;
|
||||
console.log(`ssoData (decoded): '${destination}'`);
|
||||
const realDst = this.ssoService.unHashLocalData(destination);
|
||||
console.log(`realDst: '${realDst}'`);
|
||||
this.userService
|
||||
.startSession(this.token, this.keepConnected)
|
||||
.then((userName: string) => {
|
||||
self.userName = userName;
|
||||
setTimeout(function () {
|
||||
self.router.navigate([realDst], { replaceUrl: true });
|
||||
}, 500); // 2 seconds
|
||||
})
|
||||
.catch(() => {
|
||||
this.token = 'ERROR_ME';
|
||||
});
|
||||
} else if (this.token === '__LOGOUT__') {
|
||||
this.userService.removeSession();
|
||||
const destination = this.ssoData;
|
||||
console.error(`ssoData (decoded): '${destination}'`);
|
||||
// sample : ZZ**DST:home
|
||||
const realDst = this.ssoService.unHashLocalData(destination);
|
||||
console.error(`realDst: '${realDst}'`);
|
||||
setTimeout(function () {
|
||||
self.router.navigate([realDst], { replaceUrl: true });
|
||||
}, 500); // 2 seconds
|
||||
} else {
|
||||
this.userService.removeSession();
|
||||
}
|
||||
}
|
||||
}
|
@ -1,165 +0,0 @@
|
||||
/** @file
|
||||
* @author Edouard DUPIN
|
||||
* @copyright 2018, Edouard DUPIN, all right reserved
|
||||
* @license PROPRIETARY (see license file)
|
||||
*/
|
||||
|
||||
import { Injectable } from '@angular/core';
|
||||
import { HttpWrapperService } from 'common/service/http-wrapper';
|
||||
import { isNullOrUndefined } from 'common/utils';
|
||||
import { DataInterface } from 'common/utils/dataInterface';
|
||||
|
||||
@Injectable()
|
||||
export class BddService {
|
||||
private bdd = {};
|
||||
private bddPomise = {};
|
||||
private baseLocalStorageName = 'bdd_';
|
||||
private useLocalStorage = false; // we exceed the limit of 5MB
|
||||
|
||||
constructor(private http: HttpWrapperService) {
|
||||
console.log('Start BddService');
|
||||
}
|
||||
|
||||
addAfterPost(name: string, ret: any) {
|
||||
let self = this;
|
||||
return new Promise((resolve, reject) => {
|
||||
self.get(name)
|
||||
.then((response: DataInterface) => {
|
||||
let responseTmp = response;
|
||||
ret.then(response2 => {
|
||||
responseTmp.add(response2);
|
||||
resolve(response2);
|
||||
}).catch(response2 => {
|
||||
reject(response2);
|
||||
});
|
||||
})
|
||||
.catch(response => {
|
||||
reject(response);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
setAfterPut(name: string, id: number, ret: any) {
|
||||
let self = this;
|
||||
return new Promise((resolve, reject) => {
|
||||
self.get(name)
|
||||
.then((response: DataInterface) => {
|
||||
let responseTmp = response;
|
||||
ret.then(response2 => {
|
||||
responseTmp.set(id, response2);
|
||||
resolve(response2);
|
||||
}).catch(response2 => {
|
||||
reject(response2);
|
||||
});
|
||||
})
|
||||
.catch(response => {
|
||||
reject(response);
|
||||
});
|
||||
});
|
||||
}
|
||||
asyncSetInDB(name: string, id: number, data: any) {
|
||||
let self = this;
|
||||
self.get(name)
|
||||
.then((response: DataInterface) => {
|
||||
response.set(id, data);
|
||||
})
|
||||
.catch(response => {
|
||||
// nothing to do ...
|
||||
});
|
||||
}
|
||||
|
||||
delete(name: string, id: number, ret: any) {
|
||||
let self = this;
|
||||
return new Promise((resolve, reject) => {
|
||||
self.get(name)
|
||||
.then((response: DataInterface) => {
|
||||
let responseTmp = response;
|
||||
ret.then(response2 => {
|
||||
responseTmp.delete(id);
|
||||
resolve(response2);
|
||||
}).catch(response2 => {
|
||||
reject(response2);
|
||||
});
|
||||
})
|
||||
.catch(response => {
|
||||
reject(response);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
get(name: string): Promise<DataInterface> {
|
||||
let self = this;
|
||||
//console.log(`Try to get DB '${ name }'`);
|
||||
if (!isNullOrUndefined(this.bdd[name])) {
|
||||
return new Promise((resolve, reject) => {
|
||||
resolve(self.bdd[name]);
|
||||
});
|
||||
}
|
||||
//console.log(`get DB: ?? ${ name } ??`);
|
||||
if (isNullOrUndefined(this.bddPomise[name])) {
|
||||
this.bddPomise[name] = [];
|
||||
// Try to load Local Data (storage)
|
||||
let retriveBDDString = null;
|
||||
if (this.useLocalStorage === true) {
|
||||
localStorage.getItem(this.baseLocalStorageName + name);
|
||||
}
|
||||
if (retriveBDDString !== null) {
|
||||
//console.log(`retrive local bdd string (${ name })= ${ retriveBDDString}`);
|
||||
let retriveBDD = JSON.parse(retriveBDDString);
|
||||
//console.log(`retrive local bdd (${ name })= ${ retriveBDD}`);
|
||||
let retriveBDDTmp = new DataInterface(name, retriveBDD);
|
||||
self.bdd[name] = retriveBDDTmp;
|
||||
for (let iii = 0; iii < self.bddPomise[name].length; iii++) {
|
||||
self.bddPomise[name][iii].resolve(self.bdd[name]);
|
||||
}
|
||||
// brut force update of the BDD : TODO optimise it later ...
|
||||
//console.log(`Update BDD (${ name })`);
|
||||
|
||||
self.http
|
||||
.getSpecific(name)
|
||||
.then(response => {
|
||||
//console.log(`end download DB: ==> ${ name } ${ response.length}`);
|
||||
self.bdd[name] = new DataInterface(name, response);
|
||||
localStorage.setItem(self.baseLocalStorageName + name, JSON.stringify(self.bdd[name].bdd));
|
||||
})
|
||||
.catch(response => {
|
||||
console.log(`[E] ${self.constructor.name}: cant not get data from remote server: ${name}`);
|
||||
});
|
||||
} else {
|
||||
//console.log(`Download BDD (${ name })`);
|
||||
return new Promise((resolve, reject) => {
|
||||
self.http
|
||||
.getSpecific(name)
|
||||
.then(response => {
|
||||
//console.log(`end download DB: ==> ${ name } ${ response.length}`);// + " " + JSON.stringify(response).length);
|
||||
self.bdd[name] = new DataInterface(name, response);
|
||||
if (self.useLocalStorage === true) {
|
||||
localStorage.setItem(
|
||||
self.baseLocalStorageName + name,
|
||||
JSON.stringify(self.bdd[name].bdd)
|
||||
);
|
||||
}
|
||||
for (let iii = 0; iii < self.bddPomise[name].length; iii++) {
|
||||
self.bddPomise[name][iii].resolve(self.bdd[name]);
|
||||
}
|
||||
resolve(self.bdd[name]);
|
||||
})
|
||||
.catch(response => {
|
||||
console.log(`[E] ${self.constructor.name}: can not get data from remote server: ${name}`);
|
||||
for (let iii = 0; iii < self.bddPomise[name].length; iii++) {
|
||||
self.bddPomise[name][iii].reject(response);
|
||||
}
|
||||
reject(response);
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
||||
return new Promise((resolve, reject) => {
|
||||
if (!isNullOrUndefined(self.bdd[name])) {
|
||||
resolve(self.bdd[name]);
|
||||
return;
|
||||
}
|
||||
self.bddPomise[name].push({ resolve: resolve, reject: reject });
|
||||
});
|
||||
}
|
||||
}
|
@ -1,42 +0,0 @@
|
||||
/** @file
|
||||
* @author Edouard DUPIN
|
||||
* @copyright 2018, Edouard DUPIN, all right reserved
|
||||
* @license PROPRIETARY (see license file)
|
||||
*/
|
||||
|
||||
import { Injectable } from '@angular/core';
|
||||
|
||||
@Injectable()
|
||||
export class CookiesService {
|
||||
constructor() {}
|
||||
|
||||
set(cname: string, cvalue: string, exdays: number): void {
|
||||
if (this.get(cname) !== '') {
|
||||
// reset previous cookies...
|
||||
document.cookie = `${cname}=;expires=Thu, 01 Jan 1970 00:00:00 GMT;path=/`;
|
||||
}
|
||||
let ddd = new Date();
|
||||
ddd.setTime(ddd.getTime() + exdays * 24 * 60 * 60 * 1000);
|
||||
let expires = `expires=${ddd.toUTCString()}`;
|
||||
document.cookie = `${cname}=${cvalue};${expires};path=/`;
|
||||
}
|
||||
|
||||
remove(cname: string): void {
|
||||
this.set(cname, '', 0);
|
||||
}
|
||||
|
||||
get(cname: string): string | undefined {
|
||||
let name = `${cname}=`;
|
||||
let coolies = document.cookie.split(';');
|
||||
for (let iii = 0; iii < coolies.length; iii++) {
|
||||
let ccc = coolies[iii];
|
||||
while (ccc.charAt(0) === ' ') {
|
||||
ccc = ccc.substring(1);
|
||||
}
|
||||
if (ccc.indexOf(name) === 0) {
|
||||
return ccc.substring(name.length, ccc.length);
|
||||
}
|
||||
}
|
||||
return '';
|
||||
}
|
||||
}
|
@ -1,491 +0,0 @@
|
||||
/** @file
|
||||
* @author Edouard DUPIN
|
||||
* @copyright 2018, Edouard DUPIN, all right reserved
|
||||
* @license PROPRIETARY (see license file)
|
||||
*/
|
||||
|
||||
import { Injectable } from '@angular/core';
|
||||
import { HttpClient, HttpHeaders, HttpEventType } from '@angular/common/http';
|
||||
|
||||
import { environment } from 'environments/environment';
|
||||
|
||||
import { SessionService } from './session';
|
||||
import { isArrayOfs, isBoolean, isNullOrUndefined, isNumber, isString } from 'common/utils';
|
||||
|
||||
export enum HTTPRequestModel {
|
||||
POST = 'POST',
|
||||
GET = 'GET',
|
||||
PUT = 'PUT',
|
||||
DELETE = 'DELETE',
|
||||
PATCH = 'PATCH',
|
||||
}
|
||||
export enum HTTPMimeType {
|
||||
ALL = '*/*',
|
||||
JSON = 'application/json',
|
||||
OCTET_STREAM = 'application/octet-stream',
|
||||
IMAGE = 'image/*',
|
||||
IMAGE_JPEG = 'image/jpeg',
|
||||
IMAGE_PNG = 'image/png',
|
||||
}
|
||||
|
||||
export type UrlPath = string | boolean | number | (string | boolean | number)[];
|
||||
export type ProgressCallback = (count: number, total: number) => void;
|
||||
|
||||
export interface HTTPRequest {
|
||||
server?: string;
|
||||
endPoint: UrlPath;
|
||||
requestType: HTTPRequestModel;
|
||||
accept: HTTPMimeType;
|
||||
contentType: HTTPMimeType;
|
||||
params?: object;
|
||||
body?: any;
|
||||
authorization?: string; // c'est un hook de merde ...
|
||||
disableTocken?: boolean;
|
||||
// progress interface to notify progression of the streaming.
|
||||
progress?: ProgressCallback;
|
||||
}
|
||||
|
||||
export interface ModelResponseHttp {
|
||||
status: number;
|
||||
data: any;
|
||||
}
|
||||
|
||||
/**
|
||||
* This service permit to add some data like tocken and authorisation.. ir automatically get the token if needed and retake it if expired...
|
||||
*/
|
||||
@Injectable()
|
||||
export class HttpWrapperService {
|
||||
private displayReturn: boolean = false;
|
||||
constructor(private http: HttpClient, private session: SessionService) { }
|
||||
|
||||
addTokenIfNeeded(headerOption: any): any {
|
||||
const token = this.session.getToken();
|
||||
if (!isNullOrUndefined(token)) {
|
||||
if (headerOption.Authorization === undefined) {
|
||||
headerOption.Authorization = `Yota ${token}`;
|
||||
}
|
||||
}
|
||||
return headerOption;
|
||||
}
|
||||
|
||||
request(properties: HTTPRequest): Promise<Response> {
|
||||
let connectionAddresses = this.createRESTCall2({
|
||||
server: properties.server,
|
||||
api: properties.endPoint,
|
||||
inputOptions: properties.params,
|
||||
});
|
||||
let headers: any = {
|
||||
Accept: properties.accept,
|
||||
//'Content-Type': properties.contentType,
|
||||
};
|
||||
if (properties.authorization !== undefined && properties.authorization !== null) {
|
||||
headers['Authorization'] = properties.authorization;
|
||||
}
|
||||
if (properties.requestType !== HTTPRequestModel.GET) {
|
||||
headers['Content-Type'] = properties.contentType;
|
||||
}
|
||||
if (
|
||||
properties.disableTocken === undefined ||
|
||||
properties.disableTocken === null ||
|
||||
properties.disableTocken === false
|
||||
) {
|
||||
headers = this.addTokenIfNeeded(headers);
|
||||
}
|
||||
//console.log(`header: ${JSON.stringify(headers)}`);
|
||||
let body = properties.body;
|
||||
if (properties.contentType === HTTPMimeType.JSON) {
|
||||
body = JSON.stringify(properties.body);
|
||||
}
|
||||
console.log(`Call ${connectionAddresses}`)
|
||||
const result = fetch(connectionAddresses, {
|
||||
method: properties.requestType,
|
||||
headers,
|
||||
body,
|
||||
});
|
||||
return result;
|
||||
}
|
||||
|
||||
requestJson(properties: HTTPRequest): Promise<ModelResponseHttp> {
|
||||
return new Promise((resolve, reject) => {
|
||||
this.request(properties)
|
||||
.then((response: Response) => {
|
||||
if (response.status >= 200 && response.status <= 299) {
|
||||
const contentType = response.headers.get('Content-Type');
|
||||
if (contentType === HTTPMimeType.JSON) {
|
||||
response
|
||||
.json()
|
||||
.then((value: any) => {
|
||||
//console.log(`RECEIVE ==> ${response.status}=${ JSON.stringify(value, null, 2)}`);
|
||||
resolve({ status: response.status, data: value });
|
||||
})
|
||||
.catch((reason: any) => {
|
||||
reject({ status: 999, data: reason });
|
||||
});
|
||||
} else {
|
||||
console.error(`content Type is not Json: ${contentType}`);
|
||||
reject({ status: 999, data: `content Type is not Json: ${contentType}` });
|
||||
}
|
||||
} else {
|
||||
console.error(`wring correct status: ${response.status}`);
|
||||
reject({ status: 900, data: response });
|
||||
}
|
||||
})
|
||||
.catch((error: any) => {
|
||||
reject({
|
||||
time: Date(),
|
||||
status: 999,
|
||||
error: error,
|
||||
statusMessage: "Fetch error",
|
||||
message: "http-wrapper.ts detect an error in the fetch request"
|
||||
});
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
requestImage(properties: HTTPRequest): Promise<ModelResponseHttp> {
|
||||
return new Promise((resolve, reject) => {
|
||||
this.request(properties)
|
||||
.then((response: Response) => {
|
||||
if (response.status >= 200 && response.status <= 299) {
|
||||
const contentType = response.headers.get('Content-Type');
|
||||
//console.log(`REICEIVE ==> ${response.status}`);
|
||||
resolve({ status: 900, data: response });
|
||||
/*
|
||||
resolve({ status:response.status, data:value });
|
||||
}).catch((reason:any)=> {
|
||||
reject({ status:999, data:reason });
|
||||
});
|
||||
} else {
|
||||
console.error(`content Type is not Json: ${contentType}`)
|
||||
reject({ status:999, data:`content Type is not Json: ${contentType}` });
|
||||
}
|
||||
*/
|
||||
} else {
|
||||
console.error(`wring correct status: ${response.status}`);
|
||||
resolve({ status: 900, data: response });
|
||||
}
|
||||
})
|
||||
.catch((error: any) => {
|
||||
reject({
|
||||
time: Date(),
|
||||
status: 999,
|
||||
error: error,
|
||||
statusMessage: "Fetch image error",
|
||||
message: "http-wrapper.ts detect an error in the fetch request"
|
||||
});
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
createRESTCall2({
|
||||
api,
|
||||
server,
|
||||
inputOptions,
|
||||
addURLToken,
|
||||
}: {
|
||||
server?: string;
|
||||
api: UrlPath;
|
||||
inputOptions?: object;
|
||||
addURLToken?: boolean;
|
||||
}) {
|
||||
if (isNullOrUndefined(server)) {
|
||||
server = environment.defaultServer;
|
||||
}
|
||||
const basePage = environment.server[server];
|
||||
let addressServerRest = basePage;
|
||||
if (!basePage.endsWith('/')) {
|
||||
addressServerRest = `${basePage}/`;
|
||||
}
|
||||
let options = inputOptions;
|
||||
if (isNullOrUndefined(options)) {
|
||||
options = {};
|
||||
}
|
||||
let out = addressServerRest;
|
||||
if (isArrayOfs(api, isString, isNumber, isBoolean)) {
|
||||
for (let iii = 0; iii < api.length; iii++) {
|
||||
let elem = api[iii];
|
||||
if (out.endsWith('/')) {
|
||||
out += elem;
|
||||
} else {
|
||||
out += `/${elem}`;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
out += api;
|
||||
}
|
||||
let first = true;
|
||||
let keys = Object.keys(options);
|
||||
for (let iii = 0; iii < keys.length; iii++) {
|
||||
if (first === false) {
|
||||
out = `${out}&`;
|
||||
} else {
|
||||
out = `${out}?`;
|
||||
first = false;
|
||||
}
|
||||
out = out + keys[iii];
|
||||
if (options[keys[iii]] != null) {
|
||||
out = out + '=' + options[keys[iii]];
|
||||
}
|
||||
}
|
||||
//console.log(`try to get session : ${this.session.getToken()}`);
|
||||
if (!isNullOrUndefined(this.session.getToken())) {
|
||||
if (addURLToken !== undefined && addURLToken === true) {
|
||||
if (first === false) {
|
||||
out = `${out}&`;
|
||||
} else {
|
||||
out = `${out}?`;
|
||||
}
|
||||
out = out + `Authorization=Yota ${this.session.getToken()}`;
|
||||
}
|
||||
}
|
||||
return out;
|
||||
}
|
||||
|
||||
// Deprecated ...
|
||||
createRESTCall(api: string, inputOptions?: any) {
|
||||
let basePage = environment.server[environment.defaultServer];
|
||||
let addressServerRest = `${basePage}/`;
|
||||
let options = inputOptions;
|
||||
if (options === undefined) {
|
||||
options = [];
|
||||
}
|
||||
let out = addressServerRest + api;
|
||||
let first = true;
|
||||
for (let iii = 0; iii < options.length; iii++) {
|
||||
if (first === false) {
|
||||
out = `${out}&`;
|
||||
} else {
|
||||
out = `${out}?`;
|
||||
first = false;
|
||||
}
|
||||
out = out + options[iii];
|
||||
}
|
||||
return out;
|
||||
}
|
||||
// Deprecated ... old model stream
|
||||
post(uriRest: string, headerOption: any, data: any, progress: ProgressCallback = null) {
|
||||
//console.log(`-------------------------------------------------------\nHTTP-wrapper POST '${ uriRest }'\n\t\theaderOption=${ JSON.stringify(headerOption, null, 2)}\n\t\tdata=${ JSON.stringify(data, null, 2)}`);
|
||||
this.addTokenIfNeeded(headerOption);
|
||||
let connectionAddresses = this.createRESTCall(uriRest, {});
|
||||
|
||||
return new Promise((resolve, reject) => {
|
||||
if (this.displayReturn === true) {
|
||||
console.log(`call POST ${connectionAddresses} data=${JSON.stringify(data, null, 2)}`);
|
||||
}
|
||||
let request = this.http.post(connectionAddresses, data, {
|
||||
headers: new HttpHeaders(headerOption),
|
||||
reportProgress: true,
|
||||
observe: 'events',
|
||||
});
|
||||
let self = this;
|
||||
request.subscribe(
|
||||
(res: any) => {
|
||||
if (self.displayReturn === true) {
|
||||
console.log(`!! data ${JSON.stringify(res, null, 2)}`);
|
||||
}
|
||||
if (res.type === HttpEventType.Sent) {
|
||||
/* res.type === 0 */
|
||||
//console.log('post : Sent');
|
||||
} else if (res.type === HttpEventType.UploadProgress) {
|
||||
/* res.type === 1 */
|
||||
// console.log("post : " + res.loaded + " / " + res.total);
|
||||
progress(res.loaded, res.total);
|
||||
} else if (res.type === HttpEventType.ResponseHeader) {
|
||||
/* res.type === 2 */
|
||||
//console.log('post : get header');
|
||||
} else if (res.type === HttpEventType.DownloadProgress) {
|
||||
/* res.type === 3 */
|
||||
//console.log(`post : get DownloadProgress ${ res.loaded}`);
|
||||
} else if (res.type === HttpEventType.Response) {
|
||||
/* res.type === 4 */
|
||||
//console.log('post : get response');
|
||||
if (res.httpCode) {
|
||||
resolve({ status: res.httpCode, data: res });
|
||||
} else {
|
||||
resolve({ status: 200, data: res });
|
||||
}
|
||||
} else if (res.type === HttpEventType.User) {
|
||||
/* res.type === 5 */
|
||||
//console.log('post : get User');
|
||||
} else {
|
||||
console.log(`post : get unknown ... ${res.type}`);
|
||||
}
|
||||
},
|
||||
error => {
|
||||
if (self.displayReturn === true) {
|
||||
console.log(`an error occured status: ${error.status}`);
|
||||
console.log(`answer: ${JSON.stringify(error, null, 2)}`);
|
||||
}
|
||||
reject({ status: error.status, data: error.error });
|
||||
}
|
||||
);
|
||||
});
|
||||
}
|
||||
// Deprecated ... old model stream
|
||||
uploadMultipart(base: string, multipart: FormData, progress: ProgressCallback): any {
|
||||
//console.log(`Upload multipart to ${ base}`);
|
||||
|
||||
let url = base;
|
||||
let self = this;
|
||||
return new Promise((resolve, reject) => {
|
||||
let headers = {
|
||||
// 'Content-Type': 'multipart/form-data',
|
||||
}; // new Headers();
|
||||
|
||||
self.post(url, headers, multipart, progress).then(
|
||||
(response: any) => {
|
||||
//console.log(`URL: ${ url }\nRespond(${ response.status }): ${ JSON.stringify(response.data, null, 2)}`);
|
||||
if (response.status >= 200 && response.status <= 299) {
|
||||
resolve(response.data.body);
|
||||
return;
|
||||
}
|
||||
reject('An error occured');
|
||||
},
|
||||
(response: any) => {
|
||||
if (typeof response.data === 'undefined') {
|
||||
reject('return ERROR undefined');
|
||||
} else {
|
||||
reject('return ERROR ...'); // + JSON.stringify(response, null, 2));
|
||||
}
|
||||
}
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
// Complex wrapper to simplify interaction:
|
||||
getSpecific(urlPath: UrlPath): any {
|
||||
return new Promise((resolve, reject) => {
|
||||
this.requestJson({
|
||||
endPoint: urlPath,
|
||||
requestType: HTTPRequestModel.GET,
|
||||
accept: HTTPMimeType.JSON,
|
||||
contentType: HTTPMimeType.JSON,
|
||||
}).then(
|
||||
(response: ModelResponseHttp) => {
|
||||
//console.log("URL: " + url + "\nRespond(" + response.status + "): " + JSON.stringify(response.data, null, 2));
|
||||
if (response.status === 200) {
|
||||
resolve(response.data);
|
||||
return;
|
||||
}
|
||||
reject('An error occured');
|
||||
},
|
||||
(response: ModelResponseHttp) => {
|
||||
if (isNullOrUndefined(response.data)) {
|
||||
reject('return ERROR undefined');
|
||||
} else {
|
||||
reject(`return ERROR ${JSON.stringify(response.data, null, 2)}`);
|
||||
}
|
||||
}
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
// Complex wrapper to simplify interaction:s
|
||||
putSpecific(urlPath: UrlPath, data: object): Promise<ModelResponseHttp> {
|
||||
return new Promise((resolve, reject) => {
|
||||
this.request({
|
||||
endPoint: urlPath,
|
||||
requestType: HTTPRequestModel.PUT,
|
||||
accept: HTTPMimeType.JSON,
|
||||
contentType: HTTPMimeType.JSON,
|
||||
body: data,
|
||||
})
|
||||
.then((response: Response) => {
|
||||
if (response.status >= 200 && response.status <= 201) {
|
||||
const contentType = response.headers.get('Content-Type');
|
||||
if (contentType === HTTPMimeType.JSON) {
|
||||
response
|
||||
.json()
|
||||
.then((value: any) => {
|
||||
//console.log(`REICEIVE ==> ${response.status}=${ JSON.stringify(value, null, 2)}`);
|
||||
resolve({ status: response.status, data: value });
|
||||
})
|
||||
.catch((reason: any) => {
|
||||
reject({ status: 999, data: reason });
|
||||
});
|
||||
} else {
|
||||
console.error(`content Type is not Json: ${contentType}`);
|
||||
reject({ status: 998, data: `content Type is not Json: ${contentType}` });
|
||||
}
|
||||
} else {
|
||||
console.error(`wrong correct status: ${response.status}`);
|
||||
reject({ status: 900, data: response });
|
||||
}
|
||||
})
|
||||
.catch((error: any) => {
|
||||
reject({ status: error.status, data: error.error });
|
||||
});
|
||||
});
|
||||
}
|
||||
postSpecific(urlPath: UrlPath, data: object): Promise<ModelResponseHttp> {
|
||||
return new Promise((resolve, reject) => {
|
||||
this.request({
|
||||
endPoint: urlPath,
|
||||
requestType: HTTPRequestModel.POST,
|
||||
accept: HTTPMimeType.JSON,
|
||||
contentType: HTTPMimeType.JSON,
|
||||
body: data,
|
||||
})
|
||||
.then((response: Response) => {
|
||||
if (response.status >= 200 && response.status <= 201) {
|
||||
const contentType = response.headers.get('Content-Type');
|
||||
if (contentType === HTTPMimeType.JSON) {
|
||||
response
|
||||
.json()
|
||||
.then((value: any) => {
|
||||
//console.log(`REICEIVE ==> ${response.status}=${ JSON.stringify(value, null, 2)}`);
|
||||
resolve({ status: response.status, data: value });
|
||||
})
|
||||
.catch((reason: any) => {
|
||||
reject({ status: 999, data: reason });
|
||||
});
|
||||
} else {
|
||||
console.error(`content Type is not Json: ${contentType}`);
|
||||
reject({ status: 998, data: `content Type is not Json: ${contentType}` });
|
||||
}
|
||||
} else {
|
||||
console.error(`wrong correct status: ${response.status}`);
|
||||
reject({ status: 900, data: response });
|
||||
}
|
||||
})
|
||||
.catch((error: any) => {
|
||||
reject({ status: error.status, data: error.error });
|
||||
});
|
||||
});
|
||||
}
|
||||
deleteSpecific(urlPath: UrlPath): Promise<ModelResponseHttp> {
|
||||
return new Promise((resolve, reject) => {
|
||||
this.request({
|
||||
endPoint: urlPath,
|
||||
requestType: HTTPRequestModel.DELETE,
|
||||
accept: HTTPMimeType.JSON,
|
||||
contentType: HTTPMimeType.JSON,
|
||||
})
|
||||
.then((response: Response) => {
|
||||
if (response.status >= 200 && response.status <= 201) {
|
||||
const contentType = response.headers.get('Content-Type');
|
||||
if (contentType === HTTPMimeType.JSON) {
|
||||
response
|
||||
.json()
|
||||
.then((value: any) => {
|
||||
//console.log(`REICEIVE ==> ${response.status}=${ JSON.stringify(value, null, 2)}`);
|
||||
resolve({ status: response.status, data: value });
|
||||
})
|
||||
.catch((reason: any) => {
|
||||
reject({ status: 999, data: reason });
|
||||
});
|
||||
} else {
|
||||
console.error(`content Type is not Json: ${contentType}`);
|
||||
reject({ status: 998, data: `content Type is not Json: ${contentType}` });
|
||||
}
|
||||
} else {
|
||||
console.error(`wrong correct status: ${response.status}`);
|
||||
reject({ status: 900, data: response });
|
||||
}
|
||||
})
|
||||
.catch((error: any) => {
|
||||
reject({ status: error.status, data: error.error });
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
@ -1,35 +0,0 @@
|
||||
import { BddService } from './bdd';
|
||||
import { CookiesService } from './cookies';
|
||||
import { HttpWrapperService, ModelResponseHttp, HTTPRequest, HTTPMimeType, HTTPRequestModel } from './http-wrapper';
|
||||
import { StorageService } from './local-storage';
|
||||
import { NotificationService } from './notification';
|
||||
import { PopInService } from './popin';
|
||||
import {
|
||||
OnlyAdminGuard,
|
||||
OnlyUnregisteredGuardHome,
|
||||
OnlyUsersGuard,
|
||||
OnlyUsersGuardHome,
|
||||
SessionService,
|
||||
} from './session';
|
||||
import { SSOService } from './sso';
|
||||
import { UserService } from './user';
|
||||
|
||||
export {
|
||||
BddService,
|
||||
CookiesService,
|
||||
StorageService,
|
||||
HttpWrapperService,
|
||||
ModelResponseHttp,
|
||||
HTTPRequest,
|
||||
HTTPMimeType,
|
||||
HTTPRequestModel,
|
||||
PopInService,
|
||||
SessionService,
|
||||
UserService,
|
||||
SSOService,
|
||||
OnlyUsersGuard,
|
||||
OnlyUsersGuardHome,
|
||||
OnlyUnregisteredGuardHome,
|
||||
OnlyAdminGuard,
|
||||
NotificationService,
|
||||
};
|
@ -1,50 +0,0 @@
|
||||
/** @file
|
||||
* @author Edouard DUPIN
|
||||
* @copyright 2018, Edouard DUPIN, all right reserved
|
||||
* @license PROPRIETARY (see license file)
|
||||
*/
|
||||
|
||||
import { Injectable } from '@angular/core';
|
||||
import { environment } from 'environments/environment';
|
||||
|
||||
@Injectable()
|
||||
export class StorageService {
|
||||
private baseLocalStorageName = environment.applName + '_';
|
||||
|
||||
constructor() {}
|
||||
|
||||
set(cname: string, cvalue: string): void {
|
||||
//console.debug(`storage set: ${cname} : ${cvalue}`);
|
||||
localStorage.setItem(this.baseLocalStorageName + cname, cvalue);
|
||||
}
|
||||
// limit at the current session ...
|
||||
setSession(cname: string, cvalue: string): void {
|
||||
sessionStorage.setItem(this.baseLocalStorageName + cname, cvalue);
|
||||
}
|
||||
|
||||
remove(cname: string): void {
|
||||
//console.debug(`storage remove: ${cname}`);
|
||||
localStorage.removeItem(this.baseLocalStorageName + cname);
|
||||
}
|
||||
removeSession(cname: string): void {
|
||||
sessionStorage.removeItem(this.baseLocalStorageName + cname);
|
||||
}
|
||||
|
||||
get(cname: string): string | undefined {
|
||||
//console.debug(`storage get: ${cname}`);
|
||||
// TODO check expire day...
|
||||
const data = localStorage.getItem(this.baseLocalStorageName + cname);
|
||||
//console.debug(`get value form the storage (1): ${data}`)
|
||||
if (data === null || data === undefined) {
|
||||
return undefined;
|
||||
}
|
||||
return data;
|
||||
}
|
||||
getSession(cname: string): string | undefined {
|
||||
const data = sessionStorage.getItem(this.baseLocalStorageName + cname);
|
||||
if (data === null || data === undefined) {
|
||||
return undefined;
|
||||
}
|
||||
return data;
|
||||
}
|
||||
}
|
@ -1,25 +0,0 @@
|
||||
/** @file
|
||||
* @author Edouard DUPIN
|
||||
* @copyright 2018, Edouard DUPIN, all right reserved
|
||||
* @license PROPRIETARY (see license file)
|
||||
*/
|
||||
|
||||
import { Injectable } from '@angular/core';
|
||||
|
||||
@Injectable()
|
||||
export class NotificationService {
|
||||
|
||||
constructor() {
|
||||
console.log('Start Notification Service');
|
||||
}
|
||||
|
||||
errorRaw(data: any) {
|
||||
console.error(`get notification error: ${data}`)
|
||||
}
|
||||
warningRaw(data: any) {
|
||||
console.info(`get notification warning: ${data}`)
|
||||
}
|
||||
infoRaw(data: any) {
|
||||
console.info(`get notification info: ${data}`)
|
||||
}
|
||||
}
|
@ -1,55 +0,0 @@
|
||||
/** @file
|
||||
* @author Edouard DUPIN
|
||||
* @copyright 2018, Edouard DUPIN, all right reserved
|
||||
* @license PROPRIETARY (see license file)
|
||||
*/
|
||||
|
||||
import { Injectable } from '@angular/core';
|
||||
|
||||
@Injectable()
|
||||
export class PopInService {
|
||||
private popins: any[] = [];
|
||||
|
||||
constructor() {
|
||||
console.log('Start PopIn Service');
|
||||
}
|
||||
|
||||
add(_popin: any) {
|
||||
// add popin to array of active popins
|
||||
this.popins.push(_popin);
|
||||
}
|
||||
|
||||
remove(_id: string) {
|
||||
// remove popin from array of active popins
|
||||
for (let iii = 0; iii < this.popins.length; iii++) {
|
||||
if (this.popins[iii].id === _id) {
|
||||
this.popins.splice(iii, 1);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
open(_id: string) {
|
||||
console.log("Try to open pop-in: '" + _id + "'");
|
||||
// open popin specified by id
|
||||
for (let iii = 0; iii < this.popins.length; iii++) {
|
||||
console.log(` check: ${this.popins[iii].id}`);
|
||||
if (this.popins[iii].id === _id) {
|
||||
console.log(" ==>find it ...");
|
||||
this.popins[iii].open();
|
||||
return;
|
||||
}
|
||||
}
|
||||
console.log(" ==> NOT found !!!!!");
|
||||
}
|
||||
|
||||
close(_id: string) {
|
||||
// close popin specified by id
|
||||
for (let iii = 0; iii < this.popins.length; iii++) {
|
||||
if (this.popins[iii].id === _id) {
|
||||
this.popins[iii].close();
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -1,178 +0,0 @@
|
||||
/** @file
|
||||
* @author Edouard DUPIN
|
||||
* @copyright 2018, Edouard DUPIN, all right reserved
|
||||
* @license PROPRIETARY (see license file)
|
||||
*/
|
||||
|
||||
import { Injectable, Output, EventEmitter } from '@angular/core';
|
||||
import { CanActivate, Router } from '@angular/router';
|
||||
import { isNullOrUndefined } from 'common/utils';
|
||||
import { environment } from 'environments/environment';
|
||||
|
||||
export enum UserRoles222 {
|
||||
admin = 'admin',
|
||||
user = 'user',
|
||||
guest = 'guest',
|
||||
}
|
||||
|
||||
@Injectable()
|
||||
export class SessionService {
|
||||
private tokenJwt = null;
|
||||
public userLogin = null;
|
||||
public userId = null;
|
||||
public right: any = {};
|
||||
|
||||
@Output() change: EventEmitter<boolean> = new EventEmitter();
|
||||
|
||||
constructor() { }
|
||||
|
||||
/**
|
||||
* @brief Create a new session.
|
||||
*
|
||||
* @param userId -
|
||||
* @param userLogin -
|
||||
* @param tokenJwt -
|
||||
*/
|
||||
create({
|
||||
userId,
|
||||
userLogin,
|
||||
tokenJwt,
|
||||
}: {
|
||||
userId: string;
|
||||
userLogin: string;
|
||||
tokenJwt: string;
|
||||
}) {
|
||||
console.log(
|
||||
`Session Create: userId=${userId} userLogin=${userLogin} tokenJwt = ${tokenJwt}`
|
||||
);
|
||||
this.tokenJwt = tokenJwt;
|
||||
this.userId = userId;
|
||||
this.userLogin = userLogin;
|
||||
this.right = this.parseToken(tokenJwt);
|
||||
console.log(`Retrieve right: ${JSON.stringify(this.right, null, 4)}`);
|
||||
this.change.emit(true);
|
||||
}
|
||||
|
||||
b64_to_utf8(str: string): string {
|
||||
return decodeURIComponent(window.atob(str));
|
||||
}
|
||||
parseToken(token: string): any {
|
||||
const cut = token.split('.');
|
||||
const decoded = this.b64_to_utf8(cut[1]);
|
||||
const jsonModel = JSON.parse(decoded);
|
||||
if (isNullOrUndefined(jsonModel.right)) {
|
||||
return {};
|
||||
}
|
||||
if (isNullOrUndefined(jsonModel.right[environment.applName])) {
|
||||
return {};
|
||||
}
|
||||
return jsonModel.right[environment.applName];
|
||||
}
|
||||
/**
|
||||
* @brief destroy the current session.
|
||||
*/
|
||||
destroy() {
|
||||
console.log('Session REMOVE');
|
||||
this.tokenJwt = undefined;
|
||||
this.userId = null;
|
||||
this.userLogin = null;
|
||||
this.right = {};
|
||||
this.change.emit(false);
|
||||
}
|
||||
getToken(): string | undefined {
|
||||
return this.tokenJwt;
|
||||
}
|
||||
islogged() {
|
||||
return this.userId !== null;
|
||||
}
|
||||
hasRight(type: UserRoles222): boolean {
|
||||
if (type === UserRoles222.admin) {
|
||||
if (isNullOrUndefined(this.right.ADMIN)) {
|
||||
return false;
|
||||
}
|
||||
return this.right.ADMIN;
|
||||
}
|
||||
if (type === UserRoles222.user) {
|
||||
if (isNullOrUndefined(this.right.USER)) {
|
||||
return false;
|
||||
}
|
||||
return this.right.USER;
|
||||
}
|
||||
if (type === UserRoles222.guest) {
|
||||
// all the other ... maybe unneeded
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
hasNotRight(type) {
|
||||
return !this.hasRight(type);
|
||||
}
|
||||
getLogin() {
|
||||
return this.userLogin;
|
||||
}
|
||||
getAvatar() {
|
||||
return 'assets/images/avatar_generic.svg';
|
||||
/* This is not ready:
|
||||
if(this.userAvatar === false) {
|
||||
return 'assets/images/avatar_generic.svg';
|
||||
}
|
||||
return this.userId;
|
||||
*/
|
||||
}
|
||||
}
|
||||
|
||||
@Injectable()
|
||||
export class OnlyUsersGuard implements CanActivate {
|
||||
constructor(private sessionService: SessionService, private router: Router) { }
|
||||
|
||||
canActivate() {
|
||||
console.log('OnlyLoggedInUsers');
|
||||
if (this.sessionService.hasRight(UserRoles222.user) || this.sessionService.hasRight(UserRoles222.admin)) {
|
||||
return true;
|
||||
} else {
|
||||
this.router.navigateByUrl('/forbidden');
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Injectable()
|
||||
export class OnlyUsersGuardHome implements CanActivate {
|
||||
constructor(private sessionService: SessionService, private router: Router) { }
|
||||
|
||||
canActivate() {
|
||||
if (this.sessionService.hasRight(UserRoles222.user) || this.sessionService.hasRight(UserRoles222.admin)) {
|
||||
return true;
|
||||
} else {
|
||||
this.router.navigateByUrl('/unregistered');
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
@Injectable()
|
||||
export class OnlyUnregisteredGuardHome implements CanActivate {
|
||||
constructor(private sessionService: SessionService, private router: Router) { }
|
||||
|
||||
canActivate() {
|
||||
if (!this.sessionService.islogged()) {
|
||||
return true;
|
||||
} else {
|
||||
this.router.navigateByUrl('/home');
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Injectable()
|
||||
export class OnlyAdminGuard implements CanActivate {
|
||||
constructor(private sessionService: SessionService, private router: Router) { }
|
||||
|
||||
canActivate() {
|
||||
if (this.sessionService.hasRight(UserRoles222.user)) {
|
||||
return true;
|
||||
} else {
|
||||
this.router.navigateByUrl('/forbidden');
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
@ -1,135 +0,0 @@
|
||||
/** @file
|
||||
* @author Edouard DUPIN
|
||||
* @copyright 2018, Edouard DUPIN, all right reserved
|
||||
* @license PROPRIETARY (see license file)
|
||||
*/
|
||||
|
||||
import { Injectable } from '@angular/core';
|
||||
import { environment } from 'environments/environment';
|
||||
import { getApplicationLocation, isInArray, isNullOrUndefined } from 'common/utils';
|
||||
import { HTTPMimeType, HTTPRequestModel, HttpWrapperService, ModelResponseHttp } from 'common/service';
|
||||
|
||||
@Injectable()
|
||||
export class SSOService {
|
||||
signUpEnable: boolean = undefined;
|
||||
|
||||
constructor(private http: HttpWrapperService) {
|
||||
console.log('Start SSOService');
|
||||
}
|
||||
utf8_to_b64(str: string): string {
|
||||
// remove unneeded "=" padding
|
||||
return window.btoa(encodeURIComponent(str)).replace('=', '');
|
||||
}
|
||||
|
||||
b64_to_utf8(str: string): string {
|
||||
return decodeURIComponent(window.atob(str));
|
||||
}
|
||||
/**
|
||||
* Request SSO connection
|
||||
*/
|
||||
hashLocalData(data?: string): string {
|
||||
if (
|
||||
!isNullOrUndefined(data) &&
|
||||
!isInArray(data, [
|
||||
'',
|
||||
'null',
|
||||
'NULL',
|
||||
'undefined',
|
||||
'---',
|
||||
'unregistered',
|
||||
'unregistered/',
|
||||
'forbidden',
|
||||
'forbidden/',
|
||||
])
|
||||
) {
|
||||
return this.utf8_to_b64(data);
|
||||
}
|
||||
const pathName = getApplicationLocation();
|
||||
if (isInArray(pathName, ['sso', '/sso', '/sso/'])) {
|
||||
return this.utf8_to_b64('home');
|
||||
}
|
||||
if (
|
||||
!isNullOrUndefined(pathName) &&
|
||||
!isInArray(pathName, [
|
||||
'',
|
||||
'null',
|
||||
'NULL',
|
||||
'undefined',
|
||||
'---',
|
||||
'unregistered',
|
||||
'unregistered/',
|
||||
'forbidden',
|
||||
'forbidden/',
|
||||
])
|
||||
) {
|
||||
return this.utf8_to_b64(pathName);
|
||||
}
|
||||
return this.utf8_to_b64('home');
|
||||
}
|
||||
/**
|
||||
* Request SSO connection
|
||||
*/
|
||||
unHashLocalData(data: string): string | undefined {
|
||||
if (isNullOrUndefined(data) || isInArray(data, ['', 'null', 'NULL', 'undefined', '---'])) {
|
||||
return undefined;
|
||||
}
|
||||
try {
|
||||
return this.b64_to_utf8(data);
|
||||
} catch (ex) {
|
||||
console.error(`Can not convert the data: ${data}`);
|
||||
}
|
||||
return undefined;
|
||||
}
|
||||
/**
|
||||
* Request Open SSO Global website
|
||||
*/
|
||||
requestOpenSite(): void {
|
||||
window.location.href = environment.ssoSite;
|
||||
}
|
||||
/**
|
||||
* Request SSO connection
|
||||
*/
|
||||
requestSignIn(name?: string): void {
|
||||
window.location.href = environment.ssoSignIn + this.hashLocalData(name);
|
||||
}
|
||||
/**
|
||||
* Request SSO Disconnect
|
||||
*/
|
||||
requestSignOut(name?: string): void {
|
||||
window.location.href = environment.ssoSignOut + this.hashLocalData(name);
|
||||
}
|
||||
/**
|
||||
* Request SSO signUp
|
||||
*/
|
||||
requestSignUp(name?: string): void {
|
||||
window.location.href = environment.ssoSignUp + this.hashLocalData(name);
|
||||
}
|
||||
/**
|
||||
* Checo if the signUp is authorized (generate by te SSO)
|
||||
* @returns a promise of the State for sign-up
|
||||
*/
|
||||
checkSignUpEnable(): Promise<boolean> {
|
||||
let self = this;
|
||||
return new Promise((resolve, reject) => {
|
||||
if (isNullOrUndefined(self.signUpEnable)) {
|
||||
this.http
|
||||
.requestJson({
|
||||
server: 'karso',
|
||||
endPoint: 'system_config/is_sign_up_availlable',
|
||||
requestType: HTTPRequestModel.GET,
|
||||
accept: HTTPMimeType.JSON,
|
||||
contentType: HTTPMimeType.JSON,
|
||||
})
|
||||
.then((response: ModelResponseHttp) => {
|
||||
self.signUpEnable = response.data.signup;
|
||||
resolve(self.signUpEnable);
|
||||
})
|
||||
.catch((error: any) => {
|
||||
reject(`return ERROR ${JSON.stringify(error, null, 2)}`);
|
||||
});
|
||||
return;
|
||||
}
|
||||
resolve(self.signUpEnable);
|
||||
});
|
||||
}
|
||||
}
|
@ -1,266 +0,0 @@
|
||||
/** @file
|
||||
* @author Edouard DUPIN
|
||||
* @copyright 2018, Edouard DUPIN, all right reserved
|
||||
* @license PROPRIETARY (see license file)
|
||||
*/
|
||||
|
||||
import { Injectable } from '@angular/core';
|
||||
import { Router } from '@angular/router';
|
||||
import { environment } from 'environments/environment';
|
||||
|
||||
import { HTTPMimeType, HTTPRequestModel, HttpWrapperService, ModelResponseHttp } from './http-wrapper';
|
||||
import { StorageService } from 'common/service/local-storage';
|
||||
import { SessionService } from './session';
|
||||
import { SSOService } from './sso';
|
||||
import { getApplicationLocation, isNullOrUndefined, sha512 } from 'common/utils';
|
||||
|
||||
/*
|
||||
interface MessageLogIn {
|
||||
login: string;
|
||||
method: string;
|
||||
time: number;
|
||||
password: string;
|
||||
}
|
||||
interface MessageAnswer_USER_CONNECT {
|
||||
sessionId: string;
|
||||
login: string;
|
||||
eMail: string;
|
||||
role: string;
|
||||
avatar: string;
|
||||
}
|
||||
*/
|
||||
@Injectable()
|
||||
export class UserService {
|
||||
// 0: Not hide password; 1 hide password;
|
||||
private identificationVersion: number = 1;
|
||||
private cookiesRememberMe = 'remember-me';
|
||||
private cookiesToken = 'token';
|
||||
|
||||
constructor(
|
||||
private router: Router,
|
||||
private storageService: StorageService,
|
||||
private http: HttpWrapperService,
|
||||
private sessionService: SessionService,
|
||||
private ssoService: SSOService
|
||||
) {
|
||||
console.log('Start UserService');
|
||||
}
|
||||
|
||||
/**
|
||||
* Disconnect the user from the current session ==> this remove the curreent Token
|
||||
*/
|
||||
logOut(): void {
|
||||
this.removeSession();
|
||||
this.ssoService.requestSignOut('home');
|
||||
}
|
||||
removeSession(): void {
|
||||
this.storageService.remove(this.cookiesRememberMe);
|
||||
this.storageService.removeSession(this.cookiesToken);
|
||||
this.storageService.remove(this.cookiesToken);
|
||||
this.sessionService.destroy();
|
||||
}
|
||||
|
||||
private isTokenUpToDate(token: string): boolean {
|
||||
if (token === null || token === undefined || token.length < 25) {
|
||||
return false;
|
||||
}
|
||||
// Separate the Data:
|
||||
const elems = token.split('.');
|
||||
if (elems.length !== 3) {
|
||||
return false;
|
||||
}
|
||||
// const tokenHeader = decodeURIComponent(window.atob( elems[0] ));
|
||||
const tokenData = decodeURIComponent(window.atob(elems[1]));
|
||||
// console.error(`Retreive local token: \nheader=${tokenHeader} \ndata=${tokenData}`);
|
||||
const parsedData = JSON.parse(tokenData);
|
||||
console.debug(
|
||||
`Retreive token exp data=${new Date(parsedData.exp * 1000).toISOString()} < ${new Date().toISOString()}`
|
||||
);
|
||||
const expireIn = new Date(parsedData.exp * 1000);
|
||||
const nowTime = new Date();
|
||||
// TODO: set a marging of 2 hours...
|
||||
return expireIn > nowTime;
|
||||
}
|
||||
|
||||
getRememberMe(): boolean {
|
||||
return this.storageService.get(this.cookiesRememberMe) === 'true';
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if the system can be connected
|
||||
*/
|
||||
checkAutoConnect(): Promise<void> {
|
||||
let locationOrigin = getApplicationLocation();
|
||||
const self = this;
|
||||
return new Promise<void>((resolve, reject) => {
|
||||
// Need to use the windows global route to prevent the log in cycle ...
|
||||
// And in the mlain application position, the route does not have curently root the page
|
||||
let pathName = window.location.pathname;
|
||||
// console.log("start Path-name: '" + pathName + "'");
|
||||
// console.log("check with: '" + environment.applName + "/sso/" + "'");
|
||||
if (pathName.startsWith('/sso/') || pathName.startsWith(environment.applName + '/sso/')) {
|
||||
console.log(' ==> SSo section');
|
||||
reject();
|
||||
return;
|
||||
}
|
||||
console.log(' ==> Check if need reconnect?');
|
||||
let rememberMe = self.getRememberMe();
|
||||
// TODO: in case of jest reload ==> no need to manage the SSO ==> just keep the token ... it in enought...
|
||||
let token = null;
|
||||
if (
|
||||
isNullOrUndefined(environment.tokenStoredInPermanentStorage) ||
|
||||
environment.tokenStoredInPermanentStorage !== true
|
||||
) {
|
||||
token = self.storageService.getSession(self.cookiesToken);
|
||||
} else {
|
||||
token = self.storageService.get(self.cookiesToken);
|
||||
}
|
||||
// TODO: check validity of the Token:
|
||||
if (self.isTokenUpToDate(token)) {
|
||||
// remove in case of fail !!!
|
||||
this.storageService.removeSession(this.cookiesToken);
|
||||
this.storageService.remove(this.cookiesToken);
|
||||
self.startSession(token, rememberMe)
|
||||
.then(() => {
|
||||
self.router.navigateByUrl(locationOrigin);
|
||||
console.log(`update global URL = ${locationOrigin}`);
|
||||
resolve();
|
||||
})
|
||||
.catch(() => {
|
||||
// jump in the sign-in page (automatically of request remember-me)
|
||||
if (rememberMe) {
|
||||
// jump to the sso !!! (remove local data to prevent login loop)
|
||||
this.storageService.remove(this.cookiesRememberMe);
|
||||
this.storageService.remove(this.cookiesToken);
|
||||
this.storageService.removeSession(this.cookiesToken);
|
||||
self.ssoService.requestSignIn(locationOrigin);
|
||||
reject();
|
||||
}
|
||||
resolve();
|
||||
});
|
||||
} else {
|
||||
console.log(`Get previous connection ... `);
|
||||
if (rememberMe) {
|
||||
// jump to the sso !!! (remove local data to prevent login loop)
|
||||
this.storageService.remove(this.cookiesRememberMe);
|
||||
this.storageService.remove(this.cookiesToken);
|
||||
this.storageService.removeSession(this.cookiesToken);
|
||||
self.ssoService.requestSignIn(locationOrigin);
|
||||
reject();
|
||||
}
|
||||
resolve();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
startSession(token: string, rememberMe: boolean): Promise<string> {
|
||||
const self = this;
|
||||
return new Promise((resolve, reject) => {
|
||||
self.retreiveMe(token)
|
||||
.then((value2: boolean) => {
|
||||
if (rememberMe === true) {
|
||||
self.storageService.set(self.cookiesRememberMe, rememberMe ? 'true' : 'false');
|
||||
}
|
||||
if (
|
||||
isNullOrUndefined(environment.tokenStoredInPermanentStorage) ||
|
||||
environment.tokenStoredInPermanentStorage !== true
|
||||
) {
|
||||
self.storageService.setSession(self.cookiesToken, token);
|
||||
} else {
|
||||
self.storageService.set(self.cookiesToken, token);
|
||||
}
|
||||
resolve(self.sessionService.getLogin());
|
||||
})
|
||||
.catch(() => {
|
||||
reject('sdfsdfsdf');
|
||||
});
|
||||
});
|
||||
}
|
||||
retreiveMe(token: string): Promise<boolean> {
|
||||
console.log(`AuthService.loginWithToken ... '${token}'`);
|
||||
const self = this;
|
||||
return new Promise((resolve, reject) => {
|
||||
this.http
|
||||
.requestJson({
|
||||
// server: 'karso',
|
||||
endPoint: 'users/me',
|
||||
requestType: HTTPRequestModel.GET,
|
||||
accept: HTTPMimeType.JSON,
|
||||
contentType: HTTPMimeType.JSON,
|
||||
authorization: `Yota ${token}`, // special case, the token is set after this request...
|
||||
})
|
||||
.then((response: ModelResponseHttp) => {
|
||||
// TODO: check type ...
|
||||
console.log(`loginWithToken : get some data to check: ${JSON.stringify(response.data)}`);
|
||||
self.sessionService.create({
|
||||
//sessionId: response.data.sessionId,
|
||||
userId: response.data.id,
|
||||
userLogin: response.data.login,
|
||||
//userEMail: response.data.email,
|
||||
//userAdmin: response.data.admin,
|
||||
//userBlocked: response.data.blocked,
|
||||
//userRemoved: response.data.removed,
|
||||
//userAvatar: response.data.avatar,
|
||||
tokenJwt: token,
|
||||
});
|
||||
resolve(true);
|
||||
})
|
||||
.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));
|
||||
}
|
||||
createSha(login: string, email: string, password: string) {
|
||||
let data = {
|
||||
method: 'v?',
|
||||
login: login,
|
||||
email: email,
|
||||
password: password,
|
||||
};
|
||||
console.log(`call users data=${JSON.stringify(data, null, 2)}`);
|
||||
|
||||
if (this.identificationVersion === 1) {
|
||||
data.method = 'v1';
|
||||
}
|
||||
|
||||
return new Promise((resolve, reject) => {
|
||||
this.http
|
||||
.requestJson({
|
||||
server: 'karso',
|
||||
endPoint: 'users',
|
||||
requestType: HTTPRequestModel.POST,
|
||||
accept: HTTPMimeType.JSON,
|
||||
contentType: HTTPMimeType.JSON,
|
||||
body: data,
|
||||
})
|
||||
.then((response: ModelResponseHttp) => {
|
||||
// TODO: check type ...
|
||||
console.log(`createSha : get some data to check: ${JSON.stringify(response.data)}`);
|
||||
resolve(response.data);
|
||||
})
|
||||
.catch((error: any) => {
|
||||
reject(`return ERROR ${JSON.stringify(error, null, 2)}`);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
isAuthenticated(): boolean {
|
||||
// return !!Session.userId;
|
||||
return false;
|
||||
}
|
||||
isAuthorized(authorizedRoles: string): boolean {
|
||||
/*
|
||||
if (!angular.isArray(_authorizedRoles)) {
|
||||
authorizedRoles = [_authorizedRoles];
|
||||
}
|
||||
return ( authService.isAuthenticated()
|
||||
&& _authorizedRoles.indexOf(Session.userRole) !== -1
|
||||
);
|
||||
*/
|
||||
return false;
|
||||
}
|
||||
}
|
@ -1,17 +0,0 @@
|
||||
import { environment } from 'environments/environment';
|
||||
|
||||
export function getApplicationLocation(): string {
|
||||
let pathName = location.pathname;
|
||||
//console.log("start Path-name: '" + pathName + "'");
|
||||
//console.log("check with: '" + environment.applName + "/sso/" + "'");
|
||||
if (pathName.startsWith('/' + environment.applName + '/')) {
|
||||
pathName = pathName.substring(environment.applName.length + 2);
|
||||
} else if (pathName.startsWith('/' + environment.applName)) {
|
||||
pathName = pathName.substring(environment.applName.length + 1);
|
||||
} else if (pathName.startsWith(environment.applName + '/')) {
|
||||
pathName = pathName.substring(environment.applName.length + 1);
|
||||
} else if (pathName.startsWith(environment.applName)) {
|
||||
pathName = pathName.substring(environment.applName.length);
|
||||
}
|
||||
return pathName;
|
||||
}
|
@ -1,330 +0,0 @@
|
||||
/** @file
|
||||
* @author Edouard DUPIN
|
||||
* @copyright 2018, Edouard DUPIN, all right reserved
|
||||
* @license PROPRIETARY (see license file)
|
||||
*/
|
||||
|
||||
import { NodeData } from '../model';
|
||||
import { isArray, isNullOrUndefined } from './validator';
|
||||
|
||||
export enum TypeCheck {
|
||||
CONTAINS = 'C',
|
||||
EQUAL = '==',
|
||||
NOT_EQUAL = '!=',
|
||||
LESS = '<',
|
||||
LESS_EQUAL = '<=',
|
||||
GREATER = '>',
|
||||
GREATER_EQUAL = '>=',
|
||||
}
|
||||
|
||||
export interface SelectModel {
|
||||
check: TypeCheck;
|
||||
key: string;
|
||||
value?: number | string | boolean | number[] | string[];
|
||||
}
|
||||
/*
|
||||
{ check: TypeCheck.EQUAL, key: sss, value: null}
|
||||
*/
|
||||
|
||||
/**
|
||||
* @breif Generic interface to access to the BDD (no BDD, direct file IO)
|
||||
*/
|
||||
export class DataInterface {
|
||||
static extractLimitOne(data: NodeData[], key: string): any[] {
|
||||
const out = [];
|
||||
for (let iii = 0; iii < data.length; iii++) {
|
||||
const value = data[iii][key];
|
||||
if (DataInterface.existIn(value, out) === false) {
|
||||
out.push(value);
|
||||
}
|
||||
}
|
||||
return out;
|
||||
}
|
||||
static extractLimitOneList(data: NodeData[], key: string): any[] {
|
||||
const out = [];
|
||||
for (let iii = 0; iii < data.length; iii++) {
|
||||
const value = data[iii][key];
|
||||
for (let jjj = 0; jjj < value.length; jjj++)
|
||||
if (DataInterface.existIn(value[jjj], out) === false) {
|
||||
out.push(value[jjj]);
|
||||
}
|
||||
}
|
||||
return out;
|
||||
}
|
||||
constructor(private name: string, private bdd: NodeData[]) {}
|
||||
|
||||
public getTableIndex(id: number) {
|
||||
for (let iii = 0; iii < this.bdd.length; iii++) {
|
||||
if (this.bdd[iii].id === id) {
|
||||
return iii;
|
||||
}
|
||||
}
|
||||
return undefined;
|
||||
}
|
||||
|
||||
public gets(): NodeData[] {
|
||||
console.log(`[I] gets ${this.name}`);
|
||||
return this.bdd;
|
||||
}
|
||||
|
||||
public getsWhere(select: SelectModel[], orderBy?: string[]): NodeData[] {
|
||||
// console.log("[I] gets_where " + this.name + " select " + _select);
|
||||
let tmpList = this.getSubList(this.bdd, select);
|
||||
tmpList = this.orderBy(tmpList, orderBy);
|
||||
return tmpList;
|
||||
}
|
||||
|
||||
public get(id: number): NodeData {
|
||||
// console.log("[I] get " + this.name + " " + _id);
|
||||
for (let iii = 0; iii < this.bdd.length; iii++) {
|
||||
if (this.bdd[iii].id === id) {
|
||||
return this.bdd[iii];
|
||||
}
|
||||
}
|
||||
console.log(`[W] not found element{ ${this.bdd.length}`);
|
||||
return undefined;
|
||||
}
|
||||
|
||||
public getNameLikeAll(name: string): NodeData[] {
|
||||
let out = undefined;
|
||||
let nameLower = name.toLowerCase();
|
||||
for (let iii = 0; iii < this.bdd.length; iii++) {
|
||||
if (this.bdd[iii].name.toLowerCase() === nameLower) {
|
||||
out.push(this.bdd[iii]);
|
||||
}
|
||||
}
|
||||
if (out.length === 0) {
|
||||
return undefined;
|
||||
}
|
||||
return out;
|
||||
}
|
||||
public getNameLike(name: string): NodeData[] {
|
||||
let out = [];
|
||||
let nameLower = name.toLowerCase();
|
||||
for (let iii = 0; iii < this.bdd.length; iii++) {
|
||||
// console.log("compare '" + _name + "' ??? '" + this.bdd[iii]['name'] + "'");
|
||||
if (this.bdd[iii].name.toLowerCase() === nameLower) {
|
||||
out.push(this.bdd[iii]);
|
||||
}
|
||||
}
|
||||
return out;
|
||||
}
|
||||
|
||||
public set(id: number, value: NodeData): void {
|
||||
console.log(`[I] Set ${this.name} ${id}`);
|
||||
for (let iii = 0; iii < this.bdd.length; iii++) {
|
||||
console.log(` check: ${this.bdd[iii].id}`);
|
||||
if (this.bdd[iii].id === id) {
|
||||
console.log(` *** Set specific values: ${id} ${JSON.stringify(value, null, 2)}`);
|
||||
this.bdd[iii] = value;
|
||||
}
|
||||
}
|
||||
}
|
||||
public add(value: NodeData): void {
|
||||
console.log(`[I] Set ${this.name}`);
|
||||
this.bdd.push(value);
|
||||
}
|
||||
|
||||
public delete(id: number): void {
|
||||
console.log(`[I] delete ${this.name} ${id}`);
|
||||
for (let iii = 0; iii < this.bdd.length; iii++) {
|
||||
if (this.bdd[iii].id === id) {
|
||||
this.bdd.splice(iii, 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public find(listToken, values): NodeData[] {
|
||||
let out = [];
|
||||
for (let iii = 0; iii < this.bdd.length; iii++) {
|
||||
let find = true;
|
||||
for (let jjj = 0; jjj < listToken.length; jjj++) {
|
||||
if (this.bdd[iii][listToken[jjj]] !== values[listToken[jjj]]) {
|
||||
find = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (find === true) {
|
||||
out.push(this.bdd[iii]);
|
||||
}
|
||||
}
|
||||
return out;
|
||||
}
|
||||
|
||||
public count(select?: SelectModel[]) {
|
||||
if (isNullOrUndefined(select)) {
|
||||
return this.bdd.length;
|
||||
}
|
||||
let tmp = this.getSubList(this.bdd, select);
|
||||
return tmp.length;
|
||||
}
|
||||
|
||||
public static existIn(value, listValues: number | string | boolean | number[] | string[]): boolean {
|
||||
if (isArray(listValues)) {
|
||||
for (let iii = 0; iii < listValues.length; iii++) {
|
||||
if (value === listValues[iii]) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
return value === listValues;
|
||||
}
|
||||
public static containsOneIn(
|
||||
value: number | string | boolean | number[] | string[],
|
||||
listValues: number | string | boolean | number[] | string[]
|
||||
): boolean {
|
||||
if (isArray(value)) {
|
||||
for (let iii = 0; iii < value.length; iii++) {
|
||||
if (this.existIn(value[iii], listValues) === true) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
return this.existIn(value, listValues);
|
||||
}
|
||||
|
||||
public getSubList(values: NodeData[], select?: SelectModel[]): NodeData[] {
|
||||
let out = [] as NodeData[];
|
||||
for (let iiiElem = 0; iiiElem < values.length; iiiElem++) {
|
||||
let find = true;
|
||||
if (select.length === 0) {
|
||||
find = false;
|
||||
}
|
||||
//console.log("Check : " + JSON.stringify(values[iiiElem], null, 2));
|
||||
for (let iiiSelect = 0; iiiSelect < select.length; iiiSelect++) {
|
||||
let control = select[iiiSelect];
|
||||
let valueElement = values[iiiElem][control.key];
|
||||
//console.log(" valueElement : " + JSON.stringify(valueElement, null, 2));
|
||||
if (isArray(control.value)) {
|
||||
if (control.check === TypeCheck.CONTAINS) {
|
||||
//console.log("check contains ... " + valueElement + " contains one element in " + control.value);
|
||||
if (DataInterface.containsOneIn(valueElement, control.value) === false) {
|
||||
find = false;
|
||||
break;
|
||||
}
|
||||
} else if (control.check === TypeCheck.EQUAL) {
|
||||
//console.log("check Equals ... " + valueElement + " === " + control.value);
|
||||
if (DataInterface.existIn(valueElement, control.value) === false) {
|
||||
find = false;
|
||||
break;
|
||||
}
|
||||
} else if (control.check === TypeCheck.NOT_EQUAL) {
|
||||
if (DataInterface.existIn(valueElement, control.value) === false) {
|
||||
find = true;
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
console.log('[ERROR] Internal Server Error{ unknow comparing type ...');
|
||||
return undefined;
|
||||
}
|
||||
} else {
|
||||
//console.log(" [" + control.key + "] = " + valueElement);
|
||||
if (control.check === TypeCheck.CONTAINS) {
|
||||
//console.log("check Equals ... " + valueElement + " === " + control.value + " #2");
|
||||
if (DataInterface.containsOneIn(valueElement, control.value) === false) {
|
||||
find = false;
|
||||
break;
|
||||
}
|
||||
} else if (control.check === TypeCheck.EQUAL) {
|
||||
if (valueElement !== control.value) {
|
||||
find = false;
|
||||
break;
|
||||
}
|
||||
} else if (control.check === TypeCheck.NOT_EQUAL) {
|
||||
if (valueElement === control.value) {
|
||||
find = false;
|
||||
break;
|
||||
}
|
||||
} else if (control.check === TypeCheck.LESS) {
|
||||
if (valueElement >= control.value) {
|
||||
find = false;
|
||||
break;
|
||||
}
|
||||
} else if (control.check === TypeCheck.LESS_EQUAL) {
|
||||
if (valueElement > control.value) {
|
||||
find = false;
|
||||
break;
|
||||
}
|
||||
} else if (control.check === TypeCheck.GREATER) {
|
||||
if (valueElement <= control.value) {
|
||||
find = false;
|
||||
break;
|
||||
}
|
||||
} else if (control.check === TypeCheck.GREATER_EQUAL) {
|
||||
if (valueElement < control.value) {
|
||||
find = false;
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
console.log('[ERROR] Internal Server Error{ unknow comparing type ...');
|
||||
return undefined;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (find === true) {
|
||||
// console.log(" ==> SELECTED");
|
||||
out.push(values[iiiElem]);
|
||||
} else {
|
||||
// console.log(" ==> NOT SELECTED");
|
||||
}
|
||||
}
|
||||
return out;
|
||||
}
|
||||
|
||||
public orderBy(values: NodeData[], order: string[]): NodeData[] {
|
||||
if (isNullOrUndefined(order)) {
|
||||
return values;
|
||||
}
|
||||
if (order.length === 0) {
|
||||
return values;
|
||||
}
|
||||
let valueOrder = order[0];
|
||||
let out = [];
|
||||
let outUnclassable = [];
|
||||
for (let iii = 0; iii < values.length; iii++) {
|
||||
if (values[iii][valueOrder] === undefined) {
|
||||
outUnclassable.push(values[iii]);
|
||||
continue;
|
||||
}
|
||||
if (values[iii][valueOrder] === null) {
|
||||
outUnclassable.push(values[iii]);
|
||||
continue;
|
||||
}
|
||||
out.push(values[iii]);
|
||||
}
|
||||
// console.log("order in list by : " + value_order);
|
||||
// out = sorted(out, key=lambda x{ x[value_order])
|
||||
if (valueOrder === 'name') {
|
||||
out.sort((aaa, bbb) => {
|
||||
const name1 = aaa[valueOrder].toLowerCase();
|
||||
const name2 = bbb[valueOrder].toLowerCase();
|
||||
if (name1 > name2) {
|
||||
return 1;
|
||||
}
|
||||
if (name1 < name2) {
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
});
|
||||
} else {
|
||||
out.sort((aaa, bbb) => {
|
||||
if (aaa[valueOrder] > bbb[valueOrder]) {
|
||||
return 1;
|
||||
}
|
||||
if (aaa[valueOrder] < bbb[valueOrder]) {
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
});
|
||||
}
|
||||
if (order.length > 1) {
|
||||
outUnclassable = this.orderBy(outUnclassable, order.slice(1));
|
||||
}
|
||||
for (let jjj = 0; jjj < outUnclassable.length; jjj++) {
|
||||
out.push(outUnclassable[jjj]);
|
||||
}
|
||||
return out;
|
||||
}
|
||||
}
|
@ -1,51 +0,0 @@
|
||||
import { getApplicationLocation } from './applPath';
|
||||
import { DataInterface, TypeCheck } from './dataInterface';
|
||||
import { sha512 } from './sha512';
|
||||
import {
|
||||
isArray,
|
||||
isArrayOf,
|
||||
isBoolean,
|
||||
isNull,
|
||||
isNullOrUndefined,
|
||||
isNumber,
|
||||
isNumberFinite,
|
||||
isObject,
|
||||
isOptionalOf,
|
||||
isOptionalArrayOf,
|
||||
isString,
|
||||
isUndefined,
|
||||
isArrayOfs,
|
||||
isInArray,
|
||||
isStringNullOrUndefined,
|
||||
isNumeric,
|
||||
} from './validator';
|
||||
import { checkEmailValidity, checkLoginValidity, checkPasswordValidity, createLoginState, createPasswordState, getLoginType } from './validatorPasswordEmail';
|
||||
|
||||
export {
|
||||
isNumber,
|
||||
isNumberFinite,
|
||||
isBoolean,
|
||||
isString,
|
||||
isArray,
|
||||
isNull,
|
||||
isUndefined,
|
||||
isNullOrUndefined,
|
||||
isObject,
|
||||
isArrayOf,
|
||||
isArrayOfs,
|
||||
isOptionalOf,
|
||||
isOptionalArrayOf,
|
||||
isInArray,
|
||||
isStringNullOrUndefined,
|
||||
DataInterface,
|
||||
TypeCheck,
|
||||
getApplicationLocation,
|
||||
sha512,
|
||||
createPasswordState,
|
||||
checkEmailValidity,
|
||||
checkPasswordValidity,
|
||||
checkLoginValidity,
|
||||
getLoginType,
|
||||
createLoginState,
|
||||
isNumeric,
|
||||
};
|
@ -1,3 +0,0 @@
|
||||
export function isMobileAgent() {
|
||||
return /Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(navigator.userAgent);
|
||||
}
|
@ -1,342 +0,0 @@
|
||||
/*
|
||||
* Secure Hash Algorithm (SHA512)
|
||||
*/
|
||||
|
||||
export function sha512(str) {
|
||||
function int64(msint_32, lsint_32) {
|
||||
this.highOrder = msint_32;
|
||||
this.lowOrder = lsint_32;
|
||||
}
|
||||
|
||||
let H = [
|
||||
new int64(0x6a09e667, 0xf3bcc908),
|
||||
new int64(0xbb67ae85, 0x84caa73b),
|
||||
new int64(0x3c6ef372, 0xfe94f82b),
|
||||
new int64(0xa54ff53a, 0x5f1d36f1),
|
||||
new int64(0x510e527f, 0xade682d1),
|
||||
new int64(0x9b05688c, 0x2b3e6c1f),
|
||||
new int64(0x1f83d9ab, 0xfb41bd6b),
|
||||
new int64(0x5be0cd19, 0x137e2179),
|
||||
];
|
||||
|
||||
let K = [
|
||||
new int64(0x428a2f98, 0xd728ae22),
|
||||
new int64(0x71374491, 0x23ef65cd),
|
||||
new int64(0xb5c0fbcf, 0xec4d3b2f),
|
||||
new int64(0xe9b5dba5, 0x8189dbbc),
|
||||
new int64(0x3956c25b, 0xf348b538),
|
||||
new int64(0x59f111f1, 0xb605d019),
|
||||
new int64(0x923f82a4, 0xaf194f9b),
|
||||
new int64(0xab1c5ed5, 0xda6d8118),
|
||||
new int64(0xd807aa98, 0xa3030242),
|
||||
new int64(0x12835b01, 0x45706fbe),
|
||||
new int64(0x243185be, 0x4ee4b28c),
|
||||
new int64(0x550c7dc3, 0xd5ffb4e2),
|
||||
new int64(0x72be5d74, 0xf27b896f),
|
||||
new int64(0x80deb1fe, 0x3b1696b1),
|
||||
new int64(0x9bdc06a7, 0x25c71235),
|
||||
new int64(0xc19bf174, 0xcf692694),
|
||||
new int64(0xe49b69c1, 0x9ef14ad2),
|
||||
new int64(0xefbe4786, 0x384f25e3),
|
||||
new int64(0x0fc19dc6, 0x8b8cd5b5),
|
||||
new int64(0x240ca1cc, 0x77ac9c65),
|
||||
new int64(0x2de92c6f, 0x592b0275),
|
||||
new int64(0x4a7484aa, 0x6ea6e483),
|
||||
new int64(0x5cb0a9dc, 0xbd41fbd4),
|
||||
new int64(0x76f988da, 0x831153b5),
|
||||
new int64(0x983e5152, 0xee66dfab),
|
||||
new int64(0xa831c66d, 0x2db43210),
|
||||
new int64(0xb00327c8, 0x98fb213f),
|
||||
new int64(0xbf597fc7, 0xbeef0ee4),
|
||||
new int64(0xc6e00bf3, 0x3da88fc2),
|
||||
new int64(0xd5a79147, 0x930aa725),
|
||||
new int64(0x06ca6351, 0xe003826f),
|
||||
new int64(0x14292967, 0x0a0e6e70),
|
||||
new int64(0x27b70a85, 0x46d22ffc),
|
||||
new int64(0x2e1b2138, 0x5c26c926),
|
||||
new int64(0x4d2c6dfc, 0x5ac42aed),
|
||||
new int64(0x53380d13, 0x9d95b3df),
|
||||
new int64(0x650a7354, 0x8baf63de),
|
||||
new int64(0x766a0abb, 0x3c77b2a8),
|
||||
new int64(0x81c2c92e, 0x47edaee6),
|
||||
new int64(0x92722c85, 0x1482353b),
|
||||
new int64(0xa2bfe8a1, 0x4cf10364),
|
||||
new int64(0xa81a664b, 0xbc423001),
|
||||
new int64(0xc24b8b70, 0xd0f89791),
|
||||
new int64(0xc76c51a3, 0x0654be30),
|
||||
new int64(0xd192e819, 0xd6ef5218),
|
||||
new int64(0xd6990624, 0x5565a910),
|
||||
new int64(0xf40e3585, 0x5771202a),
|
||||
new int64(0x106aa070, 0x32bbd1b8),
|
||||
new int64(0x19a4c116, 0xb8d2d0c8),
|
||||
new int64(0x1e376c08, 0x5141ab53),
|
||||
new int64(0x2748774c, 0xdf8eeb99),
|
||||
new int64(0x34b0bcb5, 0xe19b48a8),
|
||||
new int64(0x391c0cb3, 0xc5c95a63),
|
||||
new int64(0x4ed8aa4a, 0xe3418acb),
|
||||
new int64(0x5b9cca4f, 0x7763e373),
|
||||
new int64(0x682e6ff3, 0xd6b2b8a3),
|
||||
new int64(0x748f82ee, 0x5defb2fc),
|
||||
new int64(0x78a5636f, 0x43172f60),
|
||||
new int64(0x84c87814, 0xa1f0ab72),
|
||||
new int64(0x8cc70208, 0x1a6439ec),
|
||||
new int64(0x90befffa, 0x23631e28),
|
||||
new int64(0xa4506ceb, 0xde82bde9),
|
||||
new int64(0xbef9a3f7, 0xb2c67915),
|
||||
new int64(0xc67178f2, 0xe372532b),
|
||||
new int64(0xca273ece, 0xea26619c),
|
||||
new int64(0xd186b8c7, 0x21c0c207),
|
||||
new int64(0xeada7dd6, 0xcde0eb1e),
|
||||
new int64(0xf57d4f7f, 0xee6ed178),
|
||||
new int64(0x06f067aa, 0x72176fba),
|
||||
new int64(0x0a637dc5, 0xa2c898a6),
|
||||
new int64(0x113f9804, 0xbef90dae),
|
||||
new int64(0x1b710b35, 0x131c471b),
|
||||
new int64(0x28db77f5, 0x23047d84),
|
||||
new int64(0x32caab7b, 0x40c72493),
|
||||
new int64(0x3c9ebe0a, 0x15c9bebc),
|
||||
new int64(0x431d67c4, 0x9c100d4c),
|
||||
new int64(0x4cc5d4be, 0xcb3e42b6),
|
||||
new int64(0x597f299c, 0xfc657e2a),
|
||||
new int64(0x5fcb6fab, 0x3ad6faec),
|
||||
new int64(0x6c44198c, 0x4a475817),
|
||||
];
|
||||
|
||||
let W = new Array(64);
|
||||
let a, b, c, d, e, f, g, h, i, j;
|
||||
let T1, T2;
|
||||
let charsize = 8;
|
||||
|
||||
function utf8_encode(str) {
|
||||
return unescape(encodeURIComponent(str));
|
||||
}
|
||||
|
||||
function str2binb(str) {
|
||||
let bin = [];
|
||||
let mask = (1 << charsize) - 1;
|
||||
let len = str.length * charsize;
|
||||
|
||||
for (let i = 0; i < len; i += charsize) {
|
||||
bin[i >> 5] |= (str.charCodeAt(i / charsize) & mask) << (32 - charsize - (i % 32));
|
||||
}
|
||||
|
||||
return bin;
|
||||
}
|
||||
|
||||
function binb2hex(binarray) {
|
||||
let hex_tab = '0123456789abcdef';
|
||||
let str = '';
|
||||
let length = binarray.length * 4;
|
||||
let srcByte;
|
||||
|
||||
for (let i = 0; i < length; i += 1) {
|
||||
srcByte = binarray[i >> 2] >> ((3 - (i % 4)) * 8);
|
||||
str += hex_tab.charAt((srcByte >> 4) & 0xf) + hex_tab.charAt(srcByte & 0xf);
|
||||
}
|
||||
|
||||
return str;
|
||||
}
|
||||
|
||||
function safe_add_2(x, y) {
|
||||
let lsw, msw, lowOrder, highOrder;
|
||||
|
||||
lsw = (x.lowOrder & 0xffff) + (y.lowOrder & 0xffff);
|
||||
msw = (x.lowOrder >>> 16) + (y.lowOrder >>> 16) + (lsw >>> 16);
|
||||
lowOrder = ((msw & 0xffff) << 16) | (lsw & 0xffff);
|
||||
|
||||
lsw = (x.highOrder & 0xffff) + (y.highOrder & 0xffff) + (msw >>> 16);
|
||||
msw = (x.highOrder >>> 16) + (y.highOrder >>> 16) + (lsw >>> 16);
|
||||
highOrder = ((msw & 0xffff) << 16) | (lsw & 0xffff);
|
||||
|
||||
return new int64(highOrder, lowOrder);
|
||||
}
|
||||
|
||||
function safe_add_4(a, b, c, d) {
|
||||
let lsw, msw, lowOrder, highOrder;
|
||||
|
||||
lsw = (a.lowOrder & 0xffff) + (b.lowOrder & 0xffff) + (c.lowOrder & 0xffff) + (d.lowOrder & 0xffff);
|
||||
msw = (a.lowOrder >>> 16) + (b.lowOrder >>> 16) + (c.lowOrder >>> 16) + (d.lowOrder >>> 16) + (lsw >>> 16);
|
||||
lowOrder = ((msw & 0xffff) << 16) | (lsw & 0xffff);
|
||||
|
||||
lsw =
|
||||
(a.highOrder & 0xffff) +
|
||||
(b.highOrder & 0xffff) +
|
||||
(c.highOrder & 0xffff) +
|
||||
(d.highOrder & 0xffff) +
|
||||
(msw >>> 16);
|
||||
msw = (a.highOrder >>> 16) + (b.highOrder >>> 16) + (c.highOrder >>> 16) + (d.highOrder >>> 16) + (lsw >>> 16);
|
||||
highOrder = ((msw & 0xffff) << 16) | (lsw & 0xffff);
|
||||
|
||||
return new int64(highOrder, lowOrder);
|
||||
}
|
||||
|
||||
function safe_add_5(a, b, c, d, e) {
|
||||
let lsw, msw, lowOrder, highOrder;
|
||||
|
||||
lsw =
|
||||
(a.lowOrder & 0xffff) +
|
||||
(b.lowOrder & 0xffff) +
|
||||
(c.lowOrder & 0xffff) +
|
||||
(d.lowOrder & 0xffff) +
|
||||
(e.lowOrder & 0xffff);
|
||||
msw =
|
||||
(a.lowOrder >>> 16) +
|
||||
(b.lowOrder >>> 16) +
|
||||
(c.lowOrder >>> 16) +
|
||||
(d.lowOrder >>> 16) +
|
||||
(e.lowOrder >>> 16) +
|
||||
(lsw >>> 16);
|
||||
lowOrder = ((msw & 0xffff) << 16) | (lsw & 0xffff);
|
||||
|
||||
lsw =
|
||||
(a.highOrder & 0xffff) +
|
||||
(b.highOrder & 0xffff) +
|
||||
(c.highOrder & 0xffff) +
|
||||
(d.highOrder & 0xffff) +
|
||||
(e.highOrder & 0xffff) +
|
||||
(msw >>> 16);
|
||||
msw =
|
||||
(a.highOrder >>> 16) +
|
||||
(b.highOrder >>> 16) +
|
||||
(c.highOrder >>> 16) +
|
||||
(d.highOrder >>> 16) +
|
||||
(e.highOrder >>> 16) +
|
||||
(lsw >>> 16);
|
||||
highOrder = ((msw & 0xffff) << 16) | (lsw & 0xffff);
|
||||
|
||||
return new int64(highOrder, lowOrder);
|
||||
}
|
||||
|
||||
function maj(x, y, z) {
|
||||
return new int64(
|
||||
(x.highOrder & y.highOrder) ^ (x.highOrder & z.highOrder) ^ (y.highOrder & z.highOrder),
|
||||
(x.lowOrder & y.lowOrder) ^ (x.lowOrder & z.lowOrder) ^ (y.lowOrder & z.lowOrder)
|
||||
);
|
||||
}
|
||||
|
||||
function ch(x, y, z) {
|
||||
return new int64(
|
||||
(x.highOrder & y.highOrder) ^ (~x.highOrder & z.highOrder),
|
||||
(x.lowOrder & y.lowOrder) ^ (~x.lowOrder & z.lowOrder)
|
||||
);
|
||||
}
|
||||
|
||||
function rotr(x, n) {
|
||||
if (n <= 32) {
|
||||
return new int64(
|
||||
(x.highOrder >>> n) | (x.lowOrder << (32 - n)),
|
||||
(x.lowOrder >>> n) | (x.highOrder << (32 - n))
|
||||
);
|
||||
} else {
|
||||
return new int64(
|
||||
(x.lowOrder >>> n) | (x.highOrder << (32 - n)),
|
||||
(x.highOrder >>> n) | (x.lowOrder << (32 - n))
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
function sigma0(x) {
|
||||
let rotr28 = rotr(x, 28);
|
||||
let rotr34 = rotr(x, 34);
|
||||
let rotr39 = rotr(x, 39);
|
||||
|
||||
return new int64(
|
||||
rotr28.highOrder ^ rotr34.highOrder ^ rotr39.highOrder,
|
||||
rotr28.lowOrder ^ rotr34.lowOrder ^ rotr39.lowOrder
|
||||
);
|
||||
}
|
||||
|
||||
function sigma1(x) {
|
||||
let rotr14 = rotr(x, 14);
|
||||
let rotr18 = rotr(x, 18);
|
||||
let rotr41 = rotr(x, 41);
|
||||
|
||||
return new int64(
|
||||
rotr14.highOrder ^ rotr18.highOrder ^ rotr41.highOrder,
|
||||
rotr14.lowOrder ^ rotr18.lowOrder ^ rotr41.lowOrder
|
||||
);
|
||||
}
|
||||
|
||||
function gamma0(x) {
|
||||
let rotr1 = rotr(x, 1),
|
||||
rotr8 = rotr(x, 8),
|
||||
shr7 = shr(x, 7);
|
||||
|
||||
return new int64(
|
||||
rotr1.highOrder ^ rotr8.highOrder ^ shr7.highOrder,
|
||||
rotr1.lowOrder ^ rotr8.lowOrder ^ shr7.lowOrder
|
||||
);
|
||||
}
|
||||
|
||||
function gamma1(x) {
|
||||
let rotr19 = rotr(x, 19);
|
||||
let rotr61 = rotr(x, 61);
|
||||
let shr6 = shr(x, 6);
|
||||
|
||||
return new int64(
|
||||
rotr19.highOrder ^ rotr61.highOrder ^ shr6.highOrder,
|
||||
rotr19.lowOrder ^ rotr61.lowOrder ^ shr6.lowOrder
|
||||
);
|
||||
}
|
||||
|
||||
function shr(x, n) {
|
||||
if (n <= 32) {
|
||||
return new int64(x.highOrder >>> n, (x.lowOrder >>> n) | (x.highOrder << (32 - n)));
|
||||
} else {
|
||||
return new int64(0, x.highOrder << (32 - n));
|
||||
}
|
||||
}
|
||||
|
||||
str = utf8_encode(str);
|
||||
let strlen = str.length * charsize;
|
||||
str = str2binb(str);
|
||||
|
||||
str[strlen >> 5] |= 0x80 << (24 - (strlen % 32));
|
||||
str[(((strlen + 128) >> 10) << 5) + 31] = strlen;
|
||||
|
||||
for (let i = 0; i < str.length; i += 32) {
|
||||
a = H[0];
|
||||
b = H[1];
|
||||
c = H[2];
|
||||
d = H[3];
|
||||
e = H[4];
|
||||
f = H[5];
|
||||
g = H[6];
|
||||
h = H[7];
|
||||
|
||||
for (let j = 0; j < 80; j++) {
|
||||
if (j < 16) {
|
||||
W[j] = new int64(str[j * 2 + i], str[j * 2 + i + 1]);
|
||||
} else {
|
||||
W[j] = safe_add_4(gamma1(W[j - 2]), W[j - 7], gamma0(W[j - 15]), W[j - 16]);
|
||||
}
|
||||
|
||||
T1 = safe_add_5(h, sigma1(e), ch(e, f, g), K[j], W[j]);
|
||||
T2 = safe_add_2(sigma0(a), maj(a, b, c));
|
||||
h = g;
|
||||
g = f;
|
||||
f = e;
|
||||
e = safe_add_2(d, T1);
|
||||
d = c;
|
||||
c = b;
|
||||
b = a;
|
||||
a = safe_add_2(T1, T2);
|
||||
}
|
||||
|
||||
H[0] = safe_add_2(a, H[0]);
|
||||
H[1] = safe_add_2(b, H[1]);
|
||||
H[2] = safe_add_2(c, H[2]);
|
||||
H[3] = safe_add_2(d, H[3]);
|
||||
H[4] = safe_add_2(e, H[4]);
|
||||
H[5] = safe_add_2(f, H[5]);
|
||||
H[6] = safe_add_2(g, H[6]);
|
||||
H[7] = safe_add_2(h, H[7]);
|
||||
}
|
||||
|
||||
let binarray = [];
|
||||
for (let i = 0; i < H.length; i++) {
|
||||
binarray.push(H[i].highOrder);
|
||||
binarray.push(H[i].lowOrder);
|
||||
}
|
||||
return binb2hex(binarray);
|
||||
}
|
@ -1,98 +0,0 @@
|
||||
|
||||
export function isNumeric(val: string): boolean {
|
||||
return !isNaN(Number(val));
|
||||
}
|
||||
|
||||
export function isNumber(data: any): data is number {
|
||||
return typeof data === 'number';
|
||||
}
|
||||
export function isNumberFinite(data: any): data is number {
|
||||
return isNumber(data) && isFinite(data);
|
||||
}
|
||||
export function isBoolean(data: any): data is boolean {
|
||||
return typeof data === 'boolean';
|
||||
}
|
||||
export function isString(data: any): data is string {
|
||||
return typeof data === 'string';
|
||||
}
|
||||
export function isArray(data: any): data is any[] {
|
||||
return Array.isArray(data);
|
||||
}
|
||||
export function isNull(data: any): data is null {
|
||||
return data === null;
|
||||
}
|
||||
export function isUndefined(data: any): data is undefined {
|
||||
return data === undefined;
|
||||
}
|
||||
export function isNullOrUndefined(data: any): data is undefined | null {
|
||||
return data === undefined || data === null;
|
||||
}
|
||||
export function isStringNullOrUndefined(data: any): data is undefined | null {
|
||||
return data === 'undefined' || data === 'null' || data === '';
|
||||
}
|
||||
export function isObject(data: any): data is any {
|
||||
return !isNullOrUndefined(data) && typeof data === 'object' && !isArray(data);
|
||||
}
|
||||
export function isInArray(data: any, listElment: any[]): boolean {
|
||||
for (let iii = 0; iii < listElment.length; iii++) {
|
||||
if (listElment[iii] === data) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
export function isArrayOf<TYPE>(
|
||||
data: any,
|
||||
typeChecker: (subData: any) => subData is TYPE,
|
||||
length?: number
|
||||
): data is TYPE[] {
|
||||
if (!isArray(data)) {
|
||||
return false;
|
||||
}
|
||||
if (!data.every(typeChecker)) {
|
||||
return false;
|
||||
}
|
||||
if (!isUndefined(length) && data.length != length) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
export function isArrayOfs<TYPE, TYPE2, TYPE3>(
|
||||
data: any,
|
||||
typeChecker: (subData: any) => subData is TYPE,
|
||||
typeChecker2?: (subData: any) => subData is TYPE2,
|
||||
typeChecker3?: (subData: any) => subData is TYPE3
|
||||
): data is (TYPE | TYPE2 | TYPE3)[] {
|
||||
if (!isArray(data)) {
|
||||
return false;
|
||||
}
|
||||
for (let iii = 0; iii < data.length; iii++) {
|
||||
let elem = data[iii];
|
||||
if (typeChecker(elem)) {
|
||||
continue;
|
||||
}
|
||||
if (typeChecker2 != undefined && typeChecker2(elem)) {
|
||||
continue;
|
||||
}
|
||||
if (typeChecker3 != undefined && typeChecker3(elem)) {
|
||||
continue;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
export function isOptionalOf<TYPE>(
|
||||
data: any,
|
||||
typeChecker: (subData: any) => subData is TYPE
|
||||
): data is TYPE | undefined {
|
||||
return isUndefined(data) || typeChecker(data);
|
||||
}
|
||||
|
||||
export function isOptionalArrayOf<TYPE>(
|
||||
data: any,
|
||||
typeChecker: (subData: any) => subData is TYPE
|
||||
): data is TYPE[] | undefined {
|
||||
return isUndefined(data) || isArrayOf(data, typeChecker);
|
||||
}
|
@ -1,146 +0,0 @@
|
||||
import { isNullOrUndefined } from "./validator";
|
||||
|
||||
/**
|
||||
* Test the specific regexp on a value
|
||||
* @param value Value to test.
|
||||
* @param expression Regexp epression to test on the value
|
||||
* @returns true if the regexp is validate, false otherwise
|
||||
*/
|
||||
export function testRegExp(value: string, expression: string): boolean {
|
||||
let regexCheck = new RegExp(expression);
|
||||
if (regexCheck.test(value)) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
/**
|
||||
* Check the value is well formated to be a login.
|
||||
* @param value login value to check.
|
||||
* @returns true if it is compatible with a login, false otherwise.
|
||||
*/
|
||||
export function checkLoginValidity(value: string): boolean {
|
||||
return testRegExp(value, '^[a-zA-Z0-9_\\.-]+$');
|
||||
}
|
||||
/**
|
||||
* Check the value is well formated to be an e-mail.
|
||||
* @param value email value to check.
|
||||
* @returns true if it is an email, false otherwise.
|
||||
*/
|
||||
export function checkEmailValidity(value: string): boolean {
|
||||
return testRegExp(value, '^[a-zA-Z0-9_\\.@-]+@[a-zA-Z0-9_\\.-]+\\.[a-zA-Z]+$');
|
||||
}
|
||||
/**
|
||||
* Check the value is well formated to be an Password.
|
||||
* @param value password value to check.
|
||||
* @returns true if it is compatible with a password, false otherwise.
|
||||
*/
|
||||
export function checkPasswordValidity(value: string): boolean {
|
||||
return testRegExp(value, '^[a-zA-Z0-9_\\.@ %:;,=}{\\?\\!\\*\\+\\(\\)\\[\\]\\|&#%~/\\\\\\<\\>\\-£€]+$');
|
||||
}
|
||||
/**
|
||||
* Check if the value contains one alphabetical lower case character
|
||||
* @param value String value to check.
|
||||
* @returns true if it contains one lower case character, false otherwise.
|
||||
*/
|
||||
export function check1LowerChar(value: string): boolean {
|
||||
return testRegExp(value, '(.*[a-z].*)');
|
||||
}
|
||||
/**
|
||||
* Check if the value contains one alphabetical upper case character
|
||||
* @param value String value to check.
|
||||
* @returns true if it contains one upper case character, false otherwise.
|
||||
*/
|
||||
export function check1UpperChar(value: string): boolean {
|
||||
return testRegExp(value, '(.*[A-Z].*)');
|
||||
}
|
||||
/**
|
||||
* Check if the value contains one numerical character
|
||||
* @param value String value to check.
|
||||
* @returns true if it contains minimum of one digit character, false otherwise.
|
||||
*/
|
||||
export function check1DigitChar(value: string): boolean {
|
||||
return testRegExp(value, '(.*[0-9].*)');
|
||||
}
|
||||
/**
|
||||
* Check if the value contains one special character
|
||||
* @param value String value to check.
|
||||
* @returns true if it contains minimum of one special character, false otherwise.
|
||||
*/
|
||||
export function check1SpecialChar(value: string): boolean {
|
||||
return testRegExp(value, '(.*[_\\.@ %:;,=}{\\?\\!\\*\\+\\(\\)\\[\\]\\|&#%~/\\\\\\<\\>\\-£€].*)');
|
||||
}
|
||||
/**
|
||||
* Creata a pasword state of a password. it return a readable string that explain why the password is wrong.
|
||||
* if check minimum size, at lease one digit, one upper case, one lower case and one special character.
|
||||
* @param value Pasword value to check.
|
||||
* @returns true if it is compatcable, false if the value is undefined or empty,or the descriptive error string (English).
|
||||
*/
|
||||
export function createPasswordState(value: string): boolean|string {
|
||||
let ret = createPasswordStateSimple(value);
|
||||
if (ret === true) {
|
||||
if (check1LowerChar(value) === false) {
|
||||
return 'Not valid: missing 1 lower case character [a-z]';
|
||||
}
|
||||
if (check1UpperChar(value) === false) {
|
||||
return 'Not valid: missing 1 upper case character [A-Z]';
|
||||
}
|
||||
if (check1DigitChar(value) === false) {
|
||||
return 'Not valid: missing 1 digit character [0-9]';
|
||||
}
|
||||
if (check1SpecialChar(value) === false) {
|
||||
return 'Not valid: missing 1 special character: _-:;.,?!*+=}{([|)]% @&~#/\\<>';
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}/**
|
||||
* Creata a pasword state of a password. it return a readable string that explain why the password is wrong.
|
||||
* It does not check if the email have specific less one char, it is dangerous for login interface.
|
||||
* @param value Pasword value to check.
|
||||
* @returns true if it is compatcable, false if the value is undefined or empty,or the descriptive error string (English).
|
||||
*/
|
||||
export function createPasswordStateSimple(value: string): boolean|string {
|
||||
if (isNullOrUndefined(value) || value === '') {
|
||||
return false;
|
||||
}
|
||||
if (value.length < 6) {
|
||||
return 'Need 6 characters';
|
||||
}
|
||||
if (checkPasswordValidity(value) === false) {
|
||||
return 'Not valid: characters, numbers and "_-:;.,?!*+=}{([|)]% @&~#/\\<>"';
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creata a login/email state. It return a readable string that explain why the login/email is wrong.
|
||||
* if check minimum size, or not an email.
|
||||
* @param value email/login value to check.
|
||||
* @returns true if it is compatcable, false if the value is undefined or empty,or the descriptive error string (English).
|
||||
*/
|
||||
export function createLoginState(value: string): boolean|string {
|
||||
if (isNullOrUndefined(value) || value === '') {
|
||||
return false;
|
||||
}
|
||||
if (value.length < 6) {
|
||||
return 'Need 6 characters';
|
||||
}
|
||||
if (checkLoginValidity(value) === true) {
|
||||
return true;
|
||||
} else if (checkEmailValidity(value) === true) {
|
||||
return true;
|
||||
} else {
|
||||
return 'Not valid: characters, numbers, "_-." and email format: you@example.com';
|
||||
}
|
||||
}
|
||||
|
||||
export function getLoginType(value: string): string {
|
||||
if (isNullOrUndefined(value) || value.length <6 ) {
|
||||
return 'Username/E-mail';
|
||||
}
|
||||
if (checkLoginValidity(value) === true) {
|
||||
return 'Username';
|
||||
} else if (checkEmailValidity(value) === true) {
|
||||
return 'E-mail';
|
||||
}
|
||||
return 'Username/E-mail';
|
||||
}
|
Loading…
Reference in New Issue
Block a user