blob: 230b9da008825d8d5fadf0a4366a28f4a40ed4ab [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import debounce from 'lodash/debounce';
import headerTemplate from 'app/primitives/ui-grid-header/index.tpl.pug';
import ResizeObserver from 'resize-observer-polyfill';
export default class IgniteUiGrid {
/** @type {import('ui-grid').IGridOptions} */
grid;
/** @type */
gridApi;
/** @type */
gridThin;
/** @type */
gridHeight;
/** @type */
items;
/** @type */
columnDefs;
/** @type */
categories;
/** @type {boolean} */
singleSelect;
/** @type */
onSelectionChange;
/** @type */
selectedRows;
/** @type */
selectedRowsId;
/** @type */
_selected;
static $inject = ['$scope', '$element', '$timeout', 'gridUtil'];
/**
* @param {ng.IScope} $scope
* @param $element
* @param $timeout
* @param gridUtil
*/
constructor($scope, $element, $timeout, gridUtil) {
this.$scope = $scope;
this.$element = $element;
this.$timeout = $timeout;
this.gridUtil = gridUtil;
this.rowIdentityKey = '_id';
this.rowHeight = 48;
this.headerRowHeight = 70;
}
$onInit() {
this.SCROLLBAR_WIDTH = this.gridUtil.getScrollbarWidth();
if (this.gridThin) {
this.rowHeight = 36;
this.headerRowHeight = 48;
}
this.grid = {
appScopeProvider: this.$scope.$parent,
data: this.items,
columnDefs: this.columnDefs,
categories: this.categories,
rowHeight: this.rowHeight,
multiSelect: !this.singleSelect,
enableSelectAll: !this.singleSelect,
headerRowHeight: this.headerRowHeight,
columnVirtualizationThreshold: 30,
enableColumnMenus: false,
enableFullRowSelection: true,
enableFiltering: true,
enableRowHashing: false,
fastWatch: true,
showTreeExpandNoChildren: false,
modifierKeysToMultiSelect: true,
selectionRowHeaderWidth: 52,
exporterCsvColumnSeparator: ';',
onRegisterApi: (api) => {
this.gridApi = api;
api.core.on.rowsVisibleChanged(this.$scope, () => {
this.adjustHeight();
// Without property existence check non-set selectedRows or selectedRowsId
// binding might cause unwanted behavior,
// like unchecking rows during any items change,
// even if nothing really changed.
if (this._selected && this._selected.length && this.onSelectionChange) {
this.applyIncomingSelectionRows(this._selected);
// Change selected rows if filter was changed.
this.onRowsSelectionChange([]);
}
});
if (this.onSelectionChange) {
api.selection.on.rowSelectionChanged(this.$scope, (row, e) => {
this.onRowsSelectionChange([row], e);
});
api.selection.on.rowSelectionChangedBatch(this.$scope, (rows, e) => {
this.onRowsSelectionChange(rows, e);
});
}
api.core.on.filterChanged(this.$scope, (column) => {
this.onFilterChange(column);
});
this.$timeout(() => {
if (this.selectedRowsId) this.applyIncomingSelectionRowsId(this.selectedRowsId);
});
this.resizeObserver = new ResizeObserver(() => api.core.handleWindowResize());
this.resizeObserver.observe(this.$element[0]);
if (this.onApiRegistered)
this.onApiRegistered({$event: api});
}
};
if (this.grid.categories)
this.grid.headerTemplate = headerTemplate;
}
$onChanges(changes) {
const hasChanged = (binding) =>
binding in changes && changes[binding].currentValue !== changes[binding].previousValue;
if (hasChanged('items') && this.grid)
this.grid.data = changes.items.currentValue;
if (hasChanged('selectedRows') && this.grid && this.grid.data && this.onSelectionChange)
this.applyIncomingSelectionRows(changes.selectedRows.currentValue);
if (hasChanged('selectedRowsId') && this.grid && this.grid.data)
this.applyIncomingSelectionRowsId(changes.selectedRowsId.currentValue);
if (hasChanged('gridHeight') && this.grid)
this.adjustHeight();
}
$onDestroy() {
if (this.resizeObserver)
this.resizeObserver.disconnect();
}
applyIncomingSelectionRows = (selected = []) => {
this.gridApi.selection.clearSelectedRows({ ignore: true });
const visibleRows = this.gridApi.core.getVisibleRows(this.gridApi.grid)
.map(({ entity }) => entity);
const rows = visibleRows.filter((r) =>
selected.map((row) => row[this.rowIdentityKey]).includes(r[this.rowIdentityKey]));
rows.forEach((r) => {
this.gridApi.selection.selectRow(r, { ignore: true });
});
};
applyIncomingSelectionRowsId = (selected = []) => {
if (this.onSelectionChange) {
this.gridApi.selection.clearSelectedRows({ ignore: true });
const visibleRows = this.gridApi.core.getVisibleRows(this.gridApi.grid)
.map(({ entity }) => entity);
const rows = visibleRows.filter((r) =>
selected.includes(r[this.rowIdentityKey]));
rows.forEach((r) => {
this.gridApi.selection.selectRow(r, { ignore: true });
});
}
};
onRowsSelectionChange = debounce((rows, e = {}) => {
if (e.ignore)
return;
this._selected = this.gridApi.selection.legacyGetSelectedRows();
if (this.onSelectionChange)
this.onSelectionChange({ $event: this._selected });
});
onFilterChange = debounce((column) => {
if (!this.gridApi.selection)
return;
if (this.selectedRows && this.onSelectionChange)
this.applyIncomingSelectionRows(this.selectedRows);
if (this.selectedRowsId)
this.applyIncomingSelectionRowsId(this.selectedRowsId);
});
adjustHeight() {
let height = this.gridHeight;
if (!height) {
const maxRowsToShow = this.maxRowsToShow || 5;
const headerBorder = 1;
const visibleRows = this.gridApi.core.getVisibleRows().length;
const header = this.grid.headerRowHeight + headerBorder;
const optionalScroll = (visibleRows ? this.gridUtil.getScrollbarWidth() : 0);
height = Math.min(visibleRows, maxRowsToShow) * this.grid.rowHeight + header + optionalScroll;
}
this.gridApi.grid.element.css('height', height + 'px');
this.gridApi.core.handleWindowResize();
}
}