/// /** Core */ import { CoreComponent } from "cmf.core/src/core"; /** Nested modules */ import { DataGridColumn as BaseDataGridColumn, SelectionMode, DEFAULT_PAGE_SIZES, ClickGridArgs, GridLayoutDef } from "../dataGrid/dataGrid"; import { EntityTypePropertyValueType as SimpleType, ComplexType } from "cmf.core/src/domain/extensions/caches/entityType"; import { SlidingGridBag } from "./slidingGridBag"; import { LayoutBaseDef, OnLayout } from "../../directives/layout/layoutDef"; /** Kendo */ import "kendo.data"; /** Angular */ import * as ng from "@angular/core"; /** * DataSource interface to use. * Instantiate before use. Example: * ``` * new DataSource({ * data: [] * }) * ``` */ export declare class DataSource extends kendo.data.DataSource { constructor(options?: DataSourceOptions); } export declare type DataSourceOptions = kendo.data.DataSourceOptions; export { DEFAULT_PAGE_SIZES }; export { ClickGridArgs }; /** * Personalized layout definition for the SlidingGrid */ export declare class SlidingGridLayoutDef extends LayoutBaseDef { /** * Ordered inner grid layouts per level (starting at 0) */ levels: Array; } /** * It would be great to use symbols in here, however when creating a new KendoDataSource, * it will not preserve any symbols. * So there's no point in building a symbol based API, if the consumer can't use them. * We will use string properties with CMF prefix. */ /** * Will be used as a custom property for each DataGrid row to tell the sliding window if the current row has any children. * This has a direct correlation with the GUI that will show a right arrow if there are children. This right arrow will allow sliding to the right to display the children. */ export declare const HAS_CHILDREN = "CMF_Internal_HasChildren"; /** * This will be used as a custom property for each DataGrid row with the current row's children array. */ export declare const CHILDREN = "CMF_Internal_Children"; /** * Just a symbol to be used as a property to inject the current level when the double click event is raised. * This will tell consumer components of the current level of the SlidingWindow. In a eager load use case * this is really useful. */ export declare const SLIDING_WINDOW_LEVEL: unique symbol; /** * This will be used as a custom property for each DataGrid row with the current row's number of children. */ export declare const NUMBER_CHILDREN = "CMF_Internal_Number_Children"; /** * An enum to specify if the DataGrid has rows or not. * NO -> will display no right arrow * YES -> will display the right arrow * LAZY_LOAD -> will display no right arrow as this is not known when the DataGrid's data source is applied. * A fetch needs to be performed and a new DataSource submitted to check if there are any children. */ export declare const enum HasChildren { NO = 0, YES = 1, LAZY_LOAD = 2 } /** * The Fetch mode is an important part of this component has it configures how it will behave. * * ALWAYS - means that whenever sliding right or sliding back left, will trigger the fetch event. * The idea is to alway request fresh data to display. * * ONCE - probably the most frequent use case. It means the fetch will be triggered only when sliding right. * Sliding back left will not trigger a fetch and also revisiting previously fetched levels will not trigger * another fetch event. * * NONE - means eager load. This is suitable for when all the data is available up-front. No fetch request * will be raised when sliding right or left. * */ export declare const enum FetchMode { ALWAYS = 0, ONCE = 1, NONE = 2 } /** * This interface defines the data that is sent out in the fetch event, so the consumer can identify, * which DataGrid row is requesting a fetch for its children. This will be available in the root property. * The level property marks the level number that we wish to slide to. */ export interface FetchLevel { root: any; level: number; } /** * This interface represents each level of the activated path (all visited levels until the current one). * It has all sort of properties that are relevant, such as the level number, the root data element, * the title to be shown in the header, which can come from different sources on a level basis. * It also stores the dataSource and columns applied in each level. */ export interface Level { level: number; root?: any; title?: string; dataSource?: kendo.data.DataSource; columns?: DataGridColumn[]; selectionMode?: SelectionMode; } /** * This is an interface to configure the FetchMode = NONE. The basis of this mode is to provide all settings and * data up-front, so this structure aggregates everything that's relevant. * * This config can be provided for each level that is required. Each level may have different columns, titles or * even data grid options. */ export interface EagerLevelConfig { markerField?: string; slideRightHeaderTemplateClasses?: Array; selectionMode?: SelectionMode; columns?: DataGridColumn[]; dataSourceOptions?: kendo.data.DataSourceOptions; data?: any[]; hasChildrenPath?: Array; } /** * This is an interface for the DataGridColumn options. * It is based in the DataGridColumn, with some specific properties for this component. */ export interface DataGridColumn extends BaseDataGridColumn { path?: string; name?: string; custom?: boolean; customTemplate?: string; type?: SimpleType | ComplexType; } /** * @whatItDoes * * This component uses a DataGrid to display the data. Therefore, for ease of use, it exposes all the inputs defined * for the DataGrid component, so consumers of the Sliding Grid, can still configure the DataGrid as it was * being directly used. * The Sliding Grid is thought to display hierarchical data, just a like a tree. But instead of showing it * in a tree component, it displays each node level of the tree in a DataGrid and if one needs to drill down in a node * it refreshes the grid with the child nodes of the clicked row. This operation is what is called as a "slide right". * Sliding left needs going up in the tree and returning to parent node. * * The component is prepared to deal with different use cases, such as eager and lazy load data. * * @howToUse * * This component is used with the inputs and outputs mentioned below. * * ### Inputs * @see DataGrid for the complete list of inputs that are specific of the DataGrid. * * `string` : **title** - The start title of the sliding window that will be used in the header for level 0. * * `string` : **markerField** - The data item property from which each level will extract its title from (level > 0). * * `FetchMode` : **fetchMode** - The fetch mode will tell the sliding window how to behave. @see FetchMode for more detail. * * `Array` : **eagerLevelsConfig** - An array with all the configuration for each level * * (only applicable to FetchMode = NONE). Each position in the array accounts for a level in the hierarchy. * * `Array` : **slideRightHeaderTemplateClasses** -Array with all the css classes that should be applied to the * * SlideRight column header * * `string` : **hasChildrenPaths** - The path that the component will verify if the object has children * * `Array`: **selected** - The selected values in data grid, can be set via input to control the selected items outside * * `string` : **headerTitle** - The title to be passed as the DataGrid header * * `boolean` : **refresh** - Will cause changes to be detected plus it will reset the levels to only the first one. * ### Outputs * @see DataGrid for the complete list of outputs that are specific of the DataGrid. * * `FetchLevel` : **fetch** - When the level is about to change, new data needs to be fetched and a new DataSource * * needs to be provided (via the datasource input). * * `FetchLevel` : **levelChange** - When the level is about to change. The above output only emit when data is fetched. This one * emits always when the user change the level * * * `SelectionMode` : **selectionModeChange** - When the level change, notifies the parent of the selection mode of the new level * * ### Example * To use the component, assume this HTML Template as an example: * * ```HTML * * * ``` * * ## SlidingGrid Component * * ### Dependencies * * #### Components * * DataGrid : `cmf.core.controls` * * #### Services * * #### Directives * * ProgressIndicator : `cmf.core.controls` * */ export declare class SlidingGrid extends CoreComponent implements ng.OnChanges, ng.OnDestroy, ng.AfterViewInit, OnLayout { private elementRef; private _slidingGridBag; /** * The selected values uid, by level * * * Example: * ``` * const currentLevel = 2; * const selectedInstances = [ * {productName: "x", productDescription: "y", uid: "d6043baa-9db4-4b77-98a6-c7a057c5a277"}, * {productName: "x1", productDescription: "y1", uid: "7a0476bf-8b99-4d4d-9111-1b2d61a321d0"}, * ]; * this._selectedByLevel.set(currentLevel, selectedInstances.map(x=>x.uid)); * * // expected result: * * // Map(1) {3 => Array(3)} * // __proto__: Map * // [[Entries]]: Array(1) * // 0: {3 => Array(3)} * // key: 2 * // value: Array(3) * // 0: "d6043baa-9db4-4b77-98a6-c7a057c5a277" * // 1: "2fa7e502-b542-417e-9b57-4af2a3c8fe46" * // 2: "40e0d75b-b9ac-4b07-a315-665abf19ec32" * // length: 3 * // length: 1 * * ``` */ private _selectedByLevel; /** * Layouts per level */ private _layoutsPerLevel; /** * Used to count the number of progress indicators open */ _waitingForDataCounter: number; /** * Before fetch subscription */ private _onBeforeFetchSubscription; /** * @see DataGrid to inspect all the next input properties. * */ dataSource: kendo.data.DataSource; columns: DataGridColumn[]; pageable: boolean; pageSizes: number[]; filterable: boolean; /** * The selected values in data grid, can be set via input to control the selected items outside */ selected: Array; preSelectAll: boolean; selectionMode: SelectionMode; keepSelection: boolean; fullSize: boolean; isDisabledRowActive: boolean | string; isPreSelectedRowActive: boolean | string; noRecordsTemplateMessage: string; showHeader: boolean; showActionColumnOptions: boolean; headerTitle: string; /** * The start title of the sliding window that will be used in the header for level 0 */ title: string; /** * The data item property from which each level will extract its title from (level > 0) */ markerField: string; /** * The fetch mode will tell the sliding window how to behave. @see FetchMode for more detail. */ fetchMode: FetchMode; /** * An array with all the configuration for each level (only applicable to FetchMode = NONE). * Each position in the array accounts for a level in the hierarchy. */ eagerLevelsConfig: Array; /** * Array with all the css classes that should be applied to the "SlideRight" column header */ slideRightHeaderTemplateClasses: Array; /** * Path to verify if the object has children */ hasChildrenPaths: Array; /** * @see DataGrid to inspect all the next output properties. * */ selectedChange: ng.EventEmitter; dataGridReady: ng.EventEmitter; currentPageChange: ng.EventEmitter; pageSizeChange: ng.EventEmitter; clickRow: ng.EventEmitter; dblClickRow: ng.EventEmitter; /** * When the level change, notifies the parent of the selection mode of the new level */ selectionModeChange: ng.EventEmitter; /** * When the level is about to change, new data needs to be fetched and a new DataSource * needs to be provided (via the datasource input). */ fetch: ng.EventEmitter; /** * When the level is about to change. With or without the need to fetch data */ levelChange: ng.EventEmitter; /** * Event for arrow click */ rowExpanded: ng.EventEmitter; /** * Event for level row back */ rowBack: ng.EventEmitter; /** * The current level the component is in. */ currentLevel: Level; /** * All the levels visited until the current level. For example, if the array has 3 elements, it means the * level depth is 3 (0, 1, 2). */ levels: Array; /** * Only applicable to FetchMode ONCE, it conserves all the data sources and columns of each visited level. * This is helpful to prevent fetching data and reusing a stored data source if a level is revisited. */ checkInLevelsForFetchOnce: Array>; /** * Refresh input used to reset the levels of the sliding grid to the first one. */ refresh: boolean; /** * Constructor * * @param viewContainerRef the reference to the component view container * @param elementRef the reference to the component's ElementRef */ constructor(viewContainerRef: ng.ViewContainerRef, elementRef: ng.ElementRef, _slidingGridBag: SlidingGridBag); /** * This method takes the list of columns defined for the DataGrid and pushes the slide right command column. * * @param {GridColumn[]} columns to pass to the DataGrid */ private pushSlideRightColumn; /** * This method checks the data source to pass to the DataGrid and stamps the HAS_CHILDREN and CHILDREN * properties if these are not defined. If they are defined, the component will respect the setting provided * by a consumer. * * @param {kendo.data.DataSource} dataSource to pass to the DataGrid */ private augmentChildren; /** * This method sets the next level when sliding right or sliding left. This is done by updating the * current level property. */ private setLevel; /** * This method applies only to FetchMode = NONE and it deals with all operations concerning a level slide. * Since this mode is the basis of a eager-load approach, it uses the eagerLevelsConfig input to check for the * current level, which settings need to be applied, such as the dataSource to (re)use or the columns for that * specific level. * * @param {*} root of the current level */ private buildDataSourceForFetchNone; /** * This method is applicable for FetchMode = ONCE and it searches all the stored levels of a given level number * for a root item passed in. If no level is found, it means, we are entering a fresh level. * * @param {*} root item of the level to search * @param {number} level number of the level to * @returns {Level} The found level (if already visited) */ private searchCheckInLevelForFetchOnce; /** * Applies only to FetchMode = ONCE and it stores the dataSource or columns after it was fetched. * @param {string} property indicates if we are storing DataSource or Columns. */ private checkInForFetchOnce; /** * This method reuses the data source and columns of a given level. This reuse is only applicable for * FetchMode NONE and ONCE. * * @param {Level} level to reuse */ private reuseDataSourceAndColumns; /** * This method will build the columns for the sliding grid. * Since we must maintain compatibility with the old column definition which acccepts title and field directly * this method is accounting for the two types of definition. * * @param columns Columns definition, will not be typed since it can be anything * @param doNotAddSlideColumn If true, slide column (to access children) will NOT be added. * Use to avoid infinite recursion when changing columns from layout events * */ private updateColumns; /** * Update sliding grid bag with current cached layouts */ private updateSlidingGridBag; /** * Load grid layout for the current level * @param level : Level to load layout for */ private loadGridLayout; /** * Load layout for grid columns * @param columnsToSet Columns array to assign * @param layoutColumns Columns array to copy from */ private loadColumnsLayout; /** * Load personalized layouts from bag if available */ private loadPersonalizedLayouts; /** * Populates the _selected element * @param dataSource */ private populateSelected; /** * Check all the possible selections and then adds them * @param toAdd the uid's do add */ private checkPossibleSelected; /** * Removes not needed UID's on the parent array * @param toRemove uid's to remove * @param parent the parent array to be altered */ private removeAllReferences; /** * On changes method * * @param changes the changes made to the component properties */ ngOnChanges(changes: ng.SimpleChanges): void; ngOnDestroy(): void; /** * This method slides left, which in a tree structure like the one that is behind corresponds to going up one * level in the hierarchy and revisiting the parent level. * * @param {Event} event */ onSlideLeft(event: Event): void; /** * Updates the data source for the data grid, and the onSelect logic * @param dataSource */ alterDataSource(dataSource: kendo.data.DataSource): void; /** * Event handler for the DataGrid double click. We inject the current level as well to provide * additional data concerning the level. * * @param {*} data which was double clicked */ onDblClickRow(data: any): void; /** * When one or more objects are selected. We inject the current level as well to provide * additional data concerning the level. * @param instances List of selected objects */ onSelectedChange(instances: Array): void; /** * Mark every element as not selected in the total data * @param instances the selected instances */ private selectData; /** * dataGridReady event subscribe. * Is used to replace the internal text with the correct number of childs using * DOM manipulation. All of this is needed just because Kendo Grid does not allow dynamic text * set according to the DataItem. */ onDataGridReady(grid: kendo.ui.Grid): void; /** * Angular AfterViewInit */ ngAfterViewInit(): void; /** * This component has a layout available to be set */ onLoadLayout(layout: SlidingGridLayoutDef): Promise; /** * A save operation was called by the page to save the component layout */ onSaveLayout(): Promise; } export declare class SlidingGridModule { }