From 1cb10609e5b41bfcc17f015453b608fd82dbbe3a Mon Sep 17 00:00:00 2001 From: Alex ORLUC <alex.orluc@maarch.org> Date: Tue, 27 Aug 2019 20:18:27 +0200 Subject: [PATCH] FEAT #11291 TIME 5:30 front update folder + fix dnd res in folder --- src/frontend/app/app.module.ts | 7 +- .../folder-document-list.component.html | 2 +- .../folder-document-list.component.ts | 6 + .../app/folder/folder-tree.component.html | 2 + .../app/folder/folder-tree.component.ts | 22 ++- .../folder-update.component.html | 46 ++++++ .../folder-update.component.scss | 44 ++++++ .../folder-update/folder-update.component.ts | 139 ++++++++++++++++++ .../folder/panel/panel-folder.component.html | 2 +- .../folder/panel/panel-folder.component.ts | 8 +- .../app/list/basket-list.component.html | 6 +- .../app/list/basket-list.component.ts | 19 ++- src/frontend/tsconfig.app.json | 5 +- 13 files changed, 291 insertions(+), 17 deletions(-) create mode 100644 src/frontend/app/folder/folder-update/folder-update.component.html create mode 100644 src/frontend/app/folder/folder-update/folder-update.component.scss create mode 100644 src/frontend/app/folder/folder-update/folder-update.component.ts diff --git a/src/frontend/app/app.module.ts b/src/frontend/app/app.module.ts index d27b20a55d1..816313c48b4 100755 --- a/src/frontend/app/app.module.ts +++ b/src/frontend/app/app.module.ts @@ -27,6 +27,7 @@ import { FolderTreeComponent } from './folder/folder-tree.compon import { FolderDocumentListComponent } from './folder/document-list/folder-document-list.component'; import { PanelFolderComponent } from './folder/panel/panel-folder.component'; import { FolderMenuComponent } from './folder/folder-menu/folder-menu.component'; +import { FolderUpdateComponent } from './folder/folder-update/folder-update.component'; /*ACTIONS PAGES */ import { ConfirmActionComponent } from './actions/confirm-action/confirm-action.component'; @@ -119,7 +120,8 @@ import { PrintSeparatorComponent } from './separator/prin FolderTreeComponent, PanelFolderComponent, FolderDocumentListComponent, - FolderMenuComponent + FolderMenuComponent, + FolderUpdateComponent ], entryComponents: [ CustomSnackbarComponent, @@ -142,7 +144,8 @@ import { PrintSeparatorComponent } from './separator/prin ProcessActionComponent, RedirectActionComponent, SendShippingActionComponent, - ViewDocActionComponent + ViewDocActionComponent, + FolderUpdateComponent ], providers: [ HeaderService, FiltersListService ], bootstrap: [ AppComponent ] diff --git a/src/frontend/app/folder/document-list/folder-document-list.component.html b/src/frontend/app/folder/document-list/folder-document-list.component.html index ae6820341a2..aec26af4ce1 100644 --- a/src/frontend/app/folder/document-list/folder-document-list.component.html +++ b/src/frontend/app/folder/document-list/folder-document-list.component.html @@ -55,7 +55,7 @@ </div> </div> <div style="height:90%;overflow:auto;position:absolute;width:100%;"> - <table #tableBasketListSort="matSort" cdkDropList id="folder-list" [cdkDropListConnectedTo]="listTodrag()" [cdkDropListData]="data" mat-table [dataSource]="data" matSort + <table #tableBasketListSort="matSort" cdkDropList id="folder-list" [cdkDropListConnectedTo]="listTodrag()" [cdkDropListData]="data" [cdkDropListDisabled]="dragInit" mat-table [dataSource]="data" matSort matSortActive="res_id" matSortDisableClear matSortDirection="asc" style="width:100%;"> <ng-container matColumnDef="res_id"> diff --git a/src/frontend/app/folder/document-list/folder-document-list.component.ts b/src/frontend/app/folder/document-list/folder-document-list.component.ts index a696fd6d969..c3b3134eacb 100644 --- a/src/frontend/app/folder/document-list/folder-document-list.component.ts +++ b/src/frontend/app/folder/document-list/folder-document-list.component.ts @@ -46,6 +46,8 @@ export class FolderDocumentListComponent implements OnInit { filtersChange = new EventEmitter(); + dragInit: boolean = true; + dialogRef: MatDialogRef<any>; @ViewChild('snav', { static: true }) sidenavLeft: MatSidenav; @@ -119,6 +121,7 @@ export class FolderDocumentListComponent implements OnInit { this.isLoadingResults = false; this.route.params.subscribe(params => { + this.dragInit = true; this.destroy$.next(true); this.http.get('../../rest/folders/' + params['folderId']) @@ -137,6 +140,9 @@ export class FolderDocumentListComponent implements OnInit { window['MainHeaderComponent'].setSnav(this.sidenavLeft); window['MainHeaderComponent'].setSnavRight(null); + setTimeout(() => { + this.dragInit = false; + }, 1000); this.initResultList(); }, diff --git a/src/frontend/app/folder/folder-tree.component.html b/src/frontend/app/folder/folder-tree.component.html index 63fe816acb8..127a26955dc 100644 --- a/src/frontend/app/folder/folder-tree.component.html +++ b/src/frontend/app/folder/folder-tree.component.html @@ -23,6 +23,7 @@ <mat-menu #menu="matMenu"> <button mat-menu-item [disabled]="createItemNode" (click)="addNewItem(node)">Nouveau sous-dossier</button> <button mat-menu-item (click)="deleteNode(node)">Supprimer</button> + <button mat-menu-item (click)="openFolderAdmin(node)">Modifier</button> </mat-menu> </a> </mat-tree-node> @@ -61,6 +62,7 @@ <mat-menu #menu="matMenu"> <button mat-menu-item [disabled]="createItemNode" (click)="addNewItem(node)">Nouveau sous-dossier</button> <button mat-menu-item (click)="deleteNode(node)">Supprimer</button> + <button mat-menu-item (click)="openFolderAdmin(node)">Modifier</button> </mat-menu> </a> </mat-tree-node> diff --git a/src/frontend/app/folder/folder-tree.component.ts b/src/frontend/app/folder/folder-tree.component.ts index a6fe1f1493e..84fe1459d91 100644 --- a/src/frontend/app/folder/folder-tree.component.ts +++ b/src/frontend/app/folder/folder-tree.component.ts @@ -1,4 +1,4 @@ -import { Component, OnInit, ViewChild, Input, Renderer2 } from '@angular/core'; +import { Component, OnInit, ViewChild, Input, Renderer2, Output, EventEmitter } from '@angular/core'; import { HttpClient } from '@angular/common/http'; import { LANG } from '../translate.component'; import { map, tap, catchError, filter, exhaustMap, finalize } from 'rxjs/operators'; @@ -11,6 +11,7 @@ import { BehaviorSubject, of } from 'rxjs'; import { NotificationService } from '../notification.service'; import { ConfirmComponent } from '../../plugins/modal/confirm.component'; import { Router } from '@angular/router'; +import { FolderUpdateComponent } from './folder-update/folder-update.component'; declare function $j(selector: any): any; /** @@ -104,6 +105,8 @@ export class FolderTreeComponent implements OnInit { dataSource = new MatTreeFlatDataSource(this.treeControl, this.treeFlattener); @ViewChild('tree', { static: true }) tree: any; + + @Output('refreshDocList') refreshDocList = new EventEmitter<string>(); constructor( public http: HttpClient, @@ -365,7 +368,10 @@ export class FolderTreeComponent implements OnInit { tap((data: any) => { node.countResources = data.countResources; }), - tap(() => this.notify.success('Courrier classé')), + tap(() => { + this.notify.success('Courrier classé'); + this.refreshDocList.emit(); + }), finalize(() => node.drag = false), catchError((err) => { this.notify.handleErrors(err); @@ -374,8 +380,6 @@ export class FolderTreeComponent implements OnInit { ).subscribe(); } - - dragEnter(node: any) { node.drag = true; } @@ -386,7 +390,6 @@ export class FolderTreeComponent implements OnInit { } else { return []; } - } toggleInput() { @@ -397,4 +400,13 @@ export class FolderTreeComponent implements OnInit { }, 0); } } + + openFolderAdmin(node: any) { + console.log(node); + this.dialogRef = this.dialog.open(FolderUpdateComponent, { autoFocus: false, data: { folderId: node.id } }); + + this.dialogRef.afterClosed().pipe( + + ).subscribe(); + } } diff --git a/src/frontend/app/folder/folder-update/folder-update.component.html b/src/frontend/app/folder/folder-update/folder-update.component.html new file mode 100644 index 00000000000..3b1d18d4ba3 --- /dev/null +++ b/src/frontend/app/folder/folder-update/folder-update.component.html @@ -0,0 +1,46 @@ +<h1 mat-dialog-title>Dossier : {{folder.label}}</h1> +<form (ngSubmit)="onSubmit()"> + <mat-dialog-content> + <div class="col-md-12"> + <mat-form-field class="example-full-width"> + <input matInput placeholder="{{lang.label}}" name="label" [(ngModel)]="folder.label"> + </mat-form-field> + </div> + <div [class.col-md-12]="folder.sharing.entities.length === 0" + [class.col-md-6]="folder.sharing.entities.length > 0"> + <div class="formType jstreeEntities"> + <div class="formType-title"> + Périmètre de restriction + </div> + <mat-form-field appearance="outline"> + <input matInput id="jstree_search" type="text" placeholder="{{lang.searchEntities}}"> + </mat-form-field> + <div id="jstree" class="entitiesList"></div> + </div> + </div> + <div class="col-md-6" *ngIf="folder.sharing.entities.length > 0"> + <div class="formType jstreeEntities"> + <div class="formType-title"> + Paramètres + </div> + <ng-container *ngFor="let entity of entities | sortBy : 'entity_label'"> + <mat-expansion-panel class="selectedEntities" + *ngIf="checkSelectedFolder(entity)" opened> + <mat-expansion-panel-header> + <mat-panel-title> + {{entity.entity_label}} + </mat-panel-title> + </mat-expansion-panel-header> + <mat-slide-toggle color="primary">Droit de modification / suppression du dossier + </mat-slide-toggle> + </mat-expansion-panel> + </ng-container> + </div> + </div> + </mat-dialog-content> + <mat-dialog-actions> + <button mat-raised-button color="primary" type="submit" + (click)="dialogRef.close(this.data)">{{lang.validate}}</button> + <button mat-raised-button type="button" color="default" (click)="dialogRef.close()">{{lang.cancel}}</button> + </mat-dialog-actions> +</form> \ No newline at end of file diff --git a/src/frontend/app/folder/folder-update/folder-update.component.scss b/src/frontend/app/folder/folder-update/folder-update.component.scss new file mode 100644 index 00000000000..98c9836f133 --- /dev/null +++ b/src/frontend/app/folder/folder-update/folder-update.component.scss @@ -0,0 +1,44 @@ +@import '../../../css/vars.scss'; + +.mat-form-field-appearance-outline { + font-size: 11px; +} + +.formType { + display: flex; + flex-direction: column; + margin: 10px; + border-radius: 4px; + border: solid 1px #ccc; + position: relative; + padding: 10px; + + &-title { + white-space: pre; + overflow: hidden; + max-width: 85%; + text-overflow: ellipsis; + z-index: 1; + font-size: 20px; + font-weight: bold; + background: white; + position: absolute; + top: -18px; + left: 10px; + padding: 0px; + margin: 0px; + color: #135f7f; + } +} +.modal-body{ + min-height: 600px; +} + +.entitiesList { + overflow: auto; +} + +.selectedEntities { + margin-top: 5px; + margin-bottom: 5px; +} \ No newline at end of file diff --git a/src/frontend/app/folder/folder-update/folder-update.component.ts b/src/frontend/app/folder/folder-update/folder-update.component.ts new file mode 100644 index 00000000000..81a17fdbb62 --- /dev/null +++ b/src/frontend/app/folder/folder-update/folder-update.component.ts @@ -0,0 +1,139 @@ +import { Component, OnInit, Input, Output, EventEmitter, Inject } from '@angular/core'; +import { LANG } from '../../translate.component'; +import { HttpClient } from '@angular/common/http'; +import { map, tap, catchError, exhaustMap } from 'rxjs/operators'; +import { of } from 'rxjs'; +import { NotificationService } from '../../notification.service'; +import { MatDialogRef, MAT_DIALOG_DATA } from '@angular/material/dialog'; + +declare function $j(selector: any): any; + +@Component({ + templateUrl: "folder-update.component.html", + styleUrls: ['folder-update.component.scss'], + providers: [NotificationService], +}) +export class FolderUpdateComponent implements OnInit { + + lang: any = LANG; + + folder: any = { + id: 0, + label: '', + public: true, + user_id: 0, + parent_id: 0, + level: 0, + sharing: { + entities: [] + } + } + + entities: any[] = []; + + constructor( + public http: HttpClient, + private notify: NotificationService, + public dialogRef: MatDialogRef<FolderUpdateComponent>, + @Inject(MAT_DIALOG_DATA) public data: any + ) { } + + ngOnInit(): void { + this.getFolder(); + } + + getFolder() { + this.http.get('../../rest/folders/' + this.data.folderId).pipe( + tap((data: any) => this.folder = data.folder), + exhaustMap(() => this.http.get('../../rest/entities')), + map((data: any) => { + this.entities = data.entities; + data.entities.forEach((element: any) => { + if (this.folder.sharing.entities.map((data: any) => data.entity_id).indexOf(element.serialId) > -1) { + element.state.selected = true; + } + element.state.allowed = true; + element.state.disabled = false; + }); + return data; + }), + tap((data: any) => { + this.initEntitiesTree(data.entities); + }), + catchError((err: any) => { + this.notify.handleErrors(err); + return of(false); + }) + ).subscribe(); + } + + initEntitiesTree(entities: any) { + $j('#jstree').jstree({ + "checkbox": { + "three_state": false //no cascade selection + }, + 'core': { + 'themes': { + 'name': 'proton', + 'responsive': true + }, + 'data': entities + }, + "plugins": ["checkbox", "search"] + }); + $j('#jstree') + // listen for event + .on('select_node.jstree', (e: any, data: any) => { + this.selectEntity(data.node.original); + + }).on('deselect_node.jstree', (e: any, data: any) => { + this.deselectEntity(data.node.original); + }) + // create the instance + .jstree(); + var to: any = false; + $j('#jstree_search').keyup(function () { + if (to) { clearTimeout(to); } + to = setTimeout(function () { + var v = $j('#jstree_search').val(); + $j('#jstree').jstree(true).search(v); + }, 250); + }); + } + + selectEntity(newEntity: any) { + this.folder.sharing.entities.push( + { + entity_id : newEntity.serialId, + edition : false + } + ); + } + + deselectEntity(entity: any) { + let index = this.folder.sharing.entities.map((data: any) => data.entity_id).indexOf(entity.id); + this.folder.sharing.entities.splice(index, 1); + } + + onSubmit(): void { + this.http.put('../../rest/folders/' + this.folder.id, this.folder).pipe( + exhaustMap(() => this.http.put('../../rest/folders/' + this.folder.id + '/sharing', { public: this.folder.sharing.entities.length > 0, sharing: this.folder.sharing })), + tap((data: any) => { + this.notify.success('Dossier modifié'); + this.dialogRef.close(); + }), + catchError((err: any) => { + this.notify.handleErrors(err); + return of(false); + }) + ).subscribe(); + } + + checkSelectedFolder(entity: any) { + if (this.folder.sharing.entities.map((data: any) => data.entity_id).indexOf(entity.serialId) > -1) { + return true; + } else { + return false; + } + } +} diff --git a/src/frontend/app/folder/panel/panel-folder.component.html b/src/frontend/app/folder/panel/panel-folder.component.html index 1236cb99dd2..2fac3f02879 100644 --- a/src/frontend/app/folder/panel/panel-folder.component.html +++ b/src/frontend/app/folder/panel/panel-folder.component.html @@ -4,5 +4,5 @@ {{lang.folders}} </mat-panel-title> </mat-expansion-panel-header> - <folder-tree #folderTree [selectedId]="id"></folder-tree> + <folder-tree #folderTree [selectedId]="id" (refreshDocList)="refreshDocList()"></folder-tree> </mat-expansion-panel> diff --git a/src/frontend/app/folder/panel/panel-folder.component.ts b/src/frontend/app/folder/panel/panel-folder.component.ts index b613cfaa15b..43b49a802f5 100644 --- a/src/frontend/app/folder/panel/panel-folder.component.ts +++ b/src/frontend/app/folder/panel/panel-folder.component.ts @@ -1,4 +1,4 @@ -import { Component, OnInit, Input, ViewChild } from '@angular/core'; +import { Component, OnInit, Input, ViewChild, Output, EventEmitter } from '@angular/core'; import { LANG } from '../../translate.component'; import { FolderTreeComponent } from '../folder-tree.component'; @@ -16,6 +16,8 @@ export class PanelFolderComponent implements OnInit { @Input('selectedId') id: number; @ViewChild('folderTree', { static: true }) folderTree: FolderTreeComponent; + @Output('refreshEvent') refreshEvent = new EventEmitter<string>(); + constructor() { } ngOnInit(): void { } @@ -31,4 +33,8 @@ export class PanelFolderComponent implements OnInit { initTree() { this.folderTree.openTree(this.id); } + + refreshDocList() { + this.refreshEvent.emit(); + } } diff --git a/src/frontend/app/list/basket-list.component.html b/src/frontend/app/list/basket-list.component.html index 68916c2cf6b..b41ae3490d9 100644 --- a/src/frontend/app/list/basket-list.component.html +++ b/src/frontend/app/list/basket-list.component.html @@ -8,7 +8,7 @@ <basket-home *ngIf="homeData" #basketHome (refreshEvent)="refreshDao()" [homeData]="homeData" [snavL]="snav" [currentBasketInfo]="currentBasketInfo"></basket-home> <mat-divider></mat-divider> - <panel-folder #panelFolder></panel-folder> + <panel-folder #panelFolder (refreshEvent)="refreshDao()"></panel-folder> </mat-sidenav> <mat-sidenav-content> <mat-card id="viewThumbnail" style="display:none;position: fixed;z-index: 2;margin-left: 1px;"><img style="max-height: 100vh;" src="{{thumbnailUrl}}" /></mat-card> @@ -62,8 +62,8 @@ </div> </div> <div style="height:90%;overflow:auto;position:absolute;width:100%;"> - <table cdkDropList id="document-list" [cdkDropListConnectedTo]="panelFolder.getDragIds()" [cdkDropListData]="data" #tableBasketListSort="matSort" mat-table [dataSource]="data" matSort - matSortActive="res_id" matSortDisableClear matSortDirection="asc" style="width:100%;"> + <table cdkDropList id="document-list" [cdkDropListConnectedTo]="listTodrag()" [cdkDropListData]="data" #tableBasketListSort="matSort" mat-table [dataSource]="data" matSort + matSortActive="res_id" matSortDisableClear matSortDirection="asc" style="width:100%;" [cdkDropListDisabled]="dragInit"> <ng-container matColumnDef="res_id"> <td mat-cell *matCellDef="let row" diff --git a/src/frontend/app/list/basket-list.component.ts b/src/frontend/app/list/basket-list.component.ts index 3b43aeb5467..9b627fe0894 100755 --- a/src/frontend/app/list/basket-list.component.ts +++ b/src/frontend/app/list/basket-list.component.ts @@ -1,4 +1,4 @@ -import { Component, OnInit, ViewChild, EventEmitter, ViewContainerRef } from '@angular/core'; +import { Component, OnInit, ViewChild, EventEmitter, ViewContainerRef, ApplicationRef } from '@angular/core'; import { HttpClient } from '@angular/common/http'; import { LANG } from '../translate.component'; import { merge, Observable, of as observableOf, Subject } from 'rxjs'; @@ -48,6 +48,8 @@ export class BasketListComponent implements OnInit { filtersChange = new EventEmitter(); + dragInit: boolean = true; + @ViewChild('snav', { static: true }) sidenavLeft: MatSidenav; @ViewChild('snav2', { static: true }) sidenavRight: MatSidenav; @@ -124,6 +126,7 @@ export class BasketListComponent implements OnInit { this.isLoadingResults = false; this.route.params.subscribe(params => { + this.dragInit = true; this.destroy$.next(true); this.basketUrl = '../../rest/resourcesList/users/' + params['userSerialId'] + '/groups/' + params['groupSerialId'] + '/baskets/' + params['basketId']; @@ -141,6 +144,10 @@ export class BasketListComponent implements OnInit { this.listProperties = this.filtersListService.initListsProperties(this.currentBasketInfo.ownerId, this.currentBasketInfo.groupId, this.currentBasketInfo.basketId); + + setTimeout(() => { + this.dragInit = false; + }, 1000); this.initResultList(); }, @@ -178,7 +185,6 @@ export class BasketListComponent implements OnInit { this.currentBasketInfo.basket_id = data.basket_id; this.defaultAction = data.defaultAction; this.headerService.setHeader(data.basketLabel); - return data.resources; }), catchError((err: any) => { @@ -422,7 +428,14 @@ export class BasketListComponent implements OnInit { setTimeout(() => { this.actionsList.launchEvent(action, row); }, 200); - + } + + listTodrag() { + if (this.panelFolder !== undefined) { + return this.panelFolder.getDragIds(); + } else { + return [0]; + } } } export interface BasketList { diff --git a/src/frontend/tsconfig.app.json b/src/frontend/tsconfig.app.json index 79143525f9a..6d8e476354d 100755 --- a/src/frontend/tsconfig.app.json +++ b/src/frontend/tsconfig.app.json @@ -8,5 +8,8 @@ }, "exclude": [ "**/*.spec.ts" - ] + ], + "angularCompilerOptions": { + "enableIvy": false + } } -- GitLab