import { Component, OnInit, Input, ChangeDetectorRef, ViewChild, Output, EventEmitter, AfterViewInit } from '@angular/core'; import { MatTreeFlattener, MatTree } from '@angular/material'; import { NGXLogger } from 'ngx-logger'; import { DeptInfo } from '@ucap-webmessenger/protocol-query'; import { LoginResponse } from '@ucap-webmessenger/protocol-authentication'; import { FlatTreeControl } from '@angular/cdk/tree'; import { CdkVirtualScrollViewport } from '@angular/cdk/scrolling'; import { VirtualScrollTreeFlatDataSource } from '@ucap-webmessenger/ui'; interface OrganizationNode { deptInfo: DeptInfo; name: string; children?: OrganizationNode[]; } /** Flat node with expandable and level information */ interface FlatNode { expandable: boolean; name: string; level: number; } @Component({ selector: 'ucap-organization-tree', templateUrl: './tree.component.html', styleUrls: ['./tree.component.scss'] }) export class TreeComponent implements OnInit, AfterViewInit { @Output() selected = new EventEmitter(); @Input() loginRes: LoginResponse; @Input() set oraganizationList(deptInfoList: DeptInfo[]) { if (!deptInfoList || 0 === deptInfoList.length) { return; } const nodeMap = new Map(); const rootNodeList: OrganizationNode[] = []; const remainChildNodeList: OrganizationNode[] = []; let myNode: OrganizationNode; deptInfoList.forEach(deptInfo => { const node: OrganizationNode = { deptInfo, name: deptInfo.name, children: [] }; if (nodeMap.has(deptInfo.seq)) { this.logger.warn('duplicate seq', deptInfo.seq); return; } nodeMap.set(deptInfo.seq, node); if (deptInfo.seq === this.loginRes.departmentCode) { myNode = node; } if (0 === deptInfo.parentSeq) { rootNodeList.push(node); return; } if (nodeMap.has(deptInfo.parentSeq)) { nodeMap.get(deptInfo.parentSeq).children.push(node); } else { remainChildNodeList.push(node); } }); remainChildNodeList.forEach(node => { if (nodeMap.has(node.deptInfo.parentSeq)) { nodeMap.get(node.deptInfo.parentSeq).children.push(node); } }); this.dataSource.data = rootNodeList; } @ViewChild('cvsvOrganization', { static: false }) cvsvOrganization: CdkVirtualScrollViewport; @ViewChild('orgranizationTree', { static: false }) orgranizationTree: MatTree; treeControl: FlatTreeControl; treeFlattener: MatTreeFlattener; dataSource: VirtualScrollTreeFlatDataSource; constructor( private changeDetectorRef: ChangeDetectorRef, private logger: NGXLogger ) { this.treeControl = new FlatTreeControl( node => node.level, node => node.expandable ); this.treeFlattener = new MatTreeFlattener( (node: OrganizationNode, level: number) => { return { expandable: !!node.children && node.children.length > 0, name: node.name, level }; }, node => node.level, node => node.expandable, node => node.children ); this.dataSource = new VirtualScrollTreeFlatDataSource< OrganizationNode, FlatNode >(this.treeControl, this.treeFlattener); } ngOnInit() {} ngAfterViewInit(): void { this.dataSource.cdkVirtualScrollViewport = this.cvsvOrganization; } hasChild = (_: number, node: FlatNode) => node.expandable; onClickNode(node: OrganizationNode) { this.selected.emit(node.deptInfo); } }