SUPPORT-8975: add custom grid
This commit is contained in:
parent
e5c7e003a0
commit
1697d8302b
21 changed files with 1013 additions and 4 deletions
|
|
@ -0,0 +1,54 @@
|
|||
<div class="grid"
|
||||
[ngbTooltip]="tooltip | emptyIfNull">
|
||||
|
||||
<ag-grid-angular [ngClass]="theme"
|
||||
[ngStyle]="style"
|
||||
[columnDefs]="columnDefs"
|
||||
[defaultColDef]="defaultColDef"
|
||||
[headerHeight]="headerHeight"
|
||||
[rowHeight]="rowHeight"
|
||||
[rowSelection]="rowSelection"
|
||||
[rowMultiSelectWithClick]="isRowMultiSelectWithClick()"
|
||||
[suppressRowClickSelection]="isSuppressRowClickSelection()"
|
||||
[suppressLoadingOverlay]="isSuppressLoadingOverlay()"
|
||||
[suppressNoRowsOverlay]="isSuppressNoRowsOverlay()"
|
||||
[rowClassRules]="rowClassRules"
|
||||
[rowModelType]="getRowModelType()"
|
||||
[datasource]="datasource"
|
||||
[maxConcurrentDatasourceRequests]="maxConcurrentDatasourceRequests"
|
||||
[blockLoadDebounceMillis]="blockLoadDebounceMillis"
|
||||
[cacheBlockSize]="getBlockSize()"
|
||||
[pagination]="pagination"
|
||||
[paginationPageSize]="fetchSize"
|
||||
[maxBlocksInCache]="0"
|
||||
[getRowId]="getRowIdFunc()"
|
||||
[isRowSelectable]="isRowSelectableFunc()"
|
||||
[pinnedBottomRowData]="pinnedBottomRowData"
|
||||
[suppressDragLeaveHidesColumns]="true"
|
||||
[suppressCopyRowsToClipboard]="true"
|
||||
[processCellForClipboard]="processCellForClipboard"
|
||||
[allowContextMenuWithControlKey]="allowContextMenuWithControlKey"
|
||||
[localeText]="localeText"
|
||||
[enableCellTextSelection]="enableCellTextSelection"
|
||||
[overlayLoadingTemplate]="getLoadingOverlayTemplate()"
|
||||
[overlayNoRowsTemplate]="getNoRowsOverlayTemplate()"
|
||||
[tooltipShowDelay]="tooltipDelay"
|
||||
[accentedSort]="true"
|
||||
(gridReady)="onGridReady($event)"
|
||||
(cellClicked)="onCellClicked($event)"
|
||||
(rowClicked)="onRowClicked($event)"
|
||||
(rowDoubleClicked)="onRowDoubleClicked($event)"
|
||||
(selectionChanged)="onSelectionChanged($event)"
|
||||
(sortChanged)="onSortChanged($event)"
|
||||
(bodyScroll)="onBodyScroll($event)"
|
||||
(columnResized)="onColumnResized($event)"
|
||||
(columnMoved)="onColumnMoved($event)"
|
||||
(columnVisible)="onColumnVisibilityChanged($event)"
|
||||
(filterChanged)="columnFilterChanged($event)"
|
||||
(componentStateChanged)="componentStateChanged($event)">
|
||||
</ag-grid-angular>
|
||||
<div [hidden]="true">
|
||||
<ng-content></ng-content>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
|
@ -0,0 +1,26 @@
|
|||
import {
|
||||
FilterType
|
||||
} from "../../../generated/ru/micord/ervu/account_applications/component/property/grid/FilterType";
|
||||
import {DateFilter, NumberFilter, TextFilter} from "ag-grid-community";
|
||||
import {SetFilter} from "./SetFilter";
|
||||
|
||||
export class CustomGridColumnFilterUtils {
|
||||
|
||||
public static columnFilter(type: FilterType) {
|
||||
if (!type) {
|
||||
return null;
|
||||
}
|
||||
|
||||
switch (type) {
|
||||
case FilterType.NUMBER:
|
||||
return NumberFilter;
|
||||
case FilterType.DATE:
|
||||
return DateFilter;
|
||||
case FilterType.SET:
|
||||
return SetFilter;
|
||||
case FilterType.TEXT:
|
||||
default:
|
||||
return TextFilter;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,95 @@
|
|||
import {ChangeDetectionStrategy, Component} from "@angular/core";
|
||||
import {Event, GridRpcService, GridV2, GridV2Column, Visible} from "@webbpm/base-package";
|
||||
import {
|
||||
StaticGridColumn
|
||||
} from "../../../generated/ru/micord/ervu/account_applications/component/property/grid/StaticGridColumn";
|
||||
import {
|
||||
ColDef,
|
||||
FilterChangedEvent,
|
||||
ICellRendererParams,
|
||||
ITooltipParams,
|
||||
ValueFormatterParams,
|
||||
ValueGetterParams
|
||||
} from "ag-grid-community";
|
||||
import {StaticColumnInitializer} from "./StaticColumnInitializer";
|
||||
|
||||
@Component({
|
||||
moduleId: module.id,
|
||||
selector: 'ervu-static-grid',
|
||||
templateUrl: './../../../../../src/resources/template/account_applications/component/grid/ErvuStaticGrid.html',
|
||||
changeDetection: ChangeDetectionStrategy.OnPush
|
||||
})
|
||||
export class ErvuStaticGrid extends GridV2 {
|
||||
// todo: remove on updating platform version up to 3.188
|
||||
@Visible("false")
|
||||
public columnFiltersChanged: Event<any> = new Event<any>();
|
||||
private rpcService: GridRpcService;
|
||||
|
||||
protected initGrid() {
|
||||
super.initGrid();
|
||||
this.rpcService = this.getScript(GridRpcService);
|
||||
}
|
||||
|
||||
getColumns(): any[] {
|
||||
return this.getScriptsInChildren(GridV2Column)
|
||||
.map(columnV2 => columnV2.getScript(StaticGridColumn));
|
||||
}
|
||||
|
||||
protected columnV2ToColumnDef(column: GridV2Column): ColDef {
|
||||
let gridColumn = column.getScript(StaticGridColumn);
|
||||
let colDef = this.columnToColumnDef(gridColumn);
|
||||
if (column.renderer) {
|
||||
colDef.cellRenderer = (params: ICellRendererParams) => column.renderer.render(params);
|
||||
}
|
||||
if (column.valueGetter) {
|
||||
colDef.valueGetter = (params: ValueGetterParams) => column.valueGetter.get(params);
|
||||
}
|
||||
if (column.tooltipValueGetter) {
|
||||
if (gridColumn.columnTooltip) {
|
||||
throw new Error(
|
||||
"Only one type of tooltip should be specified: tooltipValueGetter or columnTooltip");
|
||||
}
|
||||
colDef.tooltipValueGetter = (params: ITooltipParams) => column.tooltipValueGetter.get(params);
|
||||
}
|
||||
|
||||
column.setGridRef(this);
|
||||
column.setColDef(colDef);
|
||||
return colDef;
|
||||
}
|
||||
|
||||
protected columnToColumnDef(column: any): ColDef {
|
||||
let colDef = StaticColumnInitializer.columnToColumnDef(this, column);
|
||||
let columnComp = column.context;
|
||||
colDef['columnUid'] = columnComp.getObjectId();
|
||||
|
||||
if (columnComp.cellCssClassRulesProvider) {
|
||||
colDef.cellClassRules = columnComp.cellCssClassRulesProvider.getRules();
|
||||
}
|
||||
|
||||
if (columnComp.valueFormatter) {
|
||||
colDef.valueFormatter = (params?: ValueFormatterParams) => {
|
||||
return columnComp.valueFormatter.format(params);
|
||||
}
|
||||
}
|
||||
console.log("Создан ColDef:", colDef);
|
||||
return colDef;
|
||||
}
|
||||
|
||||
@Visible()
|
||||
public getRowDataSize(): number {
|
||||
return this.rowData ? this.rowData.length : 0;
|
||||
}
|
||||
|
||||
// todo: remove on updating platform version up to 3.188
|
||||
@Visible()
|
||||
public hasColumnFilters(): boolean {
|
||||
const filterModel: { [key: string]: any; } = this.gridApi.getFilterModel();
|
||||
return !!filterModel && Object.keys(filterModel).length > 0;
|
||||
}
|
||||
|
||||
// todo: remove on updating platform version up to 3.188
|
||||
public columnFilterChanged(event: FilterChangedEvent) {
|
||||
this.columnFiltersChanged.trigger(event);
|
||||
super.columnFilterChanged(event);
|
||||
}
|
||||
}
|
||||
116
frontend/src/ts/account_applications/component/grid/SetFilter.ts
Normal file
116
frontend/src/ts/account_applications/component/grid/SetFilter.ts
Normal file
|
|
@ -0,0 +1,116 @@
|
|||
import {AgPromise, IDoesFilterPassParams, IFilterComp, IFilterParams} from "ag-grid-community";
|
||||
|
||||
export class SetFilter implements IFilterComp {
|
||||
|
||||
private OPTION_TEMPLATE = `<label class="ag-set-filter-item">
|
||||
<input type="checkbox" class="ag-filter-checkbox" checked/>
|
||||
<span class="ag-filter-value"></span>
|
||||
</label>`;
|
||||
|
||||
private eGui!: HTMLDivElement;
|
||||
private selectAll: HTMLInputElement;
|
||||
private checkboxes: HTMLInputElement[] = [];
|
||||
private values: any[] = [];
|
||||
private initialValues: any[] = [];
|
||||
private filterActive: boolean;
|
||||
private filterChangedCallback!: (additionalEventAttributes?: any) => void;
|
||||
private filterParams!: IFilterParams;
|
||||
private valueType: string;
|
||||
|
||||
init(params: IFilterParams): void {
|
||||
this.eGui = document.createElement('div');
|
||||
this.eGui.className = 'ag-set-filter';
|
||||
let index = 0;
|
||||
this.selectAll = this.initCheckBox('selectAll', 'Все', index);
|
||||
this.checkboxes.push(this.selectAll);
|
||||
|
||||
params.api.getRenderedNodes()
|
||||
.map(node => node.data[params.colDef.field])
|
||||
.sort((n1, n2) => n1 > n2 ? 1 : n1 < n2 ? -1 : 0)
|
||||
.forEach(value => {
|
||||
if (this.values.includes(value)) {
|
||||
return;
|
||||
}
|
||||
index++;
|
||||
let id = `option-${index}`;
|
||||
let checkbox = this.initCheckBox(id, value, index);
|
||||
this.checkboxes.push(checkbox);
|
||||
this.values.push(value);
|
||||
});
|
||||
this.initialValues = this.values.slice();
|
||||
this.filterParams = params;
|
||||
this.filterActive = false;
|
||||
this.filterChangedCallback = params.filterChangedCallback;
|
||||
|
||||
if (this.values.length > 0) {
|
||||
this.valueType = typeof this.values[0];
|
||||
}
|
||||
};
|
||||
|
||||
private initCheckBox(id: string, value: string, index: number): HTMLInputElement {
|
||||
this.eGui.insertAdjacentHTML('beforeend', this.OPTION_TEMPLATE);
|
||||
this.eGui.querySelectorAll('.ag-filter-value')[index].innerHTML = value;
|
||||
let checkbox = this.eGui.querySelectorAll('.ag-filter-checkbox')[index] as HTMLInputElement;
|
||||
checkbox.setAttribute('id', id);
|
||||
checkbox.addEventListener('change', this.onCheckBoxChanged.bind(this));
|
||||
return checkbox;
|
||||
}
|
||||
|
||||
getGui(): HTMLDivElement {
|
||||
return this.eGui;
|
||||
};
|
||||
|
||||
onCheckBoxChanged(event: any) {
|
||||
let checked = event.target.checked;
|
||||
|
||||
if (event.target === this.selectAll) {
|
||||
this.checkboxes.forEach(checkbox => checkbox.checked = checked);
|
||||
this.values = checked ? this.initialValues.slice() : [];
|
||||
}
|
||||
else {
|
||||
let value = event.target.nextElementSibling.textContent;
|
||||
value = this.valueType === 'number' ? +value : value;
|
||||
|
||||
if (checked) {
|
||||
this.values.push(value);
|
||||
|
||||
if (this.values.length == this.initialValues.length) {
|
||||
this.selectAll.checked = true;
|
||||
}
|
||||
}
|
||||
else {
|
||||
let index = this.values.indexOf(value);
|
||||
this.values.splice(index, 1);
|
||||
this.selectAll.checked = false;
|
||||
}
|
||||
}
|
||||
this.filterActive = !this.selectAll.checked;
|
||||
this.filterChangedCallback();
|
||||
}
|
||||
|
||||
doesFilterPass(params: IDoesFilterPassParams): boolean {
|
||||
let { field } = this.filterParams.colDef;
|
||||
return this.values.includes(params.data[field]);
|
||||
}
|
||||
|
||||
getModel(): any {
|
||||
return this.isFilterActive() ? { value: this.values } : null;
|
||||
}
|
||||
|
||||
isFilterActive(): boolean {
|
||||
return this.filterActive;
|
||||
}
|
||||
|
||||
setModel(model: any): void | AgPromise<void> {
|
||||
this.values = model == null ? this.initialValues.slice() : model.value;
|
||||
let predicate = checkbox => model == null ? true : model.value.includes(checkbox.value);
|
||||
this.checkboxes.filter(predicate)
|
||||
.forEach(checkbox => checkbox.checked = true);
|
||||
this.filterActive = !this.selectAll.checked;
|
||||
this.filterChangedCallback();
|
||||
}
|
||||
|
||||
destroy(): void {
|
||||
this.checkboxes.forEach(checkBox => checkBox.removeEventListener('change', this.onCheckBoxChanged.bind(this)));
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,120 @@
|
|||
import {
|
||||
DateTimeUtil,
|
||||
DefaultTooltip,
|
||||
GridCellTooltipUtils,
|
||||
GridColumnComparatorUtils,
|
||||
GridColumnKeyboardUtils,
|
||||
GridValueFormatterUtils,
|
||||
GridValueRendererUtils,
|
||||
PinnedType,
|
||||
} from "@webbpm/base-package";
|
||||
import {
|
||||
ColDef,
|
||||
DateFilter,
|
||||
ICellRendererFunc,
|
||||
SuppressKeyboardEventParams
|
||||
} from "ag-grid-community";
|
||||
import {
|
||||
StaticGridColumn
|
||||
} from "../../../generated/ru/micord/ervu/account_applications/component/property/grid/StaticGridColumn";
|
||||
import {CustomGridColumnFilterUtils} from "./CustomGridColumnFilterUtils";
|
||||
import {Moment} from "moment";
|
||||
import * as moment from "moment-timezone";
|
||||
|
||||
export class StaticColumnInitializer {
|
||||
|
||||
public static columnToColumnDef(gridRef: any, column: StaticGridColumn) {
|
||||
const columnDef: ColDef = {};
|
||||
columnDef.headerName = column.displayName ? column.displayName : '';
|
||||
columnDef.headerClass = "custom-header";
|
||||
columnDef.width = column.width;
|
||||
columnDef.suppressSizeToFit = column.widthFixed;
|
||||
columnDef.hide = column.hidden;
|
||||
columnDef.resizable = !column.widthFixed;
|
||||
columnDef.headerComponentParams = {"disable_hiding": column.disableHiding || false};
|
||||
columnDef.lockVisible = column.disableHiding;
|
||||
columnDef.headerTooltip = column.headerTooltip ? column.headerTooltip : column.displayName;
|
||||
columnDef.suppressMenu = column.suppressHeaderMenu;
|
||||
|
||||
if (column.pinned) {
|
||||
columnDef.pinned = column.pinned == PinnedType.LEFT ? 'left' : 'right';
|
||||
}
|
||||
columnDef['gridComp'] = this;
|
||||
columnDef.sortable = column.sortable;
|
||||
|
||||
if (column.sortable == null) {
|
||||
columnDef.sortable = true;
|
||||
}
|
||||
|
||||
if (column.autoHeight) {
|
||||
columnDef.autoHeight = column.autoHeight;
|
||||
columnDef.cellClass = 'ag-grid-cell-wrap-text';
|
||||
}
|
||||
|
||||
if (column.field) {
|
||||
columnDef.field = column.field.column;
|
||||
let type = column.field.type;
|
||||
|
||||
if (type != null) {
|
||||
if (gridRef.getRowModelType() == "clientSide") {
|
||||
columnDef.comparator = GridColumnComparatorUtils.columnComparator(type);
|
||||
}
|
||||
columnDef.valueFormatter = GridValueFormatterUtils.columnFormatter(type);
|
||||
columnDef.cellRenderer = gridRef.createRenderer(column);
|
||||
}
|
||||
|
||||
if (column.filter !== false) {
|
||||
columnDef.floatingFilter = gridRef.floatingFilter;
|
||||
columnDef.filter = CustomGridColumnFilterUtils.columnFilter(column.field.filterType);
|
||||
|
||||
if (columnDef.filter === DateFilter) {
|
||||
columnDef.filterParams = {
|
||||
comparator: function (filterLocalDateAtMidnight, cellValue) {
|
||||
|
||||
if (!cellValue) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
let filterMoment: Moment = moment.utc(filterLocalDateAtMidnight)
|
||||
.add(-filterLocalDateAtMidnight.getTimezoneOffset(), 'm');
|
||||
let cellMoment: Moment = DateTimeUtil.parseToMidnightUTC(cellValue);
|
||||
|
||||
if (filterMoment.isSame(cellMoment)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (cellMoment.isBefore(filterMoment)) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (cellMoment.isAfter(filterMoment)) {
|
||||
return 1;
|
||||
}
|
||||
},
|
||||
browserDatePicker: true,
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
columnDef.suppressKeyboardEvent = (params: SuppressKeyboardEventParams) => {
|
||||
return GridColumnKeyboardUtils.suppressHomeAndEndKeyboardEvent(params);
|
||||
}
|
||||
}
|
||||
|
||||
if (column.displayPopup) {
|
||||
const renderer: ICellRendererFunc = columnDef.cellRenderer as ICellRendererFunc;
|
||||
columnDef.cellRenderer = GridValueRendererUtils.tooltipValueRenderer(renderer);
|
||||
}
|
||||
else if (column.columnTooltip) {
|
||||
columnDef.tooltipComponent = DefaultTooltip;
|
||||
columnDef.tooltipValueGetter = GridCellTooltipUtils.fixedValueTooltip(column.columnTooltip);
|
||||
}
|
||||
else if (!gridRef.suppressColumnTooltip) {
|
||||
columnDef.tooltipComponent = DefaultTooltip;
|
||||
columnDef.tooltipValueGetter = GridCellTooltipUtils.defaultFormattedTooltip(
|
||||
column.field ? column.field.type : null);
|
||||
}
|
||||
|
||||
return columnDef;
|
||||
}
|
||||
}
|
||||
|
|
@ -24,6 +24,7 @@ import {TokenInterceptor} from "./interceptor/token.interceptor.service";
|
|||
import {DropdownTreeViewComponent}from "../../account_applications/component/field/DropdownTreeViewComponent";
|
||||
import {DropdownTreeviewSelectComponent} from "../../account_applications/component/external/ngx-treeview/dropdown-treeview-select/dropdown-treeview-select.component";
|
||||
import {TreeviewModule} from "ngx-treeview";
|
||||
import {ErvuStaticGrid} from "../../account_applications/component/grid/ErvuStaticGrid";
|
||||
|
||||
registerLocaleData(localeRu);
|
||||
export const DIRECTIVES = [
|
||||
|
|
@ -34,7 +35,8 @@ export const DIRECTIVES = [
|
|||
forwardRef(() => VBoxLoadValues),
|
||||
forwardRef(() => DropdownTreeViewComponent),
|
||||
forwardRef(() => DropdownTreeviewSelectComponent),
|
||||
forwardRef(() => ErvuAccountTextFieldGridEditor)
|
||||
forwardRef(() => ErvuAccountTextFieldGridEditor),
|
||||
forwardRef(() => ErvuStaticGrid)
|
||||
];
|
||||
|
||||
@NgModule({
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue