[DEV] remove cmmon

This commit is contained in:
Edouard DUPIN 2023-06-18 16:12:06 +02:00
parent 93f0915574
commit d7112e0208
90 changed files with 0 additions and 5038 deletions

View File

@ -1,3 +0,0 @@
<div>
<img height="50px" [src]="getImage()"/>
</div>

View File

@ -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);
}));
});

View File

@ -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';
}
}
}

View File

@ -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>

View File

@ -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;
}

View File

@ -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() {}
}

View File

@ -1,7 +0,0 @@
<div class="elem-checkbox">
<input
type="checkbox"
[checked]="value"
(change)="onChange($event.target.checked)" />
{{comment}}
</div>

View File

@ -1,6 +0,0 @@
.elem-checkbox {
font-size: 18px;
font-weight: bold;
margin: 0 10px 0 10px;
}

View File

@ -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);
}
}

View File

@ -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>

View File

@ -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;
}
}

View File

@ -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);
}
}

View File

@ -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>

View File

@ -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;
}

View File

@ -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,
});
}
}

View File

@ -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>

View File

@ -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;
}

View File

@ -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);
}));
});

View File

@ -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);
}
}

View File

@ -1 +0,0 @@
<div class="error color-shadow-black" *ngIf="value !== true && value !== false && value !== undefined">{{value}}</div>

View File

@ -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;
}
}

View File

@ -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;
}

View File

@ -1 +0,0 @@
<p>error works!</p>

View File

@ -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() {}
}

View File

@ -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 };

View File

@ -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>

View File

@ -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;
}

View File

@ -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);
}));
});

View File

@ -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);
}
}

View File

@ -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>

View File

@ -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;
}
}

View File

@ -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']);
}
}

View File

@ -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>

View File

@ -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 {
}

View File

@ -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>

View File

@ -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%;
}
}
}

View File

@ -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);
}
}
}

View File

@ -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 {
}

View File

@ -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>

View File

@ -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;
}
}
}

View File

@ -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;
}
}

View File

@ -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>

View File

@ -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;
}

View File

@ -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);
}
}

View File

@ -1,4 +0,0 @@
import { isMenuItem, isMenuPosition, MenuItem, MenuPosition } from './menu-item';
import { NodeData, isNodeData } from './node';
export { NodeData, isNodeData, MenuPosition, isMenuPosition, MenuItem, isMenuItem };

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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>

View File

@ -1,13 +0,0 @@
.expand {
width: 100%;
input {
width: 100%;
}
div {
width: 100%;
}
textarea {
width: 100%;
}
text-align: center;
}

View File

@ -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);
}
}
}

View File

@ -1,4 +0,0 @@
import { PopInDeleteConfirm } from './delete-confirm/delete-confirm';
import { PopInUploadProgress } from './upload-progress/upload-progress';
export { PopInDeleteConfirm, PopInUploadProgress };

View File

@ -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}}%">&nbsp;&nbsp;&nbsp;{{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>

View File

@ -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;
}

View File

@ -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;
}
}

View File

@ -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>

View File

@ -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;
}

View File

@ -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() {}
}

View File

@ -1 +0,0 @@
<p>error-viewer works!</p>

View File

@ -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() {}
}

View File

@ -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>

View File

@ -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;
}

View File

@ -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() {}
}

View File

@ -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>

View File

@ -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;
}

View File

@ -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() {}
}

View File

@ -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 };

View File

@ -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>

View File

@ -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);
}

View File

@ -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();
}
}
}

View File

@ -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 });
});
}
}

View File

@ -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 '';
}
}

View File

@ -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 });
});
});
}
}

View File

@ -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,
};

View File

@ -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;
}
}

View File

@ -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}`)
}
}

View File

@ -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;
}
}
}
}

View File

@ -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;
}
}
}

View File

@ -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);
});
}
}

View File

@ -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;
}
}

View File

@ -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;
}

View File

@ -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;
}
}

View File

@ -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,
};

View File

@ -1,3 +0,0 @@
export function isMobileAgent() {
return /Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(navigator.userAgent);
}

View File

@ -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);
}

View File

@ -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);
}

View File

@ -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';
}