diff --git a/src/app/core/export-service/browser-export.service.ts b/src/app/core/export-service/browser-export.service.ts index dd031e10995..2835768da77 100644 --- a/src/app/core/export-service/browser-export.service.ts +++ b/src/app/core/export-service/browser-export.service.ts @@ -5,6 +5,7 @@ import { saveAs } from 'file-saver'; import { BehaviorSubject } from 'rxjs'; import { ExportImageType, ExportService } from './export.service'; +import { hasValue } from '../../shared/empty.util'; /** * IMPORTANT @@ -68,4 +69,19 @@ export class BrowserExportService implements ExportService { } + /** + * Creates an image from the given base64 string. + * @param base64 the base64 string + * @param type image type (png or jpeg) + * @param fileName + * @param isLoading + */ + exportImageWithBase64(base64: string, type: ExportImageType, fileName: string, isLoading: BehaviorSubject): void { + if (hasValue(base64)) { + saveAs(base64, fileName + '.' + type); + } else { + console.error('Base64 string is empty'); + } + isLoading.next(false); + } } diff --git a/src/app/core/export-service/export.service.ts b/src/app/core/export-service/export.service.ts index 7f116b78ad0..12355f15c96 100644 --- a/src/app/core/export-service/export.service.ts +++ b/src/app/core/export-service/export.service.ts @@ -26,4 +26,13 @@ export interface ExportService { * @param isLoading A boolean representing the exporting process status. */ exportAsImage(domNode: HTMLElement, type: ExportImageType, fileName: string, isLoading: BehaviorSubject); + + /** + * Creates an image from the given base64 string. + * @param base64 the base64 string + * @param type image type (png or jpeg) + * @param fileName + * @param isLoading + */ + exportImageWithBase64(base64: string, type: ExportImageType, fileName: string, isLoading: BehaviorSubject); } diff --git a/src/app/core/export-service/server-export.service.ts b/src/app/core/export-service/server-export.service.ts index cfd97de54e7..ac59a450a94 100644 --- a/src/app/core/export-service/server-export.service.ts +++ b/src/app/core/export-service/server-export.service.ts @@ -26,4 +26,15 @@ export class ServerExportService implements ExportService { exportAsImage(domNode: HTMLElement, type: ExportImageType, fileName: string, isLoading: BehaviorSubject) { return; } + + /** + * Creates an image from the given base64 string. + * @param base64 the base64 string + * @param type image type (png or jpeg) + * @param fileName + * @param isLoading + */ + exportImageWithBase64(base64: string, type: ExportImageType, fileName: string, isLoading: BehaviorSubject) { + return; + } } diff --git a/src/app/statistics-page/cris-statistics-page/statistics-map/statistics-map.component.html b/src/app/statistics-page/cris-statistics-page/statistics-map/statistics-map.component.html index 83cb9fc6f2c..54af8dcd0e0 100644 --- a/src/app/statistics-page/cris-statistics-page/statistics-map/statistics-map.component.html +++ b/src/app/statistics-page/cris-statistics-page/statistics-map/statistics-map.component.html @@ -1 +1,31 @@ - + +
+
+
+ +
+ +
+
+
+
+ +
+ +
+
diff --git a/src/app/statistics-page/cris-statistics-page/statistics-map/statistics-map.component.spec.ts b/src/app/statistics-page/cris-statistics-page/statistics-map/statistics-map.component.spec.ts index 735f033d1fd..62ff1e1e30e 100644 --- a/src/app/statistics-page/cris-statistics-page/statistics-map/statistics-map.component.spec.ts +++ b/src/app/statistics-page/cris-statistics-page/statistics-map/statistics-map.component.spec.ts @@ -5,6 +5,9 @@ import { UsageReport } from '../../../core/statistics/models/usage-report.model' import { USAGE_REPORT } from '../../../core/statistics/models/usage-report.resource-type'; import { GoogleChartInterface } from 'ng2-google-charts'; +import { ExportService } from '../../../core/export-service/export.service'; +import { TranslateModule } from '@ngx-translate/core'; +import { By } from '@angular/platform-browser'; import { StatisticsType } from '../statistics-type.model'; describe('StatisticsMapComponent', () => { @@ -50,9 +53,20 @@ describe('StatisticsMapComponent', () => { options: { 'title': 'TopCountries' }, }; + const exportServiceMock: any = { + exportAsImage: jasmine.createSpy('exportAsImage'), + exportAsFile: jasmine.createSpy('exportAsFile'), + exportImageWithBase64: jasmine.createSpy('exportImageWithBase64') + }; + + let exportService: ExportService = exportServiceMock; beforeEach(async () => { await TestBed.configureTestingModule({ - declarations: [ StatisticsMapComponent ] + imports: [TranslateModule.forRoot()], + declarations: [ StatisticsMapComponent ], + providers: [ + // { provide: ExportService, useValue: exportServiceMock } + ], }) .compileComponents(); }); @@ -60,6 +74,8 @@ describe('StatisticsMapComponent', () => { beforeEach(() => { fixture = TestBed.createComponent(StatisticsMapComponent); component = fixture.componentInstance; + spyOn(component, 'exportMapAsImage'); + (component as any).exportService = exportServiceMock; fixture.detectChanges(); }); @@ -81,4 +97,13 @@ describe('StatisticsMapComponent', () => { expect(component.geoChart).toEqual(geoChartExpected); }); + it('should download map as png and jpg', () => { + component.report = report; + component.ngOnInit(); + fixture.detectChanges(); + const drpdButton = fixture.debugElement.query(By.css('div[ngbdropdownmenu]>button[ngbdropdownitem]')); + drpdButton.triggerEventHandler('click', null); + fixture.detectChanges(); + expect(component.exportMapAsImage).toHaveBeenCalled(); + }); }); diff --git a/src/app/statistics-page/cris-statistics-page/statistics-map/statistics-map.component.ts b/src/app/statistics-page/cris-statistics-page/statistics-map/statistics-map.component.ts index 4bd4bf8a7b5..fde75a47040 100644 --- a/src/app/statistics-page/cris-statistics-page/statistics-map/statistics-map.component.ts +++ b/src/app/statistics-page/cris-statistics-page/statistics-map/statistics-map.component.ts @@ -1,8 +1,9 @@ -import { Component, Input, OnInit } from '@angular/core'; +import { Component, Inject, Input, OnInit, PLATFORM_ID, ViewChild } from '@angular/core'; import { UsageReport } from '../../../core/statistics/models/usage-report.model'; -import { GoogleChartInterface } from 'ng2-google-charts'; - - +import { GoogleChartComponent, GoogleChartInterface, GoogleChartType } from 'ng2-google-charts'; +import { ExportImageType, ExportService } from '../../../core/export-service/export.service'; +import { BehaviorSubject } from 'rxjs'; +import { isPlatformBrowser } from '@angular/common'; @Component({ selector: 'ds-statistics-map', templateUrl: './statistics-map.component.html', @@ -30,6 +31,40 @@ export class StatisticsMapComponent implements OnInit { * Chart Columns needed to be shown in the tooltip */ chartColumns = []; + /** + * Loading utilized for export functions to disable buttons + */ + isLoading: BehaviorSubject = new BehaviorSubject(false); + + isLoading$: BehaviorSubject = new BehaviorSubject(false); + + /** + * Chart ElementRef + */ + @ViewChild('googleChartRef') googleChartRef: GoogleChartComponent; + + exportImageType = ExportImageType; + + exportImageTypes = [ + { type: ExportImageType.png, label: 'PNG' }, + { type: ExportImageType.jpeg, label: 'JPEG/JPG' } + ]; + + protected exportService: ExportService; + + constructor( + @Inject(PLATFORM_ID) protected platformId: Object + ) { + if (isPlatformBrowser(this.platformId)) { + import('../../../core/export-service/browser-export.service').then((s) => { + this.exportService = new s.BrowserExportService(); + }); + } else { + import('../../../core/export-service/server-export.service').then((s) => { + this.exportService = new s.ServerExportService(); + }); + } + } ngOnInit(): void { if ( !!this.report && !!this.report.points && this.report.points.length > 0 ) { @@ -54,16 +89,23 @@ export class StatisticsMapComponent implements OnInit { }); this.geoChart = { - chartType: 'GeoChart', + chartType: GoogleChartType.GeoChart, dataTable: [ this.chartColumns, ...this.data ], options: { 'title': this.report.reportType } }; - } - - + /** + * Export the map as an image + * @param type of export + */ + exportMapAsImage(type: ExportImageType){ + this.isLoading$.next(true); + const chart = this.googleChartRef.wrapper.getChart(); + const imageURI: string = chart?.getImageURI(); + this.exportService.exportImageWithBase64(imageURI, type, this.report.reportType, this.isLoading$); + } } diff --git a/src/assets/i18n/en.json5 b/src/assets/i18n/en.json5 index f1e075e0426..4f1570c0395 100644 --- a/src/assets/i18n/en.json5 +++ b/src/assets/i18n/en.json5 @@ -7123,6 +7123,8 @@ "authority-confidence.search-label":"Search", + "statistics-page.export-map-as-image": "Export map", + "curation-task.task.hocr.label": "Extract text (HOCR) from images", "curation-task.task.ocrfilter.label": "Consolidate hOCR for fulltext indexing",