diff --git a/ui/ui-frontend/projects/identity/src/app/user/group-attribution/group-attribution.component.html b/ui/ui-frontend/projects/identity/src/app/user/group-attribution/group-attribution.component.html index cc323e632d77a25481bfd69e8eb2c9591eefbee6..93c7f49cf1c85f196fc6a439c339d9fc26373779 100644 --- a/ui/ui-frontend/projects/identity/src/app/user/group-attribution/group-attribution.component.html +++ b/ui/ui-frontend/projects/identity/src/app/user/group-attribution/group-attribution.component.html @@ -3,36 +3,9 @@ </div> <div class="mt-3 content"> - - <div classe="mt-4 text large bold" i18n="Set group title@@setGroupTitle">Attribution de groupe</div> - - <vitamui-common-search-bar class="my-3" i18n-placeholder="user create search group@@userCreateSearchGroup" - [placeholder]="'Filtrer par «nom», «id» ...'" (search)="onSearch($event)"></vitamui-common-search-bar> - -<div class="d-flex mt-4 mb-3" *ngIf="selectedGroupName"> - <div class="text medium bold">Groupe attribué : </div> <span class="text medium">{{ selectedGroupName }}</span> -</div> - -<div class="vitamui-table"> - <div class="vitamui-table-head p-0 py-3 d-flex align-items-center"> - <div class="pl-4" i18n="Set group header@@setGroupHeader">Groupe</div> + <div> + <app-group-list [groups] = "activeGroups" (selectedGroupEvent)="updateGroup($event)"></app-group-list> </div> - - <div class="vitamui-table-body"> - <div class="vitamui-table-rows"> - <ng-container *ngFor="let group of activeGroups; let index = index"> - <div class="vitamui-row p-0 px-4" [class.no-hover]="row.state === 'expanded'" *ngIf="!group?.selected" [vitamuiCommonCollapse] #row="vitamuiCommonCollapse"> - <div class="d-flex justify-content-between align-items-center clickable"> - <div class="row-label d-flex align-items-center" (click)="updateGroup(group?.id,group?.name)">{{group?.name}}</div> - <button class="btn link underline" (click)="row.toggle()">{{row.state === 'collapsed' ? "Voir detail" : "Masquer detail"}}</button> - </div> - <app-group-detail *ngIf="row.state === 'expanded'" [group]="group" [@expansionAnimation]></app-group-detail> - </div> - </ng-container> - </div> - </div> -</div> - <div class="actions"> <button type="button" class="btn primary" (click)="saveUserUpdate()" [disabled]="!selectedGroupName" i18n="group attribution edit@@groupAttributionEdit">Modifier</button> <button type="button" class="btn cancel link" (click)="onCancel()" i18n="Cancel customer creation@@customerCreateCancelButton">Annuler</button> diff --git a/ui/ui-frontend/projects/identity/src/app/user/group-attribution/group-attribution.component.ts b/ui/ui-frontend/projects/identity/src/app/user/group-attribution/group-attribution.component.ts index 02569731f425669fbf5155e8dd1acf47dc7f5dbf..1da048a8a7126bee6a0f530153b281ae7c4c78a0 100644 --- a/ui/ui-frontend/projects/identity/src/app/user/group-attribution/group-attribution.component.ts +++ b/ui/ui-frontend/projects/identity/src/app/user/group-attribution/group-attribution.component.ts @@ -38,7 +38,6 @@ import { Group, User } from 'ui-frontend-common'; -import { animate, state, style, transition, trigger } from '@angular/animations'; import { Component, forwardRef, Inject, OnInit } from '@angular/core'; import { NG_VALUE_ACCESSOR } from '@angular/forms'; import { MAT_DIALOG_DATA, MatDialogRef } from '@angular/material/dialog'; @@ -56,19 +55,6 @@ export const GROUP_ATTRIBUTION_VALUE_ACCESSOR: any = { templateUrl: './group-attribution.component.html', styleUrls: ['./group-attribution.component.scss'], providers: [GROUP_ATTRIBUTION_VALUE_ACCESSOR], - animations: [ - trigger('expansion', [ - state('collapsed', style({ height: '0px', visibility: 'hidden' })), - state('expanded', style({ height: '*', visibility: 'visible' })), - transition('expanded <=> collapsed', animate('225ms cubic-bezier(0.4,0.0,0.2,1)')), - ]), - trigger('expansionAnimation', [ - state('true', style({ height: '*', visibility: 'visible' })), - state('void', style({ height: '0px', visibility: 'hidden' })), - transition(':enter', animate('150ms')), - transition(':leave', animate('150ms')), - ]), - ] }) export class GroupAttributionComponent implements OnInit { @@ -109,24 +95,11 @@ export class GroupAttributionComponent implements OnInit { } } - public removeGroup(): void { - this.selectedGroupName = null; - this.user.groupId = null; - this.unselectAllProfileGroups(); - } - - public updateGroup(groupId: string, groupName: string): void { - this.selectedGroupName = groupName; - this.user.groupId = groupId; - this.unselectAllProfileGroups(); - const selectedGroup = this.activeGroups.find((group) => group.id === groupId); - if (selectedGroup) { - selectedGroup.selected = true; - } - } - - public unselectAllProfileGroups(): void { - this.activeGroups.forEach((group) => group.selected = false); + updateGroup(event: any) { + const selectedGroup: GroupSelection = event; + this.selectedGroupName = selectedGroup.name; + this.user.groupId = selectedGroup.id; + this.user.level = selectedGroup.level; } public saveUserUpdate(): void { @@ -139,14 +112,7 @@ export class GroupAttributionComponent implements OnInit { } public onCancel(): void { - this.unselectAllProfileGroups(); this.dialogRef.close(); } - public onSearch(text?: string): void { - this.resetActiveGroups(); - if (text !== null && text.length > 0) { - this.activeGroups = this.activeGroups.filter((group) => group.name.includes(text) || group.description.includes(text)); - } - } } diff --git a/ui/ui-frontend/projects/identity/src/app/user/group-attribution/group-attribution.module.ts b/ui/ui-frontend/projects/identity/src/app/user/group-attribution/group-attribution.module.ts index d1e32535f5bd0615242e5cfea383d78a72eb3b08..9e68c9e969595383e0072622f716d8fe4e71e307 100644 --- a/ui/ui-frontend/projects/identity/src/app/user/group-attribution/group-attribution.module.ts +++ b/ui/ui-frontend/projects/identity/src/app/user/group-attribution/group-attribution.module.ts @@ -43,6 +43,7 @@ import {CollapseDirectiveModule, SearchBarModule} from 'ui-frontend-common'; import { SharedModule } from '../../shared/shared.module'; import { GroupAttributionComponent } from './group-attribution.component'; import { GroupDetailComponent } from './group-detail/group-detail.component'; +import {GroupListComponent} from "./group-list/group-list.component"; @NgModule({ imports: [ @@ -56,10 +57,12 @@ import { GroupDetailComponent } from './group-detail/group-detail.component'; declarations: [ GroupAttributionComponent, GroupDetailComponent, + GroupListComponent, ], exports: [ GroupAttributionComponent, GroupDetailComponent, + GroupListComponent, ] }) export class GroupAttributionModule { } diff --git a/ui/ui-frontend/projects/identity/src/app/user/group-attribution/group-list/group-list.component.html b/ui/ui-frontend/projects/identity/src/app/user/group-attribution/group-list/group-list.component.html new file mode 100644 index 0000000000000000000000000000000000000000..5f35d9fa68c76b990f9c917c6357da5a54ee1d0c --- /dev/null +++ b/ui/ui-frontend/projects/identity/src/app/user/group-attribution/group-list/group-list.component.html @@ -0,0 +1,28 @@ +<div class="text large bold" i18n="user create autorisationsTitle@@userCreateTitle">Autorisations</div> + +<vitamui-common-search-bar class="my-3" i18n-placeholder="user create search group@@userCreateSearchGroup" +[placeholder]="'Filtrer par «nom», «id» ...'" (search)="onSearch($event)" [disabled]= "searchActiv"></vitamui-common-search-bar> + +<div class="d-flex mt-4 mb-3" *ngIf="groupName"> + <div class="text medium bold">Groupe attribué : </div> <span class="text medium">{{ groupName }}</span> +</div> + +<div class="vitamui-table"> + <div class="vitamui-table-head p-0 py-3 d-flex align-items-center"> + <div class="pl-4">Groupe de profil</div> + </div> + + <div class="vitamui-table-body"> + <div class="vitamui-table-rows"> + <ng-container *ngFor="let group of groups"> + <div class="vitamui-row p-0 px-4" [class.no-hover]="row.state === 'expanded'" *ngIf="!group?.selected" [vitamuiCommonCollapse] #row="vitamuiCommonCollapse"> + <div class="d-flex justify-content-between align-items-center clickable"> + <div class="row-label d-flex align-items-center" (click)="updateGroup(group?.id,group?.name, row)">{{group?.name}}</div> + <button class="btn link underline" (click)="row.toggle()">{{row.state === 'collapsed' ? "Voir detail" : "Masquer detail"}}</button> + </div> + <app-group-detail *ngIf="row.state === 'expanded'" [group]="group" [@expansionAnimation]></app-group-detail> + </div> + </ng-container> + </div> + </div> +</div> diff --git a/ui/ui-frontend/projects/identity/src/app/user/group-attribution/group-list/group-list.component.scss b/ui/ui-frontend/projects/identity/src/app/user/group-attribution/group-list/group-list.component.scss new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/ui/ui-frontend/projects/identity/src/app/user/group-attribution/group-list/group-list.component.spec.ts b/ui/ui-frontend/projects/identity/src/app/user/group-attribution/group-list/group-list.component.spec.ts new file mode 100644 index 0000000000000000000000000000000000000000..2dbadb79adda46e9a25ab19416723d5a78c3a028 --- /dev/null +++ b/ui/ui-frontend/projects/identity/src/app/user/group-attribution/group-list/group-list.component.spec.ts @@ -0,0 +1,28 @@ +/* tslint:disable:no-unused-variable */ +import { async, ComponentFixture, TestBed } from '@angular/core/testing'; +import { By } from '@angular/platform-browser'; +import { DebugElement } from '@angular/core'; + +import { GroupListComponent } from './group-list.component'; + +describe('GroupListComponent', () => { + let component: GroupListComponent; + let fixture: ComponentFixture<GroupListComponent>; + + beforeEach(async(() => { + TestBed.configureTestingModule({ + declarations: [ GroupListComponent ] + }) + .compileComponents(); + })); + + beforeEach(() => { + fixture = TestBed.createComponent(GroupListComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/ui/ui-frontend/projects/identity/src/app/user/group-attribution/group-list/group-list.component.ts b/ui/ui-frontend/projects/identity/src/app/user/group-attribution/group-list/group-list.component.ts new file mode 100644 index 0000000000000000000000000000000000000000..51abe7b9afa326721be04b589a254146e58b7176 --- /dev/null +++ b/ui/ui-frontend/projects/identity/src/app/user/group-attribution/group-list/group-list.component.ts @@ -0,0 +1,119 @@ +/* + * Copyright French Prime minister Office/SGMAP/DINSIC/Vitam Program (2019-2020) + * and the signatories of the "VITAM - Accord du Contributeur" agreement. + * + * contact@programmevitam.fr + * + * This software is a computer program whose purpose is to implement + * implement a digital archiving front-office system for the secure and + * efficient high volumetry VITAM solution. + * + * This software is governed by the CeCILL-C license under French law and + * abiding by the rules of distribution of free software. You can use, + * modify and/ or redistribute the software under the terms of the CeCILL-C + * license as circulated by CEA, CNRS and INRIA at the following URL + * "http://www.cecill.info". + * + * As a counterpart to the access to the source code and rights to copy, + * modify and redistribute granted by the license, users are provided only + * with a limited warranty and the software's author, the holder of the + * economic rights, and the successive licensors have only limited + * liability. + * + * In this respect, the user's attention is drawn to the risks associated + * with loading, using, modifying and/or developing or reproducing the + * software by the user in light of its specific status of free software, + * that may mean that it is complicated to manipulate, and that also + * therefore means that it is reserved for developers and experienced + * professionals having in-depth computer knowledge. Users are therefore + * encouraged to load and test the software's suitability as regards their + * requirements in conditions enabling the security of their systems and/or + * data to be ensured and, more generally, to use and operate it in the + * same conditions as regards security. + * + * The fact that you are presently reading this means that you have had + * knowledge of the CeCILL-C license and that you accept its terms. + */ +/* tslint:disable: no-use-before-declare */ + +import { MAT_DIALOG_DATA } from '@angular/material/dialog'; +import { GroupSelection } from './../../group-selection.interface'; +import { Component, Input, OnInit, Inject, Output, EventEmitter } from '@angular/core'; +import { animate, state, style, transition, trigger } from '@angular/animations'; + +@Component({ + selector: 'app-group-list', + templateUrl: './group-list.component.html', + styleUrls: ['./group-list.component.scss'], + animations: [ + trigger('expansion', [ + state('collapsed', style({ height: '0px', visibility: 'hidden' })), + state('expanded', style({ height: '*', visibility: 'visible' })), + transition('expanded <=> collapsed', animate('225ms cubic-bezier(0.4,0.0,0.2,1)')), + ]), + trigger('expansionAnimation', [ + state('true', style({ height: '*', visibility: 'visible' })), + state('void', style({ height: '0px', visibility: 'hidden' })), + transition(':enter', animate('150ms')), + transition(':leave', animate('150ms')), + ]), + ] +}) +export class GroupListComponent implements OnInit { + + + public groupName: string; + + @Input() + public groups: GroupSelection[]; + + @Input() + public searchActiv = false; + + @Output() + public selectedGroupEvent = new EventEmitter<GroupSelection>(); + + CUSTOMER_ACTIVE_PROFILE_GROUPS_INDEX = 2; + + + constructor( @Inject(MAT_DIALOG_DATA) public data: any) { } + + ngOnInit() { + } + + + updateGroup(groupId: string, groupName: string) { + this.groupName = groupName; + this.unselectAllGroups(); + const selectedGroup = this.groups.find((group) => group.id === groupId); + selectedGroup.selected = true; + this.selectedGroupEvent.emit(selectedGroup); + } + + + unselectAllGroups() { + this.groups.forEach((group) => group.selected = false); + } + + public findGroup(id: string): GroupSelection { + return this.groups.find(value => value.id === id); + } + public onSearch(text?: string): void { + this.resetgroups(); + if (text !== null && text.length > 0) { + this.groups = this.groups.filter((group) => group.name.includes(text) || group.description.includes(text)); + } + } + + + public resetgroups(): void { + this.groups = this.data[this.CUSTOMER_ACTIVE_PROFILE_GROUPS_INDEX]; + this.groups.sort((a, b) => a.name.toUpperCase() < b.name.toUpperCase() ? -1 : 1); + if (this.data[1]) { + const selectedGroup = this.groups.find((group) => group.id === this.data[1].id); + if (selectedGroup) { + selectedGroup.selected = true; + } + } + } +} diff --git a/ui/ui-frontend/projects/identity/src/app/user/user-create/user-create.component.html b/ui/ui-frontend/projects/identity/src/app/user/user-create/user-create.component.html index 2cd300f4c9bb2995da3b3972c8ca4ecdcae4dee4..6a6b56a732dfa92f11eb2e5892179386b0c3990d 100644 --- a/ui/ui-frontend/projects/identity/src/app/user/user-create/user-create.component.html +++ b/ui/ui-frontend/projects/identity/src/app/user/user-create/user-create.component.html @@ -45,7 +45,7 @@ </vitamui-common-input-error> </ng-container> </vitamui-common-input> - + <h4 class="mx-2 mt-1">@</h4> <mat-form-field class="vitamui-mat-select"> @@ -104,36 +104,10 @@ </cdk-step> <cdk-step> - <div class="content"> - <div class="text large bold" i18n="user create autorisationsTitle@@userCreateTitle">Autorisations</div> - - <vitamui-common-search-bar class="my-3" i18n-placeholder="user create search group@@userCreateSearchGroup" - [placeholder]="'Filtrer par «nom», «id» ...'" disabled></vitamui-common-search-bar> - - <div class="d-flex mt-4 mb-3" *ngIf="groupName"> - <div class="text medium bold">Groupe attribué : </div> <span class="text medium">{{ groupName }}</span> - </div> - - <div class="vitamui-table"> - <div class="vitamui-table-head p-0 py-3 d-flex align-items-center"> - <div class="pl-4">Groupe de profil</div> - </div> - - <div class="vitamui-table-body"> - <div class="vitamui-table-rows"> - <ng-container *ngFor="let group of groups"> - <div class="vitamui-row p-0 px-4" [class.no-hover]="row.state === 'expanded'" *ngIf="!group?.selected" [vitamuiCommonCollapse] #row="vitamuiCommonCollapse"> - <div class="d-flex justify-content-between align-items-center clickable"> - <div class="row-label d-flex align-items-center" (click)="updateGroupe(group?.id,group?.name, row)">{{group?.name}}</div> - <button class="btn link underline" (click)="row.toggle()">{{row.state === 'collapsed' ? "Voir detail" : "Masquer detail"}}</button> - </div> - <app-group-detail *ngIf="row.state === 'expanded'" [group]="findGroup(group.id)" [@expansionAnimation]></app-group-detail> - </div> - </ng-container> - </div> - </div> + <div class="mt-3 content"> + <div> + <app-group-list [groups] = "groups" (selectedGroupEvent)="updateGroup($event)" [searchActiv] = "true"></app-group-list> </div> - <div class="actions"> <button type="button" class="btn primary" cdkStepperNext [disabled]="!groupName" i18n="user create next step otp@@userCreateNextStepAddressButton"> @@ -146,7 +120,7 @@ <i class="vitamui-icon vitamui-icon-chevron-left"></i> <ng-container i18n="Previous step button label@@customerCreateBackButton"><span class="underline">Retour</span></ng-container> </button> - </div> + </div> </cdk-step> <cdk-step> @@ -226,7 +200,7 @@ <cdk-step> <div class="content"> <div class="text large bold" i18n="user create autorisationsTitle@@userCreateTitle">Sécurité</div> - + <vitamui-common-slide-toggle formControlName="otp" i18n="user create otp@@userCreateOtp">Validation en deux étapes</vitamui-common-slide-toggle> diff --git a/ui/ui-frontend/projects/identity/src/app/user/user-create/user-create.component.ts b/ui/ui-frontend/projects/identity/src/app/user/user-create/user-create.component.ts index f24bc4dc7ec0368b1cc1684d7fbf0520e725ef11..9d5bbbdb25e155cb7aff0f0dfacc44746a5dc981 100644 --- a/ui/ui-frontend/projects/identity/src/app/user/user-create/user-create.component.ts +++ b/ui/ui-frontend/projects/identity/src/app/user/user-create/user-create.component.ts @@ -27,6 +27,7 @@ * therefore means that it is reserved for developers and experienced * professionals having in-depth computer knowledge. Users are therefore * encouraged to load and test the software's suitability as regards their + * encouraged to load and test the software's suitability as regards their * requirements in conditions enabling the security of their systems and/or * data to be ensured and, more generally, to use and operate it in the * same conditions as regards security. @@ -36,10 +37,9 @@ */ import { Subscription } from 'rxjs'; import { - AdminUserProfile, AuthService, ConfirmDialogService, Customer, Group, isRootLevel, OtpState, ProfileSelection + AdminUserProfile, AuthService, ConfirmDialogService, Customer, Group, isRootLevel, OtpState } from 'ui-frontend-common'; - -import { animate, state, style, transition, trigger } from '@angular/animations'; +import { GroupSelection } from './../group-selection.interface'; import { Component, Inject, OnDestroy, OnInit } from '@angular/core'; import { FormBuilder, FormGroup, Validators } from '@angular/forms'; import { MAT_DIALOG_DATA, MatDialogRef } from '@angular/material/dialog'; @@ -57,37 +57,14 @@ const emailValidator: RegExp = /^[a-zA-Z0-9.!#$%&'*+\/=?^_`{|}~-]+@[a-zA-Z0-9](? @Component({ selector: 'app-user-create', templateUrl: './user-create.component.html', - styleUrls: ['./user-create.component.scss'], - animations: [ - trigger('expansion', [ - state('collapsed', style({ height: '0px', visibility: 'hidden' })), - state('expanded', style({ height: '*', visibility: 'visible' })), - transition('expanded <=> collapsed', animate('225ms cubic-bezier(0.4,0.0,0.2,1)')), - ]), - trigger('expansion2', [ - transition(':enter', [ - style({ height: 0, opacity: 0 }), - animate('1s ease-out', style({ height: 300, opacity: 1 })) - ]), - transition(':leave', [ - style({ height: 300, opacity: 1 }), - animate('1s ease-in', style({ height: 0, opacity: 0 })) - ]) - ]), - trigger('expansionAnimation', [ - state('true', style({ height: '*', visibility: 'visible' })), - state('void', style({ height: '0px', visibility: 'hidden' })), - transition(':enter', animate('150ms')), - transition(':leave', animate('150ms')), - ]), - ] + styleUrls: ['./user-create.component.scss'] }) export class UserCreateComponent implements OnInit, OnDestroy { public form: FormGroup; public formEmail: FormGroup; public customer: Customer; - public groups: ProfileSelection[] = []; + public groups: GroupSelection[] = []; public fullGroup: Group[]; public groupName: string; public stepIndex = 0; @@ -192,9 +169,10 @@ export class UserCreateComponent implements OnInit, OnDestroy { this.form.updateValueAndValidity({ emitEvent: false }); } else if (this.connectedUserInfo.type === 'LIST') { this.groups = this.connectedUserInfo.profilGroup - .map((group) => ({ id: group.id, name: group.name, description: group.description, selected: false })); + .map((group) => Object({ id: group.id, name: group.name, description: group.description, selected: false })); this.groups.sort((a, b) => a.name < b.name ? -1 : a.name > b.name ? 1 : 0); } + } onCancel() { @@ -247,25 +225,11 @@ export class UserCreateComponent implements OnInit, OnDestroy { return this.form.pending || this.form.invalid; } - updateGroupe(groupId: string, groupName: string) { - this.groupName = groupName; - this.unselectAllGroups(); - const selectedGroup = this.groups.find((group) => group.id === groupId); - selectedGroup.selected = true; + updateGroup(event: any) { + const selectedGroup: GroupSelection = event; + this.groupName = selectedGroup.name; + const groupId = selectedGroup.id; this.form.patchValue({ groupId }); } - removeGroup() { - this.groupName = null; - this.unselectAllGroups(); - this.form.patchValue({ groupId: null }); - } - - unselectAllGroups() { - this.groups.forEach((group) => group.selected = false); - } - - public findGroup(id: string): Group { - return this.fullGroup.find(value => value.id === id); - } }