{{ totalDownloads }}
diff --git a/src/app/item-page/simple/field-components/file-section/total-downloads.component.ts b/src/app/item-page/simple/field-components/file-section/total-downloads.component.ts
index d5cc17cbd08..25f3d2119c0 100644
--- a/src/app/item-page/simple/field-components/file-section/total-downloads.component.ts
+++ b/src/app/item-page/simple/field-components/file-section/total-downloads.component.ts
@@ -1,14 +1,18 @@
import { Component, OnInit, Input } from '@angular/core';
import { UsageReportDataService } from 'src/app/core/statistics/usage-report-data.service';
+import { ConfigurationDataService } from 'src/app/core/data/configuration-data.service';
import { catchError } from 'rxjs/operators';
-import { of } from 'rxjs';
+import { BehaviorSubject, of } from 'rxjs';
/**
* Component that displays the total number of downloads for all bitstreams within a DSpace item.
*
- * This component fetches download statistics for a given item using its UUID and aggregates
- * the download counts from all bitstreams associated with that item. The result is displayed
- * as a single total download count.
+ * This component checks the 'item.view.total.downloads.enabled' configuration property
+ * to determine if download statistics should be displayed. If enabled, it fetches download
+ * statistics for a given item using its UUID and aggregates the download counts from all
+ * bitstreams associated with that item. The result is displayed as a single total download count.
+ *
+ * If the configuration is disabled or set to 'false', the component will not be displayed.
*/
@Component({
selector: 'ds-total-downloads',
@@ -26,7 +30,14 @@ export class TotalDownloadsComponent implements OnInit {
* The total number of downloads across all bitstreams for the item.
* Defaults to 0 and will show 0 if no data is available or an error occurs.
*/
- totalDownloads: number = 0;
+ totalDownloads: number | null = 0;
+
+ /**
+ * Flag indicating whether the total downloads feature is enabled in the configuration.
+ * Uses BehaviorSubject to allow reactive updates. Defaults to false and will only be
+ * set to true if the configuration explicitly contains 'true' value.
+ */
+ totalDownloadsEnabled = new BehaviorSubject(false);
/**
* The translation key for the downloadsLabel displayed alongside the download count.
@@ -34,15 +45,21 @@ export class TotalDownloadsComponent implements OnInit {
readonly downloadsLabel = 'item.page.files.downloads';
- constructor(private usageReportDataService: UsageReportDataService) { }
+ constructor(
+ private usageReportDataService: UsageReportDataService,
+ private configService: ConfigurationDataService
+ ) { }
/**
- * Fetches the total download statistics for the item specified by itemUuid.
+ * Fetches the configuration to check if total downloads should be shown,
+ * and if enabled, fetches the total download statistics for the item specified by itemUuid.
* The component will:
- * 1. Call the UsageReportDataService with the item UUID and 'TotalDownloads' report type
- * 2. Aggregate all download counts (views) from all bitstreams in the response
- * 3. Set the totalDownloads property with the sum
- * 4. Handle errors gracefully by setting totalDownloads to 0 and logging the error
+ * 1. Check the 'item.view.total.downloads.enabled' configuration property
+ * 2. If enabled (configuration value is explicitly 'true'), call the UsageReportDataService
+ * If configuration is not found or fails to load, defaults to false (disabled)
+ * 3. Aggregate all download counts (views) from all bitstreams in the response
+ * 4. Set the totalDownloads property with the sum
+ * 5. Handle errors gracefully by returning null and logging the error
*
* @throws Will log an error to console if the API call fails, but won't throw an exception
*/
@@ -51,6 +68,34 @@ export class TotalDownloadsComponent implements OnInit {
return;
}
+ // First, check if total downloads feature is enabled in configuration
+ this.configService.findByPropertyName('item.view.total.downloads.enabled')
+ .pipe(
+ catchError(error => {
+ console.error('Failed to fetch total downloads configuration:', error);
+ // Default to false if configuration cannot be retrieved
+ return of(null);
+ })
+ )
+ .subscribe(configData => {
+ // Extract configuration value, default to 'false' if not found
+ const itemViewTotalDownloadsEnabled = configData?.payload?.values?.[0];
+ this.totalDownloadsEnabled.next(itemViewTotalDownloadsEnabled === 'true');
+
+ // Only fetch download statistics if the feature is enabled
+ if (this.totalDownloadsEnabled.value) {
+ this.fetchDownloadStatistics();
+ } else {
+ this.totalDownloads = null; // Ensure it's null when disabled
+ }
+ });
+ }
+
+ /**
+ * Private method to fetch download statistics from the usage report service.
+ * This method is called only when the total downloads feature is enabled.
+ */
+ private fetchDownloadStatistics(): void {
const reportType = 'TotalDownloads';
this.usageReportDataService.getStatistic(this.itemUuid, reportType)
.pipe(
From 4ff27d6df732d6c9a2ae032ba5878ad37adb26ff Mon Sep 17 00:00:00 2001
From: Juraj Roka <95219754+jr-rk@users.noreply.github.com>
Date: Wed, 5 Nov 2025 14:21:38 +0100
Subject: [PATCH 3/3] refactor: provide UsageReportDataService as singleton to
avoid duplicate instances
---
src/app/core/statistics/usage-report-data.service.ts | 2 +-
src/app/item-page/item-page.module.ts | 4 ----
src/app/statistics-page/statistics-page.module.ts | 4 ----
3 files changed, 1 insertion(+), 9 deletions(-)
diff --git a/src/app/core/statistics/usage-report-data.service.ts b/src/app/core/statistics/usage-report-data.service.ts
index 5ce186f4ca6..96961a863d5 100644
--- a/src/app/core/statistics/usage-report-data.service.ts
+++ b/src/app/core/statistics/usage-report-data.service.ts
@@ -20,7 +20,7 @@ import { RequestParam } from '../cache/models/request-param.model';
/**
* A service to retrieve {@link UsageReport}s from the REST API
*/
-@Injectable()
+@Injectable({ providedIn: 'root' })
@dataService(USAGE_REPORT)
export class UsageReportDataService extends IdentifiableDataService implements SearchData {
private searchData: SearchDataImpl;
diff --git a/src/app/item-page/item-page.module.ts b/src/app/item-page/item-page.module.ts
index 26040cfcb18..db9446838eb 100644
--- a/src/app/item-page/item-page.module.ts
+++ b/src/app/item-page/item-page.module.ts
@@ -91,7 +91,6 @@ import { ClarinIdentifierItemFieldComponent } from './simple/field-components/cl
import { ClarinDateItemFieldComponent } from './simple/field-components/clarin-date-item-field/clarin-date-item-field.component';
import { ClarinDescriptionItemFieldComponent } from './simple/field-components/clarin-description-item-field/clarin-description-item-field.component';
import { ClarinFilesSectionComponent } from './clarin-files-section/clarin-files-section.component';
-import { UsageReportDataService } from '../core/statistics/usage-report-data.service';
const ENTRY_COMPONENTS = [
// put only entry components that use custom decorator
@@ -184,9 +183,6 @@ const DECLARATIONS = [
],
exports: [
...DECLARATIONS,
- ],
- providers: [
- UsageReportDataService,
]
})
export class ItemPageModule {
diff --git a/src/app/statistics-page/statistics-page.module.ts b/src/app/statistics-page/statistics-page.module.ts
index 75726de94cc..62993094a8b 100644
--- a/src/app/statistics-page/statistics-page.module.ts
+++ b/src/app/statistics-page/statistics-page.module.ts
@@ -4,7 +4,6 @@ import { CommonModule } from '@angular/common';
import { CoreModule } from '../core/core.module';
import { SharedModule } from '../shared/shared.module';
import { StatisticsModule } from '../statistics/statistics.module';
-import { UsageReportDataService } from '../core/statistics/usage-report-data.service';
import { SiteStatisticsPageComponent } from './site-statistics-page/site-statistics-page.component';
import { StatisticsTableComponent } from './statistics-table/statistics-table.component';
import { ItemStatisticsPageComponent } from './item-statistics-page/item-statistics-page.component';
@@ -35,9 +34,6 @@ const components = [
StatisticsModule.forRoot()
],
declarations: components,
- providers: [
- UsageReportDataService,
- ],
exports: components
})