1 | import {RowNode} from "../entities/rowNode";
|
2 | import {Column} from "../entities/column";
|
3 | import {Autowired, Bean, PostConstruct} from "../context/context";
|
4 | import {SortController} from "../sortController";
|
5 | import {_} from "../utils";
|
6 | import {ValueService} from "../valueService/valueService";
|
7 | import {GridOptionsWrapper} from "../gridOptionsWrapper";
|
8 | import {ColumnController} from "../columnController/columnController";
|
9 |
|
10 | export interface SortOption {
|
11 | inverter: number;
|
12 | column: Column;
|
13 | }
|
14 |
|
15 | export interface SortedRowNode {
|
16 | currentPos: number;
|
17 | rowNode: RowNode;
|
18 | }
|
19 |
|
20 | @Bean('sortService')
|
21 | export class SortService {
|
22 |
|
23 | @Autowired('sortController') private sortController: SortController;
|
24 | @Autowired('columnController') private columnController: ColumnController;
|
25 | @Autowired('valueService') private valueService: ValueService;
|
26 | @Autowired('gridOptionsWrapper') private gridOptionsWrapper: GridOptionsWrapper;
|
27 |
|
28 | private postSortFunc: (rowNodes: RowNode[]) => void;
|
29 |
|
30 | @PostConstruct
|
31 | public init(): void {
|
32 | this.postSortFunc = this.gridOptionsWrapper.getPostSortFunc();
|
33 | }
|
34 |
|
35 | public sortAccordingToColumnsState(rowNode: RowNode) {
|
36 | let sortOptions: SortOption[] = this.sortController.getSortForRowController();
|
37 | this.sort(rowNode, sortOptions);
|
38 | }
|
39 |
|
40 | public sort(rowNode: RowNode, sortOptions: SortOption[]) {
|
41 | rowNode.childrenAfterSort = rowNode.childrenAfterFilter.slice(0);
|
42 |
|
43 |
|
44 | this.pullDownDataForHideOpenParents(rowNode, true);
|
45 |
|
46 | let sortActive = _.exists(sortOptions) && sortOptions.length > 0;
|
47 | if (sortActive) {
|
48 |
|
49 |
|
50 |
|
51 |
|
52 |
|
53 | let sortedRowNodes: SortedRowNode[] = rowNode.childrenAfterSort.map((it, pos) => {
|
54 | return {currentPos: pos, rowNode: it};
|
55 | });
|
56 | sortedRowNodes.sort(this.compareRowNodes.bind(this, sortOptions));
|
57 | rowNode.childrenAfterSort = sortedRowNodes.map(sorted => sorted.rowNode);
|
58 | }
|
59 |
|
60 | this.updateChildIndexes(rowNode);
|
61 | this.pullDownDataForHideOpenParents(rowNode, false);
|
62 |
|
63 |
|
64 | rowNode.childrenAfterFilter.forEach(child => {
|
65 | if (child.hasChildren()) {
|
66 | this.sort(child, sortOptions);
|
67 | }
|
68 | });
|
69 |
|
70 | if (this.postSortFunc) {
|
71 | this.postSortFunc(rowNode.childrenAfterSort);
|
72 | }
|
73 | }
|
74 |
|
75 | private compareRowNodes(sortOptions: any, sortedNodeA: SortedRowNode, sortedNodeB: SortedRowNode) {
|
76 | let nodeA: RowNode = sortedNodeA.rowNode;
|
77 | let nodeB: RowNode = sortedNodeB.rowNode;
|
78 |
|
79 |
|
80 | for (let i = 0, len = sortOptions.length; i < len; i++) {
|
81 | let sortOption = sortOptions[i];
|
82 |
|
83 |
|
84 | let isInverted = sortOption.inverter === -1;
|
85 | let valueA: any = this.getValue(nodeA, sortOption.column);
|
86 | let valueB: any = this.getValue(nodeB, sortOption.column);
|
87 | let comparatorResult: number;
|
88 | if (sortOption.column.getColDef().comparator) {
|
89 |
|
90 | comparatorResult = sortOption.column.getColDef().comparator(valueA, valueB, nodeA, nodeB, isInverted);
|
91 | } else {
|
92 |
|
93 | comparatorResult = _.defaultComparator(valueA, valueB, this.gridOptionsWrapper.isAccentedSort());
|
94 | }
|
95 |
|
96 | if (comparatorResult !== 0) {
|
97 | return comparatorResult * sortOption.inverter;
|
98 | }
|
99 | }
|
100 |
|
101 | return sortedNodeA.currentPos - sortedNodeB.currentPos;
|
102 | }
|
103 |
|
104 | private getValue(nodeA: RowNode, column: Column): string {
|
105 | return this.valueService.getValue(column, nodeA);
|
106 | }
|
107 |
|
108 | private updateChildIndexes(rowNode: RowNode) {
|
109 | if (_.missing(rowNode.childrenAfterSort)) {
|
110 | return;
|
111 | }
|
112 |
|
113 | rowNode.childrenAfterSort.forEach((child: RowNode, index: number) => {
|
114 | let firstChild = index === 0;
|
115 | let lastChild = index === rowNode.childrenAfterSort.length - 1;
|
116 | child.setFirstChild(firstChild);
|
117 | child.setLastChild(lastChild);
|
118 | child.setChildIndex(index);
|
119 | });
|
120 | }
|
121 |
|
122 | private pullDownDataForHideOpenParents(rowNode: RowNode, clearOperation: boolean) {
|
123 | if (_.missing(rowNode.childrenAfterSort)) {
|
124 | return;
|
125 | }
|
126 |
|
127 | if (!this.gridOptionsWrapper.isGroupHideOpenParents()) {
|
128 | return;
|
129 | }
|
130 |
|
131 | rowNode.childrenAfterSort.forEach( childRowNode => {
|
132 |
|
133 | let groupDisplayCols = this.columnController.getGroupDisplayColumns();
|
134 | groupDisplayCols.forEach( groupDisplayCol => {
|
135 |
|
136 | let showRowGroup = groupDisplayCol.getColDef().showRowGroup;
|
137 | if (typeof showRowGroup !== 'string') {
|
138 | console.error('ag-Grid: groupHideOpenParents only works when specifying specific columns for colDef.showRowGroup');
|
139 | return;
|
140 | }
|
141 | let displayingGroupKey: string = <string> showRowGroup;
|
142 |
|
143 | let rowGroupColumn = this.columnController.getPrimaryColumn(displayingGroupKey);
|
144 |
|
145 | let thisRowNodeMatches = rowGroupColumn === childRowNode.rowGroupColumn;
|
146 | if (thisRowNodeMatches) { return; }
|
147 |
|
148 | if (clearOperation) {
|
149 |
|
150 | childRowNode.setGroupValue(groupDisplayCol.getId(), null);
|
151 | } else {
|
152 |
|
153 | let parentToStealFrom = childRowNode.getFirstChildOfFirstChild(rowGroupColumn);
|
154 | if (parentToStealFrom) {
|
155 | childRowNode.setGroupValue(groupDisplayCol.getId(), parentToStealFrom.key);
|
156 | }
|
157 | }
|
158 | });
|
159 | });
|
160 | }
|
161 |
|
162 | } |
\ | No newline at end of file |