Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -1,9 +1,22 @@
<ng-template #tipContent>
<div class="tooltip-content">
<p class="m-0">{{tooltipMsg | translate}}</p>
</div>
</ng-template>

<ng-template #tipContentWarning>
<div class="tooltip-content">
<p class="m-0">{{tooltipMsg | translate}}</p>
<p class="m-0 text-warning">{{exportLimitExceededMsg}}</p>
</div>
</ng-template>

@if (shouldShowButton$ | async) {
<button
class="export-button btn btn-dark btn-sm"
[ngbTooltip]="tooltipMsg | translate"
[ngbTooltip]="(shouldShowWarning$ | async) ? tipContentWarning : tipContent"
(click)="export()"
[title]="tooltipMsg |translate" [attr.aria-label]="tooltipMsg |translate">
[title]="tooltipMsg | translate" [attr.aria-label]="(shouldShowWarning$ | async) ? ((tooltipMsg | translate) + ' ' + exportLimitExceededMsg): (tooltipMsg | translate)">
<i class="fas fa-file-export fa-fw"></i>
</button>
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import { NgbModule } from '@ng-bootstrap/ng-bootstrap';
import { TranslateModule } from '@ngx-translate/core';
import { of as observableOf } from 'rxjs';

import { ConfigurationDataService } from '../../../core/data/configuration-data.service';
import { AuthorizationDataService } from '../../../core/data/feature-authorization/authorization-data.service';
import { ScriptDataService } from '../../../core/data/processes/script-data.service';
import { getProcessDetailRoute } from '../../../process-page/process-page-routing.paths';
Expand All @@ -31,6 +32,7 @@ describe('SearchExportCsvComponent', () => {
let authorizationDataService: AuthorizationDataService;
let notificationsService;
let router;
let configurationDataService: jasmine.SpyObj<ConfigurationDataService>;

const process = Object.assign(new Process(), { processId: 5, scriptName: 'metadata-export-search' });

Expand All @@ -45,6 +47,10 @@ describe('SearchExportCsvComponent', () => {
],
});

configurationDataService = jasmine.createSpyObj('ConfigurationDataService', {
findByPropertyName: observableOf({ payload: { value: '500' } }),
});

function initBeforeEachAsync() {
scriptDataService = jasmine.createSpyObj('scriptDataService', {
scriptWithNameExistsAndCanExecute: observableOf(true),
Expand All @@ -64,6 +70,7 @@ describe('SearchExportCsvComponent', () => {
{ provide: AuthorizationDataService, useValue: authorizationDataService },
{ provide: NotificationsService, useValue: notificationsService },
{ provide: Router, useValue: router },
{ provide: ConfigurationDataService, useValue: configurationDataService },
],
}).compileComponents();
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,9 @@
import {
Component,
Input,
OnChanges,
OnInit,
SimpleChanges,
} from '@angular/core';
import { Router } from '@angular/router';
import { NgbTooltipModule } from '@ng-bootstrap/ng-bootstrap';
Expand All @@ -18,10 +20,12 @@
switchMap,
} from 'rxjs/operators';

import { ConfigurationDataService } from '../../../core/data/configuration-data.service';
import { AuthorizationDataService } from '../../../core/data/feature-authorization/authorization-data.service';
import { FeatureID } from '../../../core/data/feature-authorization/feature-id';
import { ScriptDataService } from '../../../core/data/processes/script-data.service';
import { RemoteData } from '../../../core/data/remote-data';
import { ConfigurationProperty } from '../../../core/shared/configuration-property.model';
import { getFirstCompletedRemoteData } from '../../../core/shared/operators';
import { getProcessDetailRoute } from '../../../process-page/process-page-routing.paths';
import { Process } from '../../../process-page/processes/process.model';
Expand All @@ -43,13 +47,18 @@
/**
* Display a button to export the current search results as csv
*/
export class SearchExportCsvComponent implements OnInit {
export class SearchExportCsvComponent implements OnInit, OnChanges {

/**
* The current configuration of the search
*/
@Input() searchConfig: PaginatedSearchOptions;

/**
* The total number of items in the search results which can be exported
*/
@Input() total: number;

/**
* Observable used to determine whether the button should be shown
*/
Expand All @@ -60,12 +69,18 @@
*/
tooltipMsg = 'metadata-export-search.tooltip';

exportLimitExceededKey = 'metadata-export-search.submit.error.limit-exceeded';

exportLimitExceededMsg = '';

shouldShowWarning$: Observable<boolean>;

constructor(private scriptDataService: ScriptDataService,
private authorizationDataService: AuthorizationDataService,
private notificationsService: NotificationsService,
private translateService: TranslateService,
private router: Router,
) {
private configurationService: ConfigurationDataService) {
}

ngOnInit(): void {
Expand All @@ -75,6 +90,31 @@
map((canExecute: boolean) => canExecute),
startWith(false),
);
this.shouldShowWarning$ = this.itemExceeds();
}

ngOnChanges(changes: SimpleChanges): void {
if (changes.total) {
this.shouldShowWarning$ = this.itemExceeds();

Check warning on line 98 in src/app/shared/search/search-export-csv/search-export-csv.component.ts

View check run for this annotation

Codecov / codecov/patch

src/app/shared/search/search-export-csv/search-export-csv.component.ts#L98

Added line #L98 was not covered by tests
}
}

/**
* Checks if the export limit has been exceeded and updates the tooltip accordingly
*/
private itemExceeds(): Observable<boolean> {
return this.configurationService.findByPropertyName('bulkedit.export.max.items').pipe(
getFirstCompletedRemoteData(),
map((response: RemoteData<ConfigurationProperty>) => {
const limit = Number(response.payload?.values?.[0]) || 500;
if (limit < this.total) {
this.exportLimitExceededMsg = this.translateService.instant(this.exportLimitExceededKey, { limit: String(limit) });
return true;

Check warning on line 112 in src/app/shared/search/search-export-csv/search-export-csv.component.ts

View check run for this annotation

Codecov / codecov/patch

src/app/shared/search/search-export-csv/search-export-csv.component.ts#L111-L112

Added lines #L111 - L112 were not covered by tests
} else {
return false;

Check warning on line 114 in src/app/shared/search/search-export-csv/search-export-csv.component.ts

View check run for this annotation

Codecov / codecov/patch

src/app/shared/search/search-export-csv/search-export-csv.component.ts#L114

Added line #L114 was not covered by tests
}
}),
);
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
<h1>{{ (configuration ? configuration + '.search.results.head' : 'search.results.head') | translate }}</h1>
}
@if (showCsvExport) {
<ds-search-export-csv [searchConfig]="searchConfig"></ds-search-export-csv>
<ds-search-export-csv [searchConfig]="searchConfig" [total]="searchResults?.payload?.totalElements"></ds-search-export-csv>
}
</div>
@if (searchResults && searchResults?.hasSucceeded && !searchResults?.isLoading && searchResults?.payload?.page.length > 0) {
Expand Down
2 changes: 2 additions & 0 deletions src/assets/i18n/en.json5
Original file line number Diff line number Diff line change
Expand Up @@ -7050,4 +7050,6 @@
"metadata-export-filtered-items.columns.warning": "CSV export automatically includes all relevant fields, so selections in this list are not taken into account.",

"embargo.listelement.badge": "Embargo until {{ date }}",

"metadata-export-search.submit.error.limit-exceeded": "Only the first {{limit}} items will be exported",
}
Loading