From a4fe1f1ed1fd0c81770195ef21686ba73633500a Mon Sep 17 00:00:00 2001 From: Edouard DUPIN Date: Sun, 29 Jan 2023 23:14:48 +0100 Subject: [PATCH] [DEV] add application add and remove ==> no EDIT --- .../kar/karso/api/ApplicationResource.java | 40 +++- back/src/org/kar/karso/model/Application.java | 23 ++- front/src/app/app-routing.module.ts | 6 + front/src/app/app.component.ts | 7 + front/src/app/app.module.ts | 4 + front/src/app/scene/home/home.ts | 8 +- front/src/app/scene/index.ts | 2 + .../manage-application.html | 97 +++++++++ .../manage-application.less | 164 +++++++++++++++ .../manage-application/manage-application.ts | 192 ++++++++++++++++++ front/src/app/service/application.ts | 80 +++++++- front/src/app/service/index.ts | 4 +- front/src/common/service/index.ts | 2 + front/src/common/service/notification.ts | 25 +++ front/src/common/service/popin.ts | 7 +- front/src/styles.less | 33 +++ 16 files changed, 674 insertions(+), 20 deletions(-) create mode 100644 front/src/app/scene/manage-application/manage-application.html create mode 100644 front/src/app/scene/manage-application/manage-application.less create mode 100644 front/src/app/scene/manage-application/manage-application.ts create mode 100644 front/src/common/service/notification.ts diff --git a/back/src/org/kar/karso/api/ApplicationResource.java b/back/src/org/kar/karso/api/ApplicationResource.java index bdf34de..5bf4962 100755 --- a/back/src/org/kar/karso/api/ApplicationResource.java +++ b/back/src/org/kar/karso/api/ApplicationResource.java @@ -4,8 +4,8 @@ import org.kar.archidata.SqlWrapper; import org.kar.archidata.filter.GenericContext; import org.kar.karso.model.*; import org.kar.archidata.util.JWTWrapper; -import org.kar.archidata.annotation.security.PermitAll; import org.kar.archidata.annotation.security.RolesAllowed; +import org.kar.archidata.exception.InputException; import java.util.List; @@ -16,7 +16,6 @@ import javax.ws.rs.core.Response; import javax.ws.rs.core.SecurityContext; - @Path("/application") @Produces( MediaType.APPLICATION_JSON) public class ApplicationResource { @@ -30,6 +29,7 @@ public class ApplicationResource { System.out.println("getApplications"); return SqlWrapper.gets(Application.class, false); } + @GET @Path("small") @RolesAllowed(value= {"USER", "ADMIN"}) @@ -38,7 +38,6 @@ public class ApplicationResource { return SqlWrapper.gets(ApplicationSmall.class, false); } - @GET @Path("get_token") @RolesAllowed(value= {"USER", "ADMIN"}) @@ -85,6 +84,7 @@ public class ApplicationResource { } return Response.status(201).entity("{ \"url\":\"" + returnAdress + "\", \"jwt\":\"" + ret + "\"}").build(); } + @GET @Path("return") @RolesAllowed(value= {"USER", "ADMIN"}) @@ -131,6 +131,40 @@ public class ApplicationResource { return Response.status(201).entity("{ \"url\":\"" + returnAdress + "\"}").build(); } + @DELETE + @Path("{id}") + @RolesAllowed("ADMIN") + @Produces( value = MediaType.TEXT_PLAIN ) + public void remove(@Context SecurityContext sc, @PathParam("id") long applicationId) throws Exception { + SqlWrapper.setDelete(Application.class, applicationId); + } + + @POST + @RolesAllowed("ADMIN") + public Application create(Application application) throws Exception { + System.out.println("create new application " + application); + // verify login or email is correct: + if (application.name == null || application.name.length() < 6) { + throw new InputException("name", "create application (name too small: '" + application.name + "')"); + } + if (application.redirect == null || application.redirect.length() < 6) { + throw new InputException("redirect", "create application (redirect too small: '" + application.redirect + "')"); + } + application.id = null; + application.create_date = null; + application.deleted = null; + application.modify_date = null; + return SqlWrapper.insert(application); + } + + @PUT + @Path("{id}") + @RolesAllowed("ADMIN") + @Consumes(MediaType.APPLICATION_JSON) + public Application put(@PathParam("id") Long id, String jsonRequest) throws Exception { + SqlWrapper.update(Application.class, id, jsonRequest); + return SqlWrapper.get(Application.class, id); + } } diff --git a/back/src/org/kar/karso/model/Application.java b/back/src/org/kar/karso/model/Application.java index 161cc62..e259510 100644 --- a/back/src/org/kar/karso/model/Application.java +++ b/back/src/org/kar/karso/model/Application.java @@ -11,6 +11,7 @@ CREATE TABLE `application` ( */ import org.kar.archidata.annotation.SQLComment; +import org.kar.archidata.annotation.SQLDefault; import org.kar.archidata.annotation.SQLIfNotExists; import org.kar.archidata.annotation.SQLLimitSize; import org.kar.archidata.annotation.SQLNotNull; @@ -23,20 +24,23 @@ import com.fasterxml.jackson.annotation.JsonInclude; @SQLIfNotExists @JsonInclude(JsonInclude.Include.NON_NULL) public class Application extends GenericTable{ - @SQLLimitSize(512) + @SQLLimitSize(256) public String name; - @SQLLimitSize(512) + @SQLLimitSize(2048) public String description; - @SQLLimitSize(512) + @SQLLimitSize(2048) @SQLNotNull public String redirect; - @SQLLimitSize(512) + @SQLLimitSize(2048) + @SQLDefault("http://localhost:4200/sso/") public String redirectDev; - @SQLLimitSize(512) + @SQLLimitSize(2048) + @SQLDefault("http://localhost:4200/sso/notification") public String notification; @SQLNotNull @SQLComment("Expiration time ") - public int ttl; + @SQLDefault("666") + public Integer ttl; public Application() { } @@ -54,3 +58,10 @@ public class Application extends GenericTable{ '}'; } } +/* +ALTER TABLE `application` +CHANGE `description` `description` varchar(2048) COLLATE 'utf8mb4_0900_ai_ci' NULL COMMENT 'description of the application' AFTER `name`, +CHANGE `redirect` `redirect` varchar(2048) COLLATE 'latin1_bin' NOT NULL COMMENT 'Token (can be not unique)' AFTER `description`, +CHANGE `redirectDev` `redirectDev` varchar(2048) COLLATE 'latin1_bin' NOT NULL DEFAULT 'http://localhost:4200/sso/' AFTER `redirect`, +CHANGE `notification` `notification` varchar(2048) COLLATE 'latin1_bin' NOT NULL DEFAULT 'http://localhost:4200/sso/notification' AFTER `redirectDev`; +*/ \ No newline at end of file diff --git a/front/src/app/app-routing.module.ts b/front/src/app/app-routing.module.ts index 02ad7fc..25c47c1 100644 --- a/front/src/app/app-routing.module.ts +++ b/front/src/app/app-routing.module.ts @@ -17,6 +17,7 @@ import { SignUpScene, HomeUnregisteredScene, ManageAccountsScene, + ManageApplicationScene, } from './scene'; import { OnlyAdminGuard, OnlyUnregisteredGuardHome, OnlyUsersGuard, OnlyUsersGuardHome } from 'common/service/session'; import { ForbiddenScene, NotFound404Scene } from 'common/scene'; @@ -72,6 +73,11 @@ const routes: Routes = [ component: ManageAccountsScene, canActivate: [OnlyAdminGuard], }, + { + path: 'manage_applications', + component: ManageApplicationScene, + canActivate: [OnlyAdminGuard], + }, { path: '**', component: NotFound404Scene, diff --git a/front/src/app/app.component.ts b/front/src/app/app.component.ts index 25cf9ab..0e079c2 100644 --- a/front/src/app/app.component.ts +++ b/front/src/app/app.component.ts @@ -112,6 +112,13 @@ export class AppComponent implements OnInit { title: 'Manage Accounts', navigateTo: 'manage_accounts', enable: this.sessionService.userAdmin === true, + },{ + position: MenuPosition.LEFT, + hover: 'Admin of all the applications', + icon: 'app_registration', + title: 'Manage Applications', + navigateTo: 'manage_applications', + enable: this.sessionService.userAdmin === true, }, ], }, diff --git a/front/src/app/app.module.ts b/front/src/app/app.module.ts index 756c78f..2acc951 100644 --- a/front/src/app/app.module.ts +++ b/front/src/app/app.module.ts @@ -23,11 +23,13 @@ import { SettingsScene, HomeUnregisteredScene, ManageAccountsScene, + ManageApplicationScene, } from 'app/scene'; import { BddService, CookiesService, HttpWrapperService, + NotificationService, OnlyAdminGuard, OnlyUnregisteredGuardHome, OnlyUsersGuard, @@ -74,6 +76,7 @@ import { PopInUploadProgress, PopInDeleteConfirm } from 'common/popin'; ChangePasswordScene, HomeUnregisteredScene, ManageAccountsScene, + ManageApplicationScene, ], imports: [ BrowserModule, @@ -99,6 +102,7 @@ import { PopInUploadProgress, PopInDeleteConfirm } from 'common/popin'; SessionService, UserService, SSOService, + NotificationService, SettingsService, OnlyUsersGuard, OnlyAdminGuard, diff --git a/front/src/app/scene/home/home.ts b/front/src/app/scene/home/home.ts index 829735b..5baf2e6 100644 --- a/front/src/app/scene/home/home.ts +++ b/front/src/app/scene/home/home.ts @@ -6,7 +6,7 @@ import { Component, OnInit } from '@angular/core'; import { ApplicationService } from 'app/service'; -import { GetApplicationSmallnResponse, SpecificTokenResponse } from 'app/service/application'; +import { GetApplicationSmallResponse, SpecificTokenResponse } from 'app/service/application'; import { UserService } from 'common/service'; @Component({ @@ -16,21 +16,21 @@ import { UserService } from 'common/service'; }) export class HomeScene implements OnInit { error = ''; - dataList: GetApplicationSmallnResponse[]; + dataList: GetApplicationSmallResponse[]; constructor(private applicationService: ApplicationService, private userService: UserService) {} ngOnInit() { let self = this; this.applicationService .getApplicationsSmall() - .then((data: GetApplicationSmallnResponse[]) => { + .then((data: GetApplicationSmallResponse[]) => { self.dataList = data; }) .catch(error => { console.log(`fail to keep data : ${error}`); }); } - onClick(_event: any, data: GetApplicationSmallnResponse): void { + onClick(_event: any, data: GetApplicationSmallResponse): void { //window.location.href = data.redirect; let self = this; this.applicationService diff --git a/front/src/app/scene/index.ts b/front/src/app/scene/index.ts index 784a946..4ad73cf 100644 --- a/front/src/app/scene/index.ts +++ b/front/src/app/scene/index.ts @@ -5,6 +5,7 @@ import { HelpScene } from './help/help'; import { HomeUnregisteredScene } from './home-unregistered/home-unregistered'; import { HomeScene } from './home/home'; import { ManageAccountsScene } from './manage-accounts/manage-accounts'; +import { ManageApplicationScene } from './manage-application/manage-application'; import { SettingsScene } from './settings/settings'; import { SignInScene } from './sign-in/sign-in'; import { SignOutScene } from './sign-out/sign-out'; @@ -24,4 +25,5 @@ export { SettingsScene, HomeUnregisteredScene, ManageAccountsScene, + ManageApplicationScene, }; diff --git a/front/src/app/scene/manage-application/manage-application.html b/front/src/app/scene/manage-application/manage-application.html new file mode 100644 index 0000000..cd78c67 --- /dev/null +++ b/front/src/app/scene/manage-application/manage-application.html @@ -0,0 +1,97 @@ +
+
Manage Applications
+
+
+
+
Application
+
Availlable applications for this SSO
+
+
+ + + + + + + + + + + + + + + + + + + +
idnameDescriptionredirectTTLNotificationActions
{{application.id}}{{application.name}}{{application.description}}{{application.redirect}}{{application.ttl}}{{application.notification}} +   + +
+
+
+ +
+
+
+

+
+
+
Create new application
+
Add a new application on the server
+
+
+ + + + + + + + + +
Name: + + +
Redirect: + + +
+
+
+ +
+
+
+
+ + \ No newline at end of file diff --git a/front/src/app/scene/manage-application/manage-application.less b/front/src/app/scene/manage-application/manage-application.less new file mode 100644 index 0000000..2ba0e8e --- /dev/null +++ b/front/src/app/scene/manage-application/manage-application.less @@ -0,0 +1,164 @@ +.settings-title { + width: 80%; + border: solid; + border-width: 1px; + margin: auto; + padding: 10px 20px; + + border-color: black; + border-radius: 10px 10px 0px 0px; + background-color: gray; + + .group-title { + font-size: 24px; + font-weight: bold; + line-height: 24px; + vertical-align: middle; + margin: 10px 0 10px 0; + text-align: Left; + } + .group-description { + font-size: 16px; + line-height: 16px; + vertical-align: middle; + margin: 10px 0 10px 0; + text-align: Left; + } +} + +.settings-elements { + width: 80%; + border: solid; + border-width: 0px 1px; + margin: auto; + padding: 10px 20px; + + border-color: black; + border-radius: 0px; + background-color: lightgray; + vertical-align: middle; + text-align: Left; + + .elem-hr { + width: 100%; + border-color: black; + border: dashed; + border-width: 1px 0 0 0; + margin: 10px auto; + } + .elem-title { + font-size: 18px; + font-weight: bold; + margin: 0 10px 0 36px; + } + .elem-description { + font-size: 14px; + margin: 0 20px 10px 50px; + font-style: italic; + } + .elem-input { + font-size: 14px; + margin: 0 20px 10px 36px; + input { + width: 100%; + } + } +} + +.settings-validation { + width: 80%; + border: solid; + border-width: 1px; + margin: auto; + padding: 10px 20px; + + border-color: black; + border-radius: 0px 0px 10px 10px; + background-color: gray; +} + +.title { + //background-color: green; + font-size: 45px; + font-weight: bold; + line-height: 60px; + width: 100%; + text-align: center; + vertical-align: middle; + margin: 10px 0 10px 0; + text-shadow: 1px 1px 2px white, 0 0 1em white, 0 0 0.2em white; + text-transform: uppercase; + font-family: 'Roboto', 'Helvetica', 'Arial', sans-serif; +} +.item-home { + background-color: rgba(200, 200, 200, 0.5); + font-size: 20px; + height: 190px; + width: 200px; + margin: 5px; + padding: 0; + overflow: hidden; + // box-shadow: 0 1px 1.5px 0 rgba(0,0,0,.12),0 1px 1px 0 rgba(0,0,0,.24); + box-shadow: 0px 2px 4px 0 rgba(0, 0, 0, 0.6); + line-height: normal; + border: none; + font-family: 'Roboto', 'Helvetica', 'Arial', 'sans-serif'; + font-weight: 500; + text-transform: uppercase; + letter-spacing: 0; + will-change: box-shadow; + outline: none; + cursor: pointer; + text-decoration: none; + text-align: center; + transition-duration: 0.4s; + float: left; + display: block; + + h1 { + font-size: 24px; + } + + &:hover { + background-color: rgba(200, 200, 200, 1); + //box-shadow: 0px 2px 4px 0 rgba(255, 0, 0, 0.6); + } + + .material-icons { + vertical-align: middle; + } + + .material-icons { + position: absolute; + top: 50%; + left: 50%; + transform: ~'translate(-12px,-12px)'; + line-height: 24px; + width: 24px; + } +} + +@media all and (min-width: 1310px) { + .colomn_mutiple { + width: ~'calc(210px * 5)'; + margin: auto; + } +} + +.table-model { + tr:nth-child(odd) { + background-color: rgb(180, 180, 180); + //color: #fff; + } + th { + background-color: darkgray; + text-align: center; + } + td { + text-align: center; + } +} + +table { + width: 100%; +} diff --git a/front/src/app/scene/manage-application/manage-application.ts b/front/src/app/scene/manage-application/manage-application.ts new file mode 100644 index 0000000..c0c8e4a --- /dev/null +++ b/front/src/app/scene/manage-application/manage-application.ts @@ -0,0 +1,192 @@ +/** @file + * @author Edouard DUPIN + * @copyright 2018, Edouard DUPIN, all right reserved + * @license PROPRIETARY (see license file) + */ + +import { ChangeDetectionStrategy, ChangeDetectorRef, Component, OnInit } from '@angular/core'; +import { ApplicationService, ApplicationModel } from 'app/service'; +import { AsyncActionState } from 'common/component'; +import { NotificationService, PopInService } from 'common/service'; + +@Component({ + selector: 'app-settings', + templateUrl: './manage-application.html', + styleUrls: ['./manage-application.less'], + changeDetection: ChangeDetectionStrategy.Default, +}) +export class ManageApplicationScene implements OnInit { + applications: ApplicationModel[] = []; + + constructor( + private applicationService: ApplicationService, + private notificationService: NotificationService, + private popInService: PopInService, + private cdr: ChangeDetectorRef, + ) { + } + ngOnInit() { + let self = this; + this.applicationService + .gets() + .then((response: ApplicationModel[]) => { + console.log(`??? get full response: ${JSON.stringify(response, null, 4)}`); + self.applications = response; + }) + .catch((error: any) => { + console.log(`??? get ERROR response: ${JSON.stringify(error, null, 4)}`); + }); + } + + onRemoveApplication(_event: any, application: ApplicationModel) { + this.confirmDeleteComment = `Delete the application ID: [${application.id}] ${application.name}`; + this.confirmDeleteApplication = application; + this.popInService.open('popin-delete-confirm'); + } + + removeApplicationConfirm(application: ApplicationModel) { + let self = this; + this.applicationService.remove(application.id) + .then( + () => { + const index = self.applications.indexOf(application, 0); + if (index > -1) { + self.applications.splice(index, 1); + self.cdr.detectChanges(); + } + } + ).catch( + (error: any) => { + self.notificationService.errorRaw(`Fail to delete application: [${application.id}]: ${application.name} ==> ${error}`) + } + ); + } + confirmDeleteComment: string = undefined; + confirmDeleteApplication: ApplicationModel = undefined; + + deleteConfirmed() { + if(this.confirmDeleteApplication !== undefined) { + this.removeApplicationConfirm(this.confirmDeleteApplication); + this.confirmDeleteComment = undefined; + this.confirmDeleteApplication = undefined; + } + } + + + + + onEditApplication(_event: any, application: ApplicationModel) { + /* + user.admin = value; + console.log(`onSetAdmin: ${value} on ${user.login}`); + user.adminState = AsyncActionState.LOADING; + this.cdr.detectChanges(); + let self = this; + this.adminUserService.setAdmin(user.id, value) + .then( + () => { + user.adminState = AsyncActionState.DONE; + self.cdr.detectChanges(); + setTimeout(() => { + user.adminState = undefined; + self.cdr.detectChanges(); + }, 3000); + + } + ).catch( + (error: any) => { + user.adminState = AsyncActionState.FAIL; + self.cdr.detectChanges(); + setTimeout(() => { + user.adminState = undefined; + user.admin = !value; + self.cdr.detectChanges(); + }, 3000); + } + ); + */ + } + + + + + + public name: string = ''; + public nameState: boolean|string = false; + + public redirect: string = ''; + public redirectState: boolean|string = false; + + public validateButtonCreateApplicationDisabled: boolean = true; + /** + * update the state of the validation button. if all is OK, the button will became clickable + */ + updateButtonVisibility(): void { + if (this.nameState === true && this.redirectState === true) { + this.validateButtonCreateApplicationDisabled = false; + } else { + this.validateButtonCreateApplicationDisabled = true; + } + } + + /** + * Check the login writing rules + */ + checkName(newValue: string): void { + this.name = newValue; + if (this.name.length < 6) { + this.nameState = "This name is too small >=6."; + } + this.nameState = true; + for (let iii=0; iii { + self.createState = AsyncActionState.DONE; + console.log(`Get new user: ${JSON.stringify(data, null, 2)}`); + self.applications.push(data); + self.cdr.detectChanges(); + self.name = null; + self.redirect = null; + setTimeout(() => { + this.createState = undefined; + }, 3000); + } + ).catch( + (error: any) => { + self.createState = AsyncActionState.FAIL; + setTimeout(() => { + self.createState = undefined; + }, 3000); + } + ); + } +} diff --git a/front/src/app/service/application.ts b/front/src/app/service/application.ts index a705412..2b59d0e 100644 --- a/front/src/app/service/application.ts +++ b/front/src/app/service/application.ts @@ -29,12 +29,22 @@ export interface SpecificTokenResponse { export interface SpecificReturnResponse { url: string; } -export interface GetApplicationSmallnResponse { +export interface GetApplicationSmallResponse { name: string; description: string; redirect: string; } +export interface ApplicationModel { + id: number; + name: string; + description: string; + redirect: string; + redirectDev: string; + notification: string; + ttl: number; +} + @Injectable() export class ApplicationService { constructor(private http: HttpWrapperService, private sessionService: SessionService) { @@ -96,7 +106,7 @@ export class ApplicationService { }); }); } - getApplicationsSmall(): Promise { + getApplicationsSmall(): Promise { let self = this; return new Promise((resolve, reject) => { this.http @@ -120,4 +130,70 @@ export class ApplicationService { }); }); } + + gets(): Promise { + return new Promise((resolve, reject) => { + this.http + .requestJson({ + server: 'karso', + endPoint: 'application', + requestType: HTTPRequestModel.GET, + accept: HTTPMimeType.JSON, + contentType: HTTPMimeType.JSON, + }) + .then((response: ModelResponseHttp) => { + // TODO: check type ... + console.log( + `retreive return for application : get some data to check: ${JSON.stringify(response.data)}` + ); + // tODO: check the format... + resolve(response.data); + }) + .catch((error: any) => { + reject(`return ERROR ${JSON.stringify(error, null, 2)}`); + }); + }); + } + + create(name: string, redirect: string): Promise { + let body = { + name, + redirect, + }; + return new Promise((resolve, reject) => { + this.http + .requestJson({ + server: 'karso', + endPoint: 'application', + requestType: HTTPRequestModel.POST, + accept: HTTPMimeType.JSON, + contentType: HTTPMimeType.JSON, + body, + }) + .then((response: ModelResponseHttp) => { + resolve(response.data); + }) + .catch((error: any) => { + reject(`return ERROR ${JSON.stringify(error, null, 2)}`); + }); + }); + } + remove(id: number): Promise { + return new Promise((resolve, reject) => { + this.http + .request({ + server: 'karso', + endPoint: `application/${id}`, + requestType: HTTPRequestModel.DELETE, + accept: HTTPMimeType.ALL, + contentType: HTTPMimeType.JSON, + }) + .then(() => { + resolve(); + }) + .catch((error: any) => { + reject(`return ERROR ${JSON.stringify(error, null, 2)}`); + }); + }); + } } diff --git a/front/src/app/service/index.ts b/front/src/app/service/index.ts index 288754b..90f48d7 100644 --- a/front/src/app/service/index.ts +++ b/front/src/app/service/index.ts @@ -1,5 +1,5 @@ import { AdminUserService } from './admin-user'; -import { ApplicationService } from './application'; +import { ApplicationModel, ApplicationService } from './application'; import { SettingsService } from './settings'; -export { AdminUserService, ApplicationService, SettingsService }; +export { AdminUserService, ApplicationService, SettingsService, ApplicationModel }; diff --git a/front/src/common/service/index.ts b/front/src/common/service/index.ts index 348b8c9..2d36858 100644 --- a/front/src/common/service/index.ts +++ b/front/src/common/service/index.ts @@ -2,6 +2,7 @@ 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, @@ -30,4 +31,5 @@ export { OnlyUsersGuardHome, OnlyUnregisteredGuardHome, OnlyAdminGuard, + NotificationService, }; diff --git a/front/src/common/service/notification.ts b/front/src/common/service/notification.ts new file mode 100644 index 0000000..96a6b75 --- /dev/null +++ b/front/src/common/service/notification.ts @@ -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}`) + } +} diff --git a/front/src/common/service/popin.ts b/front/src/common/service/popin.ts index b328db2..039916b 100644 --- a/front/src/common/service/popin.ts +++ b/front/src/common/service/popin.ts @@ -30,16 +30,17 @@ 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++) { + console.log(` check: ${this.popins[iii].id}`); if (this.popins[iii].id === _id) { - //console.log(" ==>find it ..."); + console.log(" ==>find it ..."); this.popins[iii].open(); return; } } - // console.log(" ==> NOT found !!!!!"); + console.log(" ==> NOT found !!!!!"); } close(_id: string) { diff --git a/front/src/styles.less b/front/src/styles.less index 5da4641..8337a90 100644 --- a/front/src/styles.less +++ b/front/src/styles.less @@ -206,6 +206,39 @@ html { vertical-align: middle; } } +.square-button { + // background: #b3d4fc; + text-shadow: none; + border: none; + border-radius: 2px; + position: relative; + height: 36px; + margin: 0; + width: 36px; + display: inline-block; + font-family: 'Roboto', 'Helvetica', 'Arial', sans-serif; + //font-size: 14px; + //font-weight: 500; + text-transform: uppercase; + letter-spacing: 0; + overflow: hidden; + will-change: box-shadow; + outline: none; + cursor: pointer; + text-decoration: none; + text-align: center; + //line-height: 36px; + vertical-align: middle; + + &:disabled { + cursor: not-allowed; + } + + .material-icons { + vertical-align: middle; + } +} + .button-close { // background: #b3d4fc;