Skip to content
Snippets Groups Projects
Commit f302574e authored by Alex ORLUC's avatar Alex ORLUC
Browse files

FEAT #11291 TIME 3 begin dnd res in folders

parent 19061f89
No related branches found
No related tags found
No related merge requests found
<mat-list role="list">
<mat-list-item role="listitem">
<form>
<mat-form-field floatLabel="never" style="width: 100%;">
<input matInput #itemValue placeholder="Nouveau dossier...">
</mat-form-field>
<button type="submit" mat-icon-button (click)="createRoot(itemValue.value);itemValue.value = ''"
[disabled]="itemValue.value === ''">
<mat-icon class="fa fa-check" color="accent" [title]="lang.add"></mat-icon>
</button>
</form>
</mat-list-item>
</mat-list>
<mat-nav-list>
<mat-tree [dataSource]="dataSource" [treeControl]="treeControl">
<!-- This is the tree node template for leaf nodes -->
<mat-tree-node [@hideShow] *matTreeNodeDef="let node" matTreeNodePadding matTreeNodePaddingIndent="20px">
<mat-tree-node cdkDropList [id]="'folder-list-'+node.id" cdkDropListConnectedTo="list-1" (cdkDropListDropped)="drop($event, node)"
(cdkDropListEntered)="dragEnter(node)" (cdkDropListExited)="node.drag=false" [@hideShow] *matTreeNodeDef="let node"
matTreeNodePadding matTreeNodePaddingIndent="20px">
<!-- use a disabled button to provide padding for tree leaf -->
<button class="expandButton" mat-icon-button disabled></button>
<a mat-list-item disableRipple [class.selectedFolder]="node.selected" (mouseenter)="showAction(node)"
(mouseleave)="hideAction(node)" (click)="selectFolder(node)">
<span style="flex:1;overflow: hidden;text-overflow: ellipsis;">
<span class="treeLabel" [title]="node.label">
<span class="treeLabel" [class.private]="!node.public" [title]="node.label" [class.drag]="node.drag">
{{node.label}}
</span>
</span>
......@@ -28,54 +17,70 @@
[disabled]="!node.showAction">
<mat-icon *ngIf="node.showAction" class="folderAction fa fa-ellipsis-v"></mat-icon>
<span *ngIf="!node.showAction">
4
{{node.countRes}}
</span>
</button>
<mat-menu #menu="matMenu">
<button mat-menu-item (click)="addNewItem(node)">Nouveau sous-dossier</button>
<button mat-menu-item [disabled]="createItemNode" (click)="addNewItem(node)">Nouveau sous-dossier</button>
<button mat-menu-item (click)="deleteNode(node)">Supprimer</button>
</mat-menu>
</a>
</mat-tree-node>
<mat-tree-node *matTreeNodeDef="let node; when: hasNoContent" matTreeNodePadding
matTreeNodePaddingIndent="45px">
<mat-tree-node *matTreeNodeDef="let node; when: hasNoContent" matTreeNodePadding matTreeNodePaddingIndent="45px">
<form>
<mat-form-field floatLabel="never" style="width: 100%;">
<input matInput #itemValue placeholder="Nouveau dossier...">
<input matInput id="itemValue" #itemValue placeholder="Nouveau dossier...">
<button type="submit" matSuffix mat-icon-button (click)="saveNode(node, itemValue.value)"
[disabled]="itemValue.value === ''">
<mat-icon class="fa fa-check" color="accent" [title]="lang.add"></mat-icon>
</button>
</mat-form-field>
<button type="submit" mat-icon-button (click)="saveNode(node, itemValue.value)"
[disabled]="itemValue.value === ''">
<mat-icon class="fa fa-check" color="accent" [title]="lang.add"></mat-icon>
</button>
</form>
</mat-tree-node>
<!-- This is the tree node template for expandable nodes -->
<mat-tree-node [@hideShow] *matTreeNodeDef="let node;when: hasChild" matTreeNodePadding
matTreeNodePaddingIndent="20px">
<button class="expandButton" mat-icon-button matTreeNodeToggle [attr.aria-label]="'toggle ' + node.name">
<mat-icon
class="mat-icon-rtl-mirror fa {{treeControl.isExpanded(node) ? 'fa-chevron-down' : 'fa-chevron-right'}}">
<mat-tree-node cdkDropList [id]="'folder-list-'+node.id" cdkDropListConnectedTo="list-1" (cdkDropListDropped)="drop($event, node)"
(cdkDropListEntered)="dragEnter(node)" (cdkDropListExited)="node.drag=false" [@hideShow] *matTreeNodeDef="let node;when: hasChild"
matTreeNodePadding matTreeNodePaddingIndent="20px">
<button class="expandButton" [class.private]="!node.public" mat-icon-button matTreeNodeToggle [attr.aria-label]="'toggle ' + node.name">
<mat-icon class="mat-icon-rtl-mirror fa {{treeControl.isExpanded(node) ? 'fa-chevron-down' : 'fa-chevron-right'}}">
</mat-icon>
</button>
<a mat-list-item disableRipple [class.selectedFolder]="node.selected" (mouseleave)="hideAction(node)"
(mouseenter)="showAction(node)" (click)="selectFolder(node)">
<span style="flex:1;overflow: hidden;text-overflow: ellipsis;">
<span class="treeLabel" [title]="node.label">
<span class="treeLabel" [class.private]="!node.public" [title]="node.label" [class.drag]="node.drag">
{{node.label}}
</span>
</span>
<button mat-icon-button [matMenuTriggerFor]="menu" (click)="$event.stopPropagation();"
[disabled]="!node.showAction">
<button mat-icon-button [matMenuTriggerFor]="menu" (click)="$event.stopPropagation();" [disabled]="!node.showAction">
<mat-icon *ngIf="node.showAction" class="folderAction fa fa-ellipsis-v"></mat-icon>
<span *ngIf="!node.showAction">
4
{{node.countRes}}
</span>
</button>
<mat-menu #menu="matMenu">
<button mat-menu-item (click)="addNewItem(node)">Nouveau sous-dossier</button>
<button mat-menu-item [disabled]="createItemNode" (click)="addNewItem(node)">Nouveau sous-dossier</button>
<button mat-menu-item (click)="deleteNode(node)">Supprimer</button>
</mat-menu>
</a>
</mat-tree-node>
</mat-tree>
</mat-nav-list>
\ No newline at end of file
</mat-nav-list>
<mat-nav-list>
<mat-list-item role="listitem" disableRipple (click)="toggleInput()" class="more">
<mat-icon class="fa {{createRootNode ? 'fa-chevron-up' : 'fa-chevron-down'}}"></mat-icon>&nbsp;{{createRootNode ? 'Moins' : 'Plus'}}
</mat-list-item>
</mat-nav-list>
<mat-list *ngIf="createRootNode">
<mat-list-item role="listitem">
<form>
<mat-form-field floatLabel="never" style="width: 100%;">
<input matInput id="itemValue" #itemValue placeholder="Nouveau dossier racine...">
<button type="submit" matSuffix mat-icon-button (click)="createRoot(itemValue.value);createRootNode = !createRootNode"
[disabled]="itemValue.value === ''">
<mat-icon class="fa fa-check" color="accent" [title]="lang.add"></mat-icon>
</button>
</mat-form-field>
</form>
</mat-list-item>
</mat-list>
\ No newline at end of file
......@@ -72,4 +72,18 @@ form {
.treeLabel {
white-space: pre;
color: $primary;
}
.drag {
color: $secondary;
}
.more {
::ng-deep.mat-list-item-content {
justify-content: center;
}
}
.private {
color: $warn;
}
\ No newline at end of file
import { Component, OnInit, ViewChild, Input } from '@angular/core';
import { Component, OnInit, ViewChild, Input, Renderer2 } from '@angular/core';
import { HttpClient } from '@angular/common/http';
import { LANG } from '../translate.component';
import { map, tap, catchError, filter, exhaustMap } from 'rxjs/operators';
import { map, tap, catchError, filter, exhaustMap, finalize } from 'rxjs/operators';
import { FlatTreeControl } from '@angular/cdk/tree';
import { trigger, transition, style, animate } from '@angular/animations';
import { MatTreeFlatDataSource, MatTreeFlattener, MatDialog, MatDialogRef } from '@angular/material';
import { MatTreeFlatDataSource, MatTreeFlattener, MatDialog, MatDialogRef, MatInput } from '@angular/material';
import { BehaviorSubject, of } from 'rxjs';
import { NotificationService } from '../notification.service';
import { ConfirmComponent } from '../../plugins/modal/confirm.component';
......@@ -19,6 +19,8 @@ export class ItemNode {
children: ItemNode[];
label: string;
parent_id: number;
public: boolean;
countRes: number;
}
/** Flat to-do item node with expandable and level information */
......@@ -26,7 +28,9 @@ export class ItemFlatNode {
id: number;
label: string;
parent_id: number;
countRes: number;
level: number;
public: boolean;
expandable: boolean;
}
@Component({
......@@ -56,9 +60,13 @@ export class FolderTreeComponent implements OnInit {
lang: any = LANG;
TREE_DATA: any[] = [];
dialogRef: MatDialogRef<any>;
createRootNode: boolean = false;
createItemNode: boolean = false;
dataChange = new BehaviorSubject<ItemNode[]>([]);
@Input('selectedId') seletedId: number;
@ViewChild('itemValue') itemValue: MatInput;
get data(): ItemNode[] { return this.dataChange.value; }
......@@ -74,6 +82,8 @@ export class FolderTreeComponent implements OnInit {
? existingNode
: new ItemFlatNode();
flatNode.label = node.label;
flatNode.countRes = node.countRes;
flatNode.public = node.public;
flatNode.parent_id = node.parent_id;
flatNode.id = node.id;
flatNode.level = level;
......@@ -98,6 +108,7 @@ export class FolderTreeComponent implements OnInit {
private notify: NotificationService,
private dialog: MatDialog,
private router: Router,
private renderer: Renderer2
) { }
ngOnInit(): void {
......@@ -124,8 +135,6 @@ export class FolderTreeComponent implements OnInit {
openTree(id: number) {
let indexSelectedFolder = this.treeControl.dataNodes.map((folder: any) => folder.id).indexOf(id);
//this.treeControl.dataNodes[indexSelectedFolder].selected = true;
console.log(indexSelectedFolder);
while (indexSelectedFolder != -1) {
indexSelectedFolder = this.treeControl.dataNodes.map((folder: any) => folder.id).indexOf(this.treeControl.dataNodes[indexSelectedFolder].parent_id);
......@@ -217,6 +226,7 @@ export class FolderTreeComponent implements OnInit {
}
addNewItem(node: any) {
this.createItemNode = true;
const currentNode = this.flatNodeMap.get(node);
if (currentNode.children === undefined) {
currentNode['children'] = [];
......@@ -225,10 +235,10 @@ export class FolderTreeComponent implements OnInit {
this.dataChange.next(this.data);
this.treeControl.expand(node);
this.renderer.selectRootElement('#itemValue').focus();
}
saveNode(node: any, value: any) {
console.log(node);
this.http.post("../../rest/folders", { label: value, parent_id: node.parent_id }).pipe(
tap((data: any) => {
const nestedNode = this.flatNodeMap.get(node);
......@@ -237,6 +247,7 @@ export class FolderTreeComponent implements OnInit {
this.dataChange.next(this.data);
this.treeControl.collapseAll();
this.openTree(nestedNode.id);
this.createItemNode = false;
}),
tap(() => this.notify.success(this.lang.folderAdded)),
catchError((err) => {
......@@ -308,4 +319,44 @@ export class FolderTreeComponent implements OnInit {
}
return null;
}
drop(ev: any, node: any) {
this.dialogRef = this.dialog.open(ConfirmComponent, { autoFocus: false, disableClose: true, data: { title: 'Classer '+ ev.item.data.alt_identifier, msg: 'Voulez-vous classer <b>'+ ev.item.data.alt_identifier+'</b> dans <b>' + node.label+ '</b> ?'} });
this.dialogRef.afterClosed().pipe(
filter((data: string) => data === 'ok'),
//exhaustMap(() => this.http.post("../../rest/folders/" + node.id)),
tap(() => {
node.countRes = node.countRes + 1;
}),
tap(() => this.notify.success('Courrier classé')),
finalize(() => node.drag = false),
catchError((err) => {
this.notify.handleErrors(err);
return of(false);
})
).subscribe();
}
dragEnter(node: any) {
node.drag=true;
}
getDragIds() {
if (this.treeControl.dataNodes !== undefined) {
return this.treeControl.dataNodes.map(node => 'folder-list-'+node.id);
} else {
return [];
}
}
toggleInput() {
this.createRootNode = !this.createRootNode;
if (this.createRootNode) {
setTimeout(() => {
this.renderer.selectRootElement('#itemValue').focus();
}, 0);
}
}
}
......@@ -4,5 +4,5 @@
{{lang.folders}}
</mat-panel-title>
</mat-expansion-panel-header>
<folder-tree [selectedId]="id"></folder-tree>
<folder-tree #folderTree [selectedId]="id"></folder-tree>
</mat-expansion-panel>
import { Component, OnInit, Input } from '@angular/core';
import { Component, OnInit, Input, ViewChild } from '@angular/core';
import { LANG } from '../../translate.component';
import { FolderTreeComponent } from '../folder-tree.component';
declare function $j(selector: any): any;
......@@ -13,8 +14,13 @@ export class PanelFolderComponent implements OnInit {
lang: any = LANG;
@Input('selectedId') id: number;
@ViewChild('folderTree') folderTree: FolderTreeComponent;
constructor() { }
ngOnInit(): void { }
getDragIds() {
return this.folderTree.getDragIds();
}
}
......@@ -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></panel-folder>
<panel-folder #panelFolder></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,7 +62,7 @@
</div>
</div>
<div style="height:90%;overflow:auto;position:absolute;width:100%;">
<table #tableBasketListSort="matSort" mat-table [dataSource]="data" matSort
<table cdkDropList id="list-1" [cdkDropListConnectedTo]="panelFolder.getDragIds()" [cdkDropListData]="data" #tableBasketListSort="matSort" mat-table [dataSource]="data" matSort
matSortActive="res_id" matSortDisableClear matSortDirection="asc" style="width:100%;">
<ng-container matColumnDef="res_id">
......@@ -169,7 +169,10 @@
</td>
</ng-container>
<tr mat-row *matRowDef="let row; columns: displayedColumnsBasket;"
(contextmenu)="open($event,row);" [class.locked]="row.isLocked == true"></tr>
(contextmenu)="open($event,row);" class="rowData" [class.locked]="row.isLocked == true" cdkDrag [cdkDragData]="row" >
<div class="example-custom-placeholder" *cdkDragPlaceholder></div>
<div class="dragPreview" *cdkDragPreview><i class="fas fa-envelope-open-text fa-2x"></i><br/>Classer <b>{{row.alt_identifier}}</b> dans un dossier</div>
</tr>
</table>
</div>
<div class="table-head">
......
@import '../../css/vars.scss';
.align_leftData {
text-align: left;
}
......@@ -46,3 +48,12 @@
font-weight: bold;
opacity: 0.6;
}
.dragPreview {
text-align: center;
border-radius:5px;
background: white;
padding: 10px;
box-shadow: 0 5px 5px -3px rgba(0, 0, 0, 0.2),0 8px 10px 1px rgba(0, 0, 0, 0.14),0 3px 14px 2px rgba(0, 0, 0, 0.12);
color: $primary;
}
\ No newline at end of file
......@@ -17,6 +17,7 @@ import { Overlay } from '@angular/cdk/overlay';
import { BasketHomeComponent } from '../basket/basket-home.component';
import { PanelListComponent } from './panel/panel-list.component';
import { AppService } from '../../service/app.service';
import { PanelFolderComponent } from '../folder/panel/panel-folder.component';
declare function $j(selector: any): any;
......@@ -87,6 +88,7 @@ export class BasketListComponent implements OnInit {
@ViewChild('filtersTool') filtersTool: FiltersToolComponent;
@ViewChild('appPanelList') appPanelList: PanelListComponent;
@ViewChild('basketHome') basketHome: BasketHomeComponent;
@ViewChild('panelFolder') panelFolder: PanelFolderComponent;
currentSelectedChrono: string = '';
......@@ -173,6 +175,10 @@ export class BasketListComponent implements OnInit {
this.currentBasketInfo.basket_id = data.basket_id;
this.defaultAction = data.defaultAction;
this.headerService.setHeader(data.basketLabel);
setTimeout(() => {
console.log(this.panelFolder.getDragIds());
}, 400);
return data.resources;
}),
catchError((err: any) => {
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment