diff --git a/src/app/shared/metric/metric-embedded/metric-embedded-download/metric-embedded-download.component.spec.ts b/src/app/shared/metric/metric-embedded/metric-embedded-download/metric-embedded-download.component.spec.ts index 6f72cc7592b..ae075bea6c3 100644 --- a/src/app/shared/metric/metric-embedded/metric-embedded-download/metric-embedded-download.component.spec.ts +++ b/src/app/shared/metric/metric-embedded/metric-embedded-download/metric-embedded-download.component.spec.ts @@ -6,6 +6,7 @@ import { TranslateLoaderMock } from '../../../mocks/translate-loader.mock'; import { metricEmbeddedDownload } from '../../../../cris-layout/cris-layout-matrix/cris-layout-box-container/boxes/metrics/cris-layout-metrics-box.component.spec'; +import { Metric } from '../../../../core/shared/metric.model'; describe('MetricEmbeddedDownloadComponent', () => { let component: MetricEmbeddedDownloadComponent; @@ -34,4 +35,25 @@ describe('MetricEmbeddedDownloadComponent', () => { it('should create', () => { expect(component).toBeTruthy(); }); + + it('should append reportType to href if href is defined and does not contain query parameters', () => { + component.href = 'http://example.com'; + component.metric = {} as Metric; + component.ngOnInit(); + expect(component.href).toBe('http://example.com?reportType=TotalDownloads'); + }); + + it('should append reportType to href if href is defined and contains query parameters', () => { + component.href = 'http://example.com?param=value'; + component.metric = {} as Metric; + component.ngOnInit(); + expect(component.href).toBe('http://example.com?param=value&reportType=TotalDownloads'); + }); + + it('should not modify href if href is not defined', () => { + component.href = undefined; + component.metric = {} as Metric; + component.ngOnInit(); + expect(component.href).toBeUndefined(); + }); }); diff --git a/src/app/shared/metric/metric-embedded/metric-embedded-download/metric-embedded-download.component.ts b/src/app/shared/metric/metric-embedded/metric-embedded-download/metric-embedded-download.component.ts index d27ebda2732..89d743b28f4 100644 --- a/src/app/shared/metric/metric-embedded/metric-embedded-download/metric-embedded-download.component.ts +++ b/src/app/shared/metric/metric-embedded/metric-embedded-download/metric-embedded-download.component.ts @@ -1,15 +1,23 @@ -import { Component, Renderer2 } from '@angular/core'; +import { Component, OnInit, Renderer2 } from '@angular/core'; import { BaseEmbeddedHtmlMetricComponent } from '../base-embedded-html-metric.component'; +export const METRIC_TYPE_DOWNLOAD = 'TotalDownloads'; @Component({ selector: 'ds-metric-embedded-download', templateUrl: './metric-embedded-download.component.html', styleUrls: ['./metric-embedded-download.component.scss', '../../metric-loader/base-metric.component.scss'] }) -export class MetricEmbeddedDownloadComponent extends BaseEmbeddedHtmlMetricComponent { +export class MetricEmbeddedDownloadComponent extends BaseEmbeddedHtmlMetricComponent implements OnInit { constructor(protected render: Renderer2) { super(render); } + ngOnInit() { + super.ngOnInit(); + if (this.href) { + this.href += (this.href.includes('?') ? '&' : '?') + 'reportType=' + METRIC_TYPE_DOWNLOAD; + } + } + } diff --git a/src/app/statistics-page/cris-statistics-page/cris-statistics-page.component.spec.ts b/src/app/statistics-page/cris-statistics-page/cris-statistics-page.component.spec.ts index 7ac392545b1..e0c9e218e3c 100644 --- a/src/app/statistics-page/cris-statistics-page/cris-statistics-page.component.spec.ts +++ b/src/app/statistics-page/cris-statistics-page/cris-statistics-page.component.spec.ts @@ -4,7 +4,7 @@ import { ActivatedRoute } from '@angular/router'; import { DebugElement, NO_ERRORS_SCHEMA } from '@angular/core'; import { By } from '@angular/platform-browser'; -import { of as observableOf } from 'rxjs'; +import { of, of as observableOf } from 'rxjs'; import { TranslateLoader, TranslateModule } from '@ngx-translate/core'; import { CrisStatisticsPageComponent } from './cris-statistics-page.component'; @@ -23,6 +23,7 @@ import { TranslateLoaderMock } from '../../shared/mocks/translate-loader.mock'; import { provideMockStore } from '@ngrx/store/testing'; import { StatisticsState } from '../../core/statistics/statistics.reducer'; +import { UsageReport } from '../../core/statistics/models/usage-report.model'; describe('CrisStatisticsPageComponent', () => { @@ -141,4 +142,71 @@ describe('CrisStatisticsPageComponent', () => { fixture.detectChanges(); }); + it('should set selectedReportId to the first report id if no reportType query param is present', () => { + const category = { id: 'category1' }; + const reports = [{ id: 'report1', reportType: 'type1' }, { id: 'report2', reportType: 'type2' }]; + spyOn(component, 'getReports$').and.returnValue(of(reports as UsageReport[])); + spyOn(component, 'getReportId').and.returnValue(of(null)); + spyOn(component, 'getCategoryId').and.returnValue(of(null)); + spyOn(component, 'setStatisticsState'); + + component.getUserReports(category); + + expect(component.setStatisticsState).toHaveBeenCalledWith('report1', 'category1'); + expect(component.selectedReportId).toBe('report1'); + }); + + it('should set selectedReportId to the report id matching the reportType query param', () => { + const category = { id: 'category1' }; + const reports = [{ id: 'report1', reportType: 'type1' }, { id: 'report2', reportType: 'type2' }]; + spyOn(component, 'getReports$').and.returnValue(of(reports as UsageReport[])); + spyOn(component, 'getReportId').and.returnValue(of(null)); + spyOn(component, 'getCategoryId').and.returnValue(of(null)); + spyOn(component, 'setStatisticsState'); + + component.getUserReports(category, 'type2'); + + expect(component.setStatisticsState).toHaveBeenCalledWith('report2', 'category1'); + expect(component.selectedReportId).toBe('report2'); + }); + + it('should set selectedReportId to the first report id if reportType query param does not match any report', () => { + const category = { id: 'category1' }; + const reports = [{ id: 'report1', reportType: 'type1' }, { id: 'report2', reportType: 'type2' }]; + spyOn(component, 'getReports$').and.returnValue(of(reports as UsageReport[])); + spyOn(component, 'getReportId').and.returnValue(of(null)); + spyOn(component, 'getCategoryId').and.returnValue(of(null)); + spyOn(component, 'setStatisticsState'); + + component.getUserReports(category, 'non_existing_type'); + + expect(component.setStatisticsState).toHaveBeenCalledWith('report1', 'category1'); + expect(component.selectedReportId).toBe('report1'); + }); + + it('should set selectedReportId and categoryId from state if they exist', () => { + const category = { id: 'category1' }; + const reports = [{ id: 'report1', reportType: 'type1' }, { id: 'report2', reportType: 'type2' }]; + spyOn(component, 'getReports$').and.returnValue(of(reports as UsageReport[])); + spyOn(component, 'getReportId').and.returnValue(of('report1')); + spyOn(component, 'getCategoryId').and.returnValue(of('category1')); + spyOn(component, 'setStatisticsState'); + + component.getUserReports(category); + + expect(component.setStatisticsState).toHaveBeenCalledWith('report1', 'category1'); + }); + + it('should handle null category gracefully', () => { + spyOn(component, 'getReports$').and.returnValue(of([])); + spyOn(component, 'getReportId').and.returnValue(of(null)); + spyOn(component, 'getCategoryId').and.returnValue(of(null)); + spyOn(component, 'setStatisticsState'); + + component.getUserReports(null); + + expect(component.setStatisticsState).not.toHaveBeenCalled(); + expect(component.selectedReportId).toBeUndefined(); + }); + }); diff --git a/src/app/statistics-page/cris-statistics-page/cris-statistics-page.component.ts b/src/app/statistics-page/cris-statistics-page/cris-statistics-page.component.ts index cb2710c8004..df985f61ba8 100644 --- a/src/app/statistics-page/cris-statistics-page/cris-statistics-page.component.ts +++ b/src/app/statistics-page/cris-statistics-page/cris-statistics-page.component.ts @@ -178,8 +178,9 @@ export class CrisStatisticsPageComponent implements OnInit, OnDestroy { /** * Get the user reports for the specific category. * @param category the that is being selected + * @param reportType */ - getUserReports(category) { + getUserReports(category, reportType = this.route?.snapshot?.queryParams?.reportType) { this.reports$ = of(category) .pipe( @@ -189,8 +190,15 @@ export class CrisStatisticsPageComponent implements OnInit, OnDestroy { this.reports$, this.getReportId(), this.getCategoryId() ]).subscribe(([report, reportId, categoryId]) => { if (!reportId && !categoryId) { - this.setStatisticsState(report[0].id, category.id); - this.selectedReportId = report[0].id; + let reportToShowId = report[0].id; + if (reportType) { + const newReport = report.find((r) => r.reportType === reportType)?.id; + if (newReport) { + reportToShowId = newReport; + } + } + this.setStatisticsState(reportToShowId, category.id); + this.selectedReportId = reportToShowId; } else { this.setStatisticsState(reportId, categoryId); } diff --git a/src/app/statistics-page/cris-statistics-page/statistics-chart/statistics-chart.component.html b/src/app/statistics-page/cris-statistics-page/statistics-chart/statistics-chart.component.html index fe570f243a0..963f0db2984 100644 --- a/src/app/statistics-page/cris-statistics-page/statistics-chart/statistics-chart.component.html +++ b/src/app/statistics-page/cris-statistics-page/statistics-chart/statistics-chart.component.html @@ -10,7 +10,8 @@