Skip to content

Commit a057970

Browse files
committed
[DSC-867] fix issue with ExportAsService during SSR
1 parent 18821b7 commit a057970

13 files changed

Lines changed: 169 additions & 144 deletions
Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
import { ExportAsConfig, ExportAsService } from 'ngx-export-as';
2+
import { toJpeg, toPng } from 'html-to-image';
3+
import { Options } from 'html-to-image/es/types';
4+
import { saveAs } from 'file-saver';
5+
import { BehaviorSubject } from 'rxjs';
6+
7+
import { ExportImageType, ExportService } from './export.service';
8+
9+
/**
10+
* IMPORTANT
11+
* Due to a problem occurring on SSR with the ExportAsService dependency, which use window object, this service can't be injected.
12+
* So we need to instantiate the class directly based on current the platform whn is needed
13+
* TODO To be refactored when https://github.com/wnabil/ngx-export-as/pull/112 is fixed
14+
*/
15+
export class BrowserExportService implements ExportService {
16+
17+
/**
18+
* Configuration for CSV export process
19+
*/
20+
exportAsConfig: ExportAsConfig;
21+
22+
/**
23+
* Creates excel from the table element reference.
24+
*
25+
* @param type of export.
26+
* @param fileName is the file name to save as.
27+
* @param elementIdOrContent is the content that is being exported.
28+
* @param download option if it's going to be downloaded.
29+
*/
30+
exportAsFile(type: any, elementIdOrContent: string, fileName: string, download: boolean = true) {
31+
32+
this.exportAsConfig = {
33+
type:type,
34+
elementIdOrContent: elementIdOrContent,
35+
fileName:fileName,
36+
download:download
37+
};
38+
39+
const exportAsService: ExportAsService = new ExportAsService();
40+
return exportAsService.save(this.exportAsConfig, fileName);
41+
}
42+
43+
/**
44+
* Creates an image from the given element reference.
45+
*
46+
* @param domNode The HTMLElement.
47+
* @param type The type of image to export.
48+
* @param fileName The file name to save as.
49+
* @param isLoading A boolean representing the exporting process status.
50+
*/
51+
exportAsImage(domNode: HTMLElement, type: ExportImageType, fileName: string, isLoading: BehaviorSubject<boolean>): void {
52+
53+
const options: Options = { backgroundColor: '#ffffff' };
54+
55+
if (type === ExportImageType.png) {
56+
toPng(domNode, options)
57+
.then((dataUrl) => {
58+
saveAs(dataUrl, fileName + '.' + type);
59+
isLoading.next(false);
60+
});
61+
} else {
62+
toJpeg(domNode, options)
63+
.then((dataUrl) => {
64+
saveAs(dataUrl, fileName + '.' + type);
65+
isLoading.next(false);
66+
});
67+
}
68+
69+
}
70+
71+
}
Lines changed: 4 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -1,45 +1,21 @@
1-
import { Injectable } from '@angular/core';
2-
3-
import { ExportAsConfig, ExportAsService } from 'ngx-export-as';
4-
import { toJpeg, toPng } from 'html-to-image';
5-
import { Options } from 'html-to-image/es/types';
6-
import { saveAs } from 'file-saver';
71
import { BehaviorSubject } from 'rxjs';
82

93
export enum ExportImageType {
104
png = 'png',
115
jpeg = 'jpeg',
126
}
137

14-
@Injectable()
15-
export class ExportService {
16-
17-
/**
18-
* Configuration for CSV export process
19-
*/
20-
exportAsConfig: ExportAsConfig;
21-
22-
constructor(private exportAsService: ExportAsService) { }
8+
export interface ExportService {
239

2410
/**
2511
* Creates excel from the table element reference.
2612
*
2713
* @param type of export.
2814
* @param fileName is the file name to save as.
2915
* @param elementIdOrContent is the content that is being exported.
30-
* @param download option if its going to be downloaded.
16+
* @param download option if it's going to be downloaded.
3117
*/
32-
exportAsFile(type: any, elementIdOrContent: string, fileName: string, download: boolean = true) {
33-
34-
this.exportAsConfig = {
35-
type:type,
36-
elementIdOrContent: elementIdOrContent,
37-
fileName:fileName,
38-
download:download
39-
};
40-
41-
return this.exportAsService.save(this.exportAsConfig, fileName);
42-
}
18+
exportAsFile(type: any, elementIdOrContent: string, fileName: string, download?: boolean);
4319

4420
/**
4521
* Creates an image from the given element reference.
@@ -49,24 +25,5 @@ export class ExportService {
4925
* @param fileName The file name to save as.
5026
* @param isLoading A boolean representing the exporting process status.
5127
*/
52-
exportAsImage(domNode: HTMLElement, type: ExportImageType, fileName: string, isLoading: BehaviorSubject<boolean>): void {
53-
54-
const options: Options = { backgroundColor: '#ffffff' };
55-
56-
if (type === ExportImageType.png) {
57-
toPng(domNode, options)
58-
.then((dataUrl) => {
59-
saveAs(dataUrl, fileName + '.' + type);
60-
isLoading.next(false);
61-
});
62-
} else {
63-
toJpeg(domNode, options)
64-
.then((dataUrl) => {
65-
saveAs(dataUrl, fileName + '.' + type);
66-
isLoading.next(false);
67-
});
68-
}
69-
70-
}
71-
28+
exportAsImage(domNode: HTMLElement, type: ExportImageType, fileName: string, isLoading: BehaviorSubject<boolean>);
7229
}

src/app/core/export-service/server-export.service.ts

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,15 @@
1-
import { Injectable } from '@angular/core';
2-
31
import { BehaviorSubject } from 'rxjs';
42

5-
import { ExportImageType } from './export.service';
3+
import { ExportImageType, ExportService } from './export.service';
64

7-
@Injectable()
8-
export class ServerExportService {
5+
export class ServerExportService implements ExportService {
96
/**
107
* Creates excel from the table element reference.
118
*
129
* @param type of export.
1310
* @param fileName is the file name to save as.
1411
* @param elementIdOrContent is the content that is being exported.
15-
* @param download option if its going to be downloaded.
12+
* @param download option if it'ss going to be downloaded.
1613
*/
1714
exportAsFile(type: any, elementIdOrContent: string, fileName: string, download: boolean = true) {
1815
return;

src/app/statistics-page/cris-statistics-page/statistics-chart/statistics-chart-bar/statistics-chart-bar.component.html

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,8 +10,7 @@
1010
</div>
1111

1212
<div #chartRef id="chart" class="d-flex w-100 search-chart-container" *ngIf="(results | async) && (results | async).length > 0; else noData">
13-
<ds-chart [results]="results" [view]="view" [type]='chartType.BAR'
14-
(select)="select($event)"></ds-chart>
13+
<ds-chart [results]="results" [view]="view" [type]='chartType.BAR'></ds-chart>
1514
</div>
1615
<ng-template #noData>
1716
<ds-alert [type]="'alert-info'" [content]="'search.filters.applied.charts.no.data.found'"></ds-alert>

src/app/statistics-page/cris-statistics-page/statistics-chart/statistics-chart-bar/statistics-chart-bar.component.ts

Lines changed: 14 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,14 @@
1-
import { Component } from '@angular/core';
1+
import { Component, Inject, PLATFORM_ID } from '@angular/core';
2+
3+
import { Observable, of } from 'rxjs';
24

35
import { StatisticsType } from '../../statistics-type.model';
46
import { renderChartFor } from '../../cris-statistics-element-decorator';
57
import { StatisticsChartDataComponent } from '../statistics-chart-data/statistics-chart-data.component';
6-
7-
8-
import { Observable, of } from 'rxjs';
98
import { ChartData } from '../../../../charts/models/chart-data';
109
import { ChartSeries } from '../../../../charts/models/chart-series';
11-
12-
import { Point } from '../../../../core/statistics/models/usage-report.model';
10+
import { Point, UsageReport } from '../../../../core/statistics/models/usage-report.model';
11+
import { REPORT_DATA } from '../../../../core/statistics/data-report.service';
1312

1413
/**
1514
* This component renders a simple item page.
@@ -27,6 +26,15 @@ import { Point } from '../../../../core/statistics/models/usage-report.model';
2726
*/
2827
@renderChartFor(StatisticsType['chart.bar'])
2928
export class StatisticsChartBarComponent extends StatisticsChartDataComponent {
29+
30+
constructor(
31+
@Inject(REPORT_DATA) public report: UsageReport,
32+
@Inject('categoryType') public categoryType: string,
33+
@Inject(PLATFORM_ID) protected platformId: Object
34+
) {
35+
super(report, categoryType, platformId);
36+
}
37+
3038
/**
3139
* Parse information as needed by bar chart overriding function
3240
*/

src/app/statistics-page/cris-statistics-page/statistics-chart/statistics-chart-data/statistics-chart-data.component.ts

Lines changed: 19 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
1-
import { Component, ElementRef, Inject, OnInit, ViewChild } from '@angular/core';
1+
import { Component, ElementRef, Inject, OnInit, PLATFORM_ID, ViewChild } from '@angular/core';
2+
import { isPlatformBrowser } from '@angular/common';
23

34
import { BehaviorSubject, Observable, of } from 'rxjs';
45

@@ -16,7 +17,7 @@ import { ExportImageType, ExportService } from '../../../../core/export-service/
1617
/**
1718
* Component that is being injected by wrapper and obtains the report information
1819
*/
19-
export class StatisticsChartDataComponent implements OnInit {
20+
export abstract class StatisticsChartDataComponent implements OnInit {
2021

2122
/**
2223
* For the ChartType
@@ -43,40 +44,32 @@ export class StatisticsChartDataComponent implements OnInit {
4344
*/
4445
@ViewChild('chartRef') chartRef: ElementRef;
4546

47+
protected exportService: ExportService;
48+
4649
constructor(
4750
@Inject(REPORT_DATA) public report: UsageReport,
4851
@Inject('categoryType') public categoryType: string,
49-
private exportService: ExportService
52+
@Inject(PLATFORM_ID) protected platformId: Object
5053
) {
54+
55+
/* IMPORTANT
56+
Due to a problem occurring on SSR with the ExportAsService dependency, which use window object, the service can't be injected.
57+
So we need to instantiate the class directly based on current the platform */
58+
if (isPlatformBrowser(this.platformId)) {
59+
import('../../../../core/export-service/browser-export.service').then((s) => {
60+
this.exportService = new s.BrowserExportService();
61+
});
62+
} else {
63+
import('../../../../core/export-service/server-export.service').then((s) => {
64+
this.exportService = new s.ServerExportService();
65+
});
66+
}
5167
}
5268

5369
ngOnInit() {
54-
// super.ngOnInit();
5570
this.results = this.getInitData();
5671
}
5772

58-
select(data) {
59-
// const queryParam = this.router['browserUrlTree'].queryParamMap.params;
60-
// const key = this.filterConfig.paramName;
61-
// let value = queryParam[this.filterConfig.paramName];
62-
// if (queryParam[key]) {
63-
// if (queryParam[key].indexOf(data.extra.value) !== -1) {
64-
// value.splice(value.indexOf(data.extra.value), 1);
65-
// } else {
66-
// value.push(data.extra.value);
67-
// }
68-
// } else {
69-
// value = value ? value : [];
70-
// value.push(data.extra.value);
71-
// }
72-
// this.router.navigate(this.getSearchLinkParts(), {
73-
// queryParams: {
74-
// [key]: [...value],
75-
// },
76-
// queryParamsHandling: 'merge',
77-
// });
78-
}
79-
8073
/**
8174
* Download chart as image in png version.
8275
*/

src/app/statistics-page/cris-statistics-page/statistics-chart/statistics-chart-line/statistics-chart-line.component.html

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,8 +10,7 @@
1010
</div>
1111

1212
<div #chartRef id="chart" class="d-flex w-100 search-chart-container" *ngIf="(results | async) && !!report.points && report.points.length > 0 else noData">
13-
<ds-chart [results]="results" [view]="view" [type]='chartType.LINE' [animations]="true"
14-
(select)="select($event)"></ds-chart>
13+
<ds-chart [results]="results" [view]="view" [type]='chartType.LINE' [animations]="true"></ds-chart>
1514
</div>
1615
<ng-template #noData>
1716
<ds-alert [type]="'alert-info'" [content]="'search.filters.applied.charts.no.data.found'"></ds-alert>

src/app/statistics-page/cris-statistics-page/statistics-chart/statistics-chart-line/statistics-chart-line.component.ts

Lines changed: 14 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,20 @@
1-
import { Component } from '@angular/core';
1+
import { Component, Inject, PLATFORM_ID } from '@angular/core';
2+
3+
import { Observable, of } from 'rxjs';
24

35
import { StatisticsType } from '../../statistics-type.model';
46
import { renderChartFor } from '../../cris-statistics-element-decorator';
57
import { StatisticsChartDataComponent } from '../statistics-chart-data/statistics-chart-data.component';
6-
7-
import { Observable, of } from 'rxjs';
88
import { ChartData } from '../../../../charts/models/chart-data';
99
import { ChartSeries } from '../../../../charts/models/chart-series';
10-
11-
import { Point } from '../../../../core/statistics/models/usage-report.model';
10+
import { Point, UsageReport } from '../../../../core/statistics/models/usage-report.model';
11+
import { REPORT_DATA } from '../../../../core/statistics/data-report.service';
1212

1313
/**
1414
* This component renders a simple item page.
1515
* The route parameter 'id' is used to request the item it represents.
1616
* All fields of the item that should be displayed, are defined in its template.
1717
*/
18-
1918
@Component({
2019
selector: 'ds-statistics-chart-line',
2120
styleUrls: ['./statistics-chart-line.component.scss'],
@@ -26,6 +25,15 @@ import { Point } from '../../../../core/statistics/models/usage-report.model';
2625
*/
2726
@renderChartFor(StatisticsType['chart.line'])
2827
export class StatisticsChartLineComponent extends StatisticsChartDataComponent {
28+
29+
constructor(
30+
@Inject(REPORT_DATA) public report: UsageReport,
31+
@Inject('categoryType') public categoryType: string,
32+
@Inject(PLATFORM_ID) protected platformId: Object
33+
) {
34+
super(report, categoryType, platformId);
35+
}
36+
2937
/**
3038
* Parse information as needed by line chart overriding function
3139
*/

src/app/statistics-page/cris-statistics-page/statistics-chart/statistics-chart-pie/statistics-chart-pie.component.html

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,8 +10,7 @@
1010
</div>
1111

1212
<div #chartRef id="chart" class="d-flex w-100 search-chart-container" *ngIf="(results | async) && (results | async).length > 0; else noData">
13-
<ds-chart [results]="results" [view]="view" [type]='chartType.PIE' [animations]="true"
14-
(select)="select($event)"></ds-chart>
13+
<ds-chart [results]="results" [view]="view" [type]='chartType.PIE' [animations]="true"></ds-chart>
1514
</div>
1615
<ng-template #noData>
1716
<ds-alert [type]="'alert-info'" [content]="'search.filters.applied.charts.no.data.found'"></ds-alert>

0 commit comments

Comments
 (0)