blob: 2f5554ed6eb7f98f70343d3e28e490b4ae4edede [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 uniq from 'lodash/fp/uniq';
import difference from 'lodash/difference';
import findLast from 'lodash/findLast';
const hasGrouping = (changes) => {
return changes.gridApi.currentValue !== changes.gridApi.previousValue && changes.gridApi.currentValue.grouping;
};
const id = (column) => column.categoryDisplayName || column.displayName || column.name;
const picksrc = (state) => state.categories.length ? state.categories : state.columns;
export default class GridColumnSelectorController {
static $inject = ['$scope', 'uiGridConstants'];
constructor($scope, uiGridConstants) {
Object.assign(this, {$scope, uiGridConstants});
}
$onChanges(changes) {
if (changes && 'gridApi' in changes && changes.gridApi.currentValue) {
this.applyValues();
this.gridApi.grid.registerDataChangeCallback(() => this.applyValues(), [this.uiGridConstants.dataChange.COLUMN]);
if (hasGrouping(changes)) this.gridApi.grouping.on.groupingChanged(this.$scope, () => this.applyValues());
}
}
applyValues() {
this.state = this.getState();
this.columnsMenu = this.makeMenu();
this.selectedColumns = this.getSelectedColumns();
this.setSelectedColumns();
}
getSelectedColumns() {
return picksrc(this.state).filter((i) => i.isVisible && i.isInMenu).map((i) => id(i.item));
}
makeMenu() {
return picksrc(this.state).filter((i) => i.isInMenu).map((i) => ({
name: id(i.item),
item: i.item
}));
}
getState() {
const api = this.gridApi;
const columns = api.grid.options.columnDefs;
const categories = api.grid.options.categories || [];
const grouping = api.grouping
? api.grouping.getGrouping().grouping.map((g) => columns.find((c) => c.name === g.colName).categoryDisplayName)
: [];
const mapfn = (item) => ({
item,
isInMenu: item.enableHiding !== false && !grouping.includes(item.name),
isVisible: grouping.includes(item.name) || item.visible !== false
});
return ({
categories: categories.map(mapfn),
columns: columns.map(mapfn)
});
}
findScrollToNext(columns, prevColumns) {
if (!prevColumns)
return;
const diff = difference(columns, prevColumns);
if (diff.length === 1 && columns.includes(diff[0]))
return diff[0];
}
setSelectedColumns() {
const {selectedColumns} = this;
const scrollToNext = this.findScrollToNext(selectedColumns, this.prevSelectedColumns);
this.prevSelectedColumns = selectedColumns;
const all = this.state.categories.concat(this.state.columns);
const itemsToShow = uniq(all.filter((i) => !i.isInMenu && i.isVisible).map((i) => id(i.item)).concat(selectedColumns));
(this.gridApi.grid.options.categories || []).concat(this.gridApi.grid.options.columnDefs).forEach((item) => {
item.visible = itemsToShow.includes(id(item));
});
// Scrolls to the last matching columnDef, useful if it was out of view after being enabled.
this.refreshColumns().then(() => {
if (scrollToNext) {
const column = findLast(this.gridApi.grid.options.columnDefs, (c) => id(c) === scrollToNext);
this.gridApi.grid.scrollTo(null, column);
}
});
}
// gridApi.grid.refreshColumns method does not allow to wait until async operation completion.
// This method does roughly the same, but returns a Promise.
refreshColumns() {
return this.gridApi.grid.processColumnsProcessors(this.gridApi.grid.columns)
.then((renderableColumns) => this.gridApi.grid.setVisibleColumns(renderableColumns))
.then(() => this.gridApi.grid.redrawInPlace())
.then(() => this.gridApi.grid.refreshCanvas(true));
}
}