1 | import {Bean, Autowired, PostConstruct} from "./context/context";
|
2 | import {
|
3 | GridSerializer, RowAccumulator, BaseGridSerializingSession, RowSpanningAccumulator,
|
4 | GridSerializingSession
|
5 | } from "./gridSerializer";
|
6 | import {Downloader} from "./downloader";
|
7 | import {Column} from "./entities/column";
|
8 | import {RowNode} from "./entities/rowNode";
|
9 | import {ColumnController} from "./columnController/columnController";
|
10 | import {ValueService} from "./valueService/valueService";
|
11 | import {GridOptionsWrapper} from "./gridOptionsWrapper";
|
12 | import {
|
13 | BaseExportParams, CsvExportParams, ExportParams, ProcessCellForExportParams,
|
14 | ProcessHeaderForExportParams
|
15 | } from "./exportParams";
|
16 | import {Constants} from "./constants";
|
17 | import {_} from "./utils";
|
18 |
|
19 | let LINE_SEPARATOR = '\r\n';
|
20 |
|
21 | export class CsvSerializingSession extends BaseGridSerializingSession<string> {
|
22 | private result:string = '';
|
23 | private lineOpened:boolean = false;
|
24 |
|
25 | constructor(
|
26 | columnController: ColumnController,
|
27 | valueService: ValueService,
|
28 | gridOptionsWrapper: GridOptionsWrapper,
|
29 | processCellCallback:(params: ProcessCellForExportParams)=>string,
|
30 | processHeaderCallback:(params: ProcessHeaderForExportParams)=>string,
|
31 | private suppressQuotes: boolean,
|
32 | private columnSeparator: string
|
33 | ){
|
34 | super(columnController, valueService, gridOptionsWrapper, processCellCallback, processHeaderCallback);
|
35 | }
|
36 |
|
37 | public prepare(columnsToExport: Column[]): void {
|
38 | }
|
39 |
|
40 | public addCustomHeader(customHeader: string): void {
|
41 | if (!customHeader) return;
|
42 | this.result += customHeader + LINE_SEPARATOR;
|
43 | }
|
44 |
|
45 | public addCustomFooter(customFooter: string): void {
|
46 | if (!customFooter) return;
|
47 | this.result += customFooter + LINE_SEPARATOR;
|
48 | }
|
49 |
|
50 | public onNewHeaderGroupingRow(): RowSpanningAccumulator {
|
51 | if(this.lineOpened) this.result += LINE_SEPARATOR;
|
52 |
|
53 | return {
|
54 | onColumn: this.onNewHeaderGroupingRowColumn.bind(this)
|
55 | };
|
56 | }
|
57 |
|
58 | private onNewHeaderGroupingRowColumn (header: string, index: number, span:number) {
|
59 | if (index != 0) {
|
60 | this.result += this.columnSeparator;
|
61 | }
|
62 |
|
63 | this.result += header;
|
64 | for (let i = 1; i<= span; i++){
|
65 | this.result += this.columnSeparator + this.putInQuotes("", this.suppressQuotes);
|
66 | }
|
67 | this.lineOpened = true;
|
68 | }
|
69 |
|
70 | public onNewHeaderRow(): RowAccumulator {
|
71 | if(this.lineOpened) this.result += LINE_SEPARATOR;
|
72 |
|
73 | return {
|
74 | onColumn:this.onNewHeaderRowColumn.bind(this)
|
75 | };
|
76 | }
|
77 |
|
78 | private onNewHeaderRowColumn(column: Column, index: number, node?:RowNode):void{
|
79 | if (index != 0) {
|
80 | this.result += this.columnSeparator;
|
81 | }
|
82 | this.result += this.putInQuotes(this.extractHeaderValue(column), this.suppressQuotes);
|
83 | this.lineOpened = true;
|
84 | }
|
85 |
|
86 | public onNewBodyRow(): RowAccumulator {
|
87 | if(this.lineOpened) this.result += LINE_SEPARATOR;
|
88 |
|
89 | return {
|
90 | onColumn: this.onNewBodyRowColumn.bind(this)
|
91 | };
|
92 | }
|
93 |
|
94 | private onNewBodyRowColumn (column: Column, index: number, node?:RowNode):void{
|
95 | if (index != 0) {
|
96 | this.result += this.columnSeparator;
|
97 | }
|
98 | this.result += this.putInQuotes(this.extractRowCellValue(column, index, Constants.EXPORT_TYPE_CSV, node), this.suppressQuotes);
|
99 | this.lineOpened = true;
|
100 | }
|
101 |
|
102 |
|
103 | private putInQuotes(value: any, suppressQuotes: boolean): string {
|
104 | if (suppressQuotes) { return value; }
|
105 |
|
106 | if (value === null || value === undefined) {
|
107 | return '""';
|
108 | }
|
109 |
|
110 | let stringValue: string;
|
111 | if (typeof value === 'string') {
|
112 | stringValue = value;
|
113 | } else if (typeof value.toString === 'function') {
|
114 | stringValue = value.toString();
|
115 | } else {
|
116 | console.warn('unknown value type during csv conversion');
|
117 | stringValue = '';
|
118 | }
|
119 |
|
120 |
|
121 | let valueEscaped = stringValue.replace(/"/g, "\"\"");
|
122 |
|
123 | return '"' + valueEscaped + '"';
|
124 | }
|
125 |
|
126 | public parse(): string {
|
127 | return this.result;
|
128 | }
|
129 | }
|
130 |
|
131 | export interface BaseCreatorBeans {
|
132 | downloader: Downloader;
|
133 | gridSerializer: GridSerializer;
|
134 | gridOptionsWrapper: GridOptionsWrapper;
|
135 | }
|
136 |
|
137 | export abstract class BaseCreator<T, S extends GridSerializingSession<T>, P extends ExportParams<T>> {
|
138 |
|
139 | private beans: BaseCreatorBeans;
|
140 |
|
141 | protected setBeans(beans: BaseCreatorBeans) {
|
142 | this.beans = beans;
|
143 | }
|
144 |
|
145 | public export(userParams?: P): string {
|
146 | if (this.isExportSuppressed()){
|
147 | console.warn(`ag-grid: Export canceled. Export is not allowed as per your configuration.`);
|
148 | return "";
|
149 | }
|
150 | let {mergedParams, data} = this.getMergedParamsAndData(userParams);
|
151 |
|
152 | let fileNamePresent = mergedParams && mergedParams.fileName && mergedParams.fileName.length !== 0;
|
153 | let fileName = fileNamePresent ? mergedParams.fileName : this.getDefaultFileName();
|
154 |
|
155 | if (fileName.indexOf(".") === -1){
|
156 | fileName = fileName + "." + this.getDefaultFileExtension();
|
157 | }
|
158 |
|
159 | this.beans.downloader.download(
|
160 | fileName,
|
161 | data,
|
162 | this.getMimeType()
|
163 | );
|
164 | return data;
|
165 | }
|
166 |
|
167 | public getData (params:P):string{
|
168 | return this.getMergedParamsAndData(params).data
|
169 | }
|
170 |
|
171 | private getMergedParamsAndData(userParams: P):{mergedParams:P, data:string} {
|
172 | let mergedParams = this.mergeDefaultParams(userParams);
|
173 | let data = this.beans.gridSerializer.serialize(this.createSerializingSession(mergedParams), mergedParams);
|
174 | return {mergedParams, data};
|
175 | }
|
176 |
|
177 | private mergeDefaultParams(userParams: P):P {
|
178 | let baseParams: BaseExportParams = this.beans.gridOptionsWrapper.getDefaultExportParams();
|
179 | let params: P = <any>{};
|
180 | _.assign(params, baseParams);
|
181 | _.assign(params, userParams);
|
182 | return params;
|
183 | }
|
184 | public abstract createSerializingSession(params?: P):S;
|
185 | public abstract getMimeType():string;
|
186 | public abstract getDefaultFileName ():string;
|
187 | public abstract getDefaultFileExtension ():string;
|
188 | public abstract isExportSuppressed ():boolean;
|
189 | }
|
190 |
|
191 | @Bean('csvCreator')
|
192 | export class CsvCreator extends BaseCreator<string, CsvSerializingSession, CsvExportParams>{
|
193 |
|
194 | @Autowired('columnController') private columnController: ColumnController;
|
195 | @Autowired('valueService') private valueService: ValueService;
|
196 |
|
197 | @Autowired('downloader') private downloader: Downloader;
|
198 | @Autowired('gridSerializer') private gridSerializer: GridSerializer;
|
199 | @Autowired('gridOptionsWrapper') gridOptionsWrapper: GridOptionsWrapper;
|
200 |
|
201 | @PostConstruct
|
202 | public postConstruct(): void {
|
203 | this.setBeans({
|
204 | downloader: this.downloader,
|
205 | gridSerializer: this.gridSerializer,
|
206 | gridOptionsWrapper: this.gridOptionsWrapper
|
207 | });
|
208 | }
|
209 |
|
210 | public exportDataAsCsv(params?: CsvExportParams): string {
|
211 | return this.export(params);
|
212 | }
|
213 |
|
214 | public getDataAsCsv (params?: CsvExportParams): string {
|
215 | return this.getData(params);
|
216 | }
|
217 |
|
218 |
|
219 | public getMimeType(): string {
|
220 | return "text/csv;charset=utf-8;"
|
221 | }
|
222 |
|
223 | public getDefaultFileName(): string {
|
224 | return 'export.csv';
|
225 | }
|
226 |
|
227 | public getDefaultFileExtension(): string {
|
228 | return 'csv';
|
229 | }
|
230 |
|
231 | public createSerializingSession(params?:CsvExportParams): CsvSerializingSession{
|
232 | return new CsvSerializingSession(
|
233 | this.columnController,
|
234 | this.valueService,
|
235 | this.gridOptionsWrapper,
|
236 | params ? params.processCellCallback : null,
|
237 | params ? params.processHeaderCallback : null,
|
238 | params && params.suppressQuotes,
|
239 | (params && params.columnSeparator) || ','
|
240 | )
|
241 | }
|
242 |
|
243 | public isExportSuppressed ():boolean{
|
244 | return this.gridOptionsWrapper.isSuppressCsvExport();
|
245 | }
|
246 | }
|