/******************************************************************************* * Copyright (c) Lenovo 2020. * * LIMITED AND RESTRICTED RIGHTS NOTICE: If data or software is delivered * pursuant a General Services Administration (GSA) contract, use, reproduction, or * disclosure is subject to restrictions set forth in Contract No. GS-35F-05925. ******************************************************************************/ /** * * IMPORTANT NODE * * The fetchData function for the treetable must respect the following signature: * * getData(builder: SortingAndFilteringParamsBuilder, callback?: Function, jobId?) { this.loading = true; this.jobsSvc.getById(jobId ? jobId : this.rootJobId, builder).subscribe( (res) => { if (!jobId) { this.jobTree = [res]; this.total = this.jobTree.length; } if (callback) callback(res); this.loading = false; }, (error) => { console.error('Get job by id error:', error); this.jobTree = []; this.treetable.showDataErrorMessage(); this.loading = false; this.toasterSvc.showToaster(error, ToasterTypes.ERROR); } ); } * This is needed because of the treetable behavior (clicking on a row should get children) - in that case the callback is a function in the datatable which * actually adds the retrieved children to the tree. The first if is when we first get the root, and we need to initialize the tree with roots for the first time */ import { ChangeDetectorRef, SimpleChanges, OnChanges, OnInit, EventEmitter, AfterViewInit } from '@angular/core'; import { NgxDatatableComponent } from '../ngx-datatable/ngx-datatable.component'; import { TranslateService } from '@ngx-translate/core'; import { DataTableFooterComponent, DataTablePagerComponent } from '@swimlane/ngx-datatable'; import { TreeNode } from '../../interfaces/treeNode'; import { LocalStorageService } from '../../services/localStorageService/localStorage.service'; import { SortingAndFilteringParamsBuilder } from '../../classes/sortingFilteringUtils/sortingFilteringUtils'; import * as i0 from "@angular/core"; export declare class NgxTreetableComponent extends NgxDatatableComponent implements OnChanges, OnInit, AfterViewInit { PARENT_MARGIN_PX: number; /** * Keep track of the last selected row when the treetable has checkbox selection, using this row the parents will be checked for indeterminate selection */ lastSelectedRow: TreeNode; /** * Keep track if the last selected row was being selected or deselected */ checkboxStateForLastSelectedRow: boolean; selectionsMap: Map; /** * When expanding a row, since we are paginating on the backend side, we don't want the children to go on the other page, we want them to remain on the first page * We basically paginate only the roots. * this.limit is the limit used in requests * this.displayedLimit is actually how many items are displayed (can be greater than limit, never smaller, initialized with limit) * * displayedLimit is only used when externalPaging is true */ displayedLimit: number; /** * The count changes at expand if we use external paging but should not influence the initial count of the roots, that is why we need to retain it, to know to what value it should come back to * See line 389 */ initialCount: number; isNodeDisabled: Function; nodeExpanded: EventEmitter; nodeCollapsed: EventEmitter; pager: DataTablePagerComponent; footer: DataTableFooterComponent; selectedItemsForDisplay: any[]; constructor(detector: ChangeDetectorRef, translateSvc: TranslateService, localStorageSvc: LocalStorageService); ngOnChanges(changes: SimpleChanges): void; ngOnInit(): void; ngAfterViewInit(): void; addExportAction(): void; /** * In case of external paging, the calculation of the pages need to take into account the initial row count, without any expanded children, and the initial limit * Because the displayed limit increases when the user expands a certain row but it should not influence the actual number of pages */ overridePagerGetTotalPages(): void; onResize(evt: any): void; toggleDisplay(col: any): void; sortTree(event: any, childrenNodes?: TreeNode[]): TreeNode[]; onSort(event: any): false | TreeNode[]; /** * Method called in order to select/deselect nodes. It takes care of the state of the parents also. * * Quick note but important on tree selection: regardless of the tree type (static or with request per click), the selected array contains only what is expaned * * @param event * @param selectedNode In case of a tree structure, the parent node may have been selected but not expanded, on expand, the 'lastSelectedNode' here should be the parent which is not the last item in the array so we need to send it explicitly */ onSelect(event: any, selectedNode?: any): void; onCheckboxSelect(btn: any, row: any): void; togglePageSelection(event: any): void; setPage(pageInfo: any): void; /** * A cell or row was focused via keyboard or mouse click. (this is the only way to get the row click event in order to toggle children) * * TODO: If we have elements like mat-select inside row this event will trigger when we open up the drop-down and we don't want that * @param evt */ activate(evt: any): void; /** * Set the header checkbox state in case of tree table structure (the difference is that the rows collection for a simple table is always the same length with the limit but on a tree this is not the case) */ setGlobalSelectionCheckboxState(): void; /** * In the datatable component there is a new request performed on setRowsPerPage but for the tree it is not needed as the pagination is done on the UI side only * @param nrOfRows */ setRowsPerPage(nrOfRows: any): void; refresh(): void; /** * Method used to apply a filter - to fetch data based on a new sorting and filtering builder * * Needed to overwrite for the tree table because the sorting is always applied in the UI * @param newSortingAndFilteringBuilder */ applyFilter(newSortingAndFilteringBuilder: SortingAndFilteringParamsBuilder, sortField?: string, sortMode?: 'asc' | 'desc', limit?: number, saveActiveFiltersBeforeFetching?: boolean): void; resetSelection(): void; fetchDataBasedOnSessionStorageSettings(): void; /** * Recursive check all selected node's parents for no check/indeterminate check/ all check * * (Mark all the parents of the last selected node as checked/not checked/indeterminate depending on the selection of its children) */ private recursiveCheckParents; /** Recursive select children */ private recursiveSelect; /** Recursive deselect children */ private recursiveDeselect; protected applySorting(nodes?: TreeNode[]): void; private markNodeAsIndeterminate; private markNodeAsNotIndeterminate; private selectNode; private deselectNode; /** * This method builds a dictionary with pairs of row ids and as value either 'true' 'false' or 'indeterminate' in order to always maintain the selections on the tree (before and after filtering) * * In order to retain the selections considering that on filtering the rows collection gets replaced and we no longer have all nodes, we need to retain what is being selected when the filter is applied * and when removing the filter apply those selections * * @param nodes - each item from this array will be used for getting a key and modifying that specific entry in the selections dictionary */ private buildSelectionsMap; /** * This method applies the previously built selections dictionary in order to maintain the indeterminate or full selections from filtered results to all results */ private applySelectionsMap; /** * Get selected items for a tree. Do not use the 'selected' property or the selectedItemsForDisplay array. The selected array will contain the indeterminate selections as well. * This method filters the selected array and returns only valid items. Valid items being selected items which are not indeterminate and for those which are not indeterminate, if a root and * all children are selected, send only the root id. */ getSelectedItems(): any[]; /** * Same as getSelectedItems() but not return the indeterminate nodes * * Used in HTML */ private buildSelectedItemsForDisplay; toggleExpandChildren(row: TreeNode, childrenExpansion: boolean): void; expandChildren(row: TreeNode): void; private checkIfAllChildrenAreDisabled; collapseChildren(row: TreeNode): void; collapseAllNodes(): void; /** * In order to perform live update on the jobs, we need to perform a request only to get those jobs which are visible in the UI * This method returns all ids which are visible in the interface and which fulfill the rowRestriction condition * @param rowRestriction function which returns true if the row should be contained in the result */ getCurrentlyDisplayedItems(rowRestriction?: Function): TreeNode[]; replaceNodesInTree(newNodes: TreeNode[]): void; /** * Instead of replacing the entire node, replace only the properties for it * @param id * @param node */ private replacePropertiesForNode; /** * Method used for replacing node in the tree structure and also the array of rows * * We basically have two structures, one is the array of rows which contains the root on 0 and other expanded children on next indexes (this.tree) And it is the root/roots which are very important because based on them we calculate the depth of the tree and we add the margins in the table!! (if we have one root it will always be tree[0]) The nodes from the tree structure (aka the roots which have children and the children have children and so on) must always be in sync with the array of nodes If we have a tree with one root, 3 children, and the first child has also 2 children If the root is expanded we will have root (has children) child1 (has children) child2 child3 Now, the tree property would be this.tree = [ root (with root.children = array(3)), child1, child2, child3] If we expand the first child also we will have this.tree = [ root (with root.children=3 and root.children[0]=2), child1 (with child1.children = 2), child2, child3] So we MUST have child1.children = array(2) in this.tree[0] which is the root and also this.tree[1] which is the child node * @param id * @param node */ replaceNodeInTree(id: any, node: any): void; /** * Method used to search a node in a tree * * We have a tree with multiple roots so this should be called like so: findNode({children: this.tree}, identifier) * @param element * @param identifier */ findNode(element: TreeNode, identifier: any): TreeNode; static ɵfac: i0.ɵɵFactoryDeclaration; static ɵcmp: i0.ɵɵComponentDeclaration; }