1 | import {Column} from "./entities/column";
|
2 | import {Autowired, Bean} from "./context/context";
|
3 | import {ColumnController} from "./columnController/columnController";
|
4 | import {Constants} from "./constants";
|
5 | import {IRowModel} from "./interfaces/iRowModel";
|
6 | import {Utils as _} from "./utils";
|
7 | import {RowNode} from "./entities/rowNode";
|
8 | import {SelectionController} from "./selectionController";
|
9 | import {ValueService} from "./valueService/valueService";
|
10 | import {GridOptionsWrapper} from "./gridOptionsWrapper";
|
11 | import {
|
12 | BaseExportParams,
|
13 | ExportParams,
|
14 | ProcessCellForExportParams,
|
15 | ProcessHeaderForExportParams,
|
16 | ShouldRowBeSkippedParams
|
17 | } from "./exportParams";
|
18 | import {DisplayedGroupCreator} from "./columnController/displayedGroupCreator";
|
19 | import {BalancedColumnTreeBuilder} from "./columnController/balancedColumnTreeBuilder";
|
20 | import {GroupInstanceIdCreator} from "./columnController/groupInstanceIdCreator";
|
21 | import {ColumnGroupChild} from "./entities/columnGroupChild";
|
22 | import {ColumnGroup} from "./entities/columnGroup";
|
23 | import {GridApi} from "./gridApi";
|
24 | import {ClientSideRowModel} from "./rowModels/clientSide/clientSideRowModel";
|
25 | import {PinnedRowModel} from "./rowModels/pinnedRowModel";
|
26 |
|
27 |
|
28 |
|
29 |
|
30 |
|
31 |
|
32 |
|
33 |
|
34 |
|
35 |
|
36 |
|
37 |
|
38 |
|
39 |
|
40 |
|
41 |
|
42 |
|
43 |
|
44 |
|
45 |
|
46 |
|
47 |
|
48 |
|
49 |
|
50 |
|
51 |
|
52 | export interface GridSerializingSession<T> {
|
53 | |
54 |
|
55 |
|
56 | prepare(columnsToExport: Column[]) : void;
|
57 |
|
58 |
|
59 | |
60 |
|
61 |
|
62 | addCustomHeader(customHeader: T): void;
|
63 |
|
64 | onNewHeaderGroupingRow ():RowSpanningAccumulator;
|
65 |
|
66 | onNewHeaderRow (): RowAccumulator;
|
67 |
|
68 | onNewBodyRow (): RowAccumulator;
|
69 |
|
70 | addCustomFooter(customFooter: T): void;
|
71 |
|
72 | |
73 |
|
74 |
|
75 | parse (): string;
|
76 | }
|
77 |
|
78 | export interface RowAccumulator {
|
79 | onColumn(column: Column, index: number, node?:RowNode):void;
|
80 | }
|
81 |
|
82 | export interface RowSpanningAccumulator {
|
83 | onColumn(header: string, index: number, span:number):void;
|
84 | }
|
85 |
|
86 | export abstract class BaseGridSerializingSession<T> implements GridSerializingSession<T>{
|
87 | constructor(
|
88 | public columnController:ColumnController,
|
89 | public valueService:ValueService,
|
90 | public gridOptionsWrapper:GridOptionsWrapper,
|
91 | public processCellCallback?:(params: ProcessCellForExportParams)=>string,
|
92 | public processHeaderCallback?:(params: ProcessHeaderForExportParams)=>string,
|
93 | public cellAndHeaderEscaper?:(rawValue:string)=>string
|
94 | ){}
|
95 |
|
96 | abstract prepare(columnsToExport: Column[]) : void;
|
97 |
|
98 | abstract addCustomHeader(customHeader: T): void;
|
99 |
|
100 | abstract addCustomFooter(customFooter: T): void;
|
101 |
|
102 | abstract onNewHeaderGroupingRow (): RowSpanningAccumulator;
|
103 |
|
104 | abstract onNewHeaderRow (): RowAccumulator;
|
105 |
|
106 | abstract onNewBodyRow (): RowAccumulator;
|
107 |
|
108 | abstract parse (): string;
|
109 |
|
110 | public extractHeaderValue(column: Column): string {
|
111 | let nameForCol = this.getHeaderName(this.processHeaderCallback, column);
|
112 | if (nameForCol === null || nameForCol === undefined) {
|
113 | nameForCol = '';
|
114 | }
|
115 | return this.cellAndHeaderEscaper? this.cellAndHeaderEscaper(nameForCol) : nameForCol;
|
116 | }
|
117 |
|
118 | public extractRowCellValue (column: Column, index: number, type: string, node?:RowNode){
|
119 | let isRowGrouping = this.columnController.getRowGroupColumns().length > 0;
|
120 |
|
121 | let valueForCell: any;
|
122 | if (node.group && isRowGrouping && index === 0) {
|
123 | valueForCell = this.createValueForGroupNode(node);
|
124 | } else {
|
125 | valueForCell = this.valueService.getValue(column, node);
|
126 | }
|
127 | valueForCell = this.processCell(node, column, valueForCell, this.processCellCallback, type);
|
128 | if (valueForCell === null || valueForCell === undefined) {
|
129 | valueForCell = '';
|
130 | }
|
131 |
|
132 | return this.cellAndHeaderEscaper? this.cellAndHeaderEscaper(valueForCell) : valueForCell;
|
133 | }
|
134 |
|
135 | private getHeaderName(callback: (params: ProcessHeaderForExportParams)=>string, column: Column): string {
|
136 | if (callback) {
|
137 | return callback({
|
138 | column: column,
|
139 | api: this.gridOptionsWrapper.getApi(),
|
140 | columnApi: this.gridOptionsWrapper.getColumnApi(),
|
141 | context: this.gridOptionsWrapper.getContext()
|
142 | });
|
143 | } else {
|
144 | return this.columnController.getDisplayNameForColumn(column, 'csv', true);
|
145 | }
|
146 | }
|
147 |
|
148 |
|
149 | private createValueForGroupNode(node: RowNode): string {
|
150 | let keys = [node.key];
|
151 | while (node.parent) {
|
152 | node = node.parent;
|
153 | keys.push(node.key);
|
154 | }
|
155 | return keys.reverse().join(' -> ');
|
156 | }
|
157 |
|
158 | private processCell(rowNode: RowNode, column: Column, value: any, processCellCallback:(params: ProcessCellForExportParams)=>string, type: string): any {
|
159 | if (processCellCallback) {
|
160 | return processCellCallback({
|
161 | column: column,
|
162 | node: rowNode,
|
163 | value: value,
|
164 | api: this.gridOptionsWrapper.getApi(),
|
165 | columnApi: this.gridOptionsWrapper.getColumnApi(),
|
166 | context: this.gridOptionsWrapper.getContext(),
|
167 | type: type
|
168 | });
|
169 | } else {
|
170 | return value;
|
171 | }
|
172 | }
|
173 | }
|
174 |
|
175 |
|
176 |
|
177 | @Bean("gridSerializer")
|
178 | export class GridSerializer {
|
179 | @Autowired('displayedGroupCreator') private displayedGroupCreator: DisplayedGroupCreator;
|
180 | @Autowired('columnController') private columnController: ColumnController;
|
181 | @Autowired('rowModel') private rowModel: IRowModel;
|
182 | @Autowired('pinnedRowModel') private pinnedRowModel: PinnedRowModel;
|
183 | @Autowired('selectionController') private selectionController: SelectionController;
|
184 | @Autowired('balancedColumnTreeBuilder') private balancedColumnTreeBuilder: BalancedColumnTreeBuilder;
|
185 | @Autowired('gridOptionsWrapper') private gridOptionsWrapper: GridOptionsWrapper;
|
186 |
|
187 | public serialize<T>(gridSerializingSession: GridSerializingSession<T>, params?: ExportParams<T>): string {
|
188 |
|
189 | let dontSkipRows= (): boolean =>false;
|
190 |
|
191 | let skipGroups = params && params.skipGroups;
|
192 | let skipHeader = params && params.skipHeader;
|
193 | let columnGroups = params && params.columnGroups;
|
194 | let skipFooters = params && params.skipFooters;
|
195 | let skipPinnedTop = params && params.skipPinnedTop;
|
196 | let skipPinnedBottom = params && params.skipPinnedBottom;
|
197 | let includeCustomHeader = params && params.customHeader;
|
198 | let includeCustomFooter = params && params.customFooter;
|
199 | let allColumns = params && params.allColumns;
|
200 | let onlySelected = params && params.onlySelected;
|
201 | let columnKeys = params && params.columnKeys;
|
202 | let onlySelectedAllPages = params && params.onlySelectedAllPages;
|
203 | let rowSkipper:(params: ShouldRowBeSkippedParams)=> boolean = (params && params.shouldRowBeSkipped) || dontSkipRows;
|
204 | let api:GridApi = this.gridOptionsWrapper.getApi();
|
205 | let context:any = this.gridOptionsWrapper.getContext();
|
206 |
|
207 |
|
208 | let isPivotMode = this.columnController.isPivotMode();
|
209 | let rowModelNormal = this.rowModel.getType() === Constants.ROW_MODEL_TYPE_CLIENT_SIDE;
|
210 |
|
211 | let onlySelectedNonStandardModel = !rowModelNormal && onlySelected;
|
212 |
|
213 |
|
214 | let columnsToExport: Column[];
|
215 | if (_.existsAndNotEmpty(columnKeys)) {
|
216 | columnsToExport = this.columnController.getGridColumns(columnKeys);
|
217 | } else if (allColumns && !isPivotMode) {
|
218 | columnsToExport = this.columnController.getAllPrimaryColumns();
|
219 | } else {
|
220 | columnsToExport = this.columnController.getAllDisplayedColumns();
|
221 | }
|
222 |
|
223 | if (!columnsToExport || columnsToExport.length === 0) {
|
224 | return '';
|
225 | }
|
226 |
|
227 | gridSerializingSession.prepare(columnsToExport);
|
228 |
|
229 | if (includeCustomHeader) {
|
230 | gridSerializingSession.addCustomHeader (params.customHeader);
|
231 | }
|
232 |
|
233 |
|
234 | if (columnGroups) {
|
235 | let groupInstanceIdCreator: GroupInstanceIdCreator = new GroupInstanceIdCreator();
|
236 | let displayedGroups: ColumnGroupChild[] = this.displayedGroupCreator.createDisplayedGroups(
|
237 | columnsToExport,
|
238 | this.columnController.getGridBalancedTree(),
|
239 | groupInstanceIdCreator
|
240 | );
|
241 | this.recursivelyAddHeaderGroups(displayedGroups, gridSerializingSession);
|
242 | }
|
243 |
|
244 | if (!skipHeader){
|
245 | let gridRowIterator = gridSerializingSession.onNewHeaderRow();
|
246 | columnsToExport.forEach((column, index)=>{
|
247 | gridRowIterator.onColumn (column, index, null)
|
248 | });
|
249 | }
|
250 |
|
251 | this.pinnedRowModel.forEachPinnedTopRow(processRow);
|
252 |
|
253 | if (isPivotMode) {
|
254 | if ((<any>this.rowModel).forEachPivotNode){
|
255 | (<ClientSideRowModel>this.rowModel).forEachPivotNode(processRow);
|
256 | } else{
|
257 |
|
258 | this.rowModel.forEachNode(processRow);
|
259 | }
|
260 | } else {
|
261 |
|
262 |
|
263 |
|
264 |
|
265 |
|
266 | if (onlySelectedAllPages || onlySelectedNonStandardModel) {
|
267 | let selectedNodes = this.selectionController.getSelectedNodes();
|
268 | selectedNodes.forEach((node:RowNode)=>{
|
269 | processRow(node)
|
270 | });
|
271 | } else {
|
272 |
|
273 |
|
274 |
|
275 | if (rowModelNormal){
|
276 | (<ClientSideRowModel>this.rowModel).forEachNodeAfterFilterAndSort(processRow);
|
277 | } else {
|
278 | this.rowModel.forEachNode(processRow);
|
279 | }
|
280 | }
|
281 | }
|
282 |
|
283 | this.pinnedRowModel.forEachPinnedBottomRow(processRow);
|
284 |
|
285 | if (includeCustomFooter) {
|
286 | gridSerializingSession.addCustomFooter (params.customFooter);
|
287 | }
|
288 |
|
289 | function processRow(node: RowNode): void {
|
290 | if (skipGroups && node.group) {
|
291 | return;
|
292 | }
|
293 |
|
294 | if (skipFooters && node.footer) {
|
295 | return;
|
296 | }
|
297 |
|
298 | if (onlySelected && !node.isSelected()) {
|
299 | return;
|
300 | }
|
301 |
|
302 | if (skipPinnedTop && node.rowPinned === 'top') {
|
303 | return;
|
304 | }
|
305 |
|
306 | if (skipPinnedBottom && node.rowPinned === 'bottom') {
|
307 | return;
|
308 | }
|
309 |
|
310 |
|
311 |
|
312 | let nodeIsRootNode = node.level === -1;
|
313 | if (nodeIsRootNode && !node.leafGroup) {
|
314 | return;
|
315 | }
|
316 |
|
317 | let shouldRowBeSkipped:boolean = rowSkipper({
|
318 | node: node,
|
319 | api: api,
|
320 | context: context
|
321 | });
|
322 |
|
323 | if (shouldRowBeSkipped) return;
|
324 |
|
325 | let rowAccumulator: RowAccumulator = gridSerializingSession.onNewBodyRow();
|
326 | columnsToExport.forEach((column: Column, index: number) => {
|
327 | rowAccumulator.onColumn(column, index, node);
|
328 | });
|
329 | }
|
330 |
|
331 | return gridSerializingSession.parse();
|
332 | }
|
333 |
|
334 | recursivelyAddHeaderGroups<T> (displayedGroups:ColumnGroupChild[], gridSerializingSession:GridSerializingSession<T>):void{
|
335 | let directChildrenHeaderGroups:ColumnGroupChild[] = [];
|
336 | displayedGroups.forEach((columnGroupChild: ColumnGroupChild) => {
|
337 | let columnGroup: ColumnGroup = columnGroupChild as ColumnGroup;
|
338 | if (!columnGroup.getChildren) return;
|
339 | columnGroup.getChildren().forEach(it=>directChildrenHeaderGroups.push(it));
|
340 | });
|
341 |
|
342 | if (displayedGroups.length > 0 && displayedGroups[0] instanceof ColumnGroup) {
|
343 | this.doAddHeaderHeader(gridSerializingSession, displayedGroups);
|
344 | }
|
345 |
|
346 | if (directChildrenHeaderGroups && directChildrenHeaderGroups.length > 0){
|
347 | this.recursivelyAddHeaderGroups(directChildrenHeaderGroups, gridSerializingSession);
|
348 | }
|
349 | }
|
350 |
|
351 | private doAddHeaderHeader<T>(gridSerializingSession: GridSerializingSession<T>, displayedGroups: ColumnGroupChild[]) {
|
352 | let gridRowIterator: RowSpanningAccumulator = gridSerializingSession.onNewHeaderGroupingRow();
|
353 | let columnIndex: number = 0;
|
354 | displayedGroups.forEach((columnGroupChild: ColumnGroupChild) => {
|
355 | let columnGroup: ColumnGroup = columnGroupChild as ColumnGroup;
|
356 | let colDef = columnGroup.getDefinition();
|
357 |
|
358 | let columnName = this.columnController.getDisplayNameForColumnGroup(columnGroup, 'header');
|
359 | gridRowIterator.onColumn(columnName, columnIndex++, columnGroup.getLeafColumns().length - 1);
|
360 | });
|
361 | }
|
362 | }
|
363 |
|
364 | export enum RowType {
|
365 | HEADER_GROUPING, HEADER, BODY
|
366 | } |
\ | No newline at end of file |