[DEV] update new archidata envirinment and karso common front update

This commit is contained in:
Edouard DUPIN 2023-05-28 21:53:13 +02:00
parent c3a80dce51
commit 3cac58cc50
105 changed files with 3195 additions and 1388 deletions

View File

@ -22,7 +22,13 @@
<dependency>
<groupId>kangaroo-and-rabbit</groupId>
<artifactId>archidata</artifactId>
<version>0.3.3</version>
<version>0.3.7</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-simple</artifactId>
<version>2.0.7</version>
<!--<scope>test</scope>-->
</dependency>
</dependencies>
@ -30,6 +36,11 @@
<sourceDirectory>src</sourceDirectory>
<testSourceDirectory>test/src</testSourceDirectory>
<directory>${project.basedir}/out/maven/</directory>
<resources>
<resource>
<directory>src/resources</directory>
</resource>
</resources>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>

View File

@ -17,77 +17,91 @@ import org.kar.karusic.api.HealthCheck;
import org.kar.karusic.api.PlaylistResource;
import org.kar.karusic.api.TrackResource;
import org.kar.karusic.api.UserResource;
import org.kar.karusic.filter.KarusicAuthenticationFilter;
import org.kar.karusic.migration.Initialization;
import org.kar.archidata.GlobalConfiguration;
import org.kar.archidata.SqlWrapper;
import org.kar.archidata.UpdateJwtPublicKey;
import org.kar.archidata.api.DataResource;
import org.kar.archidata.catcher.ExceptionCatcher;
import org.kar.archidata.catcher.FailExceptionCatcher;
import org.kar.archidata.catcher.InputExceptionCatcher;
import org.kar.archidata.catcher.SystemExceptionCatcher;
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.util.ConfigBaseVariable;
import org.kar.karusic.model.Track;
import org.slf4j.LoggerFactory;
import org.slf4j.Logger;
public class WebLauncher {
private WebLauncher() {
}
final static Logger LOGGER = LoggerFactory.getLogger(WebLauncher.class);
protected UpdateJwtPublicKey keyUpdater = null;
public WebLauncher() {
ConfigBaseVariable.bdDatabase = "karusic";
}
private static URI getBaseURI() {
return UriBuilder.fromUri(ConfigBaseVariable.getlocalAddress()).build();
}
public static void main(String[] args) {
ConfigBaseVariable.bdDatabase = "karusic";
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("Add migration since last version");
// NOTHING for now
WebLauncher.LOGGER.info("Migrate the DB [START]");
migrationEngine.migrate(GlobalConfiguration.dbConfig);
WebLauncher.LOGGER.info("Migrate the DB [STOP]");
}
// generate the BDD:
try {
String out = "";
//out += SqlWrapper.createTable(User.class);
out += SqlWrapper.createTable(Track.class);
// out += SqlWrapper.createTable(Artist.class);
// out += SqlWrapper.createTable(Gender.class);
// out += SqlWrapper.createTable(Playlist.class);
// out += SqlWrapper.createTable(Album.class);
System.out.println(out);
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
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 Key updater");
launcher.stopOther();
WebLauncher.LOGGER.info("STOP the REST server:");
}
public void process() throws InterruptedException {
// ===================================================================
// Configure resources
// ===================================================================
ResourceConfig rc = new ResourceConfig();
// add multipart 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(KarusicAuthenticationFilter.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(AlbumResource.class);
rc.registerClasses(ArtistResource.class);
rc.registerClasses(GenderResource.class);
rc.registerClasses(PlaylistResource.class);
rc.registerClasses(TrackResource.class);
rc.registerClasses(DataResource.class);
rc.register(UserResource.class);
rc.register(AlbumResource.class);
rc.register(ArtistResource.class);
rc.register(GenderResource.class);
rc.register(PlaylistResource.class);
rc.register(TrackResource.class);
rc.register(DataResource.class);
rc.registerClasses(HealthCheck.class);
rc.registerClasses(Front.class);
rc.register(HealthCheck.class);
rc.register(Front.class);
// add jackson to be discovenr when we are ins standalone server
// add jackson to be discover when we are ins standalone server
rc.register(JacksonFeature.class);
// enable this to show low level request
//rc.property(LoggingFeature.LOGGING_FEATURE_LOGGER_LEVEL_SERVER, Level.WARNING.getName());
@ -112,20 +126,22 @@ public class WebLauncher {
// ===================================================================
// start periodic update of the token ...
// ===================================================================
UpdateJwtPublicKey keyUpdater = new UpdateJwtPublicKey();
keyUpdater.start();
this.keyUpdater = new UpdateJwtPublicKey();
this.keyUpdater.start();
// ===================================================================
// run JERSEY
// ===================================================================
try {
server.start();
System.out.println("Jersey app started at " + getBaseURI());
Thread.currentThread().join();
LOGGER.info("Jersey app started at {}", getBaseURI());
} catch (Exception e) {
System.out.println("There was an error while starting Grizzly HTTP server.");
LOGGER.error("There was an error while starting Grizzly HTTP server.");
e.printStackTrace();
}
}
public void stopOther() {
keyUpdater.kill();
try {
keyUpdater.join(4000, 0);

View File

@ -1,17 +1,39 @@
package org.kar.karusic;
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:19080/karusic/api/";
//ConfigBaseVariable.ssoAdress = "http://localhost:15080/karso/api/";
ConfigBaseVariable.ssoAdress = "https://atria-soft.org/karso/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

@ -4,6 +4,10 @@ import org.kar.archidata.SqlWrapper;
import org.kar.archidata.filter.GenericContext;
import org.kar.archidata.model.User;
import org.kar.karusic.model.UserKarusic;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.fasterxml.jackson.annotation.JsonInclude;
import org.kar.archidata.annotation.security.RolesAllowed;
import jakarta.ws.rs.*;
@ -16,6 +20,19 @@ import java.util.List;
@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 +59,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(UserKarusic.class, userId);
@ -53,19 +70,16 @@ 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.karusic.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 KarusicAuthenticationFilter extends AuthenticationFilter {
final Logger logger = LoggerFactory.getLogger(KarusicAuthenticationFilter.class);
public KarusicAuthenticationFilter() {
super("karusic");
}
}

View File

@ -0,0 +1,83 @@
package org.kar.karusic.migration;
import org.kar.archidata.migration.MigrationSqlStep;
import org.kar.archidata.model.Data;
import org.kar.archidata.model.User;
import org.kar.karusic.model.Album;
import org.kar.karusic.model.Artist;
import org.kar.karusic.model.Gender;
import org.kar.karusic.model.Playlist;
import org.kar.karusic.model.Track;
public class Initialization extends MigrationSqlStep {
public static final int KARSO_INITIALISATION_ID = 1;
@Override
public String getName() {
return "Initialization";
}
public Initialization() throws Exception {
addClass(Album.class);
addClass(Artist.class);
addClass(Data.class);
addClass(Gender.class);
addClass(Playlist.class);
addClass(Track.class);
addClass(User.class);
addAction("""
INSERT INTO `gender` (`id`, `name`, `description`) VALUES
(1, 'Variété française', NULL),
(2, 'Pop', NULL),
(3, 'inconnue', NULL),
(4, 'Disco', NULL),
(5, 'Enfants', NULL),
(6, 'Portugaise', NULL),
(7, 'Apprentissage', NULL),
(8, 'Blues', NULL),
(9, 'Jazz', NULL),
(10, 'Chanson Noël', NULL),
(11, 'DubStep', NULL),
(12, 'Rap français', NULL),
(13, 'Classique', NULL),
(14, 'Rock', NULL),
(15, 'Electro', NULL),
(16, 'Celtique', NULL),
(17, 'Country', NULL),
(18, 'Variété Québéquoise', NULL),
(19, 'Médiéval', NULL),
(20, 'Variété Italienne', NULL),
(21, 'Comédie Musicale', NULL),
(22, 'Vianney', NULL),
(23, 'Bande Original', NULL),
(24, 'Bande Originale', NULL),
(25, 'Variété Belge', NULL),
(26, 'Gospel', NULL);
""");
// set start increment element to permit to add after default elements
addAction("""
ALTER TABLE `album` AUTO_INCREMENT = 1000;
""");
addAction("""
ALTER TABLE `artist` AUTO_INCREMENT = 1000;
""");
addAction("""
ALTER TABLE `data` AUTO_INCREMENT = 1000;
""");
addAction("""
ALTER TABLE `gender` AUTO_INCREMENT = 1000;
""");
addAction("""
ALTER TABLE `playlist` AUTO_INCREMENT = 1000;
""");
addAction("""
ALTER TABLE `track` AUTO_INCREMENT = 1000;
""");
addAction("""
ALTER TABLE `user` AUTO_INCREMENT = 1000;
""");
}
}

View File

@ -0,0 +1,35 @@
# SLF4J's SimpleLogger configuration file
# Simple implementation of Logger that sends all enabled log messages, for all defined loggers, to System.err.
# Default logging detail level for all instances of SimpleLogger.
# Must be one of ("trace", "debug", "info", "warn", or "error").
# If not specified, defaults to "info".
org.slf4j.simpleLogger.defaultLogLevel=trace
# Logging detail level for a SimpleLogger instance named "xxxxx".
# Must be one of ("trace", "debug", "info", "warn", or "error").
# If not specified, the default logging detail level is used.
#org.slf4j.simpleLogger.log.xxxxx=
# Set to true if you want the current date and time to be included in output messages.
# Default is false, and will output the number of milliseconds elapsed since startup.
#org.slf4j.simpleLogger.showDateTime=false
# The date and time format to be used in the output messages.
# The pattern describing the date and time format is the same that is used in java.text.SimpleDateFormat.
# If the format is not specified or is invalid, the default format is used.
# The default format is yyyy-MM-dd HH:mm:ss:SSS Z.
#org.slf4j.simpleLogger.dateTimeFormat=yyyy-MM-dd HH:mm:ss:SSS Z
# Set to true if you want to output the current thread name.
# Defaults to true.
org.slf4j.simpleLogger.showThreadName=true
# Set to true if you want the Logger instance name to be included in output messages.
# Defaults to true.
#org.slf4j.simpleLogger.showLogName=true
# Set to true if you want the last component of the name to be included in output messages.
# Defaults to false.
#org.slf4j.simpleLogger.showShortLogName=false

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",
@ -220,7 +221,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",

View File

@ -11,7 +11,7 @@ import { HttpClientModule } from '@angular/common/http';
import { FormsModule, ReactiveFormsModule } from '@angular/forms'; // this is needed for dynamic selection of the select
import { AppRoutingModule } from './app-routing.module';
import { ErrorComponent, PopInComponent, TopMenuComponent, UploadFileComponent } from 'common/component/';
import { AsyncActionStatusComponent, BurgerPropertyComponent, CheckboxComponent, EntryComponent, EntryNumberComponent, EntryValidatorComponent, ErrorComponent, ErrorMessageStateComponent, PasswordEntryComponent, PopInComponent, RenderFormComponent, RenderSettingsComponent, SpinerComponent, TopMenuComponent, UploadFileComponent } from 'common/component/';
import { ElementDataImageComponent } from './component/data-image/data-image';
import { ElementTypeComponent } from './component/element-type/element-type';
@ -19,8 +19,10 @@ import { PopInCreateType } from './popin/create-type/create-type';
import { PopInDeleteConfirm, PopInUploadProgress } from 'common/popin';
import { AppComponent } from './app.component';
import { HomeScene, HelpScene, GenderScene, PlaylistScene, ArtistScene, AlbumScene, AlbumsScene, TrackScene, SettingsScene,
TrackEditScene, AlbumEditScene, ArtistEditScene, ArtistsScene, ArtistAlbumScene } from './scene';
import {
HomeScene, HelpScene, GenderScene, PlaylistScene, ArtistScene, AlbumScene, AlbumsScene, TrackScene, SettingsScene,
TrackEditScene, AlbumEditScene, ArtistEditScene, ArtistsScene, ArtistAlbumScene
} from './scene';
import { GenderService, DataService, PlaylistService, ArtistService, AlbumService, TrackService, ArianeService, PlayerService } 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';
@ -40,6 +42,17 @@ import { ElementSeriesComponent, ElementTrackComponent, ElementSeasonComponent,
ElementVideoComponent,
ElementPlayerAudioComponent,
ErrorComponent,
PasswordEntryComponent,
EntryComponent,
EntryValidatorComponent,
SpinerComponent,
AsyncActionStatusComponent,
ErrorMessageStateComponent,
CheckboxComponent,
BurgerPropertyComponent,
RenderSettingsComponent,
RenderFormComponent,
EntryNumberComponent,
PopInComponent,
PopInCreateType,
@ -99,7 +112,7 @@ import { ElementSeriesComponent, ElementTrackComponent, ElementSeasonComponent,
OnlyUnregisteredGuardHome,
],
exports: [
AppComponent,
AppComponent,
TopMenuComponent,
UploadFileComponent,
ErrorComponent,
@ -112,13 +125,15 @@ import { ElementSeriesComponent, ElementTrackComponent, ElementSeasonComponent,
PopInComponent,
PopInUploadProgress,
PopInDeleteConfirm,
],
],
bootstrap: [
AppComponent
],
/*
schemas: [
CUSTOM_ELEMENTS_SCHEMA,
NO_ERRORS_SCHEMA
]
*/
})
export class AppModule { }

View File

@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" height="48" width="48"><path d="M24 44q-4.15 0-7.8-1.575-3.65-1.575-6.35-4.275-2.7-2.7-4.275-6.35Q4 28.15 4 24t1.575-7.8Q7.15 12.55 9.85 9.85q2.7-2.7 6.35-4.275Q19.85 4 24 4t7.8 1.575q3.65 1.575 6.35 4.275 2.7 2.7 4.275 6.35Q44 19.85 44 24t-1.575 7.8q-1.575 3.65-4.275 6.35-2.7 2.7-6.35 4.275Q28.15 44 24 44Zm0-3q7.1 0 12.05-4.95Q41 31.1 41 24q0-3.05-1.05-5.85T37 13.05L13.05 37q2.25 1.95 5.075 2.975Q20.95 41 24 41Zm-12.95-6.05 23.9-23.9q-2.3-1.95-5.1-3T24 7q-7.1 0-12.05 4.95Q7 16.9 7 24q0 3.05 1.1 5.875t2.95 5.075Z"/></svg>

After

Width:  |  Height:  |  Size: 567 B

View File

@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" height="48" width="48"><path d="M25.5 19.5V6H42v13.5ZM6 25.5V6h16.5v19.5ZM25.5 42V22.5H42V42ZM6 42V28.5h16.5V42Zm3-19.5h10.5V9H9ZM28.5 39H39V25.5H28.5Zm0-22.5H39V9H28.5ZM9 39h10.5v-7.5H9Zm10.5-16.5Zm9-6Zm0 9Zm-9 6Z"/></svg>

After

Width:  |  Height:  |  Size: 263 B

View File

@ -0,0 +1,38 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg
height="48"
width="48"
version="1.1"
id="svg1543"
sodipodi:docname="group.svg"
inkscape:version="1.2.1 (9c6d41e410, 2022-07-14, custom)"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns="http://www.w3.org/2000/svg"
xmlns:svg="http://www.w3.org/2000/svg">
<defs
id="defs1547" />
<sodipodi:namedview
id="namedview1545"
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1.0"
inkscape:showpageshadow="2"
inkscape:pageopacity="0.0"
inkscape:pagecheckerboard="0"
inkscape:deskcolor="#d1d1d1"
showgrid="false"
inkscape:zoom="21.395833"
inkscape:cx="24"
inkscape:cy="24"
inkscape:window-width="3838"
inkscape:window-height="2118"
inkscape:window-x="0"
inkscape:window-y="20"
inkscape:window-maximized="1"
inkscape:current-layer="svg1543" />
<path
d="M1.9 40v-4.7q0-1.75.9-3.175Q3.7 30.7 5.3 30q3.65-1.6 6.575-2.3Q14.8 27 17.9 27q3.1 0 6 .7t6.55 2.3q1.6.7 2.525 2.125.925 1.425.925 3.175V40Zm35 0v-4.7q0-3.15-1.6-5.175t-4.2-3.275q3.45.4 6.5 1.175t4.95 1.775q1.65.95 2.6 2.35.95 1.4.95 3.15V40Zm-19-16.05q-3.3 0-5.4-2.1-2.1-2.1-2.1-5.4 0-3.3 2.1-5.4 2.1-2.1 5.4-2.1 3.3 0 5.4 2.1 2.1 2.1 2.1 5.4 0 3.3-2.1 5.4-2.1 2.1-5.4 2.1Zm18-7.5q0 3.3-2.1 5.4-2.1 2.1-5.4 2.1-.55 0-1.225-.075T25.95 23.6q1.2-1.25 1.825-3.075.625-1.825.625-4.075t-.625-3.975Q27.15 10.75 25.95 9.3q.55-.15 1.225-.25t1.225-.1q3.3 0 5.4 2.1 2.1 2.1 2.1 5.4ZM4.9 37h26v-1.7q0-.8-.475-1.55T29.25 32.7q-3.6-1.6-6.05-2.15-2.45-.55-5.3-.55-2.85 0-5.325.55T6.5 32.7q-.7.3-1.15 1.05-.45.75-.45 1.55Zm13-16.05q1.95 0 3.225-1.275Q22.4 18.4 22.4 16.45q0-1.95-1.275-3.225Q19.85 11.95 17.9 11.95q-1.95 0-3.225 1.275Q13.4 14.5 13.4 16.45q0 1.95 1.275 3.225Q15.95 20.95 17.9 20.95Zm0 16.05Zm0-20.55Z"
id="path1541"
style="fill:#ffffff;fill-opacity:1" />
</svg>

After

Width:  |  Height:  |  Size: 2.0 KiB

View File

@ -0,0 +1,63 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg
height="48"
width="48"
version="1.1"
id="svg4"
sodipodi:docname="lan.svg"
inkscape:version="1.2.1 (9c6d41e410, 2022-07-14, custom)"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns="http://www.w3.org/2000/svg"
xmlns:svg="http://www.w3.org/2000/svg">
<defs
id="defs8" />
<sodipodi:namedview
id="namedview6"
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1.0"
inkscape:showpageshadow="2"
inkscape:pageopacity="0.0"
inkscape:pagecheckerboard="0"
inkscape:deskcolor="#d1d1d1"
showgrid="false"
inkscape:zoom="16.822701"
inkscape:cx="12.691184"
inkscape:cy="39.737971"
inkscape:window-width="3838"
inkscape:window-height="2118"
inkscape:window-x="0"
inkscape:window-y="20"
inkscape:window-maximized="1"
inkscape:current-layer="svg4" />
<rect
style="fill:#000000;stroke:#ffffff;stroke-width:3;stroke-dasharray:none;stroke-opacity:1;fill-opacity:1"
id="rect897"
width="12.08835"
height="10.642548"
x="17.961397"
y="5.4625888" />
<rect
style="fill:#000000;stroke:#ffffff;stroke-width:3;stroke-dasharray:none;stroke-opacity:1;fill-opacity:1"
id="rect897-3"
width="12.08835"
height="10.642548"
x="7.428793"
y="32.038437" />
<rect
style="fill:#000000;stroke:#ffffff;stroke-width:3;stroke-dasharray:none;stroke-opacity:1;fill-opacity:1"
id="rect897-6"
width="12.08835"
height="10.642548"
x="28.561865"
y="31.936249" />
<path
style="fill:none;stroke:#ffffff;stroke-width:3;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;stroke-dasharray:none"
d="m 13.584028,32.01093 v -7.707304 h 20.889927 v 7.894963"
id="path990" />
<path
style="fill:none;stroke:#ffffff;stroke-width:3;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;stroke-dasharray:none"
d="M 24.032132,23.799058 V 16.118716"
id="path992" />
</svg>

After

Width:  |  Height:  |  Size: 2.1 KiB

View File

@ -0,0 +1,38 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg
height="48"
width="48"
version="1.1"
id="svg1004"
sodipodi:docname="person.svg"
inkscape:version="1.2.1 (9c6d41e410, 2022-07-14, custom)"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns="http://www.w3.org/2000/svg"
xmlns:svg="http://www.w3.org/2000/svg">
<defs
id="defs1008" />
<sodipodi:namedview
id="namedview1006"
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1.0"
inkscape:showpageshadow="2"
inkscape:pageopacity="0.0"
inkscape:pagecheckerboard="0"
inkscape:deskcolor="#d1d1d1"
showgrid="false"
inkscape:zoom="21.395833"
inkscape:cx="24"
inkscape:cy="24"
inkscape:window-width="3838"
inkscape:window-height="2118"
inkscape:window-x="0"
inkscape:window-y="20"
inkscape:window-maximized="1"
inkscape:current-layer="svg1004" />
<path
d="M24 23.95q-3.3 0-5.4-2.1-2.1-2.1-2.1-5.4 0-3.3 2.1-5.4 2.1-2.1 5.4-2.1 3.3 0 5.4 2.1 2.1 2.1 2.1 5.4 0 3.3-2.1 5.4-2.1 2.1-5.4 2.1ZM8 40v-4.7q0-1.9.95-3.25T11.4 30q3.35-1.5 6.425-2.25Q20.9 27 24 27q3.1 0 6.15.775 3.05.775 6.4 2.225 1.55.7 2.5 2.05.95 1.35.95 3.25V40Zm3-3h26v-1.7q0-.8-.475-1.525-.475-.725-1.175-1.075-3.2-1.55-5.85-2.125Q26.85 30 24 30t-5.55.575q-2.7.575-5.85 2.125-.7.35-1.15 1.075Q11 34.5 11 35.3Zm13-16.05q1.95 0 3.225-1.275Q28.5 18.4 28.5 16.45q0-1.95-1.275-3.225Q25.95 11.95 24 11.95q-1.95 0-3.225 1.275Q19.5 14.5 19.5 16.45q0 1.95 1.275 3.225Q22.05 20.95 24 20.95Zm0-4.5ZM24 37Z"
id="path1002"
style="stroke:none;stroke-opacity:1;fill:#ffffff;fill-opacity:1" />
</svg>

After

Width:  |  Height:  |  Size: 1.7 KiB

View File

@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" height="48" width="48"><path d="m19.4 44-1-6.3q-.95-.35-2-.95t-1.85-1.25l-5.9 2.7L4 30l5.4-3.95q-.1-.45-.125-1.025Q9.25 24.45 9.25 24q0-.45.025-1.025T9.4 21.95L4 18l4.65-8.2 5.9 2.7q.8-.65 1.85-1.25t2-.9l1-6.35h9.2l1 6.3q.95.35 2.025.925Q32.7 11.8 33.45 12.5l5.9-2.7L44 18l-5.4 3.85q.1.5.125 1.075.025.575.025 1.075t-.025 1.05q-.025.55-.125 1.05L44 30l-4.65 8.2-5.9-2.7q-.8.65-1.825 1.275-1.025.625-2.025.925l-1 6.3ZM24 30.5q2.7 0 4.6-1.9 1.9-1.9 1.9-4.6 0-2.7-1.9-4.6-1.9-1.9-4.6-1.9-2.7 0-4.6 1.9-1.9 1.9-1.9 4.6 0 2.7 1.9 4.6 1.9 1.9 4.6 1.9Zm0-3q-1.45 0-2.475-1.025Q20.5 25.45 20.5 24q0-1.45 1.025-2.475Q22.55 20.5 24 20.5q1.45 0 2.475 1.025Q27.5 22.55 27.5 24q0 1.45-1.025 2.475Q25.45 27.5 24 27.5Zm0-3.5Zm-2.2 17h4.4l.7-5.6q1.65-.4 3.125-1.25T32.7 32.1l5.3 2.3 2-3.6-4.7-3.45q.2-.85.325-1.675.125-.825.125-1.675 0-.85-.1-1.675-.1-.825-.35-1.675L40 17.2l-2-3.6-5.3 2.3q-1.15-1.3-2.6-2.175-1.45-.875-3.2-1.125L26.2 7h-4.4l-.7 5.6q-1.7.35-3.175 1.2-1.475.85-2.625 2.1L10 13.6l-2 3.6 4.7 3.45q-.2.85-.325 1.675-.125.825-.125 1.675 0 .85.125 1.675.125.825.325 1.675L8 30.8l2 3.6 5.3-2.3q1.2 1.2 2.675 2.05Q19.45 35 21.1 35.4Z"/></svg>

After

Width:  |  Height:  |  Size: 1.1 KiB

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>
@ -35,4 +35,4 @@
</div>
</div>
<div class="background"></div>
</div>
</div>

View File

@ -35,7 +35,7 @@
z-index: 1000;
/* enables scrolling for tall popins */
overflow: auto;
.header {
padding: 10px;
//display: block;
@ -49,7 +49,7 @@
float: right;
}
}
.body {
//display: block;
padding: 20px;

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"
*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="inert_element unselectable"
*ngIf="isNotButton(data)"
[ngStyle]="{'float': data.position}"
[ngClass]="getClassModel(data.model)">
<div class="xdesktop" *ngIf="data.icon"><i class="material-icons">{{data.icon}}</i> {{data.title}}</div>
<div class="xmobile" *ngIf="data.icon">
<i class="material-icons">{{data.icon}}</i>
</div>
<div class="xdesktop" *ngIf="!data.icon">
{{data.title}}
</div>
<div class="xdesktop" *ngIf="!data.icon">{{data.title}}</div>
</div>
<button class="item"
*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>
<button
class="item unselectable"
*ngIf="!isNotButton(data)"
(click)="onGeneric(data, $event)"
(auxclick)="onGeneric(data, $event)"
[ngStyle]="{'float': data.position}"
[ngClass]="getClassModel(data.model)"
[disable]="false">
<div class="avatar unselectable" *ngIf="data.image"><img class="avatar" src="{{data.image}}" /> {{data.title}}</div>
<div class="xdesktop" *ngIf="data.icon && !data.image">
<i class="material-icons">{{data.icon}}</i> {{data.title}}
</div>
<div class="xmobile" *ngIf="data.icon && !data.image">
<i class="material-icons">{{data.icon}}</i>
</div>
<div class="xdesktop" *ngIf="!data.icon && !data.image">
{{data.title}}
</div>
<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"
*ngIf="isNotButton(data)"
[ngStyle]="{'float': data.position}"
[ngClass]="getClassModel(data.model)" >
<div class="xdesktop"
*ngIf="data.icon"
[ngStyle]="{'float': data.position}">
<div
class="inert_element unselectable"
*ngIf="isNotButton(data)"
[ngStyle]="{'float': data.position}"
[ngClass]="getClassModel(data.model)">
<div class="xdesktop" *ngIf="data.icon" [ngStyle]="{'float': data.position}">
<i class="material-icons">{{data.icon}}</i> {{data.title}}
</div>
<div class="xmobile"
*ngIf="data.icon"
[ngStyle]="{'float': data.position}">
<div class="xmobile" *ngIf="data.icon" [ngStyle]="{'float': data.position}">
<i class="material-icons">{{data.icon}}</i>
</div>
<div *ngIf="!data.icon"
[ngStyle]="{'float': data.position}">
{{data.title}}
</div>
<div *ngIf="!data.icon" [ngStyle]="{'float': data.position}">{{data.title}}</div>
</div>
<button class="item"
*ngIf="isEnable(data) && !isNotButton(data)"
(click)="onGeneric(data, $event)"
(auxclick)="onGeneric(data, $event)"
[ngStyle]="{'float': data.position}"
[ngClass]="getClassModel(data.model)"
[disable]="false">
<div *ngIf="data.icon"
[ngStyle]="{'float': data.position}">
<button
class="item"
*ngIf="isEnable(data) && !isNotButton(data)"
(click)="onGeneric(data, $event)"
(auxclick)="onGeneric(data, $event)"
[ngStyle]="{'float': data.position}"
[ngClass]="getClassModel(data.model)"
[disable]="false">
<div *ngIf="data.icon" [ngStyle]="{'float': data.position}">
<i class="material-icons">{{data.icon}}</i> {{data.title}}
</div>
<div *ngIf="!data.icon"
[ngStyle]="{'float': data.position}">
{{data.title}}
</div>
<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,25 +12,24 @@
}
.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;
box-shadow: none;
flex-direction: column;
flex-wrap: nowrap;
@ -44,9 +41,9 @@
border: none;
z-index: 300;
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,61 +53,61 @@
/*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;
pointer-events: none;
}
&:after {
border-color: rgba(136, 183, 213, 0);
border-bottom-color: #263238;
border-width: 15px;
margin-left: -15px;
}
}
.menu-left {
top:75px;
left:15px;
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;
box-shadow: none;
min-height: 56px;
flex-direction: column;
@ -125,9 +122,9 @@
max-height: 1000px;
z-index: 3;
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;
@ -171,14 +167,14 @@
font-weight: bold;
font-size: 15px;
}
.material-icons {
vertical-align: middle;
}
.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,28 +42,26 @@ 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-' + this.subMenuPosition;
return 'menu-left';
}
return 'menu-' + this.subMenuPosition;
}
getClassModel(data?:string): string {
getClassModel(data?: string): string {
if (isNullOrUndefined(data)) {
return "";
}
return 'model_' + data;
return '';
}
return 'model_' + data;
}
onGeneric(data: MenuItem, event: any): void {
@ -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">
<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>
</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,71 +1,67 @@
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 {
// Position of the menue element
position: MenuPosition;
// Hover help
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
image?: string;
// Displayed Title
title: string;
// Jump Link (If undefined: it is considered as text and not a button)
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)
callback?: boolean;
// Other data that want to be set by the user
otherData?: any;
// Enable or not the elemnt
enable?: boolean;
// Menu model For a subList of elements
subMenu?: MenuItem[];
};
// Position of the menue element
position: MenuPosition;
// Hover help
hover?: string;
// Icon of the menue (need to be a meterial-icon name
icon?: string;
// Displayed Title
image?: string;
// Displayed Title
title: string;
// Model of the display:
model?: string;
// Jump Link (If undefined: it is considered as text and not a button)
navigateTo?: string;
// Menu model For a subList of elements
callback?: boolean;
// Other data that want to be set by the user
otherData?: any;
// Menu model For a subList of elements
enable?: boolean;
// Menu model For a subList of elements
subMenu?: MenuItem[];
}
export function isMenuItem(data: any): data is MenuItem {
if (isNullOrUndefined(data)) {
return false;
}
if (!isObject(data)) {
return false;
}
if (!isMenuPosition(data.position)) {
return false;
}
if (!isOptionalOf(data.hover, isString)) {
return false;
}
if (!isOptionalOf(data.icon, isString)) {
return false;
}
if (!isOptionalOf(data.image, isString)) {
return false;
}
if (!isString(data.title)) {
return false;
}
if (!isOptionalOf(data.navigateTo, isString)) {
return false;
}
if (!isOptionalArrayOf(data.subMenu, isMenuItem)) {
return false;
}
return true;
if (isNullOrUndefined(data)) {
return false;
}
if (!isObject(data)) {
return false;
}
if (!isMenuPosition(data.position)) {
return false;
}
if (!isOptionalOf(data.hover, isString)) {
return false;
}
if (!isOptionalOf(data.icon, isString)) {
return false;
}
if (!isOptionalOf(data.image, isString)) {
return false;
}
if (!isString(data.title)) {
return false;
}
if (!isOptionalOf(data.navigateTo, isString)) {
return false;
}
if (!isOptionalArrayOf(data.subMenu, isMenuItem)) {
return false;
}
return true;
}

View File

@ -1,34 +1,31 @@
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;
name: string;
description?: string;
parentId?: number;
covers?: number[];
};
id: number;
name: string;
description?: string;
parentId?: number;
covers?: number[];
}
export function isNodeData(data: any): data is NodeData {
if (!isObject(data)) {
return false;
}
if (!isNumberFinite(data.id)) {
return false;
}
if (!isString(data.name)) {
return false;
}
if (!isOptionalOf(data.description, isString)) {
return false;
}
if (!isOptionalOf(data.parentId, isNumberFinite)) {
return false;
}
if (!isOptionalArrayOf(data.cover, isNumberFinite)) {
return false;
}
return true;
}
if (!isObject(data)) {
return false;
}
if (!isNumberFinite(data.id)) {
return false;
}
if (!isString(data.name)) {
return false;
}
if (!isOptionalOf(data.description, isString)) {
return false;
}
if (!isOptionalOf(data.parentId, isNumberFinite)) {
return false;
}
if (!isOptionalArrayOf(data.cover, isNumberFinite)) {
return false;
}
return true;
}

View File

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

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,31 +1,34 @@
<div>
<app-popin id="popin-upload-progress"
popSize="medium"
popTitle="Upload Media File"
[closeTitle]="closeButtonTitle"
[otherTitle]="otherButtonTitle"
[validateTitle]="validateButtonTitle"
(callback)="eventPopUp($event[0])">
<app-popin
id="popin-upload-progress"
popSize="medium"
popTitle="Upload Media File"
[closeTitle]="closeButtonTitle"
[otherTitle]="otherButtonTitle"
[validateTitle]="validateButtonTitle"
(callback)="eventPopUp($event[0])">
<p class="expand">
<label class="unselectable"><b>{{mediaTitle}}</b></label>
</p>
<div *ngIf="progress != 100" class="progress-back">
<div class="progress-bar" style="width:{{progress}}%">&nbsp;&nbsp;&nbsp;{{progress}}%</div>
<div 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>
</div>
</div>

View File

@ -1,23 +1,21 @@
.expand {
width: 100%;
input {
width: 100%;
};
}
textarea {
width: 100%;
};
}
}
.progress-back {
color:#000!important;
background-color:#f1f1f1!important;
border-radius: 3px;
color: #000 !important;
background-color: #f1f1f1 !important;
border-radius: 3px;
}
.progress-bar {
color:#000000!important;
background-color:#4CAF50!important;
border-radius: 3px;
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}`;
}
if (count >= 100) {
return ` ${count}`;
}
if (count >= 10) {
return ` ${count}`;
}
return ` ${count}`;
}
limit3(count:number):string {
if(count >= 1000) {
return `${ count}`;
}
if(count >= 100) {
return ` ${ count}`;
}
if(count >= 10) {
return ` ${ count}`;
}
return ` ${ count}`;
}
convertInHuman(countIn:number):string {
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>
</div>

View File

@ -1,25 +1,24 @@
.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;
text-align: center;
line-height: 200%;
@ -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>
</div>

View File

@ -1,26 +1,25 @@
.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;
text-align: left;
line-height: 200%;
@ -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>
</div>

View File

@ -1,25 +1,24 @@
.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;
text-align: center;
line-height: 200%;
@ -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,17 +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,
//UploadScene,
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;
@ -77,18 +76,19 @@ span.psw {
border-style: solid;
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;
pointer-events: none;
}
&:after {
border-bottom-color: #f44336;
border-width: 10px;
@ -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) => {
self.userName = userName;
setTimeout(function(){
self.router.navigate([ realDst ], { replaceUrl:true });
}, 500); // 2 seconds
}).catch(() => {
this.token = "ERROR_ME";
})
this.userService
.startSession(this.token, this.keepConnected)
.then((userName: string) => {
self.userName = userName;
setTimeout(function () {
self.router.navigate([realDst], { replaceUrl: true });
}, 500); // 2 seconds
})
.catch(() => {
this.token = 'ERROR_ME';
});
} else if (this.token === '__LOGOUT__') {
this.userService.removeSession();
const destination = (this.ssoData);
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() {
}
set(cname: string, cvalue: string, exdays: number): void {
if(this.get(cname) !== '') {
@Injectable()
export class CookiesService {
constructor() {}
set(cname: string, cvalue: string, exdays: number): void {
if (this.get(cname) !== '') {
// reset previous cookies...
document.cookie = `${cname }=;expires=Thu, 01 Jan 1970 00:00:00 GMT;path=/`;
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({
server: properties.server,
api: properties.endPoint,
inputOptions: properties.params,
});
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,49 +96,61 @@ 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
})
return result;
};
requestJson(properties: HTTPRequest) : Promise<ModelResponseHttp> {
return new Promise((resolve, reject) => {
this.request(properties).then((response: Response) => {
if(response.status >= 200 && response.status <= 299) {
const contentType = response.headers.get('Content-Type');
if (contentType === HTTPMimeType.JSON) {
response.json().then((value:any) => {
//console.log(`REICEIVE ==> ${response.status}=${ JSON.stringify(value, null, 2)}`);
resolve({ status:response.status, data:value });
}).catch((reason:any)=> {
reject({ status:999, data:reason });
});
} else {
console.error(`content Type is not Json: ${contentType}`)
reject({ status:999, data:`content Type is not Json: ${contentType}` });
}
} else {
console.error(`wring correct status: ${response.status}`)
reject({ status:900, data: response });
}
}).catch((error: any) => {
reject({ status:error.status, data:error.error });
});
body,
});
};
return result;
}
requestImage(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) {
const contentType = response.headers.get('Content-Type');
//console.log(`REICEIVE ==> ${response.status}`);
resolve({ status:900, data: response });
/*
this.request(properties)
.then((response: Response) => {
if (response.status >= 200 && response.status <= 299) {
const contentType = response.headers.get('Content-Type');
if (contentType === HTTPMimeType.JSON) {
response
.json()
.then((value: any) => {
//console.log(`RECEIVE ==> ${response.status}=${ JSON.stringify(value, null, 2)}`);
resolve({ status: response.status, data: value });
})
.catch((reason: any) => {
reject({ status: 999, data: reason });
});
} else {
console.error(`content Type is not Json: ${contentType}`);
reject({ status: 999, data: `content Type is not Json: ${contentType}` });
}
} else {
console.error(`wring correct status: ${response.status}`);
reject({ status: 900, data: response });
}
})
.catch((error: any) => {
reject({
time: Date(),
status: 999,
error: error,
statusMessage: "Fetch error",
message: "http-wrapper.ts detect an error in the fetch request"
});
});
});
}
requestImage(properties: HTTPRequest): Promise<ModelResponseHttp> {
return new Promise((resolve, reject) => {
this.request(properties)
.then((response: Response) => {
if (response.status >= 200 && response.status <= 299) {
const contentType = response.headers.get('Content-Type');
//console.log(`REICEIVE ==> ${response.status}`);
resolve({ status: 900, data: response });
/*
resolve({ status:response.status, data:value });
}).catch((reason:any)=> {
reject({ status:999, data:reason });
@ -151,36 +160,51 @@ export class HttpWrapperService {
reject({ status:999, data:`content Type is not Json: ${contentType}` });
}
*/
} else {
console.error(`wring correct status: ${response.status}`)
resolve({ status:900, data: response });
}
}).catch((error: any) => {
reject({ status:error.status, data:error.error });
});
} else {
console.error(`wring correct status: ${response.status}`);
resolve({ status: 900, data: response });
}
})
.catch((error: any) => {
reject({
time: Date(),
status: 999,
error: error,
statusMessage: "Fetch image error",
message: "http-wrapper.ts detect an error in the fetch request"
});
});
});
}
createRESTCall2({ api, server, inputOptions, addURLToken }: { server?: string; api: UrlPath; inputOptions?: object; addURLToken?:boolean }) {
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, {
headers: new HttpHeaders(headerOption),
reportProgress: true,
observe: 'events'
});
let self = this;
request.subscribe((res: any) => {
if(self.displayReturn === true) {
console.log(`!! data ${ JSON.stringify(res, null, 2)}`);
}
if(res.type === HttpEventType.Sent) {
/* res.type === 0 */
//console.log('post : Sent');
} else if(res.type === HttpEventType.UploadProgress) {
/* res.type === 1 */
// console.log("post : " + res.loaded + " / " + res.total);
progress(res.loaded, res.total);
} else if(res.type === HttpEventType.ResponseHeader) {
/* res.type === 2 */
//console.log('post : get header');
} else if(res.type === HttpEventType.DownloadProgress) {
/* res.type === 3 */
//console.log(`post : get DownloadProgress ${ res.loaded}`);
} else if(res.type === HttpEventType.Response) {
/* res.type === 4 */
//console.log('post : get response');
if(res.httpCode) {
resolve({ status:res.httpCode, data:res });
} else {
resolve({ status:200, data:res });
}
} else if(res.type === HttpEventType.User) {
/* res.type === 5 */
//console.log('post : get User');
} else {
console.log(`post : get unknown ... ${ res.type}`);
}
},
(error) => {
if(self.displayReturn === true) {
console.log(`an error occured status: ${ error.status}`);
console.log(`answer: ${ JSON.stringify(error, null, 2)}`);
}
reject({ status:error.status, data:error.error });
let request = this.http.post(connectionAddresses, data, {
headers: new HttpHeaders(headerOption),
reportProgress: true,
observe: 'events',
});
let self = this;
request.subscribe(
(res: any) => {
if (self.displayReturn === true) {
console.log(`!! data ${JSON.stringify(res, null, 2)}`);
}
if (res.type === HttpEventType.Sent) {
/* res.type === 0 */
//console.log('post : Sent');
} else if (res.type === HttpEventType.UploadProgress) {
/* res.type === 1 */
// console.log("post : " + res.loaded + " / " + res.total);
progress(res.loaded, res.total);
} else if (res.type === HttpEventType.ResponseHeader) {
/* res.type === 2 */
//console.log('post : get header');
} else if (res.type === HttpEventType.DownloadProgress) {
/* res.type === 3 */
//console.log(`post : get DownloadProgress ${ res.loaded}`);
} else if (res.type === HttpEventType.Response) {
/* res.type === 4 */
//console.log('post : get response');
if (res.httpCode) {
resolve({ status: res.httpCode, data: res });
} else {
resolve({ status: 200, data: res });
}
} else if (res.type === HttpEventType.User) {
/* res.type === 5 */
//console.log('post : get User');
} else {
console.log(`post : get unknown ... ${res.type}`);
}
},
error => {
if (self.displayReturn === true) {
console.log(`an error occured status: ${error.status}`);
console.log(`answer: ${JSON.stringify(error, null, 2)}`);
}
reject({ status: error.status, data: error.error });
}
);
});
}
// Deprecated ... old model stream
uploadMultipart(base:string, multipart:FormData, progress: ProgressCallback): any {
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) => {
endPoint: urlPath,
requestType: HTTPRequestModel.GET,
accept: HTTPMimeType.JSON,
contentType: HTTPMimeType.JSON,
}).then(
(response: ModelResponseHttp) => {
//console.log("URL: " + url + "\nRespond(" + response.status + "): " + JSON.stringify(response.data, null, 2));
if(response.status === 200) {
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) {
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 });
});
})
.then((response: Response) => {
if (response.status >= 200 && response.status <= 201) {
const contentType = response.headers.get('Content-Type');
if (contentType === HTTPMimeType.JSON) {
response
.json()
.then((value: any) => {
//console.log(`REICEIVE ==> ${response.status}=${ JSON.stringify(value, null, 2)}`);
resolve({ status: response.status, data: value });
})
.catch((reason: any) => {
reject({ status: 999, data: reason });
});
} else {
console.error(`content Type is not Json: ${contentType}`);
reject({ status: 998, data: `content Type is not Json: ${contentType}` });
}
} else {
console.error(`content Type is not Json: ${contentType}`)
reject({ status: 998, data:`content Type is not Json: ${contentType}` });
console.error(`wrong correct status: ${response.status}`);
reject({ status: 900, data: response });
}
} else {
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,57 +425,67 @@ export class HttpWrapperService {
accept: HTTPMimeType.JSON,
contentType: HTTPMimeType.JSON,
body: data,
}).then((response: Response) => {
if(response.status >= 200 && response.status <= 201) {
const contentType = response.headers.get('Content-Type');
if (contentType === HTTPMimeType.JSON) {
response.json().then((value:any) => {
//console.log(`REICEIVE ==> ${response.status}=${ JSON.stringify(value, null, 2)}`);
resolve({ status:response.status, data:value });
}).catch((reason:any)=> {
reject({ status:999, data:reason });
});
})
.then((response: Response) => {
if (response.status >= 200 && response.status <= 201) {
const contentType = response.headers.get('Content-Type');
if (contentType === HTTPMimeType.JSON) {
response
.json()
.then((value: any) => {
//console.log(`REICEIVE ==> ${response.status}=${ JSON.stringify(value, null, 2)}`);
resolve({ status: response.status, data: value });
})
.catch((reason: any) => {
reject({ status: 999, data: reason });
});
} else {
console.error(`content Type is not Json: ${contentType}`);
reject({ status: 998, data: `content Type is not Json: ${contentType}` });
}
} else {
console.error(`content Type is not Json: ${contentType}`)
reject({ status: 998, data:`content Type is not Json: ${contentType}` });
console.error(`wrong correct status: ${response.status}`);
reject({ status: 900, data: response });
}
} else {
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) {
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 });
});
})
.then((response: Response) => {
if (response.status >= 200 && response.status <= 201) {
const contentType = response.headers.get('Content-Type');
if (contentType === HTTPMimeType.JSON) {
response
.json()
.then((value: any) => {
//console.log(`REICEIVE ==> ${response.status}=${ JSON.stringify(value, null, 2)}`);
resolve({ status: response.status, data: value });
})
.catch((reason: any) => {
reject({ status: 999, data: reason });
});
} else {
console.error(`content Type is not Json: ${contentType}`);
reject({ status: 998, data: `content Type is not Json: ${contentType}` });
}
} else {
console.error(`content Type is not Json: ${contentType}`)
reject({ status: 998, data:`content Type is not Json: ${contentType}` });
console.error(`wrong correct status: ${response.status}`);
reject({ status: 900, data: response });
}
} else {
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,29 +1,35 @@
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,
CookiesService,
StorageService,
HttpWrapperService,
ModelResponseHttp,
HTTPRequest,
HTTPMimeType,
HTTPRequestModel,
PopInService,
SessionService,
UserService,
SSOService,
OnlyUsersGuard,
OnlyUsersGuardHome,
OnlyUnregisteredGuardHome,
OnlyAdminGuard,
BddService,
CookiesService,
StorageService,
HttpWrapperService,
ModelResponseHttp,
HTTPRequest,
HTTPMimeType,
HTTPRequestModel,
PopInService,
SessionService,
UserService,
SSOService,
OnlyUsersGuard,
OnlyUsersGuardHome,
OnlyUnregisteredGuardHome,
OnlyAdminGuard,
NotificationService,
};

View File

@ -4,18 +4,16 @@
* @license PROPRIETARY (see license file)
*/
import { Injectable } from '@angular/core';
import { Injectable } from '@angular/core';
import { environment } from 'environments/environment';
@Injectable()
export class StorageService {
private baseLocalStorageName = environment.applName + '_';
constructor() {
}
set(cname: string, cvalue: string): void {
@Injectable()
export class StorageService {
private baseLocalStorageName = environment.applName + '_';
constructor() {}
set(cname: string, cvalue: string): void {
//console.debug(`storage set: ${cname} : ${cvalue}`);
localStorage.setItem(this.baseLocalStorageName + cname, cvalue);
}
@ -23,16 +21,16 @@ import { environment } from 'environments/environment';
setSession(cname: string, cvalue: string): void {
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;
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}`);
create({
userId,
userLogin,
tokenJwt,
}: {
userId: string;
userLogin: string;
tokenJwt: string;
}) {
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;
}
return this.right.ADMIN;
}
if(type === UserRoles222.user) {
// is connected ==> is user
return this.sessionId !== null;
if (type === UserRoles222.user) {
if (isNullOrUndefined(this.right.USER)) {
return false;
}
return this.right.USER;
}
if(type === UserRoles222.guest) {
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,60 +123,56 @@ 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) ) {
return true;
} else {
this.router.navigateByUrl('/forbidden');
return false;
}
}
canActivate() {
console.log('OnlyLoggedInUsers');
if (this.sessionService.hasRight(UserRoles222.user) || this.sessionService.hasRight(UserRoles222.admin)) {
return true;
} else {
this.router.navigateByUrl('/forbidden');
return false;
}
}
}
@Injectable()
export class OnlyUsersGuardHome implements CanActivate {
constructor(private sessionService: SessionService,
private router: Router) {};
constructor(private sessionService: SessionService, private router: Router) { }
canActivate() {
if (this.sessionService.hasRight(UserRoles222.user) || this.sessionService.hasRight(UserRoles222.admin) ) {
return true;
} else {
this.router.navigateByUrl('/unregistered');
return false;
}
}
canActivate() {
if (this.sessionService.hasRight(UserRoles222.user) || this.sessionService.hasRight(UserRoles222.admin)) {
return true;
} else {
this.router.navigateByUrl('/unregistered');
return false;
}
}
}
@Injectable()
export class OnlyUnregisteredGuardHome implements CanActivate {
constructor(private sessionService: SessionService,
private router: Router) {};
constructor(private sessionService: SessionService, private router: Router) { }
canActivate() {
if (!this.sessionService.islogged() ) {
return true;
} else {
this.router.navigateByUrl('/home');
return false;
}
}
canActivate() {
if (!this.sessionService.islogged()) {
return true;
} else {
this.router.navigateByUrl('/home');
return false;
}
}
}
@Injectable()
export class OnlyAdminGuard implements CanActivate {
constructor(private sessionService: SessionService,
private router: Router) {};
constructor(private sessionService: SessionService, private router: Router) { }
canActivate() {
if (this.sessionService.hasRight(UserRoles222.user)) {
return true;
} else {
this.router.navigateByUrl('/forbidden');
return false;
}
}
canActivate() {
if (this.sessionService.hasRight(UserRoles222.user)) {
return true;
} else {
this.router.navigateByUrl('/forbidden');
return false;
}
}
}

View File

@ -12,32 +12,56 @@ import { HTTPMimeType, HTTPRequestModel, HttpWrapperService, ModelResponseHttp }
@Injectable()
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

@ -14,22 +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,69 +66,81 @@ 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 ...
// 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.router.navigateByUrl(locationOrigin);
console.log(`update global URL = ${locationOrigin}`);
resolve();
}).catch(() => {
// jump in the sign-in page (automatically of request remember-me)
if(rememberMe) {
// jump to the sso !!! (remove local data to prevent login loop)
this.storageService.remove(this.cookiesRememberMe);
this.storageService.remove(this.cookiesToken);
this.storageService.removeSession(this.cookiesToken);
self.ssoService.requestSignIn(locationOrigin);
reject();
}
resolve();
});
self.startSession(token, rememberMe)
.then(() => {
self.router.navigateByUrl(locationOrigin);
console.log(`update global URL = ${locationOrigin}`);
resolve();
})
.catch(() => {
// jump in the sign-in page (automatically of request remember-me)
if (rememberMe) {
// jump to the sso !!! (remove local data to prevent login loop)
this.storageService.remove(this.cookiesRememberMe);
this.storageService.remove(this.cookiesToken);
this.storageService.removeSession(this.cookiesToken);
self.ssoService.requestSignIn(locationOrigin);
reject();
}
resolve();
});
} else {
console.log(`Get previous connection ... `);
if(rememberMe) {
if (rememberMe) {
// jump to the sso !!! (remove local data to prevent login loop)
this.storageService.remove(this.cookiesRememberMe);
this.storageService.remove(this.cookiesToken);
@ -141,94 +152,103 @@ 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,
userId: response.data.id,
userLogin: response.data.login,
userEMail: response.data.email,
userAdmin: response.data.admin,
userBlocked: response.data.blocked,
userRemoved: response.data.removed,
userAvatar: response.data.avatar,
tokenJwt: token,
});
console.log(`loginWithToken : get some data to check: ${JSON.stringify(response.data)}`);
self.sessionService.create({
//sessionId: response.data.sessionId,
userId: response.data.id,
userLogin: response.data.login,
//userEMail: response.data.email,
//userAdmin: response.data.admin,
//userBlocked: response.data.blocked,
//userRemoved: response.data.removed,
//userAvatar: response.data.avatar,
tokenJwt: token,
});
resolve(true);
}).catch((error:any) => {
reject(`return ERROR ${ JSON.stringify(error, null, 2)}`);
})
.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({
server: 'karso',
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;
}
@ -238,10 +258,9 @@ export class UserService {
authorizedRoles = [_authorizedRoles];
}
return ( authService.isAuthenticated()
&& _authorizedRoles.indexOf(Session.userRole) !== -1
);
&& _authorizedRoles.indexOf(Session.userRole) !== -1
);
*/
return false;
}
}

View File

@ -1,17 +1,17 @@
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);
} else if (pathName.startsWith('/' + environment.applName)) {
pathName = pathName.substring(environment.applName.length + 1);
} else if (pathName.startsWith(environment.applName + '/')) {
pathName = pathName.substring(environment.applName.length+1);
} else if (pathName.startsWith(environment.applName)) {
pathName = pathName.substring(environment.applName.length);
}
return pathName;
}
let pathName = location.pathname;
//console.log("start Path-name: '" + pathName + "'");
//console.log("check with: '" + environment.applName + "/sso/" + "'");
if (pathName.startsWith('/' + environment.applName + '/')) {
pathName = pathName.substring(environment.applName.length + 2);
} else if (pathName.startsWith('/' + environment.applName)) {
pathName = pathName.substring(environment.applName.length + 1);
} else if (pathName.startsWith(environment.applName + '/')) {
pathName = pathName.substring(environment.applName.length + 1);
} else if (pathName.startsWith(environment.applName)) {
pathName = pathName.substring(environment.applName.length);
}
return pathName;
}

View File

@ -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) {
out.push(value[jjj]);
}
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,29 +1,51 @@
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,
isNumberFinite,
isBoolean,
isString,
isArray,
isNull,
isUndefined,
isNullOrUndefined,
isObject,
isArrayOf,
isArrayOfs,
isOptionalOf,
isOptionalArrayOf,
isInArray,
isStringNullOrUndefined,
DataInterface,
TypeCheck,
getApplicationLocation,
sha512,
}
isNumber,
isNumberFinite,
isBoolean,
isString,
isArray,
isNull,
isUndefined,
isNullOrUndefined,
isObject,
isArrayOf,
isArrayOfs,
isOptionalOf,
isOptionalArrayOf,
isInArray,
isStringNullOrUndefined,
DataInterface,
TypeCheck,
getApplicationLocation,
sha512,
createPasswordState,
checkEmailValidity,
checkPasswordValidity,
checkLoginValidity,
getLoginType,
createLoginState,
isNumeric,
};

View File

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

Some files were not shown because too many files have changed in this diff Show More