diff --git a/src/app/user/controllers/UserController.php b/src/app/user/controllers/UserController.php index f1d76f33dd76001352da980324108d3883990868..97173dbd7915666afa18c15669b5f5338eae2185 100755 --- a/src/app/user/controllers/UserController.php +++ b/src/app/user/controllers/UserController.php @@ -1464,8 +1464,8 @@ class UserController if (!empty($responseExec['errors'])) { return $response->withStatus(400)->withJson(['errors' => $responseExec['errors']]); } - if (!empty($responseExec['message'])) { - return $response->withStatus(400)->withJson(['errors' => $responseExec['message']]); + if (!empty($responseExec['exception'])) { + return $response->withStatus(400)->withJson(['errors' => $responseExec['exception'][0]['message']]); } } else { return $response->withStatus(403)->withJson(['errors' => 'maarchParapheur is not enabled']); diff --git a/src/frontend/app/administration/user/user-administration.component.html b/src/frontend/app/administration/user/user-administration.component.html index acf49f2ff2701f4b9277bf1936b322ae6d3dce9c..98c390bb4f1812e763ac146e8dd078070d427a6c 100755 --- a/src/frontend/app/administration/user/user-administration.component.html +++ b/src/frontend/app/administration/user/user-administration.component.html @@ -1,7 +1,7 @@ <div class="admin-container" [class.admin-is-mobile]="mobileQuery.matches"> - <mat-sidenav-container autosize class="admin-sidenav-container" > - <mat-sidenav #snav [mode]="mobileQuery.matches ? 'over' : 'side'" [fixedInViewport]="mobileQuery.matches" fixedTopGap="56" - [opened]="mobileQuery.matches ? false : true"> + <mat-sidenav-container autosize class="admin-sidenav-container"> + <mat-sidenav #snav [mode]="mobileQuery.matches ? 'over' : 'side'" [fixedInViewport]="mobileQuery.matches" + fixedTopGap="56" [opened]="mobileQuery.matches ? false : true"> <menu-shortcut></menu-shortcut> <menu-nav></menu-nav> <mat-nav-list *ngIf="!creationMode && !loading"> @@ -30,13 +30,15 @@ {{lang.changePassword}} </p> </a> - <a mat-list-item *ngIf="user.canCreateMaarchParapheurUser" (click)="sendToMaarchParapheur()" title="{{lang.createUserInMaarchParapheur}}"> + <a mat-list-item *ngIf="user.canCreateMaarchParapheurUser" (click)="sendToMaarchParapheur()" + title="{{lang.createUserInMaarchParapheur}}"> <mat-icon color="primary" mat-list-icon class="fa fa-user"></mat-icon> <p mat-line> {{lang.createUserInMaarchParapheur}} </p> </a> - <a style="opacity:0.7" mat-list-item *ngIf="user.external_id.maarchParapheur" disabled title="{{lang.userCreatedInMaarchParapheur}}"> + <a style="opacity:0.7" mat-list-item *ngIf="user.external_id.maarchParapheur" disabled + title="{{lang.userCreatedInMaarchParapheur}}"> <mat-icon color="primary" mat-list-icon class="fa fa-user"></mat-icon> <p mat-line> {{lang.userCreatedInMaarchParapheur}} @@ -56,17 +58,26 @@ <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> + <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="form-group"> - <div style="text-align:center;color: rgba(0,0,0,0.54);font-size: 75%;">{{this.ruleText}}</div> + <div style="text-align:center;color: rgba(0,0,0,0.54);font-size: 75%;"> + {{this.ruleText}}</div> <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> + <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> @@ -76,10 +87,13 @@ </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 != ''"> + <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> @@ -87,21 +101,29 @@ </mat-form-field> </div> </div> - <div *ngIf="passwordRules.renewal.enabled || passwordRules.historyLastUse.enabled" class="form-group"> + <div *ngIf="passwordRules.renewal.enabled || passwordRules.historyLastUse.enabled" + class="form-group"> <div class="col-sm-12" style="padding-left:0px;padding-right:0px;"> - <div class="alert alert-warning" role="alert" [innerHTML]="otherRuleText" style="text-align:center;"></div> + <div class="alert alert-warning" role="alert" [innerHTML]="otherRuleText" + style="text-align:center;"></div> </div> </div> <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> + <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> </form> </div> - <div *ngIf="user.status == 'ABS' && !showPassword" class="text-warning" style="position: absolute;opacity: 0.25;font-size: 120px;transform: rotate(324deg);-webkit-transform: rotate(324deg);margin-left: 35%;margin-top: 90px;">{{user.status}}</div> - <form class="form-horizontal" (ngSubmit)="onSubmit()" #profileForm="ngForm" *ngIf="!showPassword"> + <div *ngIf="user.status == 'ABS' && !showPassword" class="text-warning" + style="position: absolute;opacity: 0.25;font-size: 120px;transform: rotate(324deg);-webkit-transform: rotate(324deg);margin-left: 35%;margin-top: 90px;"> + {{user.status}}</div> + <form class="form-horizontal" (ngSubmit)="onSubmit()" #profileForm="ngForm" + *ngIf="!showPassword"> <div class="form-group"> <div class="col-sm-12"> <div class="pull-left"> @@ -111,10 +133,11 @@ </div> <div class="input-group"> <mat-form-field> - <input matInput *ngIf="creationMode" type="text" title="{{lang.id}}" name="user_id" [(ngModel)]="user.userId" placeholder="{{lang.id}}" + <input matInput *ngIf="creationMode" type="text" title="{{lang.id}}" + name="user_id" [(ngModel)]="user.userId" placeholder="{{lang.id}}" pattern="^[\w.@-]*$" required (keyup)="setLowerUserId()"> - <input matInput *ngIf="!creationMode" type="text" title="{{lang.id}}" value="{{user.user_id}}" placeholder="{{lang.id}}" - disabled> + <input matInput *ngIf="!creationMode" type="text" title="{{lang.id}}" + value="{{user.user_id}}" placeholder="{{lang.id}}" disabled> </mat-form-field> </div> </div> @@ -122,26 +145,31 @@ <div class="form-group"> <div class="col-sm-5" style="font-weight:bold;"> <mat-form-field> - <input matInput type="text" id="lastname" name="lastname" title="{{lang.lastname}}" placeholder="{{lang.lastname}}" [(ngModel)]="user.lastname" - required> + <input matInput type="text" id="lastname" name="lastname" + title="{{lang.lastname}}" placeholder="{{lang.lastname}}" + [(ngModel)]="user.lastname" required> </mat-form-field> </div> <div class="col-sm-5" style="font-weight:bold;"> <mat-form-field> - <input matInput type="text" id="firstname" name="firstname" title="{{lang.firstname}}" placeholder="{{lang.firstname}}" [(ngModel)]="user.firstname" - required> + <input matInput type="text" id="firstname" name="firstname" + title="{{lang.firstname}}" placeholder="{{lang.firstname}}" + [(ngModel)]="user.firstname" required> </mat-form-field> </div> <div class="col-sm-2" style="font-style:italic;"> <mat-form-field> - <input matInput type="text" id="initials" name="initials" title="{{lang.initials}}" placeholder="{{lang.initials}}" [(ngModel)]="user.initials"> + <input matInput type="text" id="initials" name="initials" + title="{{lang.initials}}" placeholder="{{lang.initials}}" + [(ngModel)]="user.initials"> </mat-form-field> </div> </div> <div class="form-group"> <div class="col-sm-12"> <mat-form-field> - <input matInput type="tel" id="phone" name="phone" title="{{lang.phoneNumber}}" placeholder="{{lang.phoneNumber}}" [(ngModel)]="user.phone" + <input matInput type="tel" id="phone" name="phone" title="{{lang.phoneNumber}}" + placeholder="{{lang.phoneNumber}}" [(ngModel)]="user.phone" pattern="\+?((|\ |\.|\(|\)|\-)?(\d)*)*\d$"> </mat-form-field> </div> @@ -149,7 +177,8 @@ <div class="form-group"> <div class="col-sm-12"> <mat-form-field> - <input matInput type="email" id="mail" name="mail" title="{{lang.email}}" placeholder="{{lang.email}}" [(ngModel)]="user.mail" + <input matInput type="email" id="mail" name="mail" title="{{lang.email}}" + placeholder="{{lang.email}}" [(ngModel)]="user.mail" pattern="(^[a-zA-Z0-9_.+-]+@[a-zA-Z0-9-]+\.[a-zA-Z0-9-.]+$)" required> </mat-form-field> </div> @@ -163,7 +192,8 @@ </mat-expansion-panel-header> <div class="form-group"> <div class="col-sm-12"> - <mat-checkbox color="primary" matTooltip="{{lang.webserviceAccountDesc}}" name="loginmode" (change)="setUserModeLogin($event)" + <mat-checkbox color="primary" matTooltip="{{lang.webserviceAccountDesc}}" + name="loginmode" (change)="setUserModeLogin($event)" [checked]="user.loginmode == 'restMode'"> {{lang.webserviceAccount}} </mat-checkbox> @@ -173,8 +203,10 @@ </mat-accordion> <div class="form-group" style="margin-top: 10px;"> <div style="text-align:center;"> - <button mat-raised-button color="primary" *ngIf="creationMode" type="submit" [disabled]="!profileForm.form.valid">{{lang.save}}</button> - <button mat-raised-button color="primary" *ngIf="!creationMode" type="submit" [disabled]="!profileForm.form.valid">{{lang.update}}</button> + <button mat-raised-button color="primary" *ngIf="creationMode" type="submit" + [disabled]="!profileForm.form.valid">{{lang.save}}</button> + <button mat-raised-button color="primary" *ngIf="!creationMode" type="submit" + [disabled]="!profileForm.form.valid">{{lang.update}}</button> </div> </div> </form> @@ -182,7 +214,9 @@ <mat-tab *ngIf="!creationMode" label="{{lang.groups}}"> <mat-nav-list> <mat-list-item *ngFor="let group of user.allGroups" disableRipple="true"> - <mat-slide-toggle id="{{group.group_id}}" color="primary" [checked]="group.disabled == true" (change)="toggleGroup(group)">{{group.group_desc}}</mat-slide-toggle> + <mat-slide-toggle id="{{group.group_id}}" color="primary" + [checked]="group.disabled == true" (change)="toggleGroup(group)"> + {{group.group_desc}}</mat-slide-toggle> </mat-list-item> </mat-nav-list> </mat-tab> @@ -198,31 +232,41 @@ <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 *ngIf="!selectionBaskets.hasValue()" style="opacity: 0.5;font-style: italic;font-size: 80%;margin-top:10px;"> + <p mat-line *ngIf="!selectionBaskets.hasValue()" + style="opacity: 0.5;font-style: italic;font-size: 80%;margin-top:10px;"> {{lang.selectAll}} </p> <p mat-line *ngIf="selectionBaskets.hasValue()" style="margin-top:10px;"> - <button [matMenuTriggerFor]="menu" mat-icon-button matTooltip="{{ lang.redirectBaskets }}"> + <button [matMenuTriggerFor]="menu" mat-icon-button + matTooltip="{{ lang.redirectBaskets }}"> <mat-icon class="fa fa-reply"></mat-icon> <mat-divider [vertical]="true" class="vertical-divider"></mat-divider> </button> - <button color="warn" mat-icon-button matTooltip="{{lang.disableBasket}}" (click)="toggleBasket(false)"> + <button color="warn" mat-icon-button matTooltip="{{lang.disableBasket}}" + (click)="toggleBasket(false)"> <mat-icon class="fa fa-ban"></mat-icon> </button> - <button color="accent" mat-icon-button matTooltip="{{lang.enableBasket}}" (click)="toggleBasket(true)"> + <button color="accent" mat-icon-button matTooltip="{{lang.enableBasket}}" + (click)="toggleBasket(true)"> <mat-icon class="fa fa-check"></mat-icon> </button> <mat-menu #menu="matMenu"> <mat-form-field style="padding:10px;width:200px !important;"> - <input (click)="$event.stopPropagation()" type="text" placeholder="{{ lang.users }}" matInput [matAutocomplete]="auto" [formControl]="userCtrl"> + <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)"> + <mat-option *ngFor="let user of filteredUsers | async" + [value]="user.id" (click)="addBasketRedirection(user)"> <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> + <mat-icon color="primary" class="fa fa-user fa-2x" + style="margin-right:0px;"></mat-icon> </span> <span class="col-xm-11"> {{ user.idToDisplay }} @@ -239,13 +283,19 @@ <ng-container *ngFor="let basket of user.baskets;let i = index"> <mat-list-item *ngIf="basket.userToDisplay == null" 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 color="primary" style="display: flex;align-items: center;"> - <span (click)="selectionBaskets.toggle(basket);" matTooltip="{{basket.basket_name}} [{{basket.group_desc}}]" [ngStyle]="{'opacity': basket.allowed ? '1' : '0.5'}" style="flex: 2;overflow: hidden;text-overflow: ellipsis;"> + <span (click)="selectionBaskets.toggle(basket);" + matTooltip="{{basket.basket_name}} [{{basket.group_desc}}]" + [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 class="label label-primary" + style="font-weight:normal">{{basket.group_desc}}</span> </span> </h4> </mat-list-item> @@ -258,16 +308,22 @@ <mat-list> <ng-container *ngFor="let basket of user.redirectedBaskets;let i = index"> <mat-list-item> - <mat-icon mat-list-icon color="primary" style="margin-top:-60px;" class="fa fa-paper-plane"> + <mat-icon mat-list-icon color="primary" style="margin-top:-60px;" + class="fa fa-paper-plane"> </mat-icon> <h4 mat-line color="primary">{{basket.basket_name}} - <span class="label label-primary" style="font-weight:normal">{{basket.group_desc}}</span> + <span class="label label-primary" + style="font-weight:normal">{{basket.group_desc}}</span> </h4> <p mat-line> <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,i)" matTooltip="Supprimer la redirection"> - <mat-icon color="warn" class="fa fa-times text-danger"></mat-icon> + <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,i)" + matTooltip="Supprimer la redirection"> + <mat-icon color="warn" class="fa fa-times text-danger"> + </mat-icon> </button> </mat-form-field> </p> @@ -282,20 +338,29 @@ <mat-list> <ng-container *ngFor="let basket of user.assignedBaskets;let i = index"> <mat-list-item> - <mat-icon mat-list-icon color="primary" style="margin-top:-60px;" class="fa fa-reply"> + <mat-icon mat-list-icon color="primary" style="margin-top:-60px;" + class="fa fa-reply"> </mat-icon> <h4 mat-line color="primary">{{basket.basket_name}} - <span class="label label-primary" style="font-weight:normal">{{basket.group_desc}}</span> + <span class="label label-primary" + style="font-weight:normal">{{basket.group_desc}}</span> </h4> <p mat-line> - <mat-form-field *ngIf="basket.userToDisplay == null" floatLabel="never"> - <input matTooltip="{{lang.redirectBasket}}" matTooltipPosition="above" type="text" placeholder="{{lang.redirectBasket}}" - matInput [matAutocomplete]="auto" [formControl]="userCtrl"> + <mat-form-field *ngIf="basket.userToDisplay == null" + 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,i)"> + <mat-option *ngFor="let user of filteredUsers | async" + [value]="user.id" + (click)="reassignBasketRedirection(user.id,basket,i)"> <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> + <mat-icon color="primary" + class="fa fa-user fa-2x" + style="margin-right:0px;"></mat-icon> </span> <span class="col-xm-11"> {{ user.idToDisplay }} @@ -306,12 +371,19 @@ </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=null" matTooltip="{{lang.reassign}}"> + <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=null" + 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)="delBasketAssignRedirection(basket,i)" matTooltip="{{lang.deleteAssignation}}"> - <mat-icon color="warn" class="fa fa-times text-danger"></mat-icon> + <button mat-button color="warn" matSuffix mat-icon-button + aria-label="Clear" + (click)="delBasketAssignRedirection(basket,i)" + matTooltip="{{lang.deleteAssignation}}"> + <mat-icon color="warn" class="fa fa-times text-danger"> + </mat-icon> </button> </mat-form-field> </p> @@ -323,48 +395,67 @@ </div> </mat-tab> <mat-tab *ngIf="!creationMode" label="{{lang.signatures}}"> - <div dnd-droppable matTooltip="{{lang.uploadSignFileInfo}}" (click)="clickOnUploader('uploadSignFile')" [class.dndFileHighlighted]="highlightMe" - (dragover)="highlightMe=true" (dragleave)="highlightMe=false" (onDropSuccess)="test($event);highlightMe=false;" - class="dndFile"> + <div dnd-droppable matTooltip="{{lang.uploadSignFileInfo}}" + (click)="clickOnUploader('uploadSignFile')" [class.dndFileHighlighted]="highlightMe" + (dragover)="highlightMe=true" (dragleave)="highlightMe=false" + (onDropSuccess)="test($event);highlightMe=false;" class="dndFile"> {{lang.uploadSignFile}} </div> - <div class="col-md-3 col-sm-6 col-xm-12" *ngFor="let signature of user.signatures; let i = index"> - <mat-card style="margin-bottom:10px;"> - <mat-card-content style="text-align:center;"> - <mat-form-field floatLabel="never"> - <input matInput type="text" [(ngModel)]="signature.signature_label" name="selectedSignatureLabel" placeholder="{{lang.label}}" - (change)="updateSignature(i)"> - <button mat-button matSuffix mat-icon-button (click)="deleteSignature(signature)" color="warn" matTooltip="{{lang.delete}}"> - <mat-icon class="fa fa-times"></mat-icon> - </button> - </mat-form-field> - <img src="{{coreUrl}}rest/users/{{user.id}}/signatures/{{signature.id}}/content" alt="Signature" style="width:auto;height:60px;"> - </mat-card-content> - </mat-card> + <div style="display: flex;align-items: flex-start;"> + <div style="flex:1;"> + <div class="col-md-3 col-sm-6 col-xm-12" + *ngFor="let signature of user.signatures; let i = index"> + <mat-card style="margin-bottom:10px;overflow:hidden;"> + <mat-card-content style="text-align:center;"> + <mat-form-field floatLabel="never"> + <input matInput type="text" [(ngModel)]="signature.signature_label" + name="selectedSignatureLabel" placeholder="{{lang.label}}" + (change)="updateSignature(i)"> + <button mat-button matSuffix mat-icon-button + (click)="deleteSignature(signature)" color="warn" + matTooltip="{{lang.delete}}"> + <mat-icon class="fa fa-times"></mat-icon> + </button> + </mat-form-field> + <img src="{{coreUrl}}rest/users/{{user.id}}/signatures/{{signature.id}}/content" + alt="Signature" style="width:auto;height:60px;"> + </mat-card-content> + </mat-card> + </div> + </div> + <div> + <button *ngIf="user.signatures.length > 0" mat-icon-button color="primary" (click)="syncMP()" + matTooltip="{{lang.syncSignsToMaarchParapheur}}" + [disabled]="!user.external_id.maarchParapheur || loadingSign"> + <mat-icon class="fa fa-sync-alt fa-2x" [class.fa-spin]="loadingSign"></mat-icon> + </button> + </div> </div> <form (ngSubmit)="submitSignature()" #signatureForm="ngForm" style="display:none;"> <div class="col-md-11"> - <input type="text" [(ngModel)]="signatureModel.label" id="signLabel" name="label" placeholder="{{lang.label}}" class="form-control" - required> + <input type="text" [(ngModel)]="signatureModel.label" id="signLabel" name="label" + placeholder="{{lang.label}}" class="form-control" required> <div class="form-inline hide"> <div class="form-group"> - <input type="file" name="files[]" id="uploadSignFile" (change)="uploadSignatureTrigger($event)" accept="image/*"> + <input type="file" name="files[]" id="uploadSignFile" + (change)="uploadSignatureTrigger($event)" accept="image/*"> </div> </div> </div> <div class="col-md-1" style="margin-bottom:5px;"> - <button class="form-control btn btn-sm btn-success" type="submit" [disabled]="!signatureForm.form.valid || !signatureModel.size"> + <button class="form-control btn btn-sm btn-success" type="submit" + [disabled]="!signatureForm.form.valid || !signatureModel.size"> <i class="fa fa-plus"></i> </button> </div> <div [ngClass]="[signatureModel.size != '' ? 'col-md-10' : 'col-md-12']"> - <div class="upload-drop-zone" (click)="clickOnUploader('uploadSignFile')" style="cursor:pointer"> + <div class="upload-drop-zone" (click)="clickOnUploader('uploadSignFile')" + style="cursor:pointer"> {{lang.clickOn}} <i class="fa fa-upload fa-2x"></i> ( - < 2MB ) </div> - </div> - <div class="col-md-2" *ngIf="signatureModel.size"> - <img id="signaturePreview" src="{{signatureModel.base64ForJs}}" alt="Invalid image" style="width: 100%;"> + < 2MB ) </div> </div> <div class="col-md-2" *ngIf="signatureModel.size"> + <img id="signaturePreview" src="{{signatureModel.base64ForJs}}" + alt="Invalid image" style="width: 100%;"> </div> </form> </mat-tab> @@ -374,7 +465,8 @@ <div class="row"> <div class="col-md-6 col-xs-6"> <mat-form-field> - <input matInput (keyup)="applyFilter($event.target.value)" placeholder="{{lang.filterBy}}"> + <input matInput (keyup)="applyFilter($event.target.value)" + placeholder="{{lang.filterBy}}"> </mat-form-field> </div> <div class="col-md-6 col-xs-6"> @@ -382,22 +474,31 @@ </mat-paginator> </div> </div> - <mat-table #table [dataSource]="dataSource" matSort matSortActive="event_date" matSortDirection="desc"> + <mat-table #table [dataSource]="dataSource" matSort matSortActive="event_date" + matSortDirection="desc"> <ng-container matColumnDef="event_date"> - <mat-header-cell *matHeaderCellDef mat-sort-header style="flex:1;">{{lang.date}}</mat-header-cell> - <mat-cell *matCellDef="let element" style="flex:1;">{{element.event_date | date : "dd/MM/y HH:mm"}}</mat-cell> + <mat-header-cell *matHeaderCellDef mat-sort-header style="flex:1;">{{lang.date}} + </mat-header-cell> + <mat-cell *matCellDef="let element" style="flex:1;"> + {{element.event_date | date : "dd/MM/y HH:mm"}}</mat-cell> </ng-container> <ng-container matColumnDef="event_type"> - <mat-header-cell *matHeaderCellDef mat-sort-header style="flex:1;">{{lang.event}}</mat-header-cell> - <mat-cell *matCellDef="let element" style="flex:1;"> {{element.event_type}} </mat-cell> + <mat-header-cell *matHeaderCellDef mat-sort-header style="flex:1;"> + {{lang.event}}</mat-header-cell> + <mat-cell *matCellDef="let element" style="flex:1;"> {{element.event_type}} + </mat-cell> </ng-container> <ng-container matColumnDef="info"> - <mat-header-cell *matHeaderCellDef mat-sort-header style="flex:2;">{{lang.description}}</mat-header-cell> - <mat-cell *matCellDef="let element" style="flex:2;"> {{element.info}} </mat-cell> + <mat-header-cell *matHeaderCellDef mat-sort-header style="flex:2;"> + {{lang.description}}</mat-header-cell> + <mat-cell *matCellDef="let element" style="flex:2;"> {{element.info}} + </mat-cell> </ng-container> <ng-container matColumnDef="remote_ip"> - <mat-header-cell *matHeaderCellDef mat-sort-header style="flex:1;">{{lang.ip}}</mat-header-cell> - <mat-cell *matCellDef="let element" style="flex:1;"> {{element.remote_ip}} </mat-cell> + <mat-header-cell *matHeaderCellDef mat-sort-header style="flex:1;">{{lang.ip}} + </mat-header-cell> + <mat-cell *matCellDef="let element" style="flex:1;"> {{element.remote_ip}} + </mat-cell> </ng-container> <mat-header-row *matHeaderRowDef="displayedColumns"></mat-header-row> <mat-row *matRowDef="let row; columns: displayedColumns;"></mat-row> @@ -405,9 +506,11 @@ <div class="row"> <div class="col-md-3 pull-right" style="padding-top:10px;"> <mat-form-field> - <input matInput [(ngModel)]="minDate" [matDatepicker]="picker" placeholder="Depuis" disabled> + <input matInput [(ngModel)]="minDate" [matDatepicker]="picker" + placeholder="Depuis" disabled> <mat-datepicker-toggle matSuffix [for]="picker"></mat-datepicker-toggle> - <mat-datepicker #picker startView="month" [startAt]="minDate"></mat-datepicker> + <mat-datepicker #picker startView="month" [startAt]="minDate"> + </mat-datepicker> </mat-form-field> </div> </div> @@ -418,7 +521,8 @@ </mat-card> </mat-sidenav-content> <mat-sidenav #snav2 [mode]="mobileQuery.matches ? 'over' : 'side'" [fixedInViewport]="mobileQuery.matches" - fixedTopGap="56" position='end' [opened]="mobileQuery.matches || creationMode ? false : true" style="overflow-x:hidden;max-width:500px;"> + fixedTopGap="56" position='end' [opened]="mobileQuery.matches || creationMode ? false : true" + style="overflow-x:hidden;max-width:500px;"> <mat-list> <h3 mat-subheader>{{lang.groups}}</h3> <mat-list-item *ngFor="let userGroup of user.groups"> @@ -426,7 +530,8 @@ <h4 mat-line>{{userGroup.group_desc}}</h4> <p mat-line> <mat-form-field style="font-size:10px;"> - <input matInput type="text" id="role" name="role" title="{{lang.role}}" placeholder="{{lang.role}}" [(ngModel)]="userGroup.role" + <input matInput type="text" id="role" name="role" title="{{lang.role}}" + placeholder="{{lang.role}}" [(ngModel)]="userGroup.role" (change)="updateGroup(userGroup)"> <mat-hint matTooltip="{{lang.perimeter}}">{{userGroup.maarch_comment}}</mat-hint> </mat-form-field> @@ -435,20 +540,26 @@ <mat-divider></mat-divider> <h3 mat-subheader>{{lang.entities}}</h3> <mat-list-item *ngFor="let userEntity of user.entities"> - <mat-icon color="primary" *ngIf="userEntity.primary_entity == 'Y'" mat-list-icon class="fa fa-sitemap"></mat-icon> - <mat-icon color="primary" *ngIf="userEntity.primary_entity != 'Y'" mat-list-icon class="fa fa-sitemap" style="position:relative;"> - <button mat-icon-button style="cursor:pointer;position: absolute;right: -20px;top: -20px;font-size:10px;" (click)="updatePrimaryEntity(userEntity)" - matTooltip="{{lang.entityTooglePrimary}}"> + <mat-icon color="primary" *ngIf="userEntity.primary_entity == 'Y'" mat-list-icon + class="fa fa-sitemap"></mat-icon> + <mat-icon color="primary" *ngIf="userEntity.primary_entity != 'Y'" mat-list-icon + class="fa fa-sitemap" style="position:relative;"> + <button mat-icon-button + style="cursor:pointer;position: absolute;right: -20px;top: -20px;font-size:10px;" + (click)="updatePrimaryEntity(userEntity)" matTooltip="{{lang.entityTooglePrimary}}"> <mat-icon class="fa fa-arrow-up"></mat-icon> </button> </mat-icon> - <h4 mat-line [ngStyle]="{'font-weight': userEntity.primary_entity == 'Y' ? 'bold' : 'normal'}" matTooltip="{{userEntity.entity_label}}"> + <h4 mat-line [ngStyle]="{'font-weight': userEntity.primary_entity == 'Y' ? 'bold' : 'normal'}" + matTooltip="{{userEntity.entity_label}}"> {{userEntity.entity_label}} - <span *ngIf="userEntity.primary_entity == 'Y'" class="label label-primary" style="font-weight:normal">{{lang.primary}}</span> + <span *ngIf="userEntity.primary_entity == 'Y'" class="label label-primary" + style="font-weight:normal">{{lang.primary}}</span> </h4> <p mat-line> <mat-form-field style="font-size:10px;"> - <input matInput type="text" id="role" name="role" title="{{lang.role}}" placeholder="{{lang.role}}" [(ngModel)]="userEntity.user_role" + <input matInput type="text" id="role" name="role" title="{{lang.role}}" + placeholder="{{lang.role}}" [(ngModel)]="userEntity.user_role" (change)="updateEntity(userEntity)"> </mat-form-field> </p> @@ -456,4 +567,4 @@ </mat-list> </mat-sidenav> </mat-sidenav-container> - </div> \ No newline at end of file +</div> \ No newline at end of file diff --git a/src/frontend/app/administration/user/user-administration.component.ts b/src/frontend/app/administration/user/user-administration.component.ts index c7893c8de666000583c3a0d999603c4e622cfa08..19c31254804923abcd42dc1b149de84106b791a6 100755 --- a/src/frontend/app/administration/user/user-administration.component.ts +++ b/src/frontend/app/administration/user/user-administration.component.ts @@ -52,6 +52,7 @@ export class UserAdministrationComponent extends AutoCompletePlugin implements O userList : any[] = []; selectedSignature : number = -1; selectedSignatureLabel : string = ""; + loadingSign : boolean = false; data : any[] = []; CurrentYear : number = new Date().getFullYear(); currentMonth : number = new Date().getMonth() + 1; @@ -141,6 +142,7 @@ export class UserAdministrationComponent extends AutoCompletePlugin implements O this.http.get(this.coreUrl + "rest/users/" + this.serialId + "/details") .subscribe((data: any) => { this.user = data; + this.data = data.history; this.userId = data.user_id; this.minDate = new Date(this.CurrentYear + '-' + this.currentMonth + '-01'); @@ -790,6 +792,19 @@ export class UserAdministrationComponent extends AutoCompletePlugin implements O setLowerUserId() { this.user.userId = this.user.userId.toLowerCase(); } + + syncMP() { + this.loadingSign = true; + + this.http.put('../../rest/users/' + this.user.id + '/externalSignatures', {}) + .subscribe((data: any) => { + this.loadingSign = false; + this.notify.success(this.lang.signsSynchronized); + }, (err) => { + this.loadingSign = false; + this.notify.error(err.error.errors); + }); + } } @Component({ diff --git a/src/frontend/app/profile.component.html b/src/frontend/app/profile.component.html index e0ffec108553c4d6c84aeb583de577903baba325..81d811874d782e444c9e1138729287f83b7b10dc 100755 --- a/src/frontend/app/profile.component.html +++ b/src/frontend/app/profile.component.html @@ -1,7 +1,7 @@ <div class="admin-container" [class.admin-is-mobile]="mobileQuery.matches"> <mat-sidenav-container autosize class="admin-sidenav-container"> - <mat-sidenav #snav [mode]="mobileMode ? 'over' : 'side'" [fixedInViewport]="mobileMode" fixedTopGap="56" [opened]="mobileMode ? false : true" - autoFocus="false"> + <mat-sidenav #snav [mode]="mobileMode ? 'over' : 'side'" [fixedInViewport]="mobileMode" fixedTopGap="56" + [opened]="mobileMode ? false : true" autoFocus="false"> <menu-shortcut></menu-shortcut> <menu-nav></menu-nav> <mat-nav-list> @@ -31,17 +31,26 @@ <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> + <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="form-group"> - <div style="text-align:center;color: rgba(0,0,0,0.54);font-size: 75%;">{{this.ruleText}}</div> + <div style="text-align:center;color: rgba(0,0,0,0.54);font-size: 75%;"> + {{this.ruleText}}</div> <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> + <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> @@ -51,10 +60,13 @@ </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'" + <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 != ''"> + <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> @@ -62,20 +74,26 @@ </mat-form-field> </div> </div> - <div *ngIf="passwordRules.renewal.enabled || passwordRules.historyLastUse.enabled" class="form-group"> + <div *ngIf="passwordRules.renewal.enabled || passwordRules.historyLastUse.enabled" + class="form-group"> <div class="col-sm-12" style="padding-left:0px;padding-right:0px;"> - <div class="alert alert-warning" role="alert" [innerHTML]="otherRuleText" style="text-align:center;"></div> + <div class="alert alert-warning" role="alert" [innerHTML]="otherRuleText" + style="text-align:center;"></div> </div> </div> <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> + <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> </form> </div> - <form class="form-horizontal" (ngSubmit)="onSubmit()" #profileForm="ngForm" *ngIf="!showPassword"> + <form class="form-horizontal" (ngSubmit)="onSubmit()" #profileForm="ngForm" + *ngIf="!showPassword"> <div class="form-group"> <div class="col-sm-12"> <div class="pull-left"> @@ -85,7 +103,8 @@ </div> <div class="input-group"> <mat-form-field> - <input matInput type="text" title="{{lang.id}}" value="{{user.user_id}}" placeholder="{{lang.id}}" disabled> + <input matInput type="text" title="{{lang.id}}" value="{{user.user_id}}" + placeholder="{{lang.id}}" disabled> </mat-form-field> </div> </div> @@ -93,26 +112,31 @@ <div class="form-group"> <div class="col-sm-5" style="font-weight:bold;"> <mat-form-field> - <input matInput type="text" id="lastname" name="lastname" title="{{lang.lastname}}" placeholder="{{lang.lastname}}" [(ngModel)]="user.lastname" - required> + <input matInput type="text" id="lastname" name="lastname" + title="{{lang.lastname}}" placeholder="{{lang.lastname}}" + [(ngModel)]="user.lastname" required> </mat-form-field> </div> <div class="col-sm-5" style="font-weight:bold;"> <mat-form-field> - <input matInput type="text" id="firstname" name="firstname" title="{{lang.firstname}}" placeholder="{{lang.firstname}}" [(ngModel)]="user.firstname" - required> + <input matInput type="text" id="firstname" name="firstname" + title="{{lang.firstname}}" placeholder="{{lang.firstname}}" + [(ngModel)]="user.firstname" required> </mat-form-field> </div> <div class="col-sm-2" style="font-style:italic;"> <mat-form-field> - <input matInput type="text" id="initials" name="initials" title="{{lang.initials}}" placeholder="{{lang.initials}}" [(ngModel)]="user.initials"> + <input matInput type="text" id="initials" name="initials" + title="{{lang.initials}}" placeholder="{{lang.initials}}" + [(ngModel)]="user.initials"> </mat-form-field> </div> </div> <div class="form-group"> <div class="col-sm-12"> <mat-form-field> - <input matInput type="tel" id="phone" name="phone" title="{{lang.phoneNumber}}" placeholder="{{lang.phoneNumber}}" [(ngModel)]="user.phone" + <input matInput type="tel" id="phone" name="phone" title="{{lang.phoneNumber}}" + placeholder="{{lang.phoneNumber}}" [(ngModel)]="user.phone" pattern="\+?((|\ |\.|\(|\)|\-)?(\d)*)*\d$"> </mat-form-field> </div> @@ -120,14 +144,16 @@ <div class="form-group"> <div class="col-sm-12"> <mat-form-field> - <input matInput type="email" id="mail" name="mail" title="{{lang.email}}" placeholder="{{lang.email}}" [(ngModel)]="user.mail" + <input matInput type="email" id="mail" name="mail" title="{{lang.email}}" + placeholder="{{lang.email}}" [(ngModel)]="user.mail" pattern="(^[a-zA-Z0-9_.+-]+@[a-zA-Z0-9-]+\.[a-zA-Z0-9-.]+$)" required> </mat-form-field> </div> </div> <div class="form-group" style="margin-top: 10px;"> <div style="text-align:center;"> - <button mat-raised-button color="primary" type="submit" [disabled]="!profileForm.form.valid">{{lang.update}}</button> + <button mat-raised-button color="primary" type="submit" + [disabled]="!profileForm.form.valid">{{lang.update}}</button> </div> </div> </form> @@ -137,8 +163,10 @@ <mat-expansion-panel> <mat-expansion-panel-header> <mat-panel-title> - <mat-icon color="primary" class="fa fa-inbox" style="font-size:25px;width:50px;"></mat-icon> - <mat-icon color="primary" class="fa fa-magic" style="position: absolute;margin-left: 30px;margin-top: -10px;"></mat-icon> + <mat-icon color="primary" class="fa fa-inbox" + style="font-size:25px;width:50px;"></mat-icon> + <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 *ngIf="!mobileMode"> @@ -150,12 +178,16 @@ <ng-container *ngFor="let regroupedBasket of user.regroupedBaskets; let i = index"> <h3 *ngIf="regroupedBasket.baskets[0]">{{regroupedBasket.groupDesc}}</h3> <mat-list-item *ngFor="let basket of regroupedBasket.baskets; let y = index"> - <mat-icon mat-list-icon class="fa fa-inbox" [ngStyle]="{'color': user.regroupedBaskets[i].baskets[y].color}"></mat-icon> + <mat-icon mat-list-icon class="fa fa-inbox" + [ngStyle]="{'color': user.regroupedBaskets[i].baskets[y].color}"> + </mat-icon> <h4 mat-line title="{{basket.basket_id}}">{{basket.basket_name}}</h4> - <input name="color" type="color" style="background: none;border: none;height: 20px;width:20px;padding: 0;margin-right: 15px" - [(ngModel)]="user.regroupedBaskets[i].baskets[y].color" (change)="updateBasketColor(i, y)" - /> - <a (click)="user.regroupedBaskets[i].baskets[y].color = ''; updateBasketColor(i, y)" title="{{lang.resetColor}}" style="cursor: pointer;color: #666666"> + <input name="color" type="color" + style="background: none;border: none;height: 20px;width:20px;padding: 0;margin-right: 15px" + [(ngModel)]="user.regroupedBaskets[i].baskets[y].color" + (change)="updateBasketColor(i, y)" /> + <a (click)="user.regroupedBaskets[i].baskets[y].color = ''; updateBasketColor(i, y)" + title="{{lang.resetColor}}" style="cursor: pointer;color: #666666"> <i class="fa fa-magic"></i> </a> </mat-list-item> @@ -165,8 +197,10 @@ <mat-expansion-panel [expanded]="myBasketExpansionPanel"> <mat-expansion-panel-header> <mat-panel-title> - <mat-icon color="primary" class="fa fa-inbox" style="font-size:25px;width:50px;"></mat-icon> - <mat-icon color="primary" class="fa fa-reply" style="position: absolute;margin-left: 30px;margin-top: -10px;"></mat-icon> + <mat-icon color="primary" class="fa fa-inbox" + style="font-size:25px;width:50px;"></mat-icon> + <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 *ngIf="!mobileMode"> @@ -177,21 +211,28 @@ <mat-list> <mat-list-item> <mat-icon mat-list-icon color="primary"> - <mat-checkbox color="primary" (change)="$event ? masterToggleBaskets($event) : null" [checked]="selectionBaskets.hasValue()" + <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%;"> + <span *ngIf="!selectionBaskets.hasValue()" + style="opacity: 0.5;font-style: italic;font-size: 80%;"> {{lang.selectAll}} </span> <mat-form-field *ngIf="selectionBaskets.hasValue()"> - <input matTooltip="{{lang.redirectWhenAbscence}}" matTooltipPosition="above" type="text" placeholder="{{ lang.redirectBaskets }}" - matInput [matAutocomplete]="auto" [formControl]="userCtrl"> + <input matTooltip="{{lang.redirectWhenAbscence}}" + matTooltipPosition="above" type="text" + placeholder="{{ lang.redirectBaskets }}" matInput + [matAutocomplete]="auto" [formControl]="userCtrl"> <mat-autocomplete #auto="matAutocomplete"> - <mat-option *ngFor="let user of filteredUsers | async" [value]="user.id" (click)="addBasketRedirection(user)"> + <mat-option *ngFor="let user of filteredUsers | async" + [value]="user.id" (click)="addBasketRedirection(user)"> <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> + <mat-icon color="primary" class="fa fa-user fa-2x" + style="margin-right:0px;"></mat-icon> </span> <span class="col-xm-11"> {{ user.idToDisplay }} @@ -205,16 +246,22 @@ </mat-list-item> <mat-divider></mat-divider> <ng-container *ngFor="let basket of user.baskets;let i = index"> - <mat-list-item *ngIf="basket.userToDisplay == null" (mouseover)="showActions(basket)" (mouseout)="hideActions(basket)" + <mat-list-item *ngIf="basket.userToDisplay == null" + (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 color="primary" style="display: flex;align-items: center;"> - <span (click)="selectionBaskets.toggle(basket);" matTooltip="{{basket.basket_name}} [{{basket.group_desc}}]" style="flex: 2;overflow: hidden;text-overflow: ellipsis;"> + <span (click)="selectionBaskets.toggle(basket);" + matTooltip="{{basket.basket_name}} [{{basket.group_desc}}]" + 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 class="label label-primary" + style="font-weight:normal">{{basket.group_desc}}</span> </span> </h4> </mat-list-item> @@ -225,18 +272,26 @@ <mat-tab-group> <mat-tab label="{{lang.basketsRedirected}}"> <mat-list> - <ng-container *ngFor="let basket of user.redirectedBaskets;let i = index"> + <ng-container + *ngFor="let basket of user.redirectedBaskets;let i = index"> <mat-list-item> - <mat-icon mat-list-icon color="primary" style="margin-top:-60px;" class="fa fa-paper-plane"> + <mat-icon mat-list-icon color="primary" + style="margin-top:-60px;" class="fa fa-paper-plane"> </mat-icon> - <h4 mat-line color="primary">{{basket.basket_name}} - <span class="label label-primary" style="font-weight:normal">{{basket.group_desc}}</span> + <h4 mat-line color="primary">{{basket.basket_name}} + <span class="label label-primary" + style="font-weight:normal">{{basket.group_desc}}</span> </h4> <p mat-line> <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,i)" matTooltip="Supprimer la redirection"> - <mat-icon color="warn" class="fa fa-times text-danger"></mat-icon> + <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,i)" + matTooltip="Supprimer la redirection"> + <mat-icon color="warn" + class="fa fa-times text-danger"></mat-icon> </button> </mat-form-field> </p> @@ -251,20 +306,31 @@ <mat-list> <ng-container *ngFor="let basket of user.assignedBaskets;let i = index"> <mat-list-item> - <mat-icon mat-list-icon color="primary" style="margin-top:-60px;" class="fa fa-reply"> + <mat-icon mat-list-icon color="primary" + style="margin-top:-60px;" class="fa fa-reply"> </mat-icon> <h4 mat-line color="primary">{{basket.basket_name}} - <span class="label label-primary" style="font-weight:normal">{{basket.group_desc}}</span> + <span class="label label-primary" + style="font-weight:normal">{{basket.group_desc}}</span> </h4> <p mat-line> - <mat-form-field *ngIf="basket.userToDisplay == null" floatLabel="never"> - <input matTooltip="{{lang.redirectBasket}}" matTooltipPosition="above" type="text" placeholder="{{lang.redirectBasket}}" - matInput [matAutocomplete]="auto" [formControl]="userCtrl"> + <mat-form-field *ngIf="basket.userToDisplay == null" + 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,basket,i)"> + <mat-option + *ngFor="let user of filteredUsers | async" + [value]="user.id" + (click)="reassignBasketRedirection(user,basket,i)"> <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> + <mat-icon color="primary" + class="fa fa-user fa-2x" + style="margin-right:0px;"> + </mat-icon> </span> <span class="col-xm-11"> {{ user.idToDisplay }} @@ -275,12 +341,21 @@ </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=null" matTooltip="{{lang.reassign}}"> - <mat-icon color="primary" class="fa fa-edit"></mat-icon> + <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=null" + 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)="delBasketAssignRedirection(basket,i)" matTooltip="{{lang.deleteAssignation}}"> - <mat-icon color="warn" class="fa fa-times text-danger"></mat-icon> + <button mat-button color="warn" matSuffix + mat-icon-button aria-label="Clear" + (click)="delBasketAssignRedirection(basket,i)" + matTooltip="{{lang.deleteAssignation}}"> + <mat-icon color="warn" + class="fa fa-times text-danger"></mat-icon> </button> </mat-form-field> </p> @@ -295,7 +370,8 @@ <mat-expansion-panel (opened)="initMce()"> <mat-expansion-panel-header> <mat-panel-title> - <mat-icon color="primary" class="fa fa-envelope" style="font-size:25px;width:50px;"></mat-icon> + <mat-icon color="primary" class="fa fa-envelope" + style="font-size:25px;width:50px;"></mat-icon> {{lang.mySignMail}} </mat-panel-title> <mat-panel-description *ngIf="!mobileMode"> @@ -307,37 +383,50 @@ <div class="row" style="margin-top:5px;"> <div class="col-md-12"> <mat-form-field> - <input matInput type="text" [(ngModel)]="mailSignatureModel.title" name="title" placeholder="{{lang.label}}" required> + <input matInput type="text" [(ngModel)]="mailSignatureModel.title" + name="title" placeholder="{{lang.label}}" required> </mat-form-field> </div> </div> <div class="row" style="margin-top:5px;"> <div class="col-md-12"> <div id="html_mode" style="display: block; width:100%;"> - <textarea name="emailSignature" id="emailSignature" style="width:100%" rows="15" cols="60"></textarea> + <textarea name="emailSignature" id="emailSignature" + style="width:100%" rows="15" cols="60"></textarea> </div> </div> </div> <div class="col-md-12 form-group" style="margin-top: 10px;"> <div style="text-align:center;"> - <button mat-raised-button color="primary" type="submit" *ngIf="mailSignatureModel.selected==-1" [disabled]="!emailSignatureForm.form.valid">{{lang.save}}</button> - <button mat-raised-button color="primary" type="button" *ngIf="mailSignatureModel.selected!=-1" (click)="updateEmailSignature()" + <button mat-raised-button color="primary" type="submit" + *ngIf="mailSignatureModel.selected==-1" + [disabled]="!emailSignatureForm.form.valid">{{lang.save}}</button> + <button mat-raised-button color="primary" type="button" + *ngIf="mailSignatureModel.selected!=-1" + (click)="updateEmailSignature()" [disabled]="!emailSignatureForm.form.valid">{{lang.update}}</button> - <button mat-raised-button color="warn" type="button" *ngIf="mailSignatureModel.selected!=-1" (click)="deleteEmailSignature()">{{lang.delete}}</button> - <button mat-raised-button color="default" type="button" *ngIf="mailSignatureModel.selected!=-1" (click)="resetEmailSignature()">{{lang.cancel}}</button> + <button mat-raised-button color="warn" type="button" + *ngIf="mailSignatureModel.selected!=-1" + (click)="deleteEmailSignature()">{{lang.delete}}</button> + <button mat-raised-button color="default" type="button" + *ngIf="mailSignatureModel.selected!=-1" + (click)="resetEmailSignature()">{{lang.cancel}}</button> </div> </div> </form> </div> <div class="col-sm-6" style="overflow:hidden;"> - <div class="col-md-6 col-sm-6 col-xm-12" *ngFor="let emailSignature of user.emailSignatures; let i = index"> + <div class="col-md-6 col-sm-6 col-xm-12" + *ngFor="let emailSignature of user.emailSignatures; let i = index"> <mat-card style="margin-bottom:10px;"> <mat-card-content style="text-align:center;"> <mat-form-field floatLabel="never"> - <input matInput type="text" [(ngModel)]="emailSignature.title" name="selectedEmailSignatureLabel" placeholder="{{lang.label}}" + <input matInput type="text" [(ngModel)]="emailSignature.title" + name="selectedEmailSignatureLabel" placeholder="{{lang.label}}" disabled> </mat-form-field> - <button mat-icon-button color="primary" (click)="changeEmailSignature(i)" matTooltip="{{lang.update}}"> + <button mat-icon-button color="primary" + (click)="changeEmailSignature(i)" matTooltip="{{lang.update}}"> <mat-icon class="fa fa-edit fa-2x"></mat-icon> </button> </mat-card-content> @@ -349,77 +438,105 @@ <mat-expansion-panel> <mat-expansion-panel-header> <mat-panel-title> - <mat-icon color="primary" class="fa fa-certificate" style="font-size:25px;width:50px;"></mat-icon> + <mat-icon color="primary" class="fa fa-certificate" + style="font-size:25px;width:50px;"></mat-icon> {{lang.mySignSignatureBook}} </mat-panel-title> <mat-panel-description *ngIf="!mobileMode"> {{lang.mySignSignatureBookDesc}} </mat-panel-description> </mat-expansion-panel-header> - <div class="col-sm-12" style="overflow:hidden;"> - <div dnd-droppable matTooltip="{{lang.uploadSignFileInfo}}" (click)="clickOnUploader('uploadSignFile')" [class.dndFileHighlighted]="highlightMe" - (dragover)="highlightMe=true" (dragleave)="highlightMe=false" (onDropSuccess)="dndUploadSignature($event);highlightMe=false;" + + <div style="overflow:hidden;"> + <div dnd-droppable matTooltip="{{lang.uploadSignFileInfo}}" + (click)="clickOnUploader('uploadSignFile')" + [class.dndFileHighlighted]="highlightMe" (dragover)="highlightMe=true" + (dragleave)="highlightMe=false" + (onDropSuccess)="dndUploadSignature($event);highlightMe=false;" class="dndFile"> {{lang.uploadSignFile}} </div> - <form (ngSubmit)="submitSignature()" #signatureForm="ngForm" style="display:none;"> + <form (ngSubmit)="submitSignature()" #signatureForm="ngForm" + style="display:none;"> <div class="col-md-12"> <mat-form-field> - <input matInput type="text" id="signature_label" name="signature_label" title="{{lang.label}}" placeholder="{{lang.label}}" - [(ngModel)]="signatureModel.label" required> + <input matInput type="text" id="signature_label" + name="signature_label" title="{{lang.label}}" + placeholder="{{lang.label}}" [(ngModel)]="signatureModel.label" + required> </mat-form-field> <div class="form-inline hide"> <div class="form-group"> - <input type="file" name="files[]" id="uploadSignFile" (change)="uploadSignatureTrigger($event)" accept="image/*"> + <input type="file" name="files[]" id="uploadSignFile" + (change)="uploadSignatureTrigger($event)" accept="image/*"> </div> </div> </div> <div [ngClass]="[signatureModel.size != '' ? 'col-md-10' : 'col-md-12']"> - <div class="upload-drop-zone" (click)="clickOnUploader('uploadSignFile')" style="cursor:pointer"> + <div class="upload-drop-zone" + (click)="clickOnUploader('uploadSignFile')" style="cursor:pointer"> {{lang.clickOn}} <i class="fa fa-upload fa-2x"></i> ( - < 2MB) </div> - </div> - <div class="col-md-2" *ngIf="signatureModel.size"> - <img id="signaturePreview" src="{{signatureModel.base64ForJs}}" alt="Image non valide" style="width: 100%;"> + < 2MB) </div> </div> <div class="col-md-2" + *ngIf="signatureModel.size"> + <img id="signaturePreview" src="{{signatureModel.base64ForJs}}" + alt="Image non valide" style="width: 100%;"> </div> <div class="col-md-12 form-group" style="margin-top: 10px;"> <div style="text-align:center;"> - <button mat-raised-button color="primary" type="submit" [disabled]="!signatureForm.form.valid || !signatureModel.size">{{lang.save}}</button> + <button mat-raised-button color="primary" type="submit" + [disabled]="!signatureForm.form.valid || !signatureModel.size">{{lang.save}}</button> </div> </div> </form> - </div> - <div class="col-sm-12" style="overflow:hidden;"> - <div class="col-md-4 col-sm-4 col-xm-6" *ngFor="let signature of user.signatures; let i = index"> + </div> + + <div style="display: flex;align-items: flex-start;"> + <div style="flex:1;overflow:hidden;"> + <div class="col-md-4 col-sm-4 col-xm-6" + *ngFor="let signature of user.signatures; let i = index"> <mat-card style="margin-bottom:10px;"> <mat-card-content style="text-align:center;"> <mat-form-field floatLabel="never"> - <input matInput type="text" [(ngModel)]="signature.signature_label" name="selectedSignatureLabel" placeholder="{{lang.label}}" + <input matInput type="text" [(ngModel)]="signature.signature_label" + name="selectedSignatureLabel" placeholder="{{lang.label}}" (change)="updateSignature(signature)"> - <button mat-button matSuffix mat-icon-button (click)="deleteSignature(signature.id)" color="warn" matTooltip="{{lang.delete}}"> + <button mat-button matSuffix mat-icon-button + (click)="deleteSignature(signature.id)" color="warn" + matTooltip="{{lang.delete}}"> <mat-icon class="fa fa-times"></mat-icon> </button> </mat-form-field> - <img src="{{coreUrl}}rest/users/{{user.id}}/signatures/{{signature.id}}/content" alt="Signature" style="max-width:100%;height:60px;"> + <img src="{{coreUrl}}rest/users/{{user.id}}/signatures/{{signature.id}}/content" + alt="Signature" style="max-width:100%;height:60px;"> </mat-card-content> </mat-card> </div> </div> - <div style="clear:both;"></div> + <div> + <button *ngIf="user.signatures.length > 0" mat-icon-button color="primary" (click)="syncMP()" + matTooltip="{{lang.syncSignsToMaarchParapheur}}" [disabled]="!user.external_id.maarchParapheur || loadingSign"> + <mat-icon class="fa fa-sync-alt fa-2x" [class.fa-spin]="loadingSign" ></mat-icon> + </button> + </div> + </div> + <div style="clear:both;"></div> </mat-expansion-panel> <mat-expansion-panel (opened)="initGroupsContact()"> <mat-expansion-panel-header> <mat-panel-title> - <mat-icon color="primary" class="fa fa-users" style="font-size:25px;width:50px;"></mat-icon> + <mat-icon color="primary" class="fa fa-users" + style="font-size:25px;width:50px;"></mat-icon> {{lang.myContactsGroups}} </mat-panel-title> <mat-panel-description *ngIf="!mobileMode"> {{lang.myContactsGroupsDesc}} </mat-panel-description> </mat-expansion-panel-header> - <mat-tab-group (selectedIndexChange)="changeTabContactGrp($event);createGrpContPan.close();" [selectedIndex]="selectedIndexContactsGrp"> + <mat-tab-group + (selectedIndexChange)="changeTabContactGrp($event);createGrpContPan.close();" + [selectedIndex]="selectedIndexContactsGrp"> <mat-tab label="{{lang.contactGroupList}}"> <mat-accordion> <mat-expansion-panel #createGrpContPan (opened)="initGroupsContact()"> @@ -428,42 +545,53 @@ <span style="margin-top:5px;">{{lang.contactGroupCreate}}</span> </mat-panel-title> </mat-expansion-panel-header> - <form id="contactsGroupFormUp" class="form-horizontal" (ngSubmit)="contactsGroupSubmit();createGrpContPan.close();" #contactsGroupFormUp="ngForm"> - <div class="form-group"> - <div class="col-sm-12"> - <mat-form-field> - <input matInput [(ngModel)]="contactsGroup.label" required name="label" id="label" title="{{lang.label}}" type="text" placeholder="{{lang.label}}" - maxlength="32"> - </mat-form-field> - </div> + <form id="contactsGroupFormUp" class="form-horizontal" + (ngSubmit)="contactsGroupSubmit();createGrpContPan.close();" + #contactsGroupFormUp="ngForm"> + <div class="form-group"> + <div class="col-sm-12"> + <mat-form-field> + <input matInput [(ngModel)]="contactsGroup.label" + required name="label" id="label" + title="{{lang.label}}" type="text" + placeholder="{{lang.label}}" maxlength="32"> + </mat-form-field> </div> - <div class="form-group"> - <div class="col-sm-12"> - <mat-form-field> - <input matInput [(ngModel)]="contactsGroup.description" required name="description" id="description" title="{{lang.description}}" - type="text" placeholder="{{lang.description}}" maxlength="255"> - </mat-form-field> - </div> + </div> + <div class="form-group"> + <div class="col-sm-12"> + <mat-form-field> + <input matInput [(ngModel)]="contactsGroup.description" + required name="description" id="description" + title="{{lang.description}}" type="text" + placeholder="{{lang.description}}" maxlength="255"> + </mat-form-field> </div> - <div class="form-group"> - <div class="col-sm-12"> - <mat-slide-toggle name="plubic" title="{{lang.contactsGroupDesc}}" id="plubic" color="primary" [(ngModel)]="contactsGroup.public" - >{{lang.public}}</mat-slide-toggle> - </div> + </div> + <div class="form-group"> + <div class="col-sm-12"> + <mat-slide-toggle name="plubic" + title="{{lang.contactsGroupDesc}}" id="plubic" + color="primary" [(ngModel)]="contactsGroup.public"> + {{lang.public}}</mat-slide-toggle> </div> - <div class="form-group"> - <div class="col-sm-12" style="text-align:center;"> - <button mat-raised-button color="primary" type="submit" [disabled]="!contactsGroupFormUp.form.valid">{{lang.save}}</button> - </div> + </div> + <div class="form-group"> + <div class="col-sm-12" style="text-align:center;"> + <button mat-raised-button color="primary" type="submit" + [disabled]="!contactsGroupFormUp.form.valid">{{lang.save}}</button> </div> - </form> + </div> + </form> </mat-expansion-panel> </mat-accordion> <div id="contactsGroupList" style="margin-top: 10px;"> <div class="row"> <div class="col-md-6 col-xs-6"> <mat-form-field> - <input matInput (keyup)="applyFilterGroupsList($event.target.value)" placeholder="{{lang.filterBy}}"> + <input matInput + (keyup)="applyFilterGroupsList($event.target.value)" + placeholder="{{lang.filterBy}}"> </mat-form-field> </div> <div class="col-md-6 col-xs-6"> @@ -471,43 +599,65 @@ </mat-paginator> </div> </div> - <mat-table #tableGroupsListSort="matSort" [dataSource]="dataSourceGroupsList" matSort matSortActive="label" matSortDirection="asc"> + <mat-table #tableGroupsListSort="matSort" + [dataSource]="dataSourceGroupsList" matSort matSortActive="label" + matSortDirection="asc"> <ng-container matColumnDef="label"> - <mat-header-cell *matHeaderCellDef mat-sort-header [class.hide-for-mobile]="mobileQuery.matches" style="flex:2;">{{lang.label}}</mat-header-cell> - <mat-cell *matCellDef="let element" [class.hide-for-mobile]="mobileQuery.matches" style="flex:2;"> {{element.label}} </mat-cell> + <mat-header-cell *matHeaderCellDef mat-sort-header + [class.hide-for-mobile]="mobileQuery.matches" style="flex:2;"> + {{lang.label}}</mat-header-cell> + <mat-cell *matCellDef="let element" + [class.hide-for-mobile]="mobileQuery.matches" style="flex:2;"> + {{element.label}} </mat-cell> </ng-container> <ng-container matColumnDef="description"> - <mat-header-cell *matHeaderCellDef mat-sort-header style="flex:2;">{{lang.description}}</mat-header-cell> - <mat-cell *matCellDef="let element" style="flex:2;"> {{element.description}} </mat-cell> + <mat-header-cell *matHeaderCellDef mat-sort-header style="flex:2;"> + {{lang.description}}</mat-header-cell> + <mat-cell *matCellDef="let element" style="flex:2;"> + {{element.description}} </mat-cell> </ng-container> <ng-container matColumnDef="nbContacts"> - <mat-header-cell *matHeaderCellDef mat-sort-header style="flex:1;">{{lang.relatedContactNumber}}</mat-header-cell> + <mat-header-cell *matHeaderCellDef mat-sort-header style="flex:1;"> + {{lang.relatedContactNumber}}</mat-header-cell> <mat-cell *matCellDef="let element" style="flex:1;"> - <span *ngIf="element.nbContacts == 0">{{element.nbContacts}}</span> - <span *ngIf="element.nbContacts > 0" color="primary" style="font-weight:bold;">{{element.nbContacts}}</span> + <span + *ngIf="element.nbContacts == 0">{{element.nbContacts}}</span> + <span *ngIf="element.nbContacts > 0" color="primary" + style="font-weight:bold;">{{element.nbContacts}}</span> </mat-cell> </ng-container> <ng-container matColumnDef="public"> - <mat-header-cell *matHeaderCellDef mat-sort-header [class.hide-for-mobile]="mobileQuery.matches" style="flex:1;">{{lang.public}}</mat-header-cell> - <mat-cell *matCellDef="let element" [class.hide-for-mobile]="mobileQuery.matches" style="flex:1;"> + <mat-header-cell *matHeaderCellDef mat-sort-header + [class.hide-for-mobile]="mobileQuery.matches" style="flex:1;"> + {{lang.public}}</mat-header-cell> + <mat-cell *matCellDef="let element" + [class.hide-for-mobile]="mobileQuery.matches" style="flex:1;"> <span *ngIf="!element.public"> {{lang.no}} </span> <span *ngIf="element.public"> {{lang.yes}} </span> </mat-cell> </ng-container> <ng-container matColumnDef="owner"> - <mat-header-cell *matHeaderCellDef mat-sort-header style="flex:1;">{{lang.createdBy}}</mat-header-cell> - <mat-cell *matCellDef="let element" style="flex:1;"> {{element.labelledOwner}} </mat-cell> + <mat-header-cell *matHeaderCellDef mat-sort-header style="flex:1;"> + {{lang.createdBy}}</mat-header-cell> + <mat-cell *matCellDef="let element" style="flex:1;"> + {{element.labelledOwner}} </mat-cell> </ng-container> <ng-container matColumnDef="actions"> <mat-header-cell *matHeaderCellDef></mat-header-cell> - <mat-cell *matCellDef="let element" style="justify-content: flex-end;"> - <button mat-icon-button color="warn" matTooltip="{{lang.delete}}" (click)="$event.stopPropagation();deleteContactsGroup(element.position)"> - <mat-icon class="fa fa-trash-alt fa-2x" aria-hidden="true"></mat-icon> + <mat-cell *matCellDef="let element" + style="justify-content: flex-end;"> + <button mat-icon-button color="warn" + matTooltip="{{lang.delete}}" + (click)="$event.stopPropagation();deleteContactsGroup(element.position)"> + <mat-icon class="fa fa-trash-alt fa-2x" aria-hidden="true"> + </mat-icon> </button> </mat-cell> </ng-container> - <mat-header-row *matHeaderRowDef="displayedColumnsGroupsList"></mat-header-row> - <mat-row *matRowDef="let row; columns: displayedColumnsGroupsList;" (click)="loadContactsGroup(row)" style="cursor:pointer;" + <mat-header-row *matHeaderRowDef="displayedColumnsGroupsList"> + </mat-header-row> + <mat-row *matRowDef="let row; columns: displayedColumnsGroupsList;" + (click)="loadContactsGroup(row)" style="cursor:pointer;" matTooltip="{{lang.view}}"></mat-row> </mat-table> </div> @@ -525,9 +675,12 @@ <div class="row" style="margin:0px;"> <div class="col-sm-4"> <mat-form-field> - <mat-select [(ngModel)]="contactTypeSearch" placeholder="{{lang.chooseContactType}}" id="contactTypeSearch" name="contactTypeSearch"> + <mat-select [(ngModel)]="contactTypeSearch" + placeholder="{{lang.chooseContactType}}" + id="contactTypeSearch" name="contactTypeSearch"> <mat-option value="all">{{lang.all}}</mat-option> - <mat-option *ngFor="let contactType of contactTypes" [value]="contactType.id"> + <mat-option *ngFor="let contactType of contactTypes" + [value]="contactType.id"> {{contactType.label}} </mat-option> </mat-select> @@ -536,48 +689,74 @@ <div class="col-md-8" style="padding:5px;"> <mat-form-field hintLabel="3 caractères minium"> <span matPrefix> - <mat-icon class="fa fa-user-plus" color="primary"></mat-icon> </span> - <input class="autocompleteSearch" type="text" placeholder="{{lang.linkContact}}" matInput [formControl]="searchTerm" autocomplete="off" + <mat-icon class="fa fa-user-plus" color="primary"> + </mat-icon> + </span> + <input class="autocompleteSearch" type="text" + placeholder="{{lang.linkContact}}" matInput + [formControl]="searchTerm" autocomplete="off" (keyup)="launchLoading();" minlength="3"> </mat-form-field> </div> <div class="col-md-6 col-xs-6"> - <div class="alert alert-danger" *ngIf="dataSourceContactsListAutocomplete && dataSourceContactsListAutocomplete.data.length == 1000" + <div class="alert alert-danger" + *ngIf="dataSourceContactsListAutocomplete && dataSourceContactsListAutocomplete.data.length == 1000" [innerHTML]="lang.limitDataReached_1000"></div> </div> <div class="col-md-6 col-xs-6"> - <mat-paginator #paginatorContactList [length]="0" [pageSize]="10"> + <mat-paginator #paginatorContactList [length]="0" + [pageSize]="10"> </mat-paginator> </div> </div> - <mat-progress-bar mode="indeterminate" *ngIf="!dataSourceContactsListAutocomplete && !initAutoCompleteContact"></mat-progress-bar> - <mat-table #tableContactList [dataSource]="dataSourceContactsListAutocomplete" *ngIf="dataSourceContactsListAutocomplete"> + <mat-progress-bar mode="indeterminate" + *ngIf="!dataSourceContactsListAutocomplete && !initAutoCompleteContact"> + </mat-progress-bar> + <mat-table #tableContactList + [dataSource]="dataSourceContactsListAutocomplete" + *ngIf="dataSourceContactsListAutocomplete"> <ng-container matColumnDef="select"> <mat-header-cell *matHeaderCellDef style="flex:1;"> - <mat-checkbox color="primary" (change)="$event ? masterToggle($event) : null" [checked]="selection.hasValue()"> + <mat-checkbox color="primary" + (change)="$event ? masterToggle($event) : null" + [checked]="selection.hasValue()"> </mat-checkbox> </mat-header-cell> <mat-cell *matCellDef="let element" style="flex:1;"> - <mat-checkbox id="check_{{element.addressId}}" color="primary" (click)="$event.stopPropagation()" (change)="$event ? selection.toggle(element.addressId) : null" - [disabled]="isInGrp(element)" [checked]="selection.isSelected(element.addressId)"> + <mat-checkbox id="check_{{element.addressId}}" + color="primary" (click)="$event.stopPropagation()" + (change)="$event ? selection.toggle(element.addressId) : null" + [disabled]="isInGrp(element)" + [checked]="selection.isSelected(element.addressId)"> </mat-checkbox> </mat-cell> </ng-container> <ng-container matColumnDef="contact"> - <mat-header-cell *matHeaderCellDef style="flex:3;">{{lang.contact}}</mat-header-cell> - <mat-cell *matCellDef="let element" style="flex:3;"> {{element.contact}} </mat-cell> + <mat-header-cell *matHeaderCellDef style="flex:3;"> + {{lang.contact}}</mat-header-cell> + <mat-cell *matCellDef="let element" style="flex:3;"> + {{element.contact}} </mat-cell> </ng-container> <ng-container matColumnDef="address"> - <mat-header-cell *matHeaderCellDef style="flex:3;">{{lang.address}}</mat-header-cell> - <mat-cell *matCellDef="let element" style="flex:3;"> {{element.address}} </mat-cell> + <mat-header-cell *matHeaderCellDef style="flex:3;"> + {{lang.address}}</mat-header-cell> + <mat-cell *matCellDef="let element" style="flex:3;"> + {{element.address}} </mat-cell> </ng-container> - <mat-header-row *matHeaderRowDef="displayedColumnsContactsListAutocomplete"></mat-header-row> - <mat-row *matRowDef="let element; columns: displayedColumnsContactsListAutocomplete;" (click)="selectAddress(element.addressId);" - [ngStyle]="{'opacity': !isInGrp(element) ? '' : '0.5'}" style="cursor: pointer;"></mat-row> + <mat-header-row + *matHeaderRowDef="displayedColumnsContactsListAutocomplete"> + </mat-header-row> + <mat-row + *matRowDef="let element; columns: displayedColumnsContactsListAutocomplete;" + (click)="selectAddress(element.addressId);" + [ngStyle]="{'opacity': !isInGrp(element) ? '' : '0.5'}" + style="cursor: pointer;"></mat-row> </mat-table> <div class="form-group"> <div style="text-align:center;margin-top:30px"> - <button mat-raised-button color="primary" type="button" (click)="saveContactsList($event.target)" [disabled]="this.selection.selected.length == 0">{{lang.add}}</button> + <button mat-raised-button color="primary" type="button" + (click)="saveContactsList($event.target)" + [disabled]="this.selection.selected.length == 0">{{lang.add}}</button> </div> </div> </div> @@ -585,71 +764,99 @@ </mat-accordion> <div id="contactsGroup" style="margin-top:20px;"> <div class="col-sm-6"> - <form class="form-horizontal" (ngSubmit)="updateGroupSubmit()" #contactsGroupFormUp="ngForm"> + <form class="form-horizontal" (ngSubmit)="updateGroupSubmit()" + #contactsGroupFormUp="ngForm"> <div class="form-group"> <div class="col-sm-12"> <mat-form-field> - <input matInput [(ngModel)]="contactsGroup.label" required name="label" id="label" title="{{lang.label}}" type="text" placeholder="{{lang.label}}" - maxlength="32"> + <input matInput [(ngModel)]="contactsGroup.label" + required name="label" id="label" + title="{{lang.label}}" type="text" + placeholder="{{lang.label}}" maxlength="32"> </mat-form-field> </div> </div> <div class="form-group"> <div class="col-sm-12"> <mat-form-field> - <input matInput [(ngModel)]="contactsGroup.description" required name="description" id="description" title="{{lang.description}}" - type="text" placeholder="{{lang.description}}" maxlength="255"> + <input matInput [(ngModel)]="contactsGroup.description" + required name="description" id="description" + title="{{lang.description}}" type="text" + placeholder="{{lang.description}}" maxlength="255"> </mat-form-field> </div> </div> <div class="form-group"> <div class="col-sm-12"> - <mat-slide-toggle name="public" title="{{lang.public}}" id="public" color="primary" [(ngModel)]="contactsGroup.public" - >{{lang.public}}</mat-slide-toggle> + <mat-slide-toggle name="public" title="{{lang.public}}" + id="public" color="primary" + [(ngModel)]="contactsGroup.public">{{lang.public}} + </mat-slide-toggle> </div> </div> <div class="form-group"> <div class="col-sm-12" style="text-align:center;"> - <button mat-raised-button color="primary" type="submit" [disabled]="!contactsGroupFormUp.form.valid">{{lang.update}}</button> - <button mat-raised-button color="default" type="button" (click)="initGroupsContact()">{{lang.close}}</button> + <button mat-raised-button color="primary" type="submit" + [disabled]="!contactsGroupFormUp.form.valid">{{lang.update}}</button> + <button mat-raised-button color="default" type="button" + (click)="initGroupsContact()">{{lang.close}}</button> </div> </div> </form> </div> <div class="col-sm-6" *ngIf="contactsListMode"> <mat-tab-group [(selectedIndex)]="selectedTabIndex_1"> - <mat-tab label="{{contactsGroup.contacts.length}} {{lang.relatedContacts}}"> + <mat-tab + label="{{contactsGroup.contacts.length}} {{lang.relatedContacts}}"> <div class="row" style="margin:0px;"> <div class="col-md-6 col-xs-6"> <mat-form-field> - <input matInput (keyup)="applyFilterContactsList($event.target.value)" placeholder="{{lang.filterBy}}"> + <input matInput + (keyup)="applyFilterContactsList($event.target.value)" + placeholder="{{lang.filterBy}}"> </mat-form-field> </div> <div class="col-md-6 col-xs-6"> - <mat-paginator #paginatorContactsList [length]="0" [pageSize]="10"> + <mat-paginator #paginatorContactsList [length]="0" + [pageSize]="10"> </mat-paginator> </div> </div> - <mat-table *ngIf="contactsListMode" #tableContactsListSort="matSort" [dataSource]="dataSourceContactsList" matSort matSortActive="contact" - matSortDirection="asc"> + <mat-table *ngIf="contactsListMode" + #tableContactsListSort="matSort" + [dataSource]="dataSourceContactsList" matSort + matSortActive="contact" matSortDirection="asc"> <ng-container matColumnDef="contact"> - <mat-header-cell *matHeaderCellDef mat-sort-header style="flex:3;">{{lang.contact}}</mat-header-cell> - <mat-cell *matCellDef="let element" style="flex:3;"> {{element.contact}} </mat-cell> + <mat-header-cell *matHeaderCellDef mat-sort-header + style="flex:3;">{{lang.contact}}</mat-header-cell> + <mat-cell *matCellDef="let element" style="flex:3;"> + {{element.contact}} </mat-cell> </ng-container> <ng-container matColumnDef="address"> - <mat-header-cell *matHeaderCellDef mat-sort-header style="flex:3;">{{lang.address}}</mat-header-cell> - <mat-cell *matCellDef="let element" style="flex:3;"> {{element.address}} </mat-cell> + <mat-header-cell *matHeaderCellDef mat-sort-header + style="flex:3;">{{lang.address}}</mat-header-cell> + <mat-cell *matCellDef="let element" style="flex:3;"> + {{element.address}} </mat-cell> </ng-container> <ng-container matColumnDef="actions"> - <mat-header-cell *matHeaderCellDef style="flex:1;"></mat-header-cell> - <mat-cell *matCellDef="let element;let i = index" style="justify-content: flex-end;flex:1;"> - <button mat-icon-button color="warn" matTooltip="{{lang.delete}}" (click)="$event.stopPropagation();preDelete(i)"> - <mat-icon class="fa fa-trash-alt fa-2x" aria-hidden="true"></mat-icon> + <mat-header-cell *matHeaderCellDef style="flex:1;"> + </mat-header-cell> + <mat-cell *matCellDef="let element;let i = index" + style="justify-content: flex-end;flex:1;"> + <button mat-icon-button color="warn" + matTooltip="{{lang.delete}}" + (click)="$event.stopPropagation();preDelete(i)"> + <mat-icon class="fa fa-trash-alt fa-2x" + aria-hidden="true"></mat-icon> </button> </mat-cell> </ng-container> - <mat-header-row *matHeaderRowDef="displayedColumnsContactsList"></mat-header-row> - <mat-row *matRowDef="let element; columns: displayedColumnsContactsList;"></mat-row> + <mat-header-row + *matHeaderRowDef="displayedColumnsContactsList"> + </mat-header-row> + <mat-row + *matRowDef="let element; columns: displayedColumnsContactsList;"> + </mat-row> </mat-table> </mat-tab> </mat-tab-group> @@ -666,7 +873,8 @@ <div class="row"> <div class="col-md-6 col-xs-6"> <mat-form-field> - <input matInput (keyup)="applyFilter($event.target.value)" placeholder="{{lang.filterBy}}"> + <input matInput (keyup)="applyFilter($event.target.value)" + placeholder="{{lang.filterBy}}"> </mat-form-field> </div> <div class="col-md-6 col-xs-6"> @@ -674,13 +882,16 @@ </mat-paginator> </div> </div> - <mat-table #tableHistorySort="matSort" [dataSource]="dataSource" matSort matSortActive="event_date" matSortDirection="desc"> + <mat-table #tableHistorySort="matSort" [dataSource]="dataSource" matSort + matSortActive="event_date" matSortDirection="desc"> <ng-container matColumnDef="event_date"> <mat-header-cell *matHeaderCellDef mat-sort-header>{{lang.date}}</mat-header-cell> - <mat-cell *matCellDef="let element">{{element.event_date | date : "dd/MM/y HH:mm"}}</mat-cell> + <mat-cell *matCellDef="let element">{{element.event_date | date : "dd/MM/y HH:mm"}} + </mat-cell> </ng-container> <ng-container matColumnDef="info"> - <mat-header-cell *matHeaderCellDef mat-sort-header>{{lang.description}}</mat-header-cell> + <mat-header-cell *matHeaderCellDef mat-sort-header>{{lang.description}} + </mat-header-cell> <mat-cell *matCellDef="let element"> {{element.info}} </mat-cell> </ng-container> <mat-header-row *matHeaderRowDef="displayedColumns"></mat-header-row> @@ -691,8 +902,9 @@ </mat-tab-group> </mat-card> </mat-sidenav-content> - <mat-sidenav #snav2 [mode]="mobileQuery.matches ? 'over' : 'side'" [fixedInViewport]="mobileQuery.matches" fixedTopGap="56" - position='end' [opened]="mobileQuery.matches ? false : true" style="overflow-x:hidden;max-width:500px;"> + <mat-sidenav #snav2 [mode]="mobileQuery.matches ? 'over' : 'side'" [fixedInViewport]="mobileQuery.matches" + fixedTopGap="56" position='end' [opened]="mobileQuery.matches ? false : true" + style="overflow-x:hidden;max-width:500px;"> <mat-list> <h3 mat-subheader>{{lang.groups}}</h3> @@ -701,8 +913,8 @@ <h4 mat-line>{{userGroup.group_desc}}</h4> <p mat-line> <mat-form-field style="font-size:10px;"> - <input matInput type="text" id="role" name="role" title="{{lang.role}}" placeholder="{{lang.role}}" [(ngModel)]="userGroup.role" - disabled> + <input matInput type="text" id="role" name="role" title="{{lang.role}}" + placeholder="{{lang.role}}" [(ngModel)]="userGroup.role" disabled> <mat-hint matTooltip="{{lang.perimeter}}">{{userGroup.maarch_comment}}</mat-hint> </mat-form-field> </p> @@ -710,25 +922,30 @@ <mat-divider></mat-divider> <h3 mat-subheader>{{lang.entities}}</h3> <mat-list-item *ngFor="let userEntity of user.entities"> - <mat-icon color="primary" *ngIf="userEntity.primary_entity == 'Y'" mat-list-icon class="fa fa-sitemap"></mat-icon> - <mat-icon color="primary" *ngIf="userEntity.primary_entity != 'Y'" mat-list-icon class="fa fa-sitemap" style="position:relative;"> - <button mat-icon-button style="cursor:pointer;position: absolute;right: -20px;top: -20px;font-size:10px;" (click)="updatePrimaryEntity(userEntity)" - matTooltip="{{lang.entityTooglePrimary}}"> + <mat-icon color="primary" *ngIf="userEntity.primary_entity == 'Y'" mat-list-icon + class="fa fa-sitemap"></mat-icon> + <mat-icon color="primary" *ngIf="userEntity.primary_entity != 'Y'" mat-list-icon + class="fa fa-sitemap" style="position:relative;"> + <button mat-icon-button + style="cursor:pointer;position: absolute;right: -20px;top: -20px;font-size:10px;" + (click)="updatePrimaryEntity(userEntity)" matTooltip="{{lang.entityTooglePrimary}}"> <mat-icon class="fa fa-arrow-up"></mat-icon> </button> </mat-icon> - <h4 mat-line [ngStyle]="{'font-weight': userEntity.primary_entity == 'Y' ? 'bold' : 'normal'}" matTooltip="{{userEntity.entity_label}}"> + <h4 mat-line [ngStyle]="{'font-weight': userEntity.primary_entity == 'Y' ? 'bold' : 'normal'}" + matTooltip="{{userEntity.entity_label}}"> {{userEntity.entity_label}} - <span *ngIf="userEntity.primary_entity == 'Y'" class="label label-primary" style="font-weight:normal">{{lang.primary}}</span> + <span *ngIf="userEntity.primary_entity == 'Y'" class="label label-primary" + style="font-weight:normal">{{lang.primary}}</span> </h4> <p mat-line> <mat-form-field style="font-size:10px;"> - <input matInput type="text" id="role" name="role" title="{{lang.role}}" placeholder="{{lang.role}}" [(ngModel)]="userEntity.user_role" - disabled> + <input matInput type="text" id="role" name="role" title="{{lang.role}}" + placeholder="{{lang.role}}" [(ngModel)]="userEntity.user_role" disabled> </mat-form-field> </p> </mat-list-item> </mat-list> </mat-sidenav> </mat-sidenav-container> - </div> \ No newline at end of file +</div> \ No newline at end of file diff --git a/src/frontend/app/profile.component.ts b/src/frontend/app/profile.component.ts index 28e44ed0c6ae3366dcd40298408e43ab61052125..e764893f4e719d3778c738376a7645d5ac14792a 100755 --- a/src/frontend/app/profile.component.ts +++ b/src/frontend/app/profile.component.ts @@ -76,6 +76,7 @@ export class ProfileComponent extends AutoCompletePlugin implements OnInit { loading: boolean = false; selectedIndex: number = 0; selectedIndexContactsGrp: number = 0; + loadingSign : boolean = false; @ViewChild('snav2') sidenavRight: MatSidenav; @ViewChild('snav') sidenavLeft: MatSidenav; @@ -407,8 +408,7 @@ export class ProfileComponent extends AutoCompletePlugin implements OnInit { this.http.get('../../rest/currentUser/profile') .subscribe((data: any) => { this.user = data; - - + this.user.baskets.forEach((value: any, index: number) => { this.user.baskets[index]['disabled'] = false; this.user.redirectedBaskets.forEach((value2: any) => { @@ -921,4 +921,17 @@ export class ProfileComponent extends AutoCompletePlugin implements OnInit { this.initGroupsContact(); } } + + syncMP() { + this.loadingSign = true; + + this.http.put('../../rest/users/' + this.user.id + '/externalSignatures', {}) + .subscribe((data: any) => { + this.loadingSign = false; + this.notify.success(this.lang.signsSynchronized); + }, (err) => { + this.loadingSign = false; + this.notify.error(err.error.errors); + }); + } } diff --git a/src/frontend/lang/lang-en.ts b/src/frontend/lang/lang-en.ts index e42727b553a93a5a19ec6d22861d0757947a85a5..cdfee2e80fda49dfb17f9587738301825923d497 100755 --- a/src/frontend/lang/lang-en.ts +++ b/src/frontend/lang/lang-en.ts @@ -955,4 +955,6 @@ export const LANG_EN = { "docserverDoesNotExists" : "Docserver does not exists", "fileDoesNotExists" : "File does not exists", "noTemplate" : "No template", + "syncSignsToMaarchParapheur" : "Synchronize signatures to Maarch Parapheur", + "signsSynchronized" : "Signatures have been updated in Maarch Parapheur", }; diff --git a/src/frontend/lang/lang-fr.ts b/src/frontend/lang/lang-fr.ts index 4b1fd4e1d1d0e6070f73717afa726f4c6bdb7edb..cdfcbf0a1e00fe8f24b420d2abd5dace92a87b98 100755 --- a/src/frontend/lang/lang-fr.ts +++ b/src/frontend/lang/lang-fr.ts @@ -982,5 +982,7 @@ export const LANG_FR = { "docserverDoesNotExists" : "La zone de stockage n'existe pas", "fileDoesNotExists" : "Le fichier n'existe pas", "noTemplate" : "Aucun modèle", + "syncSignsToMaarchParapheur" : "Synchroniser les signatures vers Maarch Parapheur", + "signsSynchronized" : "Les signatures ont été mise à jour dans Maarch Parapheur", }; diff --git a/src/frontend/lang/lang-nl.ts b/src/frontend/lang/lang-nl.ts index c0af294584f411db5879b93cfe114b8caac542a2..5ca4362100a1d52ed61e67aaf559aa71c8d469b6 100755 --- a/src/frontend/lang/lang-nl.ts +++ b/src/frontend/lang/lang-nl.ts @@ -982,4 +982,6 @@ export const LANG_NL = { "docserverDoesNotExists" : "Docserver does not exists", //_TO_TRANSLATE "fileDoesNotExists" : "File does not exists", //_TO_TRANSLATE "noTemplate" : "No template", //_TO_TRANSLATE + "syncSignsToMaarchParapheur" : "Synchronize signatures to Maarch Parapheur", //_TO_TRANSLATE + "signsSynchronized" : "Signatures have been updated in Maarch Parapheur", //_TO_TRANSLATE };