diff --git a/apps/maarch_entreprise/Views/menu-top.component.html b/apps/maarch_entreprise/Views/menu-top.component.html index 3b5c8280d40dd3ee07dfbda7d053620e84758a65..c634b149d196341452d09b0beae8d6aaac5a7d85 100644 --- a/apps/maarch_entreprise/Views/menu-top.component.html +++ b/apps/maarch_entreprise/Views/menu-top.component.html @@ -1,4 +1,4 @@ -<button mat-button [matMenuTriggerFor]="menu"> +<button mat-button [matMenuTriggerFor]="menu" *ngIf="!mobileMode"> <mat-icon mat-list-icon class="fa fa-user fa-2x" style="color:white; margin:0px 12px 8px 0px;"></mat-icon>{{user.firstname.charAt(0) | uppercase}}. {{user.lastname | uppercase}}</button> <mat-menu #menu="matMenu" class="headerMaarch"> <canvas class="header-bg" width="250" height="70" style="margin-top:-8px;background-image: url('static.php?filename=login-banner.jpg');background-size:cover;border-bottom: solid 1px white;"></canvas> diff --git a/apps/maarch_entreprise/Views/menuNav.component.html b/apps/maarch_entreprise/Views/menuNav.component.html index 30d5dc778e763c48321bfac36e5090a0d7a7f017..7c1ce46fc2334bcbdeca94e3c81c34e28d4173c1 100644 --- a/apps/maarch_entreprise/Views/menuNav.component.html +++ b/apps/maarch_entreprise/Views/menuNav.component.html @@ -1,4 +1,32 @@ <mat-nav-list> + <ng-container *ngIf="mobileMode"> + <canvas class="header-bg" width="250" height="70" style="margin-top:-8px;background-image: url('static.php?filename=login-banner.jpg');background-size:cover;border-bottom: solid 1px white;"></canvas> + <i title="{{lang.myProfileAccess}}" routerLink="/profile" style="cursor:pointer;z-index:1;color:white;position: absolute;left: 85px;top: 17px;background-image: url('static.php?filename=logo_only.svg');width: 70px;height: 70px;background-size: cover;background-position: top center;border-radius: 50%;border: solid white;background-color:white;"></i> + <mat-expansion-panel style="margin-top:-7px;"> + <mat-expansion-panel-header> + <mat-panel-title style="justify-content: center;"> + {{user.firstname}} {{user.lastname | uppercase}} + </mat-panel-title> + </mat-expansion-panel-header> + <mat-list> + <mat-divider></mat-divider> + <mat-list-item *ngFor="let group of user.groups"> + <p mat-line style="color:#666;opacity:0.5;"> {{group.group_desc}} </p> + </mat-list-item> + <h3 mat-subheader style="color:#666;">{{lang.groups}}</h3> + <mat-divider></mat-divider> + <mat-list-item *ngFor="let group of user.groups"> + <p mat-line style="color:#666;opacity:0.5;"> {{group.group_desc}} </p> + </mat-list-item> + <h3 mat-subheader style="color:#666;">{{lang.entities}}</h3> + <mat-divider></mat-divider> + <mat-list-item *ngFor="let entity of user.entities"> + <p mat-line style="color:#666;opacity:0.5;"> {{entity.entity_label}} </p> + </mat-list-item> + </mat-list> + </mat-expansion-panel> + </ng-container> + <h3 mat-subheader>{{lang.browsing}}</h3> <a mat-list-item href="index.php"> <mat-icon color="primary" mat-list-icon class="fa fa-home"></mat-icon> diff --git a/apps/maarch_entreprise/Views/profile.component.html b/apps/maarch_entreprise/Views/profile.component.html index 3108f45ea1115f5f6828cac0ec81f0f9bfe40cb7..5eed0871f81f332aa78316c35df3c955bdae02ff 100755 --- a/apps/maarch_entreprise/Views/profile.component.html +++ b/apps/maarch_entreprise/Views/profile.component.html @@ -1,6 +1,9 @@ <div class="admin-container" [class.admin-is-mobile]="mobileQuery.matches"> <mat-toolbar color="primary" class="admin-toolbar"> - <button mat-button (click)="snav.toggle()"> + <button mat-icon-button (click)="snav.toggle()" *ngIf="mobileMode"> + <mat-icon class="fa fa-bars fa-2x"></mat-icon> + </button> + <button mat-button (click)="snav.toggle()" *ngIf="!mobileMode"> <mat-icon class="maarchLogo" [svgIcon]="mobileQuery.matches ? 'maarchLogoOnly' : 'maarchLogo'"></mat-icon> </button> <h1 class="admin-toolbar-title">{{lang.myProfile}} @@ -9,12 +12,12 @@ <span style="flex: 1 1 auto;"></span> <menu-top></menu-top> <button mat-icon-button (click)="snav2.toggle()"> - <mat-icon class="fa fa-cog fa-2x"></mat-icon> + <mat-icon class="fa fa-2x" [ngClass]="[snav2.opened ? 'fa-chevron-right' : 'fa-chevron-left']"></mat-icon> </button> </mat-toolbar> - <mat-sidenav-container class="admin-sidenav-container" [style.marginTop.px]="mobileQuery.matches ? 56 : 0"> - <mat-sidenav #snav [mode]="mobileQuery.matches ? 'over' : 'side'" [fixedInViewport]="mobileQuery.matches" fixedTopGap="56" - [opened]="mobileQuery.matches ? false : true"> + <mat-sidenav-container class="admin-sidenav-container" [style.marginTop.px]="mobileMode ? 56 : 0"> + <mat-sidenav #snav [mode]="mobileMode ? 'over' : 'side'" [fixedInViewport]="mobileMode" fixedTopGap="56" [opened]="mobileMode ? false : true" + autoFocus="false"> <menu-nav></menu-nav> <mat-divider></mat-divider> <mat-nav-list> @@ -33,6 +36,7 @@ </a> </mat-nav-list> <mat-divider></mat-divider> + <menu-shortcut></menu-shortcut> </mat-sidenav> <mat-sidenav-content> <div *ngIf="loading" style="display:flex;height:100%;"> @@ -42,29 +46,47 @@ <mat-tab-group [selectedIndex]="selectedIndex" (selectedTabChange)="initComponents($event)"> <mat-tab label="{{lang.myInformations}}"> <div *ngIf="showPassword" style="margin-bottom: 5%"> - <div class="form-group"> - <mat-form-field> - <input matInput type="password" [(ngModel)]="passwordModel.currentPassword" name="currentPassword" placeholder="{{lang.currentPsw}}"> - </mat-form-field> - </div> - <div class="form-group"> - <div class="col-sm-6"> - <mat-form-field> - <input matInput type="password" [(ngModel)]="passwordModel.newPassword" name="newPassword" placeholder="{{lang.newPsw}}"> + <form [formGroup]="firstFormGroup"> + <div class="form-group"> + <mat-form-field style="padding:10px;"> + <input matInput placeholder="{{lang.typeCurrentPassword}}" formControlName="currentPasswordCtrl" required [type]="hidePassword ? 'password' : 'text'"> + <mat-icon matSuffix (click)="hidePassword = !hidePassword" class="fa fa-2x" [ngClass]="[hidePassword ? 'fa-eye-slash' : 'fa-eye']"></mat-icon> + <mat-error *ngIf="firstFormGroup.controls['currentPasswordCtrl'].hasError('required')">{{lang.requiredField}}</mat-error> </mat-form-field> </div> - <div class="col-sm-6"> - <mat-form-field> - <input matInput type="password" [(ngModel)]="passwordModel.reNewPassword" name="reNewPassword" placeholder="{{lang.renewPsw}}"> - </mat-form-field> + <div class="form-group"> + <div class="col-sm-6" style="padding-left:0px;padding-right: 0px;"> + <mat-form-field style="padding:10px;"> + <input matInput #inputPasswd placeholder="{{lang.typeNewPassword}}" formControlName="newPasswordCtrl" required [type]="hidePassword ? 'password' : 'text'"> + <mat-icon matSuffix (click)="hidePassword = !hidePassword" class="fa fa-2x" [ngClass]="[hidePassword ? 'fa-eye-slash' : 'fa-eye']"></mat-icon> + <mat-hint *ngIf="validPassword"> + <i color="accent" class="fa fa-check"></i> + <span color="accent">{{lang.passwordValid}}</span> + </mat-hint> + <mat-hint *ngIf="!validPassword">{{this.ruleText}}</mat-hint> + <mat-error>{{getErrorMessage()}}</mat-error> + </mat-form-field> + </div> + <div class="col-sm-6" style="padding-left:0px;padding-right:0px;"> + <mat-form-field style="padding:10px;"> + <input matInput #inputPasswd2 placeholder="{{lang.retypeNewPassword}}" required [type]="hidePassword ? 'password' : 'text'" + formControlName="retypePasswordCtrl"> + <mat-icon matSuffix (click)="hidePassword = !hidePassword" class="fa fa-2x" [ngClass]="[hidePassword ? 'fa-eye-slash' : 'fa-eye']"></mat-icon> + <mat-hint *ngIf="!firstFormGroup.controls['retypePasswordCtrl'].hasError('mismatch') && firstFormGroup.controls['retypePasswordCtrl'].value != ''"> + <i color="accent" class="fa fa-check"></i> + <span color="accent">{{lang.passwordMatch}}</span> + </mat-hint> + <mat-error>{{lang.passwordNotMatch}} !</mat-error> + </mat-form-field> + </div> </div> - </div> - <div class="form-group"> - <div style="text-align:center;"> - <button mat-raised-button color="primary" type="button" (click)="updatePassword()" [disabled]="!passwordModel.currentPassword || !passwordModel.newPassword || !passwordModel.reNewPassword || (passwordModel.newPassword != passwordModel.reNewPassword)">{{lang.update}}</button> - <button mat-raised-button color="default" type="button" (click)="showPassword=false">{{lang.cancel}}</button> + <div class="form-group"> + <div style="text-align:center;"> + <button mat-raised-button color="primary" type="button" (click)="updatePassword()" [disabled]="!firstFormGroup.valid">{{lang.update}}</button> + <button mat-raised-button color="default" type="button" (click)="showPassword=false">{{lang.cancel}}</button> + </div> </div> - </div> + </form> </div> <form class="form-horizontal" (ngSubmit)="onSubmit()" #profileForm="ngForm" *ngIf="!showPassword"> <div class="form-group"> @@ -149,7 +171,7 @@ <mat-icon color="primary" class="fa fa-magic" style="position: absolute;margin-left: 30px;margin-top: -10px;"></mat-icon> <span>{{lang.basketsColor}}</span> </mat-panel-title> - <mat-panel-description> + <mat-panel-description *ngIf="!mobileMode"> {{lang.basketsColorAdmin}} </mat-panel-description> </mat-expansion-panel-header> @@ -177,7 +199,7 @@ <mat-icon color="primary" class="fa fa-reply" style="position: absolute;margin-left: 30px;margin-top: -10px;"></mat-icon> {{lang.myBaskets}} </mat-panel-title> - <mat-panel-description> + <mat-panel-description *ngIf="!mobileMode"> {{lang.myBasketsDesc}} </mat-panel-description> </mat-expansion-panel-header> @@ -185,7 +207,8 @@ <mat-list> <mat-list-item> <mat-icon mat-list-icon color="primary"> - <mat-checkbox color="primary" (change)="$event ? masterToggleBaskets($event) : null" [checked]="selectionBaskets.hasValue()" matTooltip="{{lang.selectAll}}"></mat-checkbox> + <mat-checkbox color="primary" (change)="$event ? masterToggleBaskets($event) : null" [checked]="selectionBaskets.hasValue()" + matTooltip="{{lang.selectAll}}"></mat-checkbox> </mat-icon> <p mat-line> <span *ngIf="!selectionBaskets.hasValue()" style="opacity: 0.5;font-style: italic;font-size: 80%;"> @@ -212,113 +235,115 @@ </mat-list-item> <mat-divider></mat-divider> <ng-container *ngFor="let basket of user.baskets;let i = index"> - <mat-list-item *ngIf="basket.group_id && basket.userToDisplay == ''" (mouseover)="showActions(basket)" (mouseout)="hideActions(basket)" style="cursor: pointer;"> + <mat-list-item *ngIf="basket.group_id && basket.userToDisplay == ''" (mouseover)="showActions(basket)" (mouseout)="hideActions(basket)" + style="cursor: pointer;"> <mat-icon mat-list-icon color="primary" *ngIf="basket.enabled"> - <mat-checkbox (click)="$event.stopPropagation()" (change)="$event ? selectionBaskets.toggle(basket) : null" [checked]="selectionBaskets.isSelected(basket)" color="primary"></mat-checkbox> + <mat-checkbox (click)="$event.stopPropagation()" (change)="$event ? selectionBaskets.toggle(basket) : null" [checked]="selectionBaskets.isSelected(basket)" + color="primary"></mat-checkbox> </mat-icon> <h4 mat-line [attr.color]="basket.userToDisplay != '' ? 'primary': ''" style="display: flex;align-items: center;"> - <span (click)="selectionBaskets.toggle(basket);" [ngStyle]="{'opacity': basket.allowed ? '1' : '0.5'}" style="flex: 2;overflow: hidden;text-overflow: ellipsis;"> - {{basket.basket_name}} - <span class="label label-primary" style="font-weight:normal">{{basket.group_desc}}</span> - </span> - - <span id="{{basket.basket_id}}_{{basket.group_id}}" style="display:none;flex:1;background: white;text-align: right"> - <i class="fa fa-ellipsis-v" style="opacity: 0.2;"></i> - <button [matMenuTriggerFor]="menu2" mat-icon-button matTooltip="{{lang.redirectBasket}}" (click)="selectionBaskets.clear();selectionBaskets.select(basket);"> - <mat-icon class="fa fa-reply"></mat-icon> - </button> - <mat-menu #menu2="matMenu"> - <mat-form-field style="padding:10px;width:200px !important;"> - <input (click)="$event.stopPropagation()" type="text" placeholder="{{ lang.users }}" matInput [matAutocomplete]="auto" [formControl]="userCtrl"> - <mat-autocomplete #auto="matAutocomplete"> - <mat-option *ngFor="let user of filteredUsers | async" [value]="user.id" (click)="addBasketRedirection(user.id)"> - <p mat-line matTooltip="{{ user.otherInfo }}"> - <span class="col-xm-1"> - <mat-icon color="primary" class="fa fa-user fa-2x" style="margin-right:0px;"></mat-icon> - </span> - <span class="col-xm-11"> - {{ user.idToDisplay }} - <small>{{ user.otherInfo }}</small> - </span> - </p> - </mat-option> - </mat-autocomplete> - </mat-form-field> - </mat-menu> - </span> - </h4> + <span (click)="selectionBaskets.toggle(basket);" [ngStyle]="{'opacity': basket.allowed ? '1' : '0.5'}" style="flex: 2;overflow: hidden;text-overflow: ellipsis;"> + {{basket.basket_name}} + <span class="label label-primary" style="font-weight:normal">{{basket.group_desc}}</span> + </span> + + <span id="{{basket.basket_id}}_{{basket.group_id}}" style="display:none;flex:1;background: white;text-align: right"> + <i class="fa fa-ellipsis-v" style="opacity: 0.2;"></i> + <button [matMenuTriggerFor]="menu2" mat-icon-button matTooltip="{{lang.redirectBasket}}" (click)="selectionBaskets.clear();selectionBaskets.select(basket);"> + <mat-icon class="fa fa-reply"></mat-icon> + </button> + <mat-menu #menu2="matMenu"> + <mat-form-field style="padding:10px;width:200px !important;"> + <input (click)="$event.stopPropagation()" type="text" placeholder="{{ lang.users }}" matInput [matAutocomplete]="auto" [formControl]="userCtrl"> + <mat-autocomplete #auto="matAutocomplete"> + <mat-option *ngFor="let user of filteredUsers | async" [value]="user.id" (click)="addBasketRedirection(user.id)"> + <p mat-line matTooltip="{{ user.otherInfo }}"> + <span class="col-xm-1"> + <mat-icon color="primary" class="fa fa-user fa-2x" style="margin-right:0px;"></mat-icon> + </span> + <span class="col-xm-11"> + {{ user.idToDisplay }} + <small>{{ user.otherInfo }}</small> + </span> + </p> + </mat-option> + </mat-autocomplete> + </mat-form-field> + </mat-menu> + </span> + </h4> </mat-list-item> </ng-container> </mat-list> </div> <div class="col-sm-6" style="overflow:hidden;"> - <mat-tab-group> - <mat-tab label="{{lang.basketsRedirected}}"> - <mat-list> - <ng-container *ngFor="let basket of user.baskets;let i = index"> - <mat-list-item *ngIf="basket.group_id && basket.userToDisplay != ''"> - <mat-icon mat-list-icon color="primary" *ngIf="basket.enabled" style="margin-top:-60px;" class="fa fa-paper-plane"> - </mat-icon> - <h4 mat-line [ngStyle]="{'opacity': basket.allowed ? '1' : '0.5'}" [attr.color]="basket.userToDisplay != '' ? 'primary': ''">{{basket.basket_name}} - <span class="label label-primary" style="font-weight:normal">{{basket.group_id}}</span> - </h4> - <p mat-line [ngStyle]="{'opacity': basket.allowed ? '1' : '0.5'}"> - <mat-form-field> - <input type="text" color="warn" matInput disabled value="{{lang.redirectedTo}} {{basket.userToDisplay}}"> - <button mat-button color="warn" matSuffix mat-icon-button aria-label="Clear" (click)="delBasketRedirection(basket)" matTooltip="Supprimer la redirection"> - <mat-icon color="warn" class="fa fa-times text-danger"></mat-icon> - </button> - </mat-form-field> - </p> - </mat-list-item> - </ng-container> - </mat-list> - </mat-tab> - </mat-tab-group> - - <mat-tab-group> - <mat-tab label="{{lang.basketsAssigned}}"> - <mat-list> - <ng-container *ngFor="let basket of user.baskets;let i = index"> - <mat-list-item *ngIf="!basket.group_id"> - <mat-icon mat-list-icon color="primary" style="margin-top:-60px;" class="fa fa-reply"> - </mat-icon> - <h4 mat-line [attr.color]="basket.userToDisplay != '' ? 'primary': ''">{{basket.basket_name}} - <span class="label label-primary" style="font-weight:normal">{{basket.group_id}}</span> - </h4> - <p mat-line> - <mat-form-field *ngIf="basket.userToDisplay == ''" floatLabel="never"> - <input matTooltip="{{lang.redirectBasket}}" matTooltipPosition="above" type="text" placeholder="{{lang.redirectBasket}}" - matInput [matAutocomplete]="auto" [formControl]="userCtrl"> - <mat-autocomplete #auto="matAutocomplete"> - <mat-option *ngFor="let user of filteredUsers | async" [value]="user.id" (click)="reassignBasketRedirection(user.id,basket)"> - <p mat-line matTooltip="{{ user.otherInfo }}"> - <span class="col-xm-1"> - <mat-icon color="primary" class="fa fa-user fa-2x" style="margin-right:0px;"></mat-icon> - </span> - <span class="col-xm-11"> - {{ user.idToDisplay }} - <small>{{ user.otherInfo }}</small> - </span> - </p> - </mat-option> - </mat-autocomplete> - </mat-form-field> - <mat-form-field> - <input type="text" color="warn" matInput disabled value="{{lang.assignBy}} {{basket.userToDisplay}}"> - <button mat-button color="warn" matSuffix mat-icon-button aria-label="Clear" (click)="basket.userToDisplay =''" matTooltip="{{lang.reassign}}"> - <mat-icon color="primary" class="fa fa-edit"></mat-icon> - </button> - <button mat-button color="warn" matSuffix mat-icon-button aria-label="Clear" (click)="delBasketRedirection(basket)" matTooltip="{{lang.deleteAssignation}}"> - <mat-icon color="warn" class="fa fa-times text-danger"></mat-icon> - </button> - </mat-form-field> - </p> - </mat-list-item> - </ng-container> - </mat-list> - </mat-tab> - </mat-tab-group> + <mat-tab-group> + <mat-tab label="{{lang.basketsRedirected}}"> + <mat-list> + <ng-container *ngFor="let basket of user.baskets;let i = index"> + <mat-list-item *ngIf="basket.group_id && basket.userToDisplay != ''"> + <mat-icon mat-list-icon color="primary" *ngIf="basket.enabled" style="margin-top:-60px;" class="fa fa-paper-plane"> + </mat-icon> + <h4 mat-line [ngStyle]="{'opacity': basket.allowed ? '1' : '0.5'}" [attr.color]="basket.userToDisplay != '' ? 'primary': ''">{{basket.basket_name}} + <span class="label label-primary" style="font-weight:normal">{{basket.group_id}}</span> + </h4> + <p mat-line [ngStyle]="{'opacity': basket.allowed ? '1' : '0.5'}"> + <mat-form-field> + <input type="text" color="warn" matInput disabled value="{{lang.redirectedTo}} {{basket.userToDisplay}}"> + <button mat-button color="warn" matSuffix mat-icon-button aria-label="Clear" (click)="delBasketRedirection(basket)" matTooltip="Supprimer la redirection"> + <mat-icon color="warn" class="fa fa-times text-danger"></mat-icon> + </button> + </mat-form-field> + </p> + </mat-list-item> + </ng-container> + </mat-list> + </mat-tab> + </mat-tab-group> + + <mat-tab-group> + <mat-tab label="{{lang.basketsAssigned}}"> + <mat-list> + <ng-container *ngFor="let basket of user.baskets;let i = index"> + <mat-list-item *ngIf="!basket.group_id"> + <mat-icon mat-list-icon color="primary" style="margin-top:-60px;" class="fa fa-reply"> + </mat-icon> + <h4 mat-line [attr.color]="basket.userToDisplay != '' ? 'primary': ''">{{basket.basket_name}} + <span class="label label-primary" style="font-weight:normal">{{basket.group_id}}</span> + </h4> + <p mat-line> + <mat-form-field *ngIf="basket.userToDisplay == ''" floatLabel="never"> + <input matTooltip="{{lang.redirectBasket}}" matTooltipPosition="above" type="text" placeholder="{{lang.redirectBasket}}" + matInput [matAutocomplete]="auto" [formControl]="userCtrl"> + <mat-autocomplete #auto="matAutocomplete"> + <mat-option *ngFor="let user of filteredUsers | async" [value]="user.id" (click)="reassignBasketRedirection(user.id,basket)"> + <p mat-line matTooltip="{{ user.otherInfo }}"> + <span class="col-xm-1"> + <mat-icon color="primary" class="fa fa-user fa-2x" style="margin-right:0px;"></mat-icon> + </span> + <span class="col-xm-11"> + {{ user.idToDisplay }} + <small>{{ user.otherInfo }}</small> + </span> + </p> + </mat-option> + </mat-autocomplete> + </mat-form-field> + <mat-form-field> + <input type="text" color="warn" matInput disabled value="{{lang.assignBy}} {{basket.userToDisplay}}"> + <button mat-button color="warn" matSuffix mat-icon-button aria-label="Clear" (click)="basket.userToDisplay =''" matTooltip="{{lang.reassign}}"> + <mat-icon color="primary" class="fa fa-edit"></mat-icon> + </button> + <button mat-button color="warn" matSuffix mat-icon-button aria-label="Clear" (click)="delBasketRedirection(basket)" matTooltip="{{lang.deleteAssignation}}"> + <mat-icon color="warn" class="fa fa-times text-danger"></mat-icon> + </button> + </mat-form-field> + </p> + </mat-list-item> + </ng-container> + </mat-list> + </mat-tab> + </mat-tab-group> </div> <div style="clear:both;"></div> </mat-expansion-panel> @@ -328,7 +353,7 @@ <mat-icon color="primary" class="fa fa-envelope" style="font-size:25px;width:50px;"></mat-icon> {{lang.mySignMail}} </mat-panel-title> - <mat-panel-description> + <mat-panel-description *ngIf="!mobileMode"> {{lang.mySignMailDesc}} </mat-panel-description> </mat-expansion-panel-header> @@ -382,7 +407,7 @@ <mat-icon color="primary" class="fa fa-certificate" style="font-size:25px;width:50px;"></mat-icon> {{lang.mySignSignatureBook}} </mat-panel-title> - <mat-panel-description> + <mat-panel-description *ngIf="!mobileMode"> {{lang.mySignSignatureBookDesc}} </mat-panel-description> </mat-expansion-panel-header> @@ -445,7 +470,7 @@ <mat-icon color="primary" class="fa fa-users" style="font-size:25px;width:50px;"></mat-icon> {{lang.myContactsGroups}} </mat-panel-title> - <mat-panel-description> + <mat-panel-description *ngIf="!mobileMode"> {{lang.myContactsGroupsDesc}} </mat-panel-description> </mat-expansion-panel-header> diff --git a/apps/maarch_entreprise/js/angular/app/app-common.module.ts b/apps/maarch_entreprise/js/angular/app/app-common.module.ts index 47cada73d6af97c31d501f0387bdf9f031dcab93..7d8b32a0c909a2d6b481640739d6b52cb751d815 100644 --- a/apps/maarch_entreprise/js/angular/app/app-common.module.ts +++ b/apps/maarch_entreprise/js/angular/app/app-common.module.ts @@ -9,6 +9,7 @@ import { FormsModule, ReactiveFormsModule } from '@angular/forms'; import { HttpClientModule } from '@angular/common/http'; import { RouterModule } from '@angular/router'; + /*FRONT IMPORTS*/ import { AppMaterialModule } from './app-material.module'; @@ -16,6 +17,7 @@ import { AppMaterialModule } from './app-material.module'; import { MenuComponent } from './menu/menu.component'; import { MenuNavComponent } from './menu/menu-nav.component'; import { MenuTopComponent } from './menu/menu-top.component'; +import { MenuShortcutComponent } from './menu/menu-shortcut.component'; @NgModule({ @@ -31,13 +33,15 @@ import { MenuTopComponent } from './menu/menu-top.component' declarations: [ MenuComponent, MenuNavComponent, - MenuTopComponent + MenuTopComponent, + MenuShortcutComponent ], exports: [ CommonModule, MenuComponent, MenuNavComponent, MenuTopComponent, + MenuShortcutComponent, BrowserModule, BrowserAnimationsModule, FormsModule, diff --git a/apps/maarch_entreprise/js/angular/app/app.component.ts b/apps/maarch_entreprise/js/angular/app/app.component.ts index 5fa8b78f741be79a1804119eff7e66287ad9045b..c707e3177b465cb9d02535a4a999bfb4546bc243 100755 --- a/apps/maarch_entreprise/js/angular/app/app.component.ts +++ b/apps/maarch_entreprise/js/angular/app/app.component.ts @@ -10,6 +10,7 @@ export const myCustomTooltipDefaults: MatTooltipDefaultOptions = { touchendHideDelay: 0, }; +declare const angularGlobals: any; @Component({ selector: 'my-app', template: `<router-outlet></router-outlet>`, @@ -30,5 +31,10 @@ export const myCustomTooltipDefaults: MatTooltipDefaultOptions = { export class AppComponent { constructor(iconReg: MatIconRegistry, sanitizer: DomSanitizer) { iconReg.addSvgIcon('maarchLogo', sanitizer.bypassSecurityTrustResourceUrl('img/logo_white.svg')).addSvgIcon('maarchLogoOnly', sanitizer.bypassSecurityTrustResourceUrl('img/logo_only_white.svg')); + if( /Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(navigator.userAgent) ) { + angularGlobals.mobileMode = true; + } else { + angularGlobals.mobileMode = false; + } } } diff --git a/apps/maarch_entreprise/js/angular/app/menu/menu-nav.component.ts b/apps/maarch_entreprise/js/angular/app/menu/menu-nav.component.ts index e1acffd7fe815c9c1c54c5cdb063d797101288b8..aa3a4dfdde5b4b118b2138f7b5d4250ce90188be 100644 --- a/apps/maarch_entreprise/js/angular/app/menu/menu-nav.component.ts +++ b/apps/maarch_entreprise/js/angular/app/menu/menu-nav.component.ts @@ -17,14 +17,19 @@ export class MenuNavComponent implements OnInit { lang: any = LANG; coreUrl : string; + mobileMode : boolean = false; router :any; + user : any = {}; constructor(public http: HttpClient, private _location: Location, private _router: Router, private activatedRoute:ActivatedRoute) { this.router = _router; } - ngOnInit(): void { + ngOnInit(): void { + + this.mobileMode = angularGlobals.mobileMode; this.coreUrl = angularGlobals.coreUrl; + this.user = angularGlobals.user; } backClicked() { diff --git a/apps/maarch_entreprise/js/angular/app/menu/menu-shortcut.component.ts b/apps/maarch_entreprise/js/angular/app/menu/menu-shortcut.component.ts new file mode 100644 index 0000000000000000000000000000000000000000..b44002550ba7cad7be8bb44fdcdf1ef076dd0ec0 --- /dev/null +++ b/apps/maarch_entreprise/js/angular/app/menu/menu-shortcut.component.ts @@ -0,0 +1,33 @@ +import { Component, OnInit } from '@angular/core'; +import { Router, ActivatedRoute } from '@angular/router'; +import { HttpClient } from '@angular/common/http'; +import {Location} from '@angular/common'; +import { LANG } from '../translate.component'; + +declare function $j(selector: any) : any; + +declare var angularGlobals : any; + + +@Component({ + selector: 'menu-shortcut', + templateUrl : "../../../../Views/menuShortcut.component.html", +}) +export class MenuShortcutComponent implements OnInit { + + lang: any = LANG; + mobileMode : boolean = false; + coreUrl : string; + router :any; + user : any = {}; + + constructor(public http: HttpClient, private _location: Location, private _router: Router, private activatedRoute:ActivatedRoute) { + this.mobileMode = angularGlobals.mobileMode; + this.router = _router; + } + + ngOnInit(): void { + this.coreUrl = angularGlobals.coreUrl; + } + +} diff --git a/apps/maarch_entreprise/js/angular/app/menu/menu-top.component.ts b/apps/maarch_entreprise/js/angular/app/menu/menu-top.component.ts index 9677b4889b6ff0cae86ff8eb0207af8c78d5602d..d68a1418a9d98664acbecc6b135014ea6bf3fa73 100644 --- a/apps/maarch_entreprise/js/angular/app/menu/menu-top.component.ts +++ b/apps/maarch_entreprise/js/angular/app/menu/menu-top.component.ts @@ -11,12 +11,14 @@ declare var angularGlobals : any; }) export class MenuTopComponent implements OnInit { - coreUrl : string; - lang : any = LANG; - user : any = {}; + coreUrl : string; + lang : any = LANG; + user : any = {}; + mobileMode : boolean = false; constructor() { + this.mobileMode = angularGlobals.mobileMode; } ngOnInit(): void { diff --git a/apps/maarch_entreprise/js/angular/app/profile.component.ts b/apps/maarch_entreprise/js/angular/app/profile.component.ts index f4d317830c46ff2564909180c7abbf744144d648..260927fcd5103f3724498ee5f5c366ba41bf50c7 100755 --- a/apps/maarch_entreprise/js/angular/app/profile.component.ts +++ b/apps/maarch_entreprise/js/angular/app/profile.component.ts @@ -8,7 +8,7 @@ import { MatPaginator, MatTableDataSource, MatSort, MatDialog, MatDialogRef, Mat import { AutoCompletePlugin } from '../plugins/autocomplete.plugin'; import { SelectionModel } from '@angular/cdk/collections'; -import { FormControl } from '@angular/forms'; +import { FormControl, FormGroup, Validators, AbstractControl, ValidationErrors, ValidatorFn, FormBuilder } from '@angular/forms'; declare function $j(selector: any): any; @@ -26,7 +26,7 @@ export class ProfileComponent extends AutoCompletePlugin implements OnInit { private _mobileQueryListener: () => void; mobileQuery: MediaQueryList; dialogRef: MatDialogRef<any>; - + mobileMode : boolean = false; coreUrl: string; lang: any = LANG; @@ -39,6 +39,19 @@ export class ProfileComponent extends AutoCompletePlugin implements OnInit { newPassword: "", reNewPassword: "", }; + firstFormGroup: FormGroup; + ruleText: string = ''; + OtherRuleText: string; + validPassword: Boolean = false; + matchPassword: Boolean = false; + hidePassword: Boolean = true; + passwordRules: any = { + minLength: { enabled: false, value: 0 }, + complexityUpper: { enabled: false, value: 0 }, + complexityNumber: { enabled: false, value: 0 }, + complexitySpecial: { enabled: false, value: 0 }, + renewal: { enabled: false, value: 0 }, + }; signatureModel: any = { base64: "", base64ForJs: "", @@ -144,8 +157,9 @@ export class ProfileComponent extends AutoCompletePlugin implements OnInit { } - constructor(changeDetectorRef: ChangeDetectorRef, media: MediaMatcher, public http: HttpClient, private zone: NgZone, private notify: NotificationService, public dialog: MatDialog) { + constructor(changeDetectorRef: ChangeDetectorRef, media: MediaMatcher, public http: HttpClient, private zone: NgZone, private notify: NotificationService, public dialog: MatDialog, private _formBuilder: FormBuilder) { super(http, ['users']); + this.mobileMode = angularGlobals.mobileMode; $j("link[href='merged_css.php']").remove(); this.mobileQuery = media.matchMedia('(max-width: 768px)'); this._mobileQueryListener = () => changeDetectorRef.detectChanges(); @@ -184,7 +198,9 @@ export class ProfileComponent extends AutoCompletePlugin implements OnInit { initComponents(event: any) { this.selectedIndex = event.index; if (event.index == 2) { - this.sidenav.open(); + if (!this.mobileMode) { + this.sidenav.open(); + } //if (this.histories.length == 0) { this.http.get(this.coreUrl + 'rest/histories/users/' + this.user.id) .subscribe((data: any) => { @@ -200,7 +216,7 @@ export class ProfileComponent extends AutoCompletePlugin implements OnInit { //} } else if(event.index == 1) { this.sidenav.close(); - } else { + } else if(!this.mobileMode){ this.sidenav.open(); } } @@ -588,6 +604,9 @@ export class ProfileComponent extends AutoCompletePlugin implements OnInit { } updatePassword() { + this.passwordModel.currentPassword = this.firstFormGroup.controls['currentPasswordCtrl'].value; + this.passwordModel.newPassword = this.firstFormGroup.controls['newPasswordCtrl'].value; + this.passwordModel.reNewPassword = this.firstFormGroup.controls['retypePasswordCtrl'].value; this.http.put(this.coreUrl + 'rest/currentUser/password', this.passwordModel) .subscribe((data: any) => { this.showPassword = false; @@ -712,11 +731,123 @@ export class ProfileComponent extends AutoCompletePlugin implements OnInit { }); } + regexValidator(regex: RegExp, error: ValidationErrors): ValidatorFn { + return (control: AbstractControl): { [key: string]: any } => { + if (!control.value) { + return null; + } + const valid = regex.test(control.value); + return valid ? null : error; + }; + } + changePasswd() { + this.http.get(this.coreUrl + 'rest/passwordRules') + .subscribe((data: any) => { + let ruleTextArr: String[] = []; + data.rules.forEach((rule: any) => { + if (rule.label == 'minLength') { + this.passwordRules.minLength.enabled = rule.enabled; + this.passwordRules.minLength.value = rule.value; + if (rule.enabled) { + ruleTextArr.push(rule.value + ' ' + this.lang['password' + rule.label]); + } + + + } else if (rule.label == 'complexityUpper') { + this.passwordRules.complexityUpper.enabled = rule.enabled; + this.passwordRules.complexityUpper.value = rule.value; + if (rule.enabled) { + ruleTextArr.push(this.lang['password' + rule.label]); + } + + + } else if (rule.label == 'complexityNumber') { + this.passwordRules.complexityNumber.enabled = rule.enabled; + this.passwordRules.complexityNumber.value = rule.value; + if (rule.enabled) { + ruleTextArr.push(this.lang['password' + rule.label]); + } + + + } else if (rule.label == 'complexitySpecial') { + this.passwordRules.complexitySpecial.enabled = rule.enabled; + this.passwordRules.complexitySpecial.value = rule.value; + if (rule.enabled) { + ruleTextArr.push(this.lang['password' + rule.label]); + } + + + } else if (rule.label == 'renewal') { + this.passwordRules.renewal.enabled = rule.enabled; + this.passwordRules.renewal.value = rule.value; + this.OtherRuleText = this.lang['password' + rule.label] + ' <b>' + rule.value + ' ' + this.lang.days + '</b>. ' + this.lang['password2' + rule.label]; + } + + }); + this.ruleText = ruleTextArr.join(', '); + }, (err) => { + this.notify.error(err.error.errors); + }); + + this.firstFormGroup = this._formBuilder.group({ + newPasswordCtrl: [ + '', + Validators.compose([Validators.minLength(6), this.regexValidator(new RegExp('[A-Z]'), { 'complexityUpper': '' }), this.regexValidator(new RegExp('[0-9]'), { 'complexityNumber': '' }), this.regexValidator(new RegExp('[^A-Za-z0-9]'), { 'complexitySpecial': '' })]) + ], + retypePasswordCtrl: [ + '', + Validators.compose([Validators.required]) + ], + currentPasswordCtrl: [ + '', + Validators.compose([Validators.required]) + ] + + }, { + validator: this.matchValidator + }); + this.validPassword =false; + this.firstFormGroup.controls['currentPasswordCtrl'].setErrors(null) + this.firstFormGroup.controls['newPasswordCtrl'].setErrors(null) + this.firstFormGroup.controls['retypePasswordCtrl'].setErrors(null) this.selectedIndex = 0; this.showPassword = true; } + matchValidator(group: FormGroup) { + + if (group.controls['newPasswordCtrl'].value == group.controls['retypePasswordCtrl'].value) { + return false; + } else { + group.controls['retypePasswordCtrl'].setErrors({'mismatch': true}) + return {'mismatch': true}; + } + } + + getErrorMessage() { + if (this.firstFormGroup.controls['newPasswordCtrl'].hasError('required')) { + return this.lang.requiredField + ' !'; + + } else if (this.firstFormGroup.controls['newPasswordCtrl'].hasError('minlength') && this.passwordRules.minLength.enabled) { + return this.passwordRules.minLength.value + ' ' + this.lang.passwordminLength + ' !'; + + } else if (this.firstFormGroup.controls['newPasswordCtrl'].errors != null && this.firstFormGroup.controls['newPasswordCtrl'].errors.complexityUpper !== undefined && this.passwordRules.complexityUpper.enabled) { + return this.lang.passwordcomplexityUpper + ' !'; + + } else if (this.firstFormGroup.controls['newPasswordCtrl'].errors != null && this.firstFormGroup.controls['newPasswordCtrl'].errors.complexityNumber !== undefined && this.passwordRules.complexityNumber.enabled) { + return this.lang.passwordcomplexityNumber + ' !'; + + } else if (this.firstFormGroup.controls['newPasswordCtrl'].errors != null && this.firstFormGroup.controls['newPasswordCtrl'].errors.complexitySpecial !== undefined && this.passwordRules.complexitySpecial.enabled) { + return this.lang.passwordcomplexitySpecial + ' !'; + + } else { + this.firstFormGroup.controls['newPasswordCtrl'].setErrors(null) + this.validPassword = true; + return ''; + } + } + showActions(basket:any){ $j('#'+basket.basket_id+'_'+basket.group_id).show(); }