diff --git a/src/app/core/suggestion-notifications/qa/events/quality-assurance-event-data.service.ts b/src/app/core/suggestion-notifications/qa/events/quality-assurance-event-data.service.ts index 284cd8791a..8eb8359164 100644 --- a/src/app/core/suggestion-notifications/qa/events/quality-assurance-event-data.service.ts +++ b/src/app/core/suggestion-notifications/qa/events/quality-assurance-event-data.service.ts @@ -86,6 +86,16 @@ export class QualityAssuranceEventDataService extends IdentifiableDataService[]): Observable>> { + return this.searchData.searchBy('findByTopic', options, true, true, ...linksToFollow); + } + /** * Clear findByTopic requests from cache */ diff --git a/src/app/core/suggestion-notifications/qa/source/quality-assurance-source-data.service.ts b/src/app/core/suggestion-notifications/qa/source/quality-assurance-source-data.service.ts index 03a5da2e8c..30f3b848f4 100644 --- a/src/app/core/suggestion-notifications/qa/source/quality-assurance-source-data.service.ts +++ b/src/app/core/suggestion-notifications/qa/source/quality-assurance-source-data.service.ts @@ -16,6 +16,7 @@ import { PaginatedList } from '../../../data/paginated-list.model'; import { FindListOptions } from '../../../data/find-list-options.model'; import { IdentifiableDataService } from '../../../data/base/identifiable-data.service'; import { FindAllData, FindAllDataImpl } from '../../../data/base/find-all-data'; +import { SearchData } from '../../../data/base/search-data'; /** * The service handling all Quality Assurance source REST requests. @@ -25,6 +26,9 @@ import { FindAllData, FindAllDataImpl } from '../../../data/base/find-all-data'; export class QualityAssuranceSourceDataService extends IdentifiableDataService { private findAllData: FindAllData; + private searchAllData: SearchData; + + private searchByTargetMethod = 'byTarget'; /** * Initialize service variables @@ -84,4 +88,17 @@ export class QualityAssuranceSourceDataService extends IdentifiableDataService[]): Observable> { return this.findById(id, useCachedVersionIfAvailable, reRequestOnStale, ...linksToFollow); } + + /** + * Retrieves a paginated list of QualityAssuranceSourceObject objects that are associated with a given target object. + * @param options The options for the search query. + * @param useCachedVersionIfAvailable Whether to use a cached version of the data if available. + * @param reRequestOnStale Whether to re-request the data if the cached version is stale. + * @param linksToFollow The links to follow to retrieve the data. + * @returns An observable that emits a RemoteData object containing the paginated list of QualityAssuranceSourceObject objects. + */ + public getSourcesByTarget(options: FindListOptions = {}, useCachedVersionIfAvailable = true, reRequestOnStale = true, ...linksToFollow: FollowLinkConfig[]): Observable>> { + return this.searchAllData.searchBy(this.searchByTargetMethod, options, useCachedVersionIfAvailable, reRequestOnStale, ...linksToFollow); + } + } diff --git a/src/app/item-page/item-page.module.ts b/src/app/item-page/item-page.module.ts index a8d41d1535..5aa1b6e508 100644 --- a/src/app/item-page/item-page.module.ts +++ b/src/app/item-page/item-page.module.ts @@ -60,6 +60,7 @@ import { ThemedItemAlertsComponent } from './alerts/themed-item-alerts.component import { ThemedFullFileSectionComponent } from './full/field-components/file-section/themed-full-file-section.component'; +import { QaEventNotificationComponent } from './simple/qa-event-notification/qa-event-notification.component'; const ENTRY_COMPONENTS = [ // put only entry components that use custom decorator @@ -103,6 +104,7 @@ const DECLARATIONS = [ ItemAlertsComponent, ThemedItemAlertsComponent, BitstreamRequestACopyPageComponent, + QaEventNotificationComponent ]; @NgModule({ diff --git a/src/app/item-page/simple/item-page.component.html b/src/app/item-page/simple/item-page.component.html index cc9983bb35..37a5e0c4cb 100644 --- a/src/app/item-page/simple/item-page.component.html +++ b/src/app/item-page/simple/item-page.component.html @@ -2,6 +2,7 @@
+ diff --git a/src/app/item-page/simple/qa-event-notification/qa-event-notification.component.html b/src/app/item-page/simple/qa-event-notification/qa-event-notification.component.html new file mode 100644 index 0000000000..f2a06bd4fd --- /dev/null +++ b/src/app/item-page/simple/qa-event-notification/qa-event-notification.component.html @@ -0,0 +1,15 @@ + + +
+ +
+
{{'item.qa-event-notification.check.notification-info' | translate : {num: + source.totalEvents } }}
+ +
+
+
+
+Added file diff --git a/src/app/item-page/simple/qa-event-notification/qa-event-notification.component.scss b/src/app/item-page/simple/qa-event-notification/qa-event-notification.component.scss new file mode 100644 index 0000000000..f852bb8454 --- /dev/null +++ b/src/app/item-page/simple/qa-event-notification/qa-event-notification.component.scss @@ -0,0 +1,7 @@ +.source-logo { + max-height: var(--ds-header-logo-height); +} + +.sections-gap { + gap: 1rem; +} diff --git a/src/app/item-page/simple/qa-event-notification/qa-event-notification.component.spec.ts b/src/app/item-page/simple/qa-event-notification/qa-event-notification.component.spec.ts new file mode 100644 index 0000000000..2621f1e6d0 --- /dev/null +++ b/src/app/item-page/simple/qa-event-notification/qa-event-notification.component.spec.ts @@ -0,0 +1,19 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; +import { QaEventNotificationComponent } from './qa-event-notification.component'; + +describe('QaEventNotificationComponent', () => { + let component: QaEventNotificationComponent; + let fixture: ComponentFixture; + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [ QaEventNotificationComponent ] + }) + .compileComponents(); + fixture = TestBed.createComponent(QaEventNotificationComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/src/app/item-page/simple/qa-event-notification/qa-event-notification.component.ts b/src/app/item-page/simple/qa-event-notification/qa-event-notification.component.ts new file mode 100644 index 0000000000..c48d30851e --- /dev/null +++ b/src/app/item-page/simple/qa-event-notification/qa-event-notification.component.ts @@ -0,0 +1,48 @@ +import { ChangeDetectionStrategy, Component, Input } from '@angular/core'; +import { Item } from '../../../core/shared/item.model'; +import { getFirstCompletedRemoteData, getPaginatedListPayload, getRemoteDataPayload } from '../../../core/shared/operators'; +import { Observable } from 'rxjs'; +import { AlertType } from '../../../shared/alert/aletr-type'; +import { FindListOptions } from '../../../core/data/find-list-options.model'; +import { RequestParam } from '../../../core/cache/models/request-param.model'; +import { QualityAssuranceSourceDataService } from '../../../core/suggestion-notifications/qa/source/quality-assurance-source-data.service'; +import { QualityAssuranceSourceObject } from '../../../core/suggestion-notifications/qa/models/quality-assurance-source.model'; +@Component({ + selector: 'ds-qa-event-notification', + templateUrl: './qa-event-notification.component.html', + styleUrls: ['./qa-event-notification.component.scss'], + changeDetection: ChangeDetectionStrategy.OnPush, + providers: [QualityAssuranceSourceDataService] +}) +/** + * Component for displaying quality assurance event notifications for an item. + */ +export class QaEventNotificationComponent { + /** + * The item to display quality assurance event notifications for. + */ + @Input() item: Item; + /** + * The type of alert to display for the notification. + */ + AlertTypeInfo = AlertType.Info; + constructor( + private qualityAssuranceSourceDataService: QualityAssuranceSourceDataService, + ) { } + /** + * Returns an Observable of QualityAssuranceSourceObject[] for the current item. + * @returns An Observable of QualityAssuranceSourceObject[] for the current item. + * Note: sourceId is composed as: id: "sourceName:" + */ + getQualityAssuranceSources$(): Observable { + const findListTopicOptions: FindListOptions = { + searchParams: [new RequestParam('target', this.item.uuid)] + }; + return this.qualityAssuranceSourceDataService.getSourcesByTarget(findListTopicOptions) + .pipe( + getFirstCompletedRemoteData(), + getRemoteDataPayload(), + getPaginatedListPayload(), + ); + } +} diff --git a/src/app/my-dspace-page/my-dspace-page.component.html b/src/app/my-dspace-page/my-dspace-page.component.html index ea5784170f..ed3c58a286 100644 --- a/src/app/my-dspace-page/my-dspace-page.component.html +++ b/src/app/my-dspace-page/my-dspace-page.component.html @@ -1,4 +1,5 @@
+
diff --git a/src/app/my-dspace-page/my-dspace-page.module.ts b/src/app/my-dspace-page/my-dspace-page.module.ts index 6ad50af96a..30dd49b145 100644 --- a/src/app/my-dspace-page/my-dspace-page.module.ts +++ b/src/app/my-dspace-page/my-dspace-page.module.ts @@ -15,6 +15,9 @@ import { MyDSpaceNewExternalDropdownComponent } from './my-dspace-new-submission import { ThemedMyDSpacePageComponent } from './themed-my-dspace-page.component'; import { SearchModule } from '../shared/search/search.module'; import { UploadModule } from '../shared/upload/upload.module'; +import { + MyDspaceQaEventsNotificationsComponent +} from './my-dspace-qa-events-notifications/my-dspace-qa-events-notifications.component'; const DECLARATIONS = [ MyDSpacePageComponent, @@ -22,7 +25,8 @@ const DECLARATIONS = [ MyDSpaceNewSubmissionComponent, CollectionSelectorComponent, MyDSpaceNewSubmissionDropdownComponent, - MyDSpaceNewExternalDropdownComponent + MyDSpaceNewExternalDropdownComponent, + MyDspaceQaEventsNotificationsComponent ]; @NgModule({ diff --git a/src/app/my-dspace-page/my-dspace-qa-events-notifications/my-dspace-qa-events-notifications.component.html b/src/app/my-dspace-page/my-dspace-qa-events-notifications/my-dspace-qa-events-notifications.component.html new file mode 100644 index 0000000000..e4713d282f --- /dev/null +++ b/src/app/my-dspace-page/my-dspace-qa-events-notifications/my-dspace-qa-events-notifications.component.html @@ -0,0 +1,25 @@ + + +
+ +
+
+ {{ "mydspace.qa-event-notification.check.notification-info" | translate : { num: source.totalEvents } }} +
+ +
+
+
+
diff --git a/src/app/my-dspace-page/my-dspace-qa-events-notifications/my-dspace-qa-events-notifications.component.scss b/src/app/my-dspace-page/my-dspace-qa-events-notifications/my-dspace-qa-events-notifications.component.scss new file mode 100644 index 0000000000..f0a8fa2959 --- /dev/null +++ b/src/app/my-dspace-page/my-dspace-qa-events-notifications/my-dspace-qa-events-notifications.component.scss @@ -0,0 +1,6 @@ +.source-logo { + max-height: var(--ds-header-logo-height); +} +.sections-gap { + gap: 1rem; +} diff --git a/src/app/my-dspace-page/my-dspace-qa-events-notifications/my-dspace-qa-events-notifications.component.ts b/src/app/my-dspace-page/my-dspace-qa-events-notifications/my-dspace-qa-events-notifications.component.ts new file mode 100644 index 0000000000..38a154ceaa --- /dev/null +++ b/src/app/my-dspace-page/my-dspace-qa-events-notifications/my-dspace-qa-events-notifications.component.ts @@ -0,0 +1,41 @@ +import { ChangeDetectionStrategy, Component, OnInit } from '@angular/core'; +import { QualityAssuranceSourceDataService } from '../../core/suggestion-notifications/qa/source/quality-assurance-source-data.service'; +import { getFirstCompletedRemoteData, getPaginatedListPayload, getRemoteDataPayload } from '../../core/shared/operators'; +import { Observable, of, tap } from 'rxjs'; +import { QualityAssuranceSourceObject } from 'src/app/core/suggestion-notifications/qa/models/quality-assurance-source.model'; +@Component({ + selector: 'ds-my-dspace-qa-events-notifications', + templateUrl: './my-dspace-qa-events-notifications.component.html', + styleUrls: ['./my-dspace-qa-events-notifications.component.scss'], + changeDetection: ChangeDetectionStrategy.OnPush +}) +export class MyDspaceQaEventsNotificationsComponent implements OnInit { + /** + * An Observable that emits an array of QualityAssuranceSourceObject. + */ + sources$: Observable = of([]); + constructor(private qualityAssuranceSourceDataService: QualityAssuranceSourceDataService) { } + + ngOnInit(): void { + this.getSources(); + } + /** + * Retrieves the sources for Quality Assurance. + * @returns An Observable of the sources for Quality Assurance. + * @throws An error if the retrieval of Quality Assurance sources fails. + */ + getSources() { + this.sources$ = this.qualityAssuranceSourceDataService.getSources() + .pipe( + getFirstCompletedRemoteData(), + tap((rd) => { + if (rd.hasFailed) { + throw new Error('Can\'t retrieve Quality Assurance sources'); + } + }), + getRemoteDataPayload(), + getPaginatedListPayload(), + ); + } + +} diff --git a/src/app/shared/shared.module.ts b/src/app/shared/shared.module.ts index 90a853168c..2881d46c2b 100644 --- a/src/app/shared/shared.module.ts +++ b/src/app/shared/shared.module.ts @@ -287,6 +287,7 @@ import { NgxPaginationModule } from 'ngx-pagination'; import { QualityAssuranceEventDataService } from '../core/suggestion-notifications/qa/events/quality-assurance-event-data.service'; +import { SplitPipe } from './utils/split.pipe'; const MODULES = [ CommonModule, @@ -326,7 +327,8 @@ const PIPES = [ ObjNgFor, BrowserOnlyPipe, MarkdownPipe, - ShortNumberPipe + ShortNumberPipe, + SplitPipe ]; const COMPONENTS = [ diff --git a/src/app/shared/utils/split.pipe.ts b/src/app/shared/utils/split.pipe.ts new file mode 100644 index 0000000000..cccd285922 --- /dev/null +++ b/src/app/shared/utils/split.pipe.ts @@ -0,0 +1,10 @@ +import { Pipe, PipeTransform } from '@angular/core'; +@Pipe({ + name: 'dsSplit' +}) +export class SplitPipe implements PipeTransform { + transform(value: string, separator: string): string[] { + return value.split(separator); + } + +}