[DEV] update new archodata and karso update

This commit is contained in:
Edouard DUPIN 2023-05-28 18:52:22 +02:00
parent b5ce560c88
commit 78663ed522
99 changed files with 3016 additions and 1426 deletions

View File

@ -20,7 +20,7 @@
<dependency>
<groupId>kangaroo-and-rabbit</groupId>
<artifactId>archidata</artifactId>
<version>0.3.3</version>
<version>0.3.7</version>
</dependency>
</dependencies>

View File

@ -6,10 +6,15 @@ import org.glassfish.jersey.grizzly2.httpserver.GrizzlyHttpServerFactory;
import org.glassfish.jersey.media.multipart.MultiPartFeature;
import org.glassfish.jersey.server.ResourceConfig;
import org.kar.karideo.api.*;
import org.kar.karideo.filter.KarideoAuthenticationFilter;
import org.kar.karideo.migration.Initialization;
import org.kar.karideo.model.Media;
import org.kar.karideo.model.Season;
import org.kar.karideo.model.Series;
import org.kar.karideo.model.Type;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.kar.archidata.GlobalConfiguration;
import org.kar.archidata.SqlWrapper;
import org.kar.archidata.UpdateJwtPublicKey;
import org.kar.archidata.api.DataResource;
@ -18,9 +23,9 @@ import org.kar.archidata.catcher.FailExceptionCatcher;
import org.kar.archidata.catcher.InputExceptionCatcher;
import org.kar.archidata.catcher.SystemExceptionCatcher;
import org.kar.archidata.db.DBConfig;
import org.kar.archidata.filter.AuthenticationFilter;
import org.kar.archidata.filter.CORSFilter;
import org.kar.archidata.filter.OptionFilter;
import org.kar.archidata.migration.MigrationEngine;
import org.kar.archidata.model.Data;
import org.kar.archidata.model.User;
import org.kar.archidata.util.ConfigBaseVariable;
@ -30,59 +35,68 @@ import jakarta.ws.rs.core.UriBuilder;
import java.net.URI;
public class WebLauncher {
final static Logger LOGGER = LoggerFactory.getLogger(WebLauncher.class);
public static DBConfig dbConfig;
private WebLauncher() {
public WebLauncher() {
ConfigBaseVariable.bdDatabase = "karideo";
}
private static URI getBaseURI() {
return UriBuilder.fromUri(ConfigBaseVariable.getlocalAddress()).build();
}
public static void main(String[] args) {
ConfigBaseVariable.bdDatabase = "karideo";
try {
String out = "";
out += SqlWrapper.createTable(Data.class);
out += SqlWrapper.createTable(Media.class);
out += SqlWrapper.createTable(Type.class);
out += SqlWrapper.createTable(Series.class);
out += SqlWrapper.createTable(Season.class);
out += SqlWrapper.createTable(User.class);
System.out.println(out);
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
public void migrateDB() throws Exception {
WebLauncher.LOGGER.info("Create migration engine");
MigrationEngine migrationEngine = new MigrationEngine();
WebLauncher.LOGGER.info("Add initialization");
migrationEngine.setInit(new Initialization());
WebLauncher.LOGGER.info("Migrate the DB [START]");
migrationEngine.migrate(GlobalConfiguration.dbConfig);
WebLauncher.LOGGER.info("Migrate the DB [STOP]");
}
public static void main(String[] args) throws Exception {
WebLauncher.LOGGER.info("[START] application wake UP");
WebLauncher launcher = new WebLauncher();
launcher.migrateDB();
launcher.process();
WebLauncher.LOGGER.info("end-configure the server & wait finish process:");
Thread.currentThread().join();
WebLauncher.LOGGER.info("STOP the REST server:");
}
public void process() throws InterruptedException {
// ===================================================================
// Configure resources
// ===================================================================
ResourceConfig rc = new ResourceConfig();
// add multi-part models ..
rc.register(new MultiPartFeature());
rc.register(MultiPartFeature.class);
// global authentication system
rc.register(new OptionFilter());
rc.register(OptionFilter.class);
// remove cors ==> all time called by an other system...
rc.register(new CORSFilter());
rc.register(CORSFilter.class);
// global authentication system
rc.registerClasses(AuthenticationFilter.class);
rc.register(KarideoAuthenticationFilter.class);
// register exception catcher
rc.register(InputExceptionCatcher.class);
rc.register(SystemExceptionCatcher.class);
rc.register(FailExceptionCatcher.class);
rc.register(ExceptionCatcher.class);
// add default resource:
rc.registerClasses(UserResource.class);
rc.registerClasses(SeriesResource.class);
rc.registerClasses(DataResource.class);
rc.registerClasses(SeasonResource.class);
rc.registerClasses(TypeResource.class);
rc.registerClasses(VideoResource.class);
rc.register(UserResource.class);
rc.register(SeriesResource.class);
rc.register(DataResource.class);
rc.register(SeasonResource.class);
rc.register(TypeResource.class);
rc.register(VideoResource.class);
rc.registerClasses(HealthCheck.class);
rc.registerClasses(Front.class);
rc.register(HealthCheck.class);
rc.register(Front.class);
// add jackson to be discover when we are ins stand-alone server
rc.register(JacksonFeature.class);

View File

@ -2,15 +2,37 @@
package org.kar.karideo;
import org.kar.archidata.util.ConfigBaseVariable;
import org.slf4j.LoggerFactory;
import org.slf4j.Logger;
public class WebLauncherLocal {
public class WebLauncherLocal extends WebLauncher {
final Logger logger = LoggerFactory.getLogger(WebLauncherLocal.class);
private WebLauncherLocal() {}
public static void main(String[] args) throws InterruptedException {
WebLauncherLocal launcher = new WebLauncherLocal();
launcher.process();
launcher.logger.info("end-configure the server & wait finish process:");
Thread.currentThread().join();
launcher.logger.info("STOP the REST server:");
}
@Override
public void process() throws InterruptedException {
if (true) {
// for local test:
ConfigBaseVariable.apiAdress = "http://0.0.0.0:18080/karideo/api/";
}
WebLauncher.main(args);
try {
super.migrateDB();
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
while (true) {
logger.error("Migration fail ==> waiting intervention of administrator...");
Thread.sleep(60*60*1000);
}
}
super.process();
}
}

View File

@ -5,18 +5,34 @@ import org.kar.archidata.filter.GenericContext;
import org.kar.archidata.model.User;
import org.kar.karideo.model.UserKarideo;
import com.fasterxml.jackson.annotation.JsonInclude;
import org.kar.archidata.annotation.security.RolesAllowed;
import jakarta.ws.rs.*;
import jakarta.ws.rs.core.Context;
import jakarta.ws.rs.core.MediaType;
import jakarta.ws.rs.core.SecurityContext;
import java.util.List;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@Path("/users")
@Produces({MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON})
public class UserResource {
final Logger logger = LoggerFactory.getLogger(UserResource.class);
@JsonInclude(JsonInclude.Include.NON_NULL)
public class UserOut {
public long id;
public String login;
public UserOut(long id, String login) {
super();
this.id = id;
this.login = login;
}
}
public UserResource() {
}
@ -42,7 +58,7 @@ public class UserResource {
System.out.println("getUser " + userId);
GenericContext gc = (GenericContext) sc.getUserPrincipal();
System.out.println("===================================================");
System.out.println("== USER ? " + gc.user);
System.out.println("== USER ? " + gc.userByToken.name);
System.out.println("===================================================");
try {
return SqlWrapper.get(UserKarideo.class, userId);
@ -53,17 +69,14 @@ public class UserResource {
return null;
}
// curl http://localhost:9993/api/users/3
@GET
@Path("me")
@RolesAllowed("USER")
public User getMe(@Context SecurityContext sc) {
System.out.println("getMe()");
public UserOut getMe(@Context SecurityContext sc) {
logger.debug("getMe()");
GenericContext gc = (GenericContext) sc.getUserPrincipal();
System.out.println("===================================================");
System.out.println("== USER ? " + gc.user);
System.out.println("===================================================");
return gc.user;
logger.debug("== USER ? {}", gc.userByToken);
return new UserOut(gc.userByToken.id, gc.userByToken.name);
}
}

View File

@ -0,0 +1,23 @@
package org.kar.karideo.filter;
import org.kar.archidata.filter.AuthenticationFilter;
import jakarta.ws.rs.Priorities;
import jakarta.ws.rs.ext.Provider;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import jakarta.annotation.Priority;
//@PreMatching
@Provider
@Priority(Priorities.AUTHENTICATION)
public class KarideoAuthenticationFilter extends AuthenticationFilter {
final Logger logger = LoggerFactory.getLogger(KarideoAuthenticationFilter.class);
public KarideoAuthenticationFilter() {
super("karideo");
}
}

View File

@ -0,0 +1,59 @@
package org.kar.karideo.migration;
import org.kar.archidata.migration.MigrationSqlStep;
import org.kar.archidata.model.Data;
import org.kar.archidata.model.User;
import org.kar.karideo.model.Media;
import org.kar.karideo.model.Season;
import org.kar.karideo.model.Series;
import org.kar.karideo.model.Type;
public class Initialization extends MigrationSqlStep {
public static final int KARSO_INITIALISATION_ID = 1;
@Override
public String getName() {
return "Initialization";
}
public Initialization() throws Exception {
addClass(Data.class);
addClass(Media.class);
addClass(Type.class);
addClass(Series.class);
addClass(Season.class);
addClass(User.class);
addAction("""
INSERT INTO `type` (`id`, `name`, `description`) VALUES
(1, 'Documentary', 'Documentary (animals, space, earth...)'),
(2, 'Movie', 'Movie with real humans (film)'),
(3, 'Animation', 'Animation movies (film)'),
(4, 'Short movie', 'Small movies (less 2 minutes)'),
(5, 'TV show', 'TV show for old peoples'),
(6, 'Animation TV show', 'TV show for young peoples'),
(7, 'Theater', 'Theater play'),
(8, 'One man show', 'Recorded stand up'),
(9, 'Concert', 'Recorded concert'),
(10, 'Opera', 'Recorded opera');
""");
// set start increment element to permit to add after default elements
addAction("""
ALTER TABLE `data` AUTO_INCREMENT = 1000;
""");
addAction("""
ALTER TABLE `media` AUTO_INCREMENT = 1000;
""");
addAction("""
ALTER TABLE `type` AUTO_INCREMENT = 1000;
""");
addAction("""
ALTER TABLE `series` AUTO_INCREMENT = 1000;
""");
addAction("""
ALTER TABLE `season` AUTO_INCREMENT = 1000;
""");
}
}

View File

@ -1,7 +1,7 @@
{
"name": "karideo",
"version": "0.0.0",
"license": "MIT",
"license": "MPL-2",
"scripts": {
"all": "npm run build && npm run test",
"ng": "ng",
@ -9,6 +9,7 @@
"build": "ng build --prod",
"test": "ng test",
"lint": "ng lint",
"style": "prettier --write .",
"e2e": "ng e2e"
},
"private": true,

View File

@ -10,6 +10,7 @@ import { MenuItem, MenuPosition } from 'common/model';
import { UserService, SessionService, SSOService } from 'common/service';
import { isNullOrUndefined } from 'common/utils';
import { ArianeService } from './service';
import { UserRoles222 } from 'common/service/session';
enum MenuEventType {
SSO_LOGIN = "SSO_CALL_LOGIN",
@ -51,7 +52,7 @@ export class AppComponent implements OnInit {
this.updateMainMenu();
let self = this;
this.sessionService.change.subscribe((isConnected) => {
console.log(`receive event from session ...${ isConnected}`);
console.log(`receive event from session ...${isConnected}`);
self.isConnected = isConnected;
self.autoConnectedDone = true;
self.updateMainMenu();
@ -95,7 +96,7 @@ export class AppComponent implements OnInit {
eventOnMenu(data: EventOnMenu): void {
//console.log(`plopppppppppp ${JSON.stringify(this.route.snapshot.url)}`);
//console.log(`Get event on menu: ${JSON.stringify(data, null, 4)}`);
switch(data.menu.otherData) {
switch (data.menu.otherData) {
case MenuEventType.SSO_LOGIN:
this.ssoService.requestSignIn();
break;
@ -180,7 +181,7 @@ export class AppComponent implements OnInit {
icon: "add_circle",
title: "Add media",
navigateTo: "upload",
enable: this.sessionService.userAdmin === true,
enable: this.sessionService.hasRight(UserRoles222.admin),
}, {
position: MenuPosition.LEFT,
icon: "settings",
@ -216,7 +217,7 @@ export class AppComponent implements OnInit {
icon: "add_circle_outline",
title: "Sign-up",
callback: true,
model: this.signUpEnable?undefined:"disable",
model: this.signUpEnable ? undefined : "disable",
otherData: MenuEventType.SSO_SIGNUP,
}, {
position: MenuPosition.RIGHT,

View File

@ -24,25 +24,38 @@ import { PopInUploadProgress } from 'common/popin/upload-progress/upload-progres
import { PopInDeleteConfirm } from 'common/popin/delete-confirm/delete-confirm';
import { AppComponent } from './app.component';
import { HomeScene, HelpScene, TypeScene, SeriesScene, SeasonScene, VideoScene, SettingsScene,
VideoEditScene, SeasonEditScene, SeriesEditScene } from './scene';
import {
HomeScene, HelpScene, TypeScene, SeriesScene, SeasonScene, VideoScene, SettingsScene,
VideoEditScene, SeasonEditScene, SeriesEditScene
} from './scene';
import { TypeService, DataService, SeriesService, SeasonService, VideoService, ArianeService } from './service';
import { BddService, CookiesService, HttpWrapperService, OnlyAdminGuard, OnlyUnregisteredGuardHome, OnlyUsersGuard, OnlyUsersGuardHome, PopInService, SessionService, SSOService, StorageService, UserService } from 'common/service';
import { ErrorViewerScene, ForbiddenScene, HomeOutScene, NotFound404Scene, SsoScene } from 'common/scene';
import { UploadScene } from './scene/upload/upload';
import { ErrorComponent, TopMenuComponent } from 'common/component';
import { AsyncActionStatusComponent, BurgerPropertyComponent, CheckboxComponent, EntryComponent, EntryNumberComponent, EntryValidatorComponent, ErrorComponent, ErrorMessageStateComponent, PasswordEntryComponent, RenderFormComponent, RenderSettingsComponent, SpinerComponent, TopMenuComponent } from 'common/component';
@NgModule({
declarations: [
AppComponent,
TopMenuComponent,
UploadFileComponent,
ElementDataImageComponent,
ElementTypeComponent,
ElementSeriesComponent,
ElementSeasonComponent,
ElementVideoComponent,
AppComponent,
TopMenuComponent,
UploadFileComponent,
ErrorComponent,
PasswordEntryComponent,
EntryComponent,
EntryValidatorComponent,
SpinerComponent,
AsyncActionStatusComponent,
ErrorMessageStateComponent,
CheckboxComponent,
BurgerPropertyComponent,
RenderSettingsComponent,
RenderFormComponent,
EntryNumberComponent,
PopInComponent,
PopInCreateType,

View File

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

View File

@ -0,0 +1,68 @@
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

@ -0,0 +1,37 @@
/** @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

@ -0,0 +1,13 @@
<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

@ -0,0 +1,78 @@
.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

@ -0,0 +1,18 @@
/** @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

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

View File

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

View File

@ -0,0 +1,29 @@
/** @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

@ -0,0 +1,15 @@
<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

@ -0,0 +1,39 @@
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

@ -0,0 +1,70 @@
/** @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

@ -0,0 +1,8 @@
<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

@ -0,0 +1,9 @@
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

@ -0,0 +1,59 @@
/** @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

@ -0,0 +1,9 @@
<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

@ -0,0 +1,9 @@
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

@ -0,0 +1,68 @@
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

@ -0,0 +1,35 @@
/** @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

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

View File

@ -0,0 +1,34 @@
.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

@ -0,0 +1,17 @@
/** @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,3 +1 @@
<p>
error works!
</p>
<p>error works!</p>

View File

@ -9,11 +9,10 @@ import { Component, OnInit } from '@angular/core';
@Component({
selector: 'app-error',
templateUrl: './error.html',
styleUrls: [ './error.less' ]
styleUrls: ['./error.less'],
})
export class ErrorComponent implements OnInit {
constructor() { }
constructor() {}
ngOnInit() {
}
ngOnInit() {}
}

View File

@ -1,14 +1,17 @@
import { ErrorComponent } from "./error/error";
import { PopInComponent } from "./popin/popin";
import { TopMenuComponent } from "./top-menu/top-menu";
import { UploadFileComponent } from "./upload-file/upload-file";
export {
PopInComponent,
TopMenuComponent,
UploadFileComponent,
ErrorComponent,
};
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

@ -0,0 +1,12 @@
<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

@ -0,0 +1,25 @@
.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

@ -0,0 +1,68 @@
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

@ -0,0 +1,39 @@
/** @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

@ -2,7 +2,7 @@
<div class="element {{popSize}}">
<div class="header">
<label class="unselectable">{{popTitle}}</label>
<div class="close" *ngIf="closeTopRight == true" >
<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>
@ -12,22 +12,22 @@
<ng-content></ng-content>
</div>
<div class="footer">
<div class="action" *ngIf="validateTitle != null" >
<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" >
<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" >
<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" >
<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>

View File

@ -5,14 +5,13 @@
*/
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' ]
styleUrls: ['./popin.less'],
})
export class PopInComponent implements OnInit, OnDestroy {
@Input() id: string;
@ -28,12 +27,10 @@ export class PopInComponent implements OnInit, OnDestroy {
public displayPopIn: boolean = false;
constructor(private popInService: PopInService) {
}
constructor(private popInService: PopInService) {}
ngOnInit(): void {
// ensure id attribute exists
if(!this.id) {
if (!this.id) {
console.error('popin must have an id');
return;
}
@ -60,22 +57,22 @@ export class PopInComponent implements OnInit, OnDestroy {
}
onCloseTop(): void {
this.callback.emit([ 'close-top' ]);
this.callback.emit(['close-top']);
}
onValidate(): void {
this.callback.emit([ 'validate' ]);
this.callback.emit(['validate']);
}
onClose(): void {
this.callback.emit([ 'close' ]);
this.callback.emit(['close']);
}
onOther(): void {
this.callback.emit([ 'other' ]);
this.callback.emit(['other']);
}
onSave(): void {
this.callback.emit([ 'save' ]);
this.callback.emit(['save']);
}
}

View File

@ -0,0 +1,47 @@
<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

@ -0,0 +1,17 @@
/** @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

@ -0,0 +1,39 @@
<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

@ -0,0 +1,32 @@
.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

@ -0,0 +1,204 @@
/** @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

@ -0,0 +1,14 @@
/** @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,80 +1,64 @@
<div class="top">
<div id="main-menu" class="main-menu color-menu-background">
<div *ngFor="let data of menu">
<div class="inert_element"
<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="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 class="xdesktop" *ngIf="!data.icon">{{data.title}}</div>
</div>
</div>
<button class="item"
<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" *ngIf="data.image">
<img class="avatar" src="{{data.image}}"/> {{data.title}}
</div>
<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>
<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"
[ngClass]="getClassMenuPosition()">
<div class="sub-menu color-menu-background unselectable" [ngClass]="getClassMenuPosition()">
<div *ngFor="let data of subMenu">
<div class="inert_element unselectable"
<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}">
[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}">
<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 *ngIf="!data.icon" [ngStyle]="{'float': data.position}">{{data.title}}</div>
</div>
</div>
<button class="item"
<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}">
<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>
<div *ngIf="!data.icon" [ngStyle]="{'float': data.position}">{{data.title}}</div>
</button>
</div>
</div>

View File

@ -1,5 +1,3 @@
.element-pos-left {
z-index: 5;
float: left;
@ -14,21 +12,20 @@
}
.model_happy {
color:yellow;
color: yellow;
}
.model_disable {
color:rgb(100, 100, 100);
color: rgb(100, 100, 100);
}
.model_error {
color:darkred;
color: darkred;
}
.top {
.sub-menu {
position: fixed;
min-width:150px;
min-height:70px;
min-width: 150px;
min-height: 70px;
display: block;
overflow: visible;
@ -46,7 +43,7 @@
box-shadow: 0px 2px 4px 0 rgba(0, 0, 0, 0.6);
.item {
display:block;
display: block;
float: top;
line-height: 56px;
z-index: 4;
@ -56,18 +53,19 @@
/*text-transform: uppercase;*/
font-weight: bold;
font-size: 17px;
width:100%;
width: 100%;
}
.material-icons {
vertical-align: middle;
}
/* Create an Arraw on the top ob the box ... */
&:after, &:before {
&:after,
&:before {
bottom: 100%;
right: 13px;
border: solid transparent;
content: " ";
content: ' ';
height: 0;
width: 0;
position: absolute;
@ -80,33 +78,32 @@
border-width: 15px;
margin-left: -15px;
}
}
.menu-left {
top:75px;
left:15px;
top: 75px;
left: 15px;
}
.menu-right {
top:75px;
right:15px;
top: 75px;
right: 15px;
}
.fill-all {
position: absolute;
top: 0;
left: 0;
width:100%;
height:100%;
width: 100%;
height: 100%;
/*
background-color: #0F0;
*/
z-index:400;
z-index: 400;
}
.main-menu {
position: fixed;
top:0px;
left:0px;
top: 0px;
left: 0px;
display: block;
overflow: visible;
@ -127,7 +124,7 @@
box-shadow: 0px 2px 4px 0 rgba(0, 0, 0, 0.6);
.item {
display:block;
display: block;
float: left;
line-height: 56px;
z-index: 4;
@ -137,18 +134,17 @@
font-weight: bold;
font-size: 17px;
.comment {
visibility: "hidden";
visibility: 'hidden';
}
@media all and (min-width: 700px) {
.comment {
visibility: "visible";
visibility: 'visible';
}
}
}
.inert_element {
display:block;
display: block;
float: left;
line-height: 56px;
z-index: 4;
@ -160,7 +156,7 @@
}
.ariane {
display:block;
display: block;
float: left;
line-height: 56px;
z-index: 4;
@ -177,8 +173,8 @@
}
.avatar {
height:42px;
width:42px;
height: 42px;
width: 42px;
border-radius: 50%;
vertical-align: middle;
}

View File

@ -9,8 +9,6 @@ import { Router } from '@angular/router';
import { isNullOrUndefined } from 'common/utils';
import { MenuItem } from 'common/model/menu-item';
export interface EventOnMenu {
menu: MenuItem;
newWindows: boolean;
@ -20,7 +18,7 @@ export interface EventOnMenu {
@Component({
selector: 'app-top-menu',
templateUrl: './top-menu.html',
styleUrls: [ './top-menu.less' ]
styleUrls: ['./top-menu.less'],
})
export class TopMenuComponent implements OnInit {
@Input() menu: MenuItem[];
@ -28,14 +26,14 @@ export class TopMenuComponent implements OnInit {
subMenuPosition: String = undefined;
@Output() callback: EventEmitter<EventOnMenu> = new EventEmitter();
constructor(private router: Router) {
}
constructor(private router: Router) {}
isNotButton(data: MenuItem) {
return isNullOrUndefined(data.navigateTo)
&& (isNullOrUndefined(data.callback) || data.callback === false)
&& isNullOrUndefined(data.subMenu);
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) {
@ -44,26 +42,24 @@ export class TopMenuComponent implements OnInit {
return true;
}
getPosition(data: string) : string {
getPosition(data: string): string {
return `float: ${data}`;
}
ngOnInit() {
}
ngOnInit() {}
onOutUserProperty(): void {
//console.log('onOutUserProperty ==> event...');
this.subMenu = undefined;
}
getClassMenuPosition(): string {
if (isNullOrUndefined(this.subMenuPosition)) {
return "menu-left";
return 'menu-left';
}
return 'menu-' + this.subMenuPosition;
}
getClassModel(data?:string): string {
getClassModel(data?: string): string {
if (isNullOrUndefined(data)) {
return "";
return '';
}
return 'model_' + data;
}
@ -73,9 +69,9 @@ export class TopMenuComponent implements OnInit {
// check if we need to navigate
if (!isNullOrUndefined(data.navigateTo)) {
// remove in every case the subMenu:
this.subMenu = undefined
this.subMenu = undefined;
this.subMenuPosition = undefined;
this.router.navigate([ data.navigateTo ]);
this.router.navigate([data.navigateTo]);
return;
}
if (!isNullOrUndefined(data.callback) && data.callback === true) {
@ -105,5 +101,4 @@ export class TopMenuComponent implements OnInit {
this.subMenu = data.subMenu;
this.subMenuPosition = data.position;
}
}

View File

@ -1,11 +1,9 @@
<div>
<div class="uploadfilecontainer" (click)="fileInput.click()" appDragDrop (onFileDropped)="uploadFile($event)" >
<input hidden type="file" #fileInput (change)="uploadFile($event.target.files)">
<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>
<button class="delete-file" (click)="deleteAttachment(i)">// DELETE //</button>
</div>
</div>

View File

@ -6,7 +6,7 @@
height: 200px;
width: 80%;
margin: 20px auto;
border: 2px dashed #1C8ADB;
border: 2px dashed #1c8adb;
border-radius: 10px;
}
@ -34,6 +34,6 @@
cursor: pointer;
}
.files-list .delete-file img{
width:30px;
.files-list .delete-file img {
width: 30px;
}

View File

@ -9,12 +9,12 @@ import { Component } from '@angular/core';
@Component({
selector: 'app-upload-file',
templateUrl: './upload-file.html',
styleUrls: [ './upload-file.less' ]
styleUrls: ['./upload-file.less'],
})
export class UploadFileComponent {
files: any = [];
uploadFile(event) {
for(let index = 0; index < event.length; index++) {
for (let index = 0; index < event.length; index++) {
const element = event[index];
this.files.push(element.name);
}

View File

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

View File

@ -1,16 +1,13 @@
import { isObject, isOptionalOf, isString, isNullOrUndefined, isOptionalArrayOf } from "common/utils";
import { isObject, isOptionalOf, isString, isNullOrUndefined, isOptionalArrayOf, isInArray } from 'common/utils';
export enum MenuPosition {
LEFT = "left",
RIGHT = "right",
CENTER = "none",
LEFT = 'left',
RIGHT = 'right',
CENTER = 'none',
}
export function isMenuPosition(data: any): data is MenuPosition {
return data === "left"
|| data === "right"
|| data === "none";
return isInArray(data, ['left', 'right', 'none']);
}
export interface MenuItem {
@ -20,24 +17,23 @@ export interface MenuItem {
hover?: string;
// Icon of the menue (need to be a meterial-icon name
icon?: string;
// If we want to display an image instead of an icon
// Displayed Title
image?: string;
// Displayed Title
title: string;
// Jump Link (If undefined: it is considered as text and not a button)
// Model of the display:
model?: string;
// Jump Link (If undefined: it is considered as text and not a button)
navigateTo?: string;
// if it request a callbak with the curent element: (not compatible with the previous)
// Menu model For a subList of elements
callback?: boolean;
// Other data that want to be set by the user
otherData?: any;
// Enable or not the elemnt
// 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)) {

View File

@ -1,6 +1,4 @@
import { isArrayOf, isNumberFinite, isObject, isOptionalOf, isOptionalArrayOf, isString } from "common/utils";
import { isArrayOf, isNumberFinite, isObject, isOptionalOf, isOptionalArrayOf, isString } from 'common/utils';
export interface NodeData {
id: number;
@ -8,8 +6,7 @@ export interface NodeData {
description?: string;
parentId?: number;
covers?: number[];
};
}
export function isNodeData(data: any): data is NodeData {
if (!isObject(data)) {

View File

@ -1,5 +1,6 @@
<div>
<app-popin id="popin-delete-confirm"
<app-popin
id="popin-delete-confirm"
popSize="small"
popTitle="Confirm Remove"
[closeTitle]="closeButtonTitle"
@ -7,7 +8,7 @@
closeTopRight="true"
(callback)="eventPopUp($event[0])">
<div class="expand" *ngIf="imageUrl != null">
<img src="{{imageUrl}}" class="cover"/>
<img src="{{imageUrl}}" class="cover" />
</div>
<p class="expand">
<label class="unselectable"><b>{{comment}}</b></label>

View File

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

View File

@ -11,7 +11,7 @@ import { PopInService } from 'common/service';
@Component({
selector: 'delete-confirm',
templateUrl: './delete-confirm.html',
styleUrls: [ './delete-confirm.less' ]
styleUrls: ['./delete-confirm.less'],
})
export class PopInDeleteConfirm implements OnInit {
@Input() comment: string = null;
@ -21,22 +21,16 @@ export class PopInDeleteConfirm implements OnInit {
public closeButtonTitle: string = 'Cancel';
public validateButtonTitle: string = 'Validate';
constructor(private popInService: PopInService) {
constructor(private popInService: PopInService) {}
}
OnDestroy() {}
OnDestroy() {
}
ngOnInit() {
}
ngOnInit() {}
eventPopUp(_event: string): void {
console.log(`GET event: ${ _event}`);
console.log(`GET event: ${_event}`);
this.popInService.close('popin-delete-confirm');
if(_event === 'validate') {
if (_event === 'validate') {
this.callback.emit(null);
}
}

View File

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

View File

@ -1,5 +1,6 @@
<div>
<app-popin id="popin-upload-progress"
<app-popin
id="popin-upload-progress"
popSize="medium"
popTitle="Upload Media File"
[closeTitle]="closeButtonTitle"
@ -12,19 +13,21 @@
<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 *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" >
<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/>
<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/>
<div *ngIf="result != null">
<label class="unselectable"><b>Upload finished:</b></label
><br />
<label class="unselectable">{{result}}</label>
</div>
</app-popin>

View File

@ -1,23 +1,21 @@
.expand {
width: 100%;
input {
width: 100%;
};
}
textarea {
width: 100%;
};
}
}
.progress-back {
color:#000!important;
background-color:#f1f1f1!important;
color: #000 !important;
background-color: #f1f1f1 !important;
border-radius: 3px;
}
.progress-bar {
color:#000000!important;
background-color:#4CAF50!important;
color: #000000 !important;
background-color: #4caf50 !important;
border-radius: 3px;
}

View File

@ -12,7 +12,7 @@ import { PopInService } from 'common/service';
@Component({
selector: 'upload-progress',
templateUrl: './upload-progress.html',
styleUrls: [ './upload-progress.less' ]
styleUrls: ['./upload-progress.less'],
})
export class PopInUploadProgress implements OnInit {
@Input() mediaTitle: string = '';
@ -26,37 +26,28 @@ export class PopInUploadProgress implements OnInit {
public uploadDisplay: string = '';
public sizeDisplay: string = '';
public progress: number = 0;
constructor(private router: Router,
private popInService: PopInService) {
}
OnDestroy() {
}
ngOnInit() {
}
constructor(private router: Router, private popInService: PopInService) {}
OnDestroy() {}
ngOnInit() {}
eventPopUp(_event: string): void {
console.log(`GET event: ${ _event}`);
console.log(`GET event: ${_event}`);
this.popInService.close('popin-upload-progress');
}
updateNeedSend():void {
updateNeedSend(): void {}
limit3(count: number): string {
if (count >= 1000) {
return `${count}`;
}
limit3(count:number):string {
if(count >= 1000) {
return `${ count}`;
if (count >= 100) {
return ` ${count}`;
}
if(count >= 100) {
return ` ${ count}`;
if (count >= 10) {
return ` ${count}`;
}
if(count >= 10) {
return ` ${ count}`;
return ` ${count}`;
}
return ` ${ count}`;
}
convertInHuman(countIn:number):string {
convertInHuman(countIn: number): string {
let count = countIn;
let tera = Math.trunc(count / (1024 * 1024 * 1024 * 1024));
count = count - tera * 1024 * 1024 * 1024 * 1024;
@ -67,34 +58,34 @@ export class PopInUploadProgress implements OnInit {
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 || tera !== 0) {
out = `${out} ${this.limit3(tera)}T`;
}
if(out.length !== 0 || giga !== 0) {
out = `${out } ${ this.limit3(giga) }G`;
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 || mega !== 0) {
out = `${out} ${this.limit3(mega)}M`;
}
if(out.length !== 0 || kilo !== 0) {
out = `${out } ${ this.limit3(kilo) }k`;
if (out.length !== 0 || kilo !== 0) {
out = `${out} ${this.limit3(kilo)}k`;
}
if(out.length !== 0 || count !== 0) {
out = `${out } ${ this.limit3(count) }B`;
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.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) {
if (this.error === null && this.result === null) {
this.closeButtonTitle = 'Abort';
this.otherButtonTitle = null;
this.validateButtonTitle = null;
} else if(this.result === null) {
} else if (this.result === null) {
this.closeButtonTitle = null;
this.otherButtonTitle = 'Close';
this.validateButtonTitle = null;
@ -106,7 +97,6 @@ export class PopInUploadProgress implements OnInit {
}
}
export class UploadProgress {
labelMediaTitle: string = '';
mediaSendSize: number = 0;

View File

@ -1,6 +1,8 @@
<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="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,23 +1,22 @@
.full-mode{
width:100%;
height:100%;
top:0;
left:0;
margin:0;
padding:0;
border:0;
float:left;
display:block;
.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%;
position: relative;
max-width: 75%;
padding: 16px 32px 16px 32px;
top: 50%;
transform: ~"translate(0, -50%)";
transform: ~'translate(0, -50%)';
font-size: 30px;
font-weight: 600;
@ -32,7 +31,7 @@
background-position: 0% 50%;
padding: 0 0 0 58px;
margin: 17px 0 17px 0;
text-shadow:0px 0px 4px #000000;
text-shadow: 0px 0px 4px #000000;
color: rgb(160, 44, 44);
i {
font-size: 55px;
@ -45,6 +44,6 @@
background-position: 0% 50%;
padding: 0 0 0 58px;
margin: 17px 0 17px 0;
text-shadow:0px 0px 4px #07213a;
text-shadow: 0px 0px 4px #07213a;
color: white;
}

View File

@ -9,8 +9,8 @@ import { Component } from '@angular/core';
@Component({
selector: 'app-404-not-found',
templateUrl: './404.html',
styleUrls: [ './404.less' ]
styleUrls: ['./404.less'],
})
export class NotFound404Scene {
constructor() { }
constructor() {}
}

View File

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

View File

@ -10,13 +10,10 @@ import { ActivatedRoute } from '@angular/router';
@Component({
selector: 'app-error-viewer',
templateUrl: './error-viewer.html',
styleUrls: [ './error-viewer.less' ]
styleUrls: ['./error-viewer.less'],
})
export class ErrorViewerScene implements OnInit {
constructor(private route: ActivatedRoute) { }
constructor(private route: ActivatedRoute) {}
ngOnInit() {
}
ngOnInit() {}
}

View File

@ -1,6 +1,10 @@
<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 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,24 +1,23 @@
.full-mode{
width:100%;
height:100%;
top:0;
left:0;
margin:0;
padding:0;
border:0;
float:left;
display:block;
.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;
position: relative;
max-width: 500px;
padding: 16px 32px 16px 32px;
top: 50%;
left: 50%;
transform: ~"translate(-50%, -50%)";
transform: ~'translate(-50%, -50%)';
font-size: 30px;
font-weight: 600;
@ -33,7 +32,7 @@
background-position: 0% 50%;
padding: 0 0 0 58px;
margin: 17px 0 17px 0;
text-shadow:0px 0px 4px #000000;
text-shadow: 0px 0px 4px #000000;
color: rgb(160, 44, 44);
i {
font-size: 55px;
@ -46,6 +45,6 @@
background-position: 0% 50%;
padding: 0 0 0 58px;
margin: 17px 0 17px 0;
text-shadow:0px 0px 4px #07213a;
text-shadow: 0px 0px 4px #07213a;
color: white;
}

View File

@ -9,8 +9,8 @@ import { Component } from '@angular/core';
@Component({
selector: 'app-forbidden',
templateUrl: './forbidden.html',
styleUrls: [ './forbidden.less' ]
styleUrls: ['./forbidden.less'],
})
export class ForbiddenScene {
constructor() { }
constructor() {}
}

View File

@ -1,6 +1,8 @@
<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="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,23 +1,22 @@
.full-mode{
width:100%;
height:100%;
top:0;
left:0;
margin:0;
padding:0;
border:0;
float:left;
display:block;
.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%;
position: relative;
max-width: 75%;
padding: 16px 32px 16px 32px;
top: 50%;
transform: ~"translate(0, -50%)";
transform: ~'translate(0, -50%)';
font-size: 30px;
font-weight: 600;
@ -32,7 +31,7 @@
background-position: 0% 50%;
padding: 0 0 0 58px;
margin: 17px 0 17px 0;
text-shadow:0px 0px 4px #000000;
text-shadow: 0px 0px 4px #000000;
color: rgb(160, 44, 44);
i {
font-size: 55px;
@ -45,6 +44,6 @@
background-position: 0% 50%;
padding: 0 0 0 58px;
margin: 17px 0 17px 0;
text-shadow:0px 0px 4px #07213a;
text-shadow: 0px 0px 4px #07213a;
color: white;
}

View File

@ -9,8 +9,8 @@ import { Component } from '@angular/core';
@Component({
selector: 'app-home-out',
templateUrl: './home-out.html',
styleUrls: [ './home-out.less' ]
styleUrls: ['./home-out.less'],
})
export class HomeOutScene {
constructor() { }
constructor() {}
}

View File

@ -1,16 +1,8 @@
import { ErrorViewerScene } from "./error-viewer/error-viewer";
import { ForbiddenScene } from "./forbidden/forbidden";
import { SsoScene } from "./sso/sso";
//import { UploadScene } from "../../app/scene/upload/upload";
import { HomeOutScene } from "./home-out/home-out";
import { NotFound404Scene } from "./404/404";
export {
ErrorViewerScene,
SsoScene,
ForbiddenScene,
HomeOutScene,
NotFound404Scene,
};
//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

@ -4,7 +4,7 @@
<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"/>
<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>
@ -18,10 +18,14 @@
<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__'">
<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__'">
<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>

View File

@ -1,16 +1,16 @@
.full{
width:100%;
height:100%;
right:0;
margin:0;
padding:0;
border:0;
float:right;
display:block;
.full {
width: 100%;
height: 100%;
right: 0;
margin: 0;
padding: 0;
border: 0;
float: right;
display: block;
}
input[type=text], input[type=password] {
input[type='text'],
input[type='password'] {
width: 100%;
padding: 12px 20px;
margin: 8px 0;
@ -33,7 +33,6 @@ input[type=text], input[type=password] {
margin: 15px 0 0 0;
}
.imgContainer {
text-align: center;
margin: 15px 0 0 0;
@ -58,7 +57,7 @@ span.psw {
}
.forgot {
color: #00B;
color: #00b;
font-size: 14px;
float: right;
buttum: 0;
@ -78,11 +77,12 @@ span.psw {
border-width: 0px;
box-sizing: border-box;
&:after, &:before {
&:after,
&:before {
bottom: 100%;
left: 25px;
border: solid transparent;
content: " ";
content: ' ';
height: 0;
width: 0;
position: absolute;
@ -96,14 +96,13 @@ span.psw {
}
}
.container-global {
position:relative;
max-width:400px;
position: relative;
max-width: 400px;
padding: 16px 32px 16px 32px;
top: 50%;
left: 50%;
transform: ~"translate(-50%, -50%)";
transform: ~'translate(-50%, -50%)';
box-shadow: 0px 8px 20px 0 rgba(0, 0, 0, 0.9);
}

View File

@ -11,20 +11,21 @@ import { SSOService, UserService } from 'common/service';
@Component({
selector: 'app-sso',
templateUrl: './sso.html',
styleUrls: [ './sso.less' ]
styleUrls: ['./sso.less'],
})
export class SsoScene implements OnInit {
ssoData: string;
token: string;
keepConnected: boolean
userName: string
keepConnected: boolean;
userName: string;
constructor(
private router: Router,
private route: ActivatedRoute,
private ssoService: SSOService,
private userService: UserService) {
console.error("retreive data after SSO");
private userService: UserService
) {
console.error('retreive data after SSO');
}
ngOnInit() {
@ -52,34 +53,33 @@ export class SsoScene implements OnInit {
console.log(`token: '${token}'`);
console.log(`keepConnected: '${keepConnected}'`);
if (this.token !== '__CANCEL__' && this.token !== '__FAIL__' && this.token !== '__LOGOUT__') {
const destination = (this.ssoData);
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) => {
this.userService
.startSession(this.token, this.keepConnected)
.then((userName: string) => {
self.userName = userName;
setTimeout(function(){
self.router.navigate([ realDst ], { replaceUrl:true });
setTimeout(function () {
self.router.navigate([realDst], { replaceUrl: true });
}, 500); // 2 seconds
}).catch(() => {
this.token = "ERROR_ME";
})
.catch(() => {
this.token = 'ERROR_ME';
});
} else if (this.token === '__LOGOUT__') {
this.userService.removeSession();
const destination = (this.ssoData);
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 });
setTimeout(function () {
self.router.navigate([realDst], { replaceUrl: true });
}, 500); // 2 seconds
} else {
this.userService.removeSession();
}
}
}

View File

@ -9,7 +9,6 @@ import { HttpWrapperService } from 'common/service/http-wrapper';
import { isNullOrUndefined } from 'common/utils';
import { DataInterface } from 'common/utils/dataInterface';
@Injectable()
export class BddService {
private bdd = {};
@ -25,15 +24,16 @@ export class BddService {
let self = this;
return new Promise((resolve, reject) => {
self.get(name)
.then((response:DataInterface) => {
.then((response: DataInterface) => {
let responseTmp = response;
ret.then((response2) => {
ret.then(response2 => {
responseTmp.add(response2);
resolve(response2);
}).catch((response2) => {
}).catch(response2 => {
reject(response2);
});
}).catch((response) => {
})
.catch(response => {
reject(response);
});
});
@ -43,15 +43,16 @@ export class BddService {
let self = this;
return new Promise((resolve, reject) => {
self.get(name)
.then((response:DataInterface) => {
.then((response: DataInterface) => {
let responseTmp = response;
ret.then((response2) => {
ret.then(response2 => {
responseTmp.set(id, response2);
resolve(response2);
}).catch((response2) => {
}).catch(response2 => {
reject(response2);
});
}).catch((response) => {
})
.catch(response => {
reject(response);
});
});
@ -59,9 +60,10 @@ export class BddService {
asyncSetInDB(name: string, id: number, data: any) {
let self = this;
self.get(name)
.then((response:DataInterface) => {
.then((response: DataInterface) => {
response.set(id, data);
}).catch((response) => {
})
.catch(response => {
// nothing to do ...
});
}
@ -70,15 +72,16 @@ export class BddService {
let self = this;
return new Promise((resolve, reject) => {
self.get(name)
.then((response:DataInterface) => {
.then((response: DataInterface) => {
let responseTmp = response;
ret.then((response2) => {
ret.then(response2 => {
responseTmp.delete(id);
resolve(response2);
}).catch((response2) => {
}).catch(response2 => {
reject(response2);
});
}).catch((response) => {
})
.catch(response => {
reject(response);
});
});
@ -87,56 +90,63 @@ export class BddService {
get(name: string): Promise<DataInterface> {
let self = this;
//console.log(`Try to get DB '${ name }'`);
if( !isNullOrUndefined(this.bdd[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])) {
if (isNullOrUndefined(this.bddPomise[name])) {
this.bddPomise[name] = [];
// Try to load Local Data (storage)
let retriveBDDString = null;
if(this.useLocalStorage === true) {
if (this.useLocalStorage === true) {
localStorage.getItem(this.baseLocalStorageName + name);
}
if(retriveBDDString !== null) {
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++) {
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) => {
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}`);
})
.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) => {
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));
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++) {
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++) {
})
.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);
@ -145,7 +155,7 @@ export class BddService {
}
}
return new Promise((resolve, reject) => {
if(!isNullOrUndefined(self.bdd[name])) {
if (!isNullOrUndefined(self.bdd[name])) {
resolve(self.bdd[name]);
return;
}
@ -153,4 +163,3 @@ export class BddService {
});
}
}

View File

@ -4,44 +4,39 @@
* @license PROPRIETARY (see license file)
*/
import { Injectable } from '@angular/core';
import { Injectable } from '@angular/core';
@Injectable()
export class CookiesService {
constructor() {
}
@Injectable()
export class CookiesService {
constructor() {}
set(cname: string, cvalue: string, exdays: number): void {
if(this.get(cname) !== '') {
if (this.get(cname) !== '') {
// reset previous cookies...
document.cookie = `${cname }=;expires=Thu, 01 Jan 1970 00:00:00 GMT;path=/`;
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=/`;
document.cookie = `${cname}=${cvalue};${expires};path=/`;
}
remove(cname: string) : void {
remove(cname: string): void {
this.set(cname, '', 0);
}
get(cname: string) : string | undefined {
let name = `${cname }=`;
get(cname: string): string | undefined {
let name = `${cname}=`;
let coolies = document.cookie.split(';');
for(let iii = 0; iii < coolies.length; iii++) {
for (let iii = 0; iii < coolies.length; iii++) {
let ccc = coolies[iii];
while(ccc.charAt(0) === ' ') {
while (ccc.charAt(0) === ' ') {
ccc = ccc.substring(1);
}
if(ccc.indexOf(name) === 0) {
if (ccc.indexOf(name) === 0) {
return ccc.substring(name.length, ccc.length);
}
}
return '';
}
}
}

View File

@ -13,28 +13,28 @@ 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",
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",
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 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 ;
requestType: HTTPRequestModel;
accept: HTTPMimeType;
contentType: HTTPMimeType;
params?: object;
@ -46,8 +46,8 @@ export interface HTTPRequest {
}
export interface ModelResponseHttp {
status: number,
data: any,
status: number;
data: any;
}
/**
@ -55,43 +55,40 @@ export interface ModelResponseHttp {
*/
@Injectable()
export class HttpWrapperService {
private displayReturn:boolean = false;
constructor(private http: HttpClient,
private session: SessionService) {
private displayReturn: boolean = false;
constructor(private http: HttpClient, private session: SessionService) { }
}
addTokenIfNeeded(headerOption:any): any {
addTokenIfNeeded(headerOption: any): any {
const token = this.session.getToken();
if(!isNullOrUndefined(token)) {
if(headerOption.Authorization === undefined) {
if (!isNullOrUndefined(token)) {
if (headerOption.Authorization === undefined) {
headerOption.Authorization = `Yota ${token}`;
}
}
return headerOption;
}
request(properties: HTTPRequest) : Promise<Response> {
//uriRest:string, headerOption:any, params:any): Promise<{status:number, data:any}> {
//console.log(`-------------------------------------------------------\nHTTP-wrapper GET '${ properties.endPoint }'\n\t\tparams=${ JSON.stringify(properties, null, 2)}`);
let connectionAdresse = this.createRESTCall2({
request(properties: HTTPRequest): Promise<Response> {
let connectionAddresses = this.createRESTCall2({
server: properties.server,
api: properties.endPoint,
inputOptions: properties.params,
});
let headers: any = {
'Accept': properties.accept,
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;
}
//console.log(`disble tocken : ${JSON.stringify(properties)} properties.disableTocken=${properties.disableTocken}`);
if (properties.disableTocken === undefined || properties.disableTocken === null || properties.disableTocken === false) {
if (
properties.disableTocken === undefined ||
properties.disableTocken === null ||
properties.disableTocken === false
) {
headers = this.addTokenIfNeeded(headers);
}
//console.log(`header: ${JSON.stringify(headers)}`);
@ -99,48 +96,60 @@ export class HttpWrapperService {
if (properties.contentType === HTTPMimeType.JSON) {
body = JSON.stringify(properties.body);
}
const result = fetch(connectionAdresse, {
console.log(`Call ${connectionAddresses}`)
const result = fetch(connectionAddresses, {
method: properties.requestType,
headers,
body
})
body,
});
return result;
};
}
requestJson(properties: HTTPRequest) : Promise<ModelResponseHttp> {
requestJson(properties: HTTPRequest): Promise<ModelResponseHttp> {
return new Promise((resolve, reject) => {
this.request(properties).then((response: Response) => {
if(response.status >= 200 && response.status <= 299) {
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(`REICEIVE ==> ${response.status}=${ JSON.stringify(value, null, 2)}`);
resolve({ status:response.status, data:value });
}).catch((reason:any)=> {
reject({ status:999, data:reason });
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}` });
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 });
console.error(`wring correct status: ${response.status}`);
reject({ status: 900, data: response });
}
}).catch((error: any) => {
reject({ status:error.status, data:error.error });
})
.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> {
requestImage(properties: HTTPRequest): Promise<ModelResponseHttp> {
return new Promise((resolve, reject) => {
this.request(properties).then((response: Response) => {
if(response.status >= 200 && response.status <= 299) {
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: 900, data: response });
/*
resolve({ status:response.status, data:value });
}).catch((reason:any)=> {
@ -152,35 +161,50 @@ export class HttpWrapperService {
}
*/
} else {
console.error(`wring correct status: ${response.status}`)
resolve({ status:900, data: response });
console.error(`wring correct status: ${response.status}`);
resolve({ status: 900, data: response });
}
}).catch((error: any) => {
reject({ status:error.status, data:error.error });
})
.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 }) {
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("/")) {
if (!basePage.endsWith('/')) {
addressServerRest = `${basePage}/`;
}
let options = inputOptions;
if(isNullOrUndefined(options)) {
if (isNullOrUndefined(options)) {
options = {};
}
let out = addressServerRest;
if (isArrayOfs(api, isString, isNumber, isBoolean)) {
for (let iii=0; iii<api.length; iii++) {
for (let iii = 0; iii < api.length; iii++) {
let elem = api[iii];
if (out.endsWith("/")) {
if (out.endsWith('/')) {
out += elem;
} else {
out += `/${elem}`;
@ -191,25 +215,25 @@ export class HttpWrapperService {
}
let first = true;
let keys = Object.keys(options);
for(let iii = 0; iii < keys.length; iii++) {
if(first === false) {
out = `${out }&`;
for (let iii = 0; iii < keys.length; iii++) {
if (first === false) {
out = `${out}&`;
} else {
out = `${out }?`;
out = `${out}?`;
first = false;
}
out = out + keys[iii];
if (options[keys[iii]] != null) {
out = out + "=" + options[keys[iii]];
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 }&`;
if (first === false) {
out = `${out}&`;
} else {
out = `${out }?`;
out = `${out}?`;
}
out = out + `Authorization=Yota ${this.session.getToken()}`;
}
@ -220,18 +244,18 @@ export class HttpWrapperService {
// Deprecated ...
createRESTCall(api: string, inputOptions?: any) {
let basePage = environment.server[environment.defaultServer];
let addressServerRest = `${basePage }/`;
let addressServerRest = `${basePage}/`;
let options = inputOptions;
if(options === undefined) {
if (options === undefined) {
options = [];
}
let out = addressServerRest + api;
let first = true;
for(let iii = 0; iii < options.length; iii++) {
if(first === false) {
out = `${out }&`;
for (let iii = 0; iii < options.length; iii++) {
if (first === false) {
out = `${out}&`;
} else {
out = `${out }?`;
out = `${out}?`;
first = false;
}
out = out + options[iii];
@ -239,65 +263,66 @@ export class HttpWrapperService {
return out;
}
// Deprecated ... old model stream
post(uriRest:string, headerOption:any, data:any, progress:ProgressCallback = null) {
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 connectionAdresse = this.createRESTCall(uriRest, {});
let connectionAddresses = this.createRESTCall(uriRest, {});
return new Promise((resolve, reject) => {
if(this.displayReturn === true) {
console.log(`call POST ${ connectionAdresse } data=${ JSON.stringify(data, null, 2)}`);
if (this.displayReturn === true) {
console.log(`call POST ${connectionAddresses} data=${JSON.stringify(data, null, 2)}`);
}
let request = this.http.post(connectionAdresse, data, {
let request = this.http.post(connectionAddresses, data, {
headers: new HttpHeaders(headerOption),
reportProgress: true,
observe: 'events'
observe: 'events',
});
let self = this;
request.subscribe((res: any) => {
if(self.displayReturn === true) {
console.log(`!! data ${ JSON.stringify(res, null, 2)}`);
request.subscribe(
(res: any) => {
if (self.displayReturn === true) {
console.log(`!! data ${JSON.stringify(res, null, 2)}`);
}
if(res.type === HttpEventType.Sent) {
if (res.type === HttpEventType.Sent) {
/* res.type === 0 */
//console.log('post : Sent');
} else if(res.type === HttpEventType.UploadProgress) {
} 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) {
} else if (res.type === HttpEventType.ResponseHeader) {
/* res.type === 2 */
//console.log('post : get header');
} else if(res.type === HttpEventType.DownloadProgress) {
} else if (res.type === HttpEventType.DownloadProgress) {
/* res.type === 3 */
//console.log(`post : get DownloadProgress ${ res.loaded}`);
} else if(res.type === HttpEventType.Response) {
} else if (res.type === HttpEventType.Response) {
/* res.type === 4 */
//console.log('post : get response');
if(res.httpCode) {
resolve({ status:res.httpCode, data:res });
if (res.httpCode) {
resolve({ status: res.httpCode, data: res });
} else {
resolve({ status:200, data:res });
resolve({ status: 200, data: res });
}
} else if(res.type === HttpEventType.User) {
} else if (res.type === HttpEventType.User) {
/* res.type === 5 */
//console.log('post : get User');
} else {
console.log(`post : get unknown ... ${ res.type}`);
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)}`);
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 });
});
reject({ status: error.status, data: error.error });
}
);
});
}
// Deprecated ... old model stream
uploadMultipart(base:string, multipart:FormData, progress: ProgressCallback): any {
uploadMultipart(base: string, multipart: FormData, progress: ProgressCallback): any {
//console.log(`Upload multipart to ${ base}`);
let url = base;
@ -305,54 +330,58 @@ export class HttpWrapperService {
return new Promise((resolve, reject) => {
let headers = {
// 'Content-Type': 'multipart/form-data',
};// new Headers();
}; // new Headers();
self.post(url, headers, multipart, progress)
.then((response: any) => {
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) {
if (response.status >= 200 && response.status <= 299) {
resolve(response.data.body);
return;
}
reject('An error occured');
}, (response: any) => {
if(typeof response.data === 'undefined') {
},
(response: any) => {
if (typeof response.data === 'undefined') {
reject('return ERROR undefined');
} else {
reject('return ERROR ...');// + JSON.stringify(response, null, 2));
reject('return ERROR ...'); // + JSON.stringify(response, null, 2));
}
});
}
);
});
}
// Complex wrapper to simplify interaction:
getSpecific(urlPath: UrlPath):any {
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) => {
}).then(
(response: ModelResponseHttp) => {
//console.log("URL: " + url + "\nRespond(" + response.status + "): " + JSON.stringify(response.data, null, 2));
if(response.status === 200) {
if (response.status === 200) {
resolve(response.data);
return;
}
reject('An error occured');
}, (response: ModelResponseHttp) => {
if(isNullOrUndefined(response.data)) {
},
(response: ModelResponseHttp) => {
if (isNullOrUndefined(response.data)) {
reject('return ERROR undefined');
} else {
reject(`return ERROR ${ JSON.stringify(response.data, null, 2)}`);
reject(`return ERROR ${JSON.stringify(response.data, null, 2)}`);
}
});
}
);
});
}
// Complex wrapper to simplify interaction:s
putSpecific(urlPath: UrlPath, data: object):Promise<ModelResponseHttp> {
putSpecific(urlPath: UrlPath, data: object): Promise<ModelResponseHttp> {
return new Promise((resolve, reject) => {
this.request({
endPoint: urlPath,
@ -360,30 +389,35 @@ export class HttpWrapperService {
accept: HTTPMimeType.JSON,
contentType: HTTPMimeType.JSON,
body: data,
}).then((response: Response) => {
if(response.status >= 200 && response.status <= 201) {
})
.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) => {
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 });
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}` });
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}`)
console.error(`wrong correct status: ${response.status}`);
reject({ status: 900, data: response });
}
}).catch((error: any) => {
reject({ status:error.status, data:error.error });
})
.catch((error: any) => {
reject({ status: error.status, data: error.error });
});
});
}
postSpecific(urlPath: UrlPath, data: object):Promise<ModelResponseHttp> {
postSpecific(urlPath: UrlPath, data: object): Promise<ModelResponseHttp> {
return new Promise((resolve, reject) => {
this.request({
endPoint: urlPath,
@ -391,56 +425,66 @@ export class HttpWrapperService {
accept: HTTPMimeType.JSON,
contentType: HTTPMimeType.JSON,
body: data,
}).then((response: Response) => {
if(response.status >= 200 && response.status <= 201) {
})
.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) => {
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 });
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}` });
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}`)
console.error(`wrong correct status: ${response.status}`);
reject({ status: 900, data: response });
}
}).catch((error: any) => {
reject({ status:error.status, data:error.error });
})
.catch((error: any) => {
reject({ status: error.status, data: error.error });
});
});
}
deleteSpecific(urlPath: UrlPath ):Promise<ModelResponseHttp> {
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) {
})
.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) => {
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 });
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}` });
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}`)
console.error(`wrong correct status: ${response.status}`);
reject({ status: 900, data: response });
}
}).catch((error: any) => {
reject({ status:error.status, data:error.error });
})
.catch((error: any) => {
reject({ status: error.status, data: error.error });
});
});
}

View File

@ -1,11 +1,18 @@
import { BddService } from "./bdd";
import { CookiesService } from "./cookies";
import { HttpWrapperService, ModelResponseHttp, HTTPRequest, HTTPMimeType, HTTPRequestModel } from "./http-wrapper";
import { StorageService } from "./local-storage";
import { PopInService } from "./popin";
import { OnlyAdminGuard, OnlyUnregisteredGuardHome, OnlyUsersGuard, OnlyUsersGuardHome, SessionService } from "./session";
import { SSOService } from "./sso";
import { UserService } from "./user";
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,
@ -24,6 +31,5 @@ export {
OnlyUsersGuardHome,
OnlyUnregisteredGuardHome,
OnlyAdminGuard,
NotificationService,
};

View File

@ -4,16 +4,14 @@
* @license PROPRIETARY (see license file)
*/
import { Injectable } from '@angular/core';
import { Injectable } from '@angular/core';
import { environment } from 'environments/environment';
@Injectable()
export class StorageService {
@Injectable()
export class StorageService {
private baseLocalStorageName = environment.applName + '_';
constructor() {
}
constructor() {}
set(cname: string, cvalue: string): void {
//console.debug(`storage set: ${cname} : ${cvalue}`);
@ -24,15 +22,15 @@ import { environment } from 'environments/environment';
sessionStorage.setItem(this.baseLocalStorageName + cname, cvalue);
}
remove(cname: string) : void {
remove(cname: string): void {
//console.debug(`storage remove: ${cname}`);
localStorage.removeItem(this.baseLocalStorageName + cname);
}
removeSession(cname: string) : void {
removeSession(cname: string): void {
sessionStorage.removeItem(this.baseLocalStorageName + cname);
}
get(cname: string) : string | undefined {
get(cname: string): string | undefined {
//console.debug(`storage get: ${cname}`);
// TODO check expire day...
const data = localStorage.getItem(this.baseLocalStorageName + cname);
@ -42,13 +40,11 @@ import { environment } from 'environments/environment';
}
return data;
}
getSession(cname: string) : string | undefined {
getSession(cname: string): string | undefined {
const data = sessionStorage.getItem(this.baseLocalStorageName + cname);
if (data === null || data === undefined) {
return undefined;
}
return data;
}
}
}

View File

@ -0,0 +1,25 @@
/** @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

@ -21,8 +21,8 @@ export class PopInService {
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) {
for (let iii = 0; iii < this.popins.length; iii++) {
if (this.popins[iii].id === _id) {
this.popins.splice(iii, 1);
return;
}
@ -30,22 +30,23 @@ export class PopInService {
}
open(_id: string) {
// console.log("Try to open pop-in: '" + _id + "'");
console.log("Try to open pop-in: '" + _id + "'");
// open popin specified by id
for(let iii = 0; iii < this.popins.length; iii++) {
if(this.popins[iii].id === _id) {
// console.log(" ==>find it ...");
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 !!!!!");
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) {
for (let iii = 0; iii < this.popins.length; iii++) {
if (this.popins[iii].id === _id) {
this.popins[iii].close();
return;
}

View File

@ -6,92 +6,99 @@
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 = 10000,
user = 1,
guest = 10
admin = 'admin',
user = 'user',
guest = 'guest',
}
@Injectable()
export class SessionService {
private tokenJwt = null;
public sessionId = null;
public userLogin = null;
public userAdmin = null;
public userEMail = null;
public userAvatar = null;
public userId = null;
public right: any = {};
@Output() change: EventEmitter<boolean> = new EventEmitter();
constructor() {
}
constructor() { }
/**
* @brief Create a new session.
*
* @param sessionId -
* @param userId -
* @param userLogin -
* @param userEMail -
* @param userAdmin -
* @param userAvatar -
* @param tokenJwt -
*/
create({ sessionId, userId, userLogin, userEMail, userAdmin, userAvatar, tokenJwt }: {
sessionId;
create({
userId,
userLogin,
tokenJwt,
}: {
userId: string;
userLogin: string;
userEMail: string;
userAdmin: boolean;
userBlocked: boolean;
userRemoved: boolean;
userAvatar: string;
tokenJwt: string;
}) {
console.log(`Session Create: userId=${userId} userLogin=${userLogin} userEMail=${userEMail} userAdmin=${userAdmin} userAvatar=${userAvatar} sessionId = ${sessionId} tokenJwt = ${tokenJwt}`);
console.log(
`Session Create: userId=${userId} userLogin=${userLogin} tokenJwt = ${tokenJwt}`
);
this.tokenJwt = tokenJwt;
this.sessionId = sessionId;
this.userId = userId;
this.userLogin = userLogin;
this.userAdmin = userAdmin;
this.userEMail = userEMail;
this.userAvatar = userAvatar;
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');
let last = this.sessionId;
this.sessionId = null;
this.tokenJwt = undefined;
this.userId = null;
this.userLogin = null;
this.userAdmin = null;
this.userEMail = null;
this.userAvatar = null;
this.right = {};
this.change.emit(false);
}
getToken(): string | undefined {
return this.tokenJwt;
}
islogged() {
return this.sessionId !== null;
return this.userId !== null;
}
hasRight(type) {
if(type === UserRoles222.admin) {
// sometime needed...
return this.userAdmin;
hasRight(type: UserRoles222): boolean {
if (type === UserRoles222.admin) {
if (isNullOrUndefined(this.right.ADMIN)) {
return false;
}
if(type === UserRoles222.user) {
// is connected ==> is user
return this.sessionId !== null;
return this.right.ADMIN;
}
if(type === UserRoles222.guest) {
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;
}
@ -105,7 +112,7 @@ export class SessionService {
}
getAvatar() {
return 'assets/images/avatar_generic.svg';
/* This is not ready :
/* This is not ready:
if(this.userAvatar === false) {
return 'assets/images/avatar_generic.svg';
}
@ -116,12 +123,11 @@ export class SessionService {
@Injectable()
export class OnlyUsersGuard implements CanActivate {
constructor(private sessionService: SessionService,
private router: Router) {};
constructor(private sessionService: SessionService, private router: Router) { }
canActivate() {
console.log("OnlyLoggedInUsers");
if (this.sessionService.hasRight(UserRoles222.user) || this.sessionService.hasRight(UserRoles222.admin) ) {
console.log('OnlyLoggedInUsers');
if (this.sessionService.hasRight(UserRoles222.user) || this.sessionService.hasRight(UserRoles222.admin)) {
return true;
} else {
this.router.navigateByUrl('/forbidden');
@ -132,11 +138,10 @@ export class OnlyUsersGuard implements CanActivate {
@Injectable()
export class OnlyUsersGuardHome implements CanActivate {
constructor(private sessionService: SessionService,
private router: Router) {};
constructor(private sessionService: SessionService, private router: Router) { }
canActivate() {
if (this.sessionService.hasRight(UserRoles222.user) || this.sessionService.hasRight(UserRoles222.admin) ) {
if (this.sessionService.hasRight(UserRoles222.user) || this.sessionService.hasRight(UserRoles222.admin)) {
return true;
} else {
this.router.navigateByUrl('/unregistered');
@ -146,11 +151,10 @@ export class OnlyUsersGuardHome implements CanActivate {
}
@Injectable()
export class OnlyUnregisteredGuardHome implements CanActivate {
constructor(private sessionService: SessionService,
private router: Router) {};
constructor(private sessionService: SessionService, private router: Router) { }
canActivate() {
if (!this.sessionService.islogged() ) {
if (!this.sessionService.islogged()) {
return true;
} else {
this.router.navigateByUrl('/home');
@ -161,8 +165,7 @@ export class OnlyUnregisteredGuardHome implements CanActivate {
@Injectable()
export class OnlyAdminGuard implements CanActivate {
constructor(private sessionService: SessionService,
private router: Router) {};
constructor(private sessionService: SessionService, private router: Router) { }
canActivate() {
if (this.sessionService.hasRight(UserRoles222.user)) {

View File

@ -13,31 +13,55 @@ import { HTTPMimeType, HTTPRequestModel, HttpWrapperService, ModelResponseHttp }
export class SSOService {
signUpEnable: boolean = undefined;
constructor(
private http: HttpWrapperService,
) {
constructor(private http: HttpWrapperService) {
console.log('Start SSOService');
}
utf8_to_b64( str:string ): string {
utf8_to_b64(str: string): string {
// remove unneeded "=" padding
return window.btoa(encodeURIComponent( str )).replace("=", "");
return window.btoa(encodeURIComponent(str)).replace('=', '');
}
b64_to_utf8( str:string ): string {
return decodeURIComponent(window.atob( str ));
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/"])) {
if (
!isNullOrUndefined(data) &&
!isInArray(data, [
'',
'null',
'NULL',
'undefined',
'---',
'unregistered',
'unregistered/',
'forbidden',
'forbidden/',
])
) {
return this.utf8_to_b64(data);
}
let pathName = getApplicationLocation();
if (isInArray(pathName, ["sso", "/sso", "/sso/"])) {
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/"])) {
if (
!isNullOrUndefined(pathName) &&
!isInArray(pathName, [
'',
'null',
'NULL',
'undefined',
'---',
'unregistered',
'unregistered/',
'forbidden',
'forbidden/',
])
) {
return this.utf8_to_b64(pathName);
}
return this.utf8_to_b64('home');
@ -46,17 +70,22 @@ export class SSOService {
* Request SSO connection
*/
unHashLocalData(data: string): string | undefined {
if (isNullOrUndefined(data) || isInArray(data, ["", "null", "NULL", "undefined", "---"])) {
if (isNullOrUndefined(data) || isInArray(data, ['', 'null', 'NULL', 'undefined', '---'])) {
return undefined;
}
try {
return this.b64_to_utf8(data);
}
catch (ex) {
} 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
*/
@ -83,24 +112,24 @@ export class SSOService {
let self = this;
return new Promise((resolve, reject) => {
if (isNullOrUndefined(self.signUpEnable)) {
this.http.requestJson({
this.http
.requestJson({
server: 'karso',
endPoint: 'system_config/is_sign_up_availlable',
requestType: HTTPRequestModel.GET,
accept: HTTPMimeType.JSON,
contentType: HTTPMimeType.JSON,
}).then((response: ModelResponseHttp) =>{
})
.then((response: ModelResponseHttp) => {
self.signUpEnable = response.data.signup;
resolve(self.signUpEnable);
}).catch((error:any) => {
reject(`return ERROR ${ JSON.stringify(error, null, 2)}`);
})
.catch((error: any) => {
reject(`return ERROR ${JSON.stringify(error, null, 2)}`);
});
return;
}
resolve(self.signUpEnable);
});
}
}

View File

@ -6,7 +6,6 @@
import { Injectable } from '@angular/core';
import { Router } from '@angular/router';
import { environment } from 'environments/environment';
import { HTTPMimeType, HTTPRequestModel, HttpWrapperService, ModelResponseHttp } from './http-wrapper';
@ -15,21 +14,21 @@ 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
sessionId: string;
login: string;
eMail: string;
role: string;
avatar: string;
}
*/
@Injectable()
export class UserService {
// 0: Not hide password; 1 hide password;
@ -42,7 +41,8 @@ export class UserService {
private storageService: StorageService,
private http: HttpWrapperService,
private sessionService: SessionService,
private ssoService: SSOService) {
private ssoService: SSOService
) {
console.log('Start UserService');
}
@ -51,8 +51,7 @@ export class UserService {
*/
logOut(): void {
this.removeSession();
this.ssoService.requestSignOut("home");
this.ssoService.requestSignOut('home');
}
removeSession(): void {
this.storageService.remove(this.cookiesRememberMe);
@ -67,57 +66,69 @@ export class UserService {
}
// Separate the Data:
const elems = token.split('.');
if (elems.length !== 3 ) {
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 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);
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();
let self = this;
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");
// 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.storageService.get(self.cookiesRememberMe)==="true";
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) {
if (
isNullOrUndefined(environment.tokenStoredInPermanentStorage) ||
environment.tokenStoredInPermanentStorage !== true
) {
token = self.storageService.getSession(self.cookiesToken);
} else {
token = self.storageService.get(self.cookiesToken);
}
// TODO: check validity of th eToken:
// 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.startSession(token, rememberMe)
.then(() => {
self.router.navigateByUrl(locationOrigin);
console.log(`update global URL = ${locationOrigin}`);
resolve();
}).catch(() => {
})
.catch(() => {
// jump in the sign-in page (automatically of request remember-me)
if(rememberMe) {
if (rememberMe) {
// jump to the sso !!! (remove local data to prevent login loop)
this.storageService.remove(this.cookiesRememberMe);
this.storageService.remove(this.cookiesToken);
@ -129,7 +140,7 @@ export class UserService {
});
} else {
console.log(`Get previous connection ... `);
if(rememberMe) {
if (rememberMe) {
// jump to the sso !!! (remove local data to prevent login loop)
this.storageService.remove(this.cookiesRememberMe);
this.storageService.remove(this.cookiesToken);
@ -142,93 +153,102 @@ export class UserService {
});
}
startSession(token : string, rememberMe: boolean): Promise<string> {
let self = this;
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");
self.retreiveMe(token)
.then((value2: boolean) => {
if (rememberMe === true) {
self.storageService.set(self.cookiesRememberMe, rememberMe ? 'true' : 'false');
}
if (isNullOrUndefined(environment.tokenStoredInPermanentStorage) || environment.tokenStoredInPermanentStorage !== true) {
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(() => {
})
.catch(() => {
reject('sdfsdfsdf');
});
});
}
retreiveMe(token : string): Promise<boolean> {
console.log(`AuthService.loginWithToken ... '${ token }'`);
let self = this;
retreiveMe(token: string): Promise<boolean> {
console.log(`AuthService.loginWithToken ... '${token}'`);
const self = this;
return new Promise((resolve, reject) => {
this.http.requestJson({
//server: 'karso',
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) =>{
})
.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,
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,
//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)}`);
})
.catch((error: any) => {
reject(`return ERROR ${JSON.stringify(error, null, 2)}`);
});
});
}
create(login : string, email : string, password : string) {
create(login: string, email: string, password: string) {
return this.createSha(login, email, sha512(password));
}
createSha(login : string, email : string, password : string) {
createSha(login: string, email: string, password: string) {
let data = {
method: 'v?',
login: login,
email: email,
password: password
password: password,
};
console.log(`call users data=${ JSON.stringify(data, null, 2)}`);
console.log(`call users data=${JSON.stringify(data, null, 2)}`);
if(this.identificationVersion === 1) {
if (this.identificationVersion === 1) {
data.method = 'v1';
}
return new Promise((resolve, reject) => {
this.http.requestJson({
this.http
.requestJson({
server: 'karso',
endPoint: 'users',
requestType: HTTPRequestModel.POST,
accept: HTTPMimeType.JSON,
contentType: HTTPMimeType.JSON,
body: data,
}).then((response: ModelResponseHttp) =>{
})
.then((response: ModelResponseHttp) => {
// TODO: check type ...
console.log(`createSha : get some data to check: ${JSON.stringify(response.data)}`)
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)}`);
})
.catch((error: any) => {
reject(`return ERROR ${JSON.stringify(error, null, 2)}`);
});
});
}
isAuthenticated():boolean {
isAuthenticated(): boolean {
// return !!Session.userId;
return false;
}
@ -244,4 +264,3 @@ export class UserService {
return false;
}
}

View File

@ -1,15 +1,15 @@
import { environment } from "environments/environment";
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);
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);
pathName = pathName.substring(environment.applName.length + 1);
} else if (pathName.startsWith(environment.applName)) {
pathName = pathName.substring(environment.applName.length);
}

View File

@ -4,8 +4,8 @@
* @license PROPRIETARY (see license file)
*/
import { NodeData } from "../model";
import { isArray, isNullOrUndefined } from "./validator";
import { NodeData } from '../model';
import { isArray, isNullOrUndefined } from './validator';
export enum TypeCheck {
CONTAINS = 'C',
@ -20,7 +20,7 @@ export enum TypeCheck {
export interface SelectModel {
check: TypeCheck;
key: string;
value?: number|string|boolean|number[]|string[];
value?: number | string | boolean | number[] | string[];
}
/*
{ check: TypeCheck.EQUAL, key: sss, value: null}
@ -32,9 +32,9 @@ export interface SelectModel {
export class DataInterface {
static extractLimitOne(data: NodeData[], key: string): any[] {
const out = [];
for (let iii=0; iii<data.length; iii++) {
for (let iii = 0; iii < data.length; iii++) {
const value = data[iii][key];
if(DataInterface.existIn(value, out) === false) {
if (DataInterface.existIn(value, out) === false) {
out.push(value);
}
}
@ -42,23 +42,20 @@ export class DataInterface {
}
static extractLimitOneList(data: NodeData[], key: string): any[] {
const out = [];
for (let iii=0; iii<data.length; iii++) {
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) {
if (DataInterface.existIn(value[jjj], out) === false) {
out.push(value[jjj]);
}
}
return out;
}
constructor(
private name: string,
private bdd: NodeData[] ) {
}
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) {
for (let iii = 0; iii < this.bdd.length; iii++) {
if (this.bdd[iii].id === id) {
return iii;
}
}
@ -66,7 +63,7 @@ export class DataInterface {
}
public gets(): NodeData[] {
console.log(`[I] gets ${ this.name}`);
console.log(`[I] gets ${this.name}`);
return this.bdd;
}
@ -79,24 +76,24 @@ export class DataInterface {
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) {
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}`);
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) {
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) {
if (out.length === 0) {
return undefined;
}
return out;
@ -104,9 +101,9 @@ export class DataInterface {
public getNameLike(name: string): NodeData[] {
let out = [];
let nameLower = name.toLowerCase();
for(let iii = 0; iii < this.bdd.length; iii++) {
for (let iii = 0; iii < this.bdd.length; iii++) {
// console.log("compare '" + _name + "' ??? '" + this.bdd[iii]['name'] + "'");
if(this.bdd[iii].name.toLowerCase() === nameLower) {
if (this.bdd[iii].name.toLowerCase() === nameLower) {
out.push(this.bdd[iii]);
}
}
@ -114,24 +111,24 @@ export class DataInterface {
}
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)}`);
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 }`);
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) {
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);
}
}
@ -139,15 +136,15 @@ export class DataInterface {
public find(listToken, values): NodeData[] {
let out = [];
for(let iii = 0; iii < this.bdd.length; iii++) {
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]]) {
for (let jjj = 0; jjj < listToken.length; jjj++) {
if (this.bdd[iii][listToken[jjj]] !== values[listToken[jjj]]) {
find = false;
break;
}
}
if(find === true) {
if (find === true) {
out.push(this.bdd[iii]);
}
}
@ -155,17 +152,17 @@ export class DataInterface {
}
public count(select?: SelectModel[]) {
if(isNullOrUndefined(select)) {
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 {
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]) {
for (let iii = 0; iii < listValues.length; iii++) {
if (value === listValues[iii]) {
return true;
}
}
@ -173,10 +170,13 @@ export class DataInterface {
}
return value === listValues;
}
public static containsOneIn(value: number|string|boolean|number[]|string[], listValues:number|string|boolean|number[]|string[]): boolean {
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) {
for (let iii = 0; iii < value.length; iii++) {
if (this.existIn(value[iii], listValues) === true) {
return true;
}
}
@ -185,33 +185,33 @@ export class DataInterface {
return this.existIn(value, listValues);
}
public getSubList(values: NodeData[], select?: SelectModel[] ): NodeData[] {
public getSubList(values: NodeData[], select?: SelectModel[]): NodeData[] {
let out = [] as NodeData[];
for(let iiiElem = 0; iiiElem < values.length; iiiElem++) {
for (let iiiElem = 0; iiiElem < values.length; iiiElem++) {
let find = true;
if(select.length === 0) {
if (select.length === 0) {
find = false;
}
// console.log("Check : " + JSON.stringify(_values[iii_elem], null, 2));
for(let iiiSelect = 0; iiiSelect < select.length; iiiSelect++) {
//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]
let valueElement = values[iiiElem][control.key];
//console.log(" valueElement : " + JSON.stringify(valueElement, null, 2));
if(isArray(control.value)) {
if(control.check === TypeCheck.CONTAINS) {
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) {
if (DataInterface.containsOneIn(valueElement, control.value) === false) {
find = false;
break;
}
} else if(control.check === TypeCheck.EQUAL) {
} else if (control.check === TypeCheck.EQUAL) {
//console.log("check Equals ... " + valueElement + " === " + control.value);
if(DataInterface.existIn(valueElement, control.value) === false) {
if (DataInterface.existIn(valueElement, control.value) === false) {
find = false;
break;
}
} else if(control.check === TypeCheck.NOT_EQUAL) {
if(DataInterface.existIn(valueElement, control.value) === false) {
} else if (control.check === TypeCheck.NOT_EQUAL) {
if (DataInterface.existIn(valueElement, control.value) === false) {
find = true;
break;
}
@ -221,39 +221,39 @@ export class DataInterface {
}
} else {
//console.log(" [" + control.key + "] = " + valueElement);
if(control.check === TypeCheck.CONTAINS) {
if (control.check === TypeCheck.CONTAINS) {
//console.log("check Equals ... " + valueElement + " === " + control.value + " #2");
if(DataInterface.containsOneIn(valueElement, control.value) === false) {
if (DataInterface.containsOneIn(valueElement, control.value) === false) {
find = false;
break;
}
} else if(control.check === TypeCheck.EQUAL) {
if(valueElement !== control.value) {
} else if (control.check === TypeCheck.EQUAL) {
if (valueElement !== control.value) {
find = false;
break;
}
} else if(control.check === TypeCheck.NOT_EQUAL) {
if(valueElement === control.value) {
} else if (control.check === TypeCheck.NOT_EQUAL) {
if (valueElement === control.value) {
find = false;
break;
}
} else if(control.check === TypeCheck.LESS) {
if(valueElement >= control.value) {
} else if (control.check === TypeCheck.LESS) {
if (valueElement >= control.value) {
find = false;
break;
}
} else if(control.check === TypeCheck.LESS_EQUAL) {
if(valueElement > control.value) {
} else if (control.check === TypeCheck.LESS_EQUAL) {
if (valueElement > control.value) {
find = false;
break;
}
} else if(control.check === TypeCheck.GREATER) {
if(valueElement <= control.value) {
} else if (control.check === TypeCheck.GREATER) {
if (valueElement <= control.value) {
find = false;
break;
}
} else if(control.check === TypeCheck.GREATER_EQUAL) {
if(valueElement < control.value) {
} else if (control.check === TypeCheck.GREATER_EQUAL) {
if (valueElement < control.value) {
find = false;
break;
}
@ -263,7 +263,7 @@ export class DataInterface {
}
}
}
if(find === true) {
if (find === true) {
// console.log(" ==> SELECTED");
out.push(values[iiiElem]);
} else {
@ -274,21 +274,21 @@ export class DataInterface {
}
public orderBy(values: NodeData[], order: string[]): NodeData[] {
if(isNullOrUndefined(order)) {
if (isNullOrUndefined(order)) {
return values;
}
if(order.length === 0) {
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) {
for (let iii = 0; iii < values.length; iii++) {
if (values[iii][valueOrder] === undefined) {
outUnclassable.push(values[iii]);
continue;
}
if(values[iii][valueOrder] === null) {
if (values[iii][valueOrder] === null) {
outUnclassable.push(values[iii]);
continue;
}
@ -296,36 +296,35 @@ export class DataInterface {
}
// console.log("order in list by : " + value_order);
// out = sorted(out, key=lambda x{ x[value_order])
if(valueOrder === 'name') {
if (valueOrder === 'name') {
out.sort((aaa, bbb) => {
const name1 = aaa[valueOrder].toLowerCase();
const name2 = bbb[valueOrder].toLowerCase();
if(name1 > name2) {
if (name1 > name2) {
return 1;
}
if(name1 < name2) {
if (name1 < name2) {
return -1;
}
return 0;
});
} else {
out.sort((aaa, bbb) => {
if(aaa[valueOrder] > bbb[valueOrder]) {
if (aaa[valueOrder] > bbb[valueOrder]) {
return 1;
}
if(aaa[valueOrder] < bbb[valueOrder]) {
if (aaa[valueOrder] < bbb[valueOrder]) {
return -1;
}
return 0;
});
}
if(order.length > 1) {
if (order.length > 1) {
outUnclassable = this.orderBy(outUnclassable, order.slice(1));
}
for(let jjj = 0; jjj < outUnclassable.length; jjj++) {
for (let jjj = 0; jjj < outUnclassable.length; jjj++) {
out.push(outUnclassable[jjj]);
}
return out;
}
}

View File

@ -1,9 +1,25 @@
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 } from "./validator";
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,
@ -25,5 +41,11 @@ export {
TypeCheck,
getApplicationLocation,
sha512,
}
createPasswordState,
checkEmailValidity,
checkPasswordValidity,
checkLoginValidity,
getLoginType,
createLoginState,
isNumeric,
};

View File

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

View File

@ -1,6 +1,6 @@
/*
* Secure Hash Algorithm (SHA512)
*/
* Secure Hash Algorithm (SHA512)
*/
export function sha512(str) {
function int64(msint_32, lsint_32) {
@ -8,51 +8,99 @@ export function sha512(str) {
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 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 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;
@ -76,14 +124,14 @@ export function sha512(str) {
}
function binb2hex(binarray) {
let hex_tab = "0123456789abcdef";
let str = "";
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);
str += hex_tab.charAt((srcByte >> 4) & 0xf) + hex_tab.charAt(srcByte & 0xf);
}
return str;
@ -92,13 +140,13 @@ export function sha512(str) {
function safe_add_2(x, y) {
let lsw, msw, lowOrder, highOrder;
lsw = (x.lowOrder & 0xFFFF) + (y.lowOrder & 0xFFFF);
lsw = (x.lowOrder & 0xffff) + (y.lowOrder & 0xffff);
msw = (x.lowOrder >>> 16) + (y.lowOrder >>> 16) + (lsw >>> 16);
lowOrder = ((msw & 0xFFFF) << 16) | (lsw & 0xFFFF);
lowOrder = ((msw & 0xffff) << 16) | (lsw & 0xffff);
lsw = (x.highOrder & 0xFFFF) + (y.highOrder & 0xFFFF) + (msw >>> 16);
lsw = (x.highOrder & 0xffff) + (y.highOrder & 0xffff) + (msw >>> 16);
msw = (x.highOrder >>> 16) + (y.highOrder >>> 16) + (lsw >>> 16);
highOrder = ((msw & 0xFFFF) << 16) | (lsw & 0xFFFF);
highOrder = ((msw & 0xffff) << 16) | (lsw & 0xffff);
return new int64(highOrder, lowOrder);
}
@ -106,13 +154,18 @@ export function sha512(str) {
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);
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);
lowOrder = ((msw & 0xffff) << 16) | (lsw & 0xffff);
lsw = (a.highOrder & 0xFFFF) + (b.highOrder & 0xFFFF) + (c.highOrder & 0xFFFF) + (d.highOrder & 0xFFFF) + (msw >>> 16);
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);
highOrder = ((msw & 0xffff) << 16) | (lsw & 0xffff);
return new int64(highOrder, lowOrder);
}
@ -120,13 +173,36 @@ export function sha512(str) {
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.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);
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);
}
@ -182,7 +258,9 @@ export function sha512(str) {
}
function gamma0(x) {
let rotr1 = rotr(x, 1), rotr8 = rotr(x, 8), shr7 = shr(x, 7);
let rotr1 = rotr(x, 1),
rotr8 = rotr(x, 8),
shr7 = shr(x, 7);
return new int64(
rotr1.highOrder ^ rotr8.highOrder ^ shr7.highOrder,
@ -203,23 +281,17 @@ export function sha512(str) {
function shr(x, n) {
if (n <= 32) {
return new int64(
x.highOrder >>> n,
x.lowOrder >>> n | (x.highOrder << (32 - n))
);
return new int64(x.highOrder >>> n, (x.lowOrder >>> n) | (x.highOrder << (32 - n)));
} else {
return new int64(
0,
x.highOrder << (32 - n)
);
return new int64(0, x.highOrder << (32 - n));
}
}
str = utf8_encode(str);
let strlen = str.length*charsize;
let strlen = str.length * charsize;
str = str2binb(str);
str[strlen >> 5] |= 0x80 << (24 - strlen % 32);
str[strlen >> 5] |= 0x80 << (24 - (strlen % 32));
str[(((strlen + 128) >> 10) << 5) + 31] = strlen;
for (let i = 0; i < str.length; i += 32) {
@ -234,7 +306,7 @@ export function sha512(str) {
for (let j = 0; j < 80; j++) {
if (j < 16) {
W[j] = new int64(str[j*2 + i], str[j*2 + i + 1]);
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]);
}

View File

@ -1,15 +1,19 @@
export function isNumeric(val: string): boolean {
return !isNaN(Number(val));
}
export function isNumber(data: any): data is number {
return typeof data === "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";
return typeof data === 'boolean';
}
export function isString(data: any): data is string {
return typeof data === "string";
return typeof data === 'string';
}
export function isArray(data: any): data is any[] {
return Array.isArray(data);
@ -24,15 +28,13 @@ 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 === "";
return data === 'undefined' || data === 'null' || data === '';
}
export function isObject(data: any): data is any {
return !isNullOrUndefined(data)
&& typeof data === 'object'
&& !isArray(data);
return !isNullOrUndefined(data) && typeof data === 'object' && !isArray(data);
}
export function isInArray(data: any, listElment: any[]): boolean {
for (let iii=0; iii<listElment.length; iii++) {
for (let iii = 0; iii < listElment.length; iii++) {
if (listElment[iii] === data) {
return true;
}
@ -40,7 +42,11 @@ export function isInArray(data: any, listElment: any[]): boolean {
return false;
}
export function isArrayOf<TYPE>(data: any, typeChecker: (subData: any) => subData is TYPE, length?: number): data is TYPE[] {
export function isArrayOf<TYPE>(
data: any,
typeChecker: (subData: any) => subData is TYPE,
length?: number
): data is TYPE[] {
if (!isArray(data)) {
return false;
}
@ -52,22 +58,24 @@ export function isArrayOf<TYPE>(data: any, typeChecker: (subData: any) => subDat
}
return true;
}
export function isArrayOfs<TYPE,TYPE2,TYPE3>(data: any,
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)[] {
typeChecker3?: (subData: any) => subData is TYPE3
): data is (TYPE | TYPE2 | TYPE3)[] {
if (!isArray(data)) {
return false;
}
for (let iii=0; iii<data.length; iii++) {
for (let iii = 0; iii < data.length; iii++) {
let elem = data[iii];
if (typeChecker(elem) ) {
if (typeChecker(elem)) {
continue;
}
if (typeChecker2 != undefined && typeChecker2(elem) ) {
if (typeChecker2 != undefined && typeChecker2(elem)) {
continue;
}
if (typeChecker3 != undefined && typeChecker3(elem) ) {
if (typeChecker3 != undefined && typeChecker3(elem)) {
continue;
}
return false;
@ -75,11 +83,16 @@ export function isArrayOfs<TYPE,TYPE2,TYPE3>(data: any,
return true;
}
export function isOptionalOf<TYPE>(data: any, typeChecker: (subData: any) => subData is TYPE): data is TYPE | undefined {
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 {
export function isOptionalArrayOf<TYPE>(
data: any,
typeChecker: (subData: any) => subData is TYPE
): data is TYPE[] | undefined {
return isUndefined(data) || isArrayOf(data, typeChecker);
}

View File

@ -0,0 +1,146 @@
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';
}

View File

@ -12,6 +12,7 @@ export const environment = {
karideo: `${location.origin}/karideo/api`,
karso: `${location.origin}/karso/api`,
},
ssoSite: `${location.origin}/karso/`,
ssoSignIn: `${location.origin}/karso/signin/karideo/`,
ssoSignUp: `${location.origin}/karso/signup/karideo/`,
ssoSignOut: `${location.origin}/karso/signout/karideo/`,

View File

@ -3,18 +3,21 @@
// `ng build --env=prod` then `environment.prod.ts` will be used instead.
// The list of which env maps to which file can be found in `.angular-cli.json`.
const serverSSOAddress = 'http://atria-soft.org'
const environment_back_prod = {
production: false,
// URL of development API
applName: "karideo",
defaultServer: "karideo",
server: {
karideo: 'http://192.168.1.156/karideo/api',
karso: 'http://192.168.1.156/karso/api',
karideo: `${serverSSOAddress}/karideo/api`,
karso: `${serverSSOAddress}/karso/api`,
},
ssoSignIn: 'http://192.168.1.156/karso/signin/karideo-dev/',
ssoSignUp: 'http://192.168.1.156/karso/signup/karideo-dev/',
ssoSignOut: 'http://192.168.1.156/karso/signout/karideo-dev/',
ssoSite: `${serverSSOAddress}/karso/`,
ssoSignIn: `${serverSSOAddress}/karso/signin/karideo-dev/`,
ssoSignUp: `${serverSSOAddress}/karso/signup/karideo-dev/`,
ssoSignOut: `${serverSSOAddress}/karso/signout/karideo-dev/`,
tokenStoredInPermanentStorage: false,
};
@ -25,11 +28,12 @@ const environment_local = {
defaultServer: "karideo",
server: {
karideo: 'http://localhost:18080/karideo/api',
karso: 'http://192.168.1.156/karso/api',
karso: `${serverSSOAddress}/karso/api`,
},
ssoSignIn: 'http://192.168.1.156/karso/signin/karideo-dev/',
ssoSignUp: 'http://192.168.1.156/karso/signup/karideo-dev/',
ssoSignOut: 'http://192.168.1.156/karso/signout/karideo-dev/',
ssoSite: `${serverSSOAddress}/karso/`,
ssoSignIn: `${serverSSOAddress}/karso/signin/karideo-dev/`,
ssoSignUp: `${serverSSOAddress}/karso/signup/karideo-dev/`,
ssoSignOut: `${serverSSOAddress}/karso/signout/karideo-dev/`,
tokenStoredInPermanentStorage: false,
};
@ -39,15 +43,16 @@ const environment_hybrid = {
applName: "karideo",
defaultServer: "karideo",
server: {
karideo: 'http://192.168.1.156/karideo/api',
karso: 'http://192.168.1.156/karso/api',
karideo: `${serverSSOAddress}/karideo/api`,
karso: `${serverSSOAddress}/karso/api`,
},
ssoSignIn: 'http://192.168.1.156/karso/signin/karideo-dev/',
ssoSignUp: 'http://192.168.1.156/karso/signup/karideo-dev/',
ssoSignOut: 'http://192.168.1.156/karso/signout/karideo-dev/',
ssoSite: `${serverSSOAddress}/karso/`,
ssoSignIn: `${serverSSOAddress}/karso/signin/karideo-dev/`,
ssoSignUp: `${serverSSOAddress}/karso/signup/karideo-dev/`,
ssoSignOut: `${serverSSOAddress}/karso/signout/karideo-dev/`,
tokenStoredInPermanentStorage: false,
};
export const environment = environment_back_prod;
export const environment = environment_local;