This is an automated email from the ASF dual-hosted git repository. dgnatyshyn pushed a commit to branch DLAB-1551 in repository https://gitbox.apache.org/repos/asf/incubator-dlab.git
commit 084a9ecced5d8e3e20428759460cc1dc64467e77 Author: Dmytro Gnatyshyn <di1...@ukr.net> AuthorDate: Fri Apr 10 11:52:29 2020 +0300 [DLAB-1551]: Added folders menu --- .../app/core/services/bucket-browser.service.ts | 46 ++++++----- .../bucket-browser/bucket-browser.component.html | 38 ++++++---- .../bucket-browser/bucket-browser.component.scss | 51 ++++++++++++- .../bucket-browser/bucket-browser.component.ts | 43 ++++++++++- .../folder-tree/folder-tree.component.html | 20 ++--- .../folder-tree/folder-tree.component.scss | 22 ++++++ .../folder-tree/folder-tree.component.ts | 88 ++++++++++++++++++---- 7 files changed, 242 insertions(+), 66 deletions(-) diff --git a/services/self-service/src/main/resources/webapp/src/app/core/services/bucket-browser.service.ts b/services/self-service/src/main/resources/webapp/src/app/core/services/bucket-browser.service.ts index 0c334a1..c98df9b 100644 --- a/services/self-service/src/main/resources/webapp/src/app/core/services/bucket-browser.service.ts +++ b/services/self-service/src/main/resources/webapp/src/app/core/services/bucket-browser.service.ts @@ -4,6 +4,7 @@ import {BehaviorSubject} from 'rxjs'; export class TodoItemNode { children: TodoItemNode[]; item: string; + id: string; } /** Flat to-do item node with expandable and level information */ @@ -17,23 +18,26 @@ export class TodoItemFlatNode { * The Json object for to-do list data. */ const TREE_DATA = { - FirsrFolder: { - folder: { - folder: ['file1', 'file2'], - file1: null, - file2: null + 'dlab-local-shared-bucket': { + FirsrFolder: { + folder: { + folder: ['2008.cvs.bz2', 'airports.csv', 'carriers.csv'], + folder1: [], + folder2: [] + }, + 'folder1': [], + 'file2': null, + 'file3': null, }, - 'file': null, - 'file2': null, - 'file3': null, - }, - SecondFolder: [ - 'file1', - 'file2', - 'file3' - ] + SecondFolder: [ + 'file1', + 'file2', + 'file3' + ] + } }; + @Injectable({ providedIn: 'root' }) @@ -50,7 +54,7 @@ export class BucketBrowserService { // Build the tree nodes from Json object. The result is a list of `TodoItemNode` with nested // file node as children. const data = this.buildFileTree(TREE_DATA, 0); - + console.log(data); // Notify the change. this.dataChange.next(data); } @@ -64,7 +68,6 @@ export class BucketBrowserService { const value = obj[key]; const node = new TodoItemNode(); node.item = key; - if (value != null) { if (typeof value === 'object') { node.children = this.buildFileTree(value, level + 1); @@ -78,9 +81,9 @@ export class BucketBrowserService { } /** Add an item to to-do list */ - insertItem(parent: TodoItemNode, name: string) { + insertItem(parent: TodoItemNode, name: string, isFile) { if (parent.children) { - parent.children.push({item: name} as TodoItemNode); + parent.children.push(isFile ? {item: name} as TodoItemNode : {item: name, children: []} as TodoItemNode); this.dataChange.next(this.data); } } @@ -89,4 +92,11 @@ export class BucketBrowserService { node.item = name; this.dataChange.next(this.data); } + + uploadFile(parent: TodoItemNode, name: string) { + if (parent.children) { + parent.children.push({item: name, children: []} as TodoItemNode); + this.dataChange.next(this.data); + } + } } diff --git a/services/self-service/src/main/resources/webapp/src/app/resources/bucket-browser/bucket-browser.component.html b/services/self-service/src/main/resources/webapp/src/app/resources/bucket-browser/bucket-browser.component.html index 307f21b..50c812d 100644 --- a/services/self-service/src/main/resources/webapp/src/app/resources/bucket-browser/bucket-browser.component.html +++ b/services/self-service/src/main/resources/webapp/src/app/resources/bucket-browser/bucket-browser.component.html @@ -25,38 +25,44 @@ <div class="dialog-content tabs"> <div class="submit m-bott-10 m-top-10"> <button mat-raised-button type="button" class="butt action"><input type="file" (change)="handleFileInput($event.target.files)">Add file</button> -<!-- <button mat-raised-button type="button" class="butt action"><input type="file" (change)="filesPicked($event.target.files)" webkitdirectory directory multiple/>Upload folder</button>--> -<!-- <button mat-raised-button type="button" class="butt action">Download files</button>--> - <button mat-raised-button type="button" class="butt action">Create folder</button> + <button mat-raised-button type="button" class="butt action" (click)="folderTreeComponent.addNewItem(selectedFolder, '', false)">Create folder</button> </div> + <p class="path"><span class="strong">Bucket path:</span><i> {{path}}</i></p> <div class="backet-wrapper" id="scrolling"> <div class="navigation"> - <dlab-folder-tree></dlab-folder-tree> -<!-- <ul class="folder-tree">--> -<!-- <li class="folder-item">--> -<!-- <i class="material-icons">folder</i>--> -<!-- <span class="folder">bucket</span>--> -<!-- </li>--> -<!-- </ul>--> + <dlab-folder-tree (showFolderContent)=onFolderClick($event)> </dlab-folder-tree> </div> <div class="directory"> -<!-- <dlab-folder-tree></dlab-folder-tree>--> + <ul class="folder-tree" *ngIf="!uploadPaths.length"> + <li *ngFor="let file of folderItems" class="folder-item" > + <div class="folder-item-wrapper" *ngIf="file.children" (click)="showItem(file)"> + <div class="name name-folder"><i class="material-icons folder-icon" >folder</i><span>{{file.item}}</span></div> + <div class="size">2.4kb</div> + </div> + <div class="folder-item-wrapper" *ngIf="!file.children"> + <div class="name name-file"> <mat-checkbox ></mat-checkbox><span>{{file.item}}</span></div> +<!-- [checked]="descendantsAllSelected(node)"--> +<!-- [indeterminate]="descendantsPartiallySelected(node)"--> +<!-- (change)="todoItemSelectionToggle(node)"--> + <div class="size">2.4kb</div> + </div> + <!-- <div class="progres"></div>--> + </li> + </ul> <ul class="folder-tree"> <li *ngFor="let file of uploadPaths" class="folder-item"> <div class="name">{{file}}</div> <div class="size">2.4kb</div> <div class="progres"></div> - </li> - <li class="folder-item"> - + <div (click)="deleteAddedFile(file)">X</div> </li> </ul> </div> </div> <div class="text-center m-top-30 m-bott-30"> <button type="button" class="butt" mat-raised-button (click)="this.dialogRef.close()">Close</button> - <button type="button" class="butt butt-success" mat-raised-button>Download</button> - <button type="button" class="butt butt-success" mat-raised-button>Upload</button> + <button *ngIf="!this.uploadPaths.length" type="button" class="butt butt-success" mat-raised-button >Download</button> + <button *ngIf="this.uploadPaths.length !== 0" type="button" class="butt butt-success" mat-raised-button (click)="uploadItems()">Upload</button> </div> </div> </div> diff --git a/services/self-service/src/main/resources/webapp/src/app/resources/bucket-browser/bucket-browser.component.scss b/services/self-service/src/main/resources/webapp/src/app/resources/bucket-browser/bucket-browser.component.scss index 9d839bb..dba2d31 100644 --- a/services/self-service/src/main/resources/webapp/src/app/resources/bucket-browser/bucket-browser.component.scss +++ b/services/self-service/src/main/resources/webapp/src/app/resources/bucket-browser/bucket-browser.component.scss @@ -18,7 +18,13 @@ */ .bucket-browser { + .path{ + margin-bottom: 8px; + padding-left: 20px; + .url{ + } + } bottom: 0; .dialog-content{ padding: 0 35px; @@ -51,7 +57,6 @@ left: 0; right: 0; } - } .backet-wrapper{ @@ -60,6 +65,8 @@ border-radius: 5px; display: flex; + + .navigation{ flex: 1; border-right: 2px solid rgba(0,0,0,.12); @@ -79,6 +86,19 @@ .folder-tree{ .name{ flex:2; + display: flex; + align-items: center; + &-folder{ + span{ + padding-left: 10px; + } + } + &-file{ + padding-left: 4px; + span{ + padding-left: 14px; + } + } } .size{ flex:1; @@ -118,6 +138,33 @@ .folder-item{ display: flex; align-items: center; - + .folder-item-wrapper{ + width: 100%; + display: flex; + justify-content: space-between; + align-items: center; + cursor: pointer; + color: rgba(0,0,0,.87); + i{ + color: rgb(232, 232, 232); + } + &:hover{ + color: #00bcd4; + transition: .3s ease-in-out; + i{ + color: #00bcd4; + transition: .3s ease-in-out; + } + } + } } } + +.folder-item-name{ + span{ + color: #000; + } + + + +} diff --git a/services/self-service/src/main/resources/webapp/src/app/resources/bucket-browser/bucket-browser.component.ts b/services/self-service/src/main/resources/webapp/src/app/resources/bucket-browser/bucket-browser.component.ts index 447501e..71d9dba 100644 --- a/services/self-service/src/main/resources/webapp/src/app/resources/bucket-browser/bucket-browser.component.ts +++ b/services/self-service/src/main/resources/webapp/src/app/resources/bucket-browser/bucket-browser.component.ts @@ -22,9 +22,10 @@ import { FormGroup, FormBuilder, Validators } from '@angular/forms'; import { MatDialog, MatDialogRef, MAT_DIALOG_DATA } from '@angular/material/dialog'; import { ToastrService } from 'ngx-toastr'; -import { AccountCredentials, MangeUngitModel } from './bucket-browser.model'; +// import { AccountCredentials, MangeUngitModel } from './bucket-browser.model'; import { ManageUngitService } from '../../core/services'; import {logger} from 'codelyzer/util/logger'; +import {FolderTreeComponent} from './folder-tree/folder-tree.component'; @Component({ selector: 'dlab-bucket-browser', @@ -34,7 +35,12 @@ import {logger} from 'codelyzer/util/logger'; export class BucketBrowserComponent implements OnInit { filenames: Array<any> = []; uploadPaths = []; - @ViewChild('tabGroupGit', { static: false }) tabGroupGit; + folderItems = []; + path = ''; + selectedFolderItems = []; + // @ViewChild('tabGroupGit', { static: false }) tabGroupGit; + @ViewChild(FolderTreeComponent, {static: true}) folderTreeComponent; + private selectedFolder: any; constructor( public toastr: ToastrService, @@ -50,14 +56,22 @@ export class BucketBrowserComponent implements OnInit { } + showItem(item) { + const flatItem = this.folderTreeComponent.nestedNodeMap.get(item); + // this.folderTreeComponent.treeControl.isExpanded(flatItem) = ; + this.folderTreeComponent.showItem(flatItem); + // console.log(item); + // this.onFolderClick(item); + } + handleFileInput(files) { // for (let i = 0; i < files.length; i++) { // const file = files[i]; // const path = file.webkitRelativePath.split('/'); // } // } - console.log(files) - this.filenames = Object['values'](files).map(v => v.name) + console.log(files); + this.filenames = Object['values'](files).map(v => v.name); this.uploadPaths = [...this.uploadPaths, ...this.filenames]; } @@ -70,6 +84,13 @@ export class BucketBrowserComponent implements OnInit { console.log(this.uploadPaths); } + onFolderClick(event) { + this.selectedFolder = event.element1; + this.folderItems = event.element ? event.element.children : event.children; + this.path = event.path; + + } + private upload(tree, path) { tree.files.forEach(file => { this.uploadPaths.push(path + file.name); @@ -80,6 +101,20 @@ export class BucketBrowserComponent implements OnInit { this.upload(directory, newPath); }); } + + deleteAddedFile(file) { + this.uploadPaths.splice(this.uploadPaths.indexOf(file), 1); + } + + uploadItems(){ + // this.folderTreeComponent.addNewItem(this.selectedFolder); + this.uploadPaths.forEach(v => { + this.folderTreeComponent.addNewItem(this.selectedFolder, v, true); + }); + this.uploadPaths = []; + // this.folderTreeComponent.saveNode(this.selectedFolder); + + } } // @Component({ diff --git a/services/self-service/src/main/resources/webapp/src/app/resources/bucket-browser/folder-tree/folder-tree.component.html b/services/self-service/src/main/resources/webapp/src/app/resources/bucket-browser/folder-tree/folder-tree.component.html index 2ba6ed8..5b05dea 100644 --- a/services/self-service/src/main/resources/webapp/src/app/resources/bucket-browser/folder-tree/folder-tree.component.html +++ b/services/self-service/src/main/resources/webapp/src/app/resources/bucket-browser/folder-tree/folder-tree.component.html @@ -1,16 +1,16 @@ <mat-tree [dataSource]="dataSource" [treeControl]="treeControl"> - <mat-tree-node *matTreeNodeDef="let node" matTreeNodeToggle matTreeNodePadding> - <button mat-icon-button disabled></button> -<!-- <mat-checkbox class="checklist-leaf-node"--> -<!-- [checked]="checklistSelection.isSelected(node)"--> -<!-- (change)="todoLeafItemSelectionToggle(node)"></mat-checkbox>--> - {{node.item}} - </mat-tree-node> + <mat-tree-node *matTreeNodeDef="let node" matTreeNodeToggle matTreeNodePadding [ngStyle]="{'display': 'none'}"> + <button mat-icon-button disabled></button> + <!-- <mat-checkbox class="checklist-leaf-node"--> + <!-- [checked]="checklistSelection.isSelected(node)"--> + <!-- (change)="todoLeafItemSelectionToggle(node)"></mat-checkbox>--> + {{node.item}} +</mat-tree-node> <mat-tree-node *matTreeNodeDef="let node; when: hasNoContent" matTreeNodePadding> <button mat-icon-button disabled></button> <mat-form-field> - <mat-label>New item...</mat-label> + <mat-label>New folder</mat-label> <input matInput #itemValue placeholder="Ex. Lettuce"> </mat-form-field> <button mat-button (click)="saveNode(node, itemValue.value)">Save</button> @@ -25,8 +25,8 @@ </button> <!-- <mat-checkbox [checked]="descendantsAllSelected(node)"--> <!-- [indeterminate]="descendantsPartiallySelected(node)"--> -<!-- (change)="todoItemSelectionToggle(node)">{{node.item}}</mat-checkbox>--> - <i class="material-icons folder-icon">folder</i> <span class="folder">{{node.item}}</span> +<!-- (change)="todoItemSelectionToggle(node)"></mat-checkbox>--> + <div (click)="showItem(node)" class="folder-item-line" [ngClass]="{'active': selectedFolder === node}"><i class="material-icons folder-icon">folder</i> <span class="folder">{{node.item}}</span></div> <!-- <button mat-icon-button (click)="addNewItem(node)"><mat-icon>add</mat-icon></button>--> </mat-tree-node> </mat-tree> diff --git a/services/self-service/src/main/resources/webapp/src/app/resources/bucket-browser/folder-tree/folder-tree.component.scss b/services/self-service/src/main/resources/webapp/src/app/resources/bucket-browser/folder-tree/folder-tree.component.scss index a842b13..8da2b8d 100644 --- a/services/self-service/src/main/resources/webapp/src/app/resources/bucket-browser/folder-tree/folder-tree.component.scss +++ b/services/self-service/src/main/resources/webapp/src/app/resources/bucket-browser/folder-tree/folder-tree.component.scss @@ -1,3 +1,4 @@ + .folder{ padding-left: 5px; } @@ -5,3 +6,24 @@ .folder-icon{ color: rgb(232, 232, 232); } + +.folder-item-line{ + display: flex; + align-items: center; + cursor: pointer; + &.active { + //border-bottom: 1px solid #00bcd4; + color: #00bcd4; + i{ + color: #00bcd4; + } + +} + &:hover{ + color: #00bcd4; + i{ + color: #00bcd4; + } + } + +} diff --git a/services/self-service/src/main/resources/webapp/src/app/resources/bucket-browser/folder-tree/folder-tree.component.ts b/services/self-service/src/main/resources/webapp/src/app/resources/bucket-browser/folder-tree/folder-tree.component.ts index bba1a45..7070c25 100644 --- a/services/self-service/src/main/resources/webapp/src/app/resources/bucket-browser/folder-tree/folder-tree.component.ts +++ b/services/self-service/src/main/resources/webapp/src/app/resources/bucket-browser/folder-tree/folder-tree.component.ts @@ -1,13 +1,13 @@ -import { Component, OnInit, Injectable } from '@angular/core'; +import {Component, OnInit, AfterViewInit, Output, EventEmitter} from '@angular/core'; import {SelectionModel} from '@angular/cdk/collections'; import {FlatTreeControl} from '@angular/cdk/tree'; import {MatTreeFlatDataSource, MatTreeFlattener} from '@angular/material/tree'; import {BucketBrowserService, TodoItemFlatNode, TodoItemNode} from '../../../core/services/bucket-browser.service'; +import {Logger} from 'codelyzer/util/logger'; class ChecklistDatabase { } - /** * @title Tree with checkboxes */ @@ -17,7 +17,12 @@ class ChecklistDatabase { templateUrl: './folder-tree.component.html', styleUrls: ['./folder-tree.component.scss'] }) -export class FolderTreeComponent { +export class FolderTreeComponent implements AfterViewInit{ + + @Output() showFolderContent: EventEmitter<any> = new EventEmitter(); + + path = []; + selectedFolder: TodoItemFlatNode; /** Map from flat node to nested node. This helps us finding the nested node to be modified */ flatNodeMap = new Map<TodoItemFlatNode, TodoItemNode>(); @@ -29,7 +34,9 @@ export class FolderTreeComponent { /** The new item's name */ newItemName = ''; + isOpened = { + }; treeControl: FlatTreeControl<TodoItemFlatNode>; treeFlattener: MatTreeFlattener<TodoItemNode, TodoItemFlatNode>; @@ -42,14 +49,20 @@ export class FolderTreeComponent { constructor(private bucketBrowserService: BucketBrowserService) { this.treeFlattener = new MatTreeFlattener(this.transformer, this.getLevel, this.isExpandable, this.getChildren); + this.treeControl = new FlatTreeControl<TodoItemFlatNode>(this.getLevel, this.isExpandable); this.dataSource = new MatTreeFlatDataSource(this.treeControl, this.treeFlattener); bucketBrowserService.dataChange.subscribe(data => { this.dataSource.data = data; + console.log(this.dataSource); }); } + // ngAfterViewInit(): void { + // + // } + getLevel = (node: TodoItemFlatNode) => node.level; isExpandable = (node: TodoItemFlatNode) => node.expandable; @@ -76,6 +89,46 @@ export class FolderTreeComponent { return flatNode; } + + ngAfterViewInit() { + const subject = this.dataSource._flattenedData; + let firstSelected; + subject.subscribe((data) => { + firstSelected = data[0]; + // this.selectedFolder = ; + this.treeControl.expand(data[0]); + }); + this.selectedFolder = firstSelected; + } + + showItem(el) { + this.treeControl.expand(el); + this.selectedFolder = el; + const path = this.getpath(el); + this.path = []; + const data = { + flatNode: el, + element: this.flatNodeMap.get(el), + element1: el, + path: path.join('/') + }; + console.log(data); + this.showFolderContent.emit(data); + } + + getpath(el) { + if (this.path.length === 0) { + this.path.unshift(el.item); + } + if (this.getParentNode(el) !== null) { + this.path.unshift(this.getParentNode(el).item); + this.getpath(this.getParentNode(el)); + } + return this.path; + } + + + /** Whether all the descendants of the node are selected. */ descendantsAllSelected(node: TodoItemFlatNode): boolean { const descendants = this.treeControl.getDescendants(node); @@ -95,17 +148,17 @@ export class FolderTreeComponent { /** Toggle the to-do item selection. Select/deselect all the descendants node */ todoItemSelectionToggle(node: TodoItemFlatNode): void { this.checklistSelection.toggle(node); - const descendants = this.treeControl.getDescendants(node); - this.checklistSelection.isSelected(node) - ? this.checklistSelection.select(...descendants) - : this.checklistSelection.deselect(...descendants); - - // Force update for the parent - descendants.every(child => - this.checklistSelection.isSelected(child) - ); - this.checkAllParentsSelection(node); - } + const descendants = this.treeControl.getDescendants(node); + this.checklistSelection.isSelected(node) +? this.checklistSelection.select(...descendants) + : this.checklistSelection.deselect(...descendants); + + // Force update for the parent + descendants.every(child => + this.checklistSelection.isSelected(child) +); + this.checkAllParentsSelection(node); +} /** Toggle a leaf to-do item selection. Check all the parents to see if they changed */ todoLeafItemSelectionToggle(node: TodoItemFlatNode): void { @@ -157,15 +210,18 @@ export class FolderTreeComponent { } /** Select the category so we can insert the new item. */ - addNewItem(node: TodoItemFlatNode) { + addNewItem(node: TodoItemFlatNode, name, isFile) { + console.log(node); const parentNode = this.flatNodeMap.get(node); - this.bucketBrowserService.insertItem(parentNode!, ''); + this.bucketBrowserService.insertItem(parentNode!, name, isFile); this.treeControl.expand(node); } /** Save the node to database */ saveNode(node: TodoItemFlatNode, itemValue: string) { const nestedNode = this.flatNodeMap.get(node); + console.log(nestedNode); + console.log(itemValue); this.bucketBrowserService.updateItem(nestedNode!, itemValue); } } --------------------------------------------------------------------- To unsubscribe, e-mail: commits-unsubscr...@dlab.apache.org For additional commands, e-mail: commits-h...@dlab.apache.org