mirror of
https://github.com/DSpace/dspace-angular.git
synced 2025-10-11 03:53:02 +00:00
[CST-12709] partial implementation with mock data
This commit is contained in:
@@ -195,6 +195,9 @@ import {
|
||||
CoarNotifyConfigDataService
|
||||
} from '../submission/sections/section-coar-notify/coar-notify-config-data.service';
|
||||
import { SubmissionCoarNotifyConfig } from '../submission/sections/section-coar-notify/submission-coar-notify.config';
|
||||
import { NotifyRequestsStatus } from '../item-page/simple/notify-requests-status/notify-requests-status.model';
|
||||
import { NotifyRequestsStatusDataService } from './data/notify-services-status-data.service';
|
||||
|
||||
|
||||
/**
|
||||
* When not in production, endpoint responses can be mocked for testing purposes
|
||||
@@ -320,7 +323,8 @@ const PROVIDERS = [
|
||||
SupervisionOrderDataService,
|
||||
LdnServicesService,
|
||||
LdnItemfiltersService,
|
||||
CoarNotifyConfigDataService
|
||||
CoarNotifyConfigDataService,
|
||||
NotifyRequestsStatusDataService
|
||||
];
|
||||
|
||||
/**
|
||||
@@ -404,8 +408,8 @@ export const models =
|
||||
SuggestionSource,
|
||||
LdnService,
|
||||
Itemfilter,
|
||||
SubmissionCoarNotifyConfig
|
||||
|
||||
SubmissionCoarNotifyConfig,
|
||||
NotifyRequestsStatus,
|
||||
];
|
||||
|
||||
@NgModule({
|
||||
|
49
src/app/core/data/notify-services-status-data.service.ts
Normal file
49
src/app/core/data/notify-services-status-data.service.ts
Normal file
@@ -0,0 +1,49 @@
|
||||
import { Injectable } from '@angular/core';
|
||||
import { RequestService } from './request.service';
|
||||
import { RemoteDataBuildService } from '../cache/builders/remote-data-build.service';
|
||||
import { ObjectCacheService } from '../cache/object-cache.service';
|
||||
import { HALEndpointService } from '../shared/hal-endpoint.service';
|
||||
import { IdentifiableDataService } from './base/identifiable-data.service';
|
||||
import { dataService } from './base/data-service.decorator';
|
||||
import { NotifyRequestsStatus } from '../../item-page/simple/notify-requests-status/notify-requests-status.model';
|
||||
import { NOTIFYREQUEST} from '../../item-page/simple/notify-requests-status/notify-requests-status.resource-type';
|
||||
import { Observable, map, take, tap } from 'rxjs';
|
||||
import { RemoteData } from './remote-data';
|
||||
import { GetRequest } from './request.models';
|
||||
|
||||
|
||||
@Injectable()
|
||||
@dataService(NOTIFYREQUEST)
|
||||
export class NotifyRequestsStatusDataService extends IdentifiableDataService<NotifyRequestsStatus> {
|
||||
|
||||
private notifyRequestLink = 'notifyrequests';
|
||||
|
||||
constructor(
|
||||
protected requestService: RequestService,
|
||||
protected rdbService: RemoteDataBuildService,
|
||||
protected objectCache: ObjectCacheService,
|
||||
protected halService: HALEndpointService,
|
||||
protected rdb: RemoteDataBuildService,
|
||||
) {
|
||||
super('ldn', requestService, rdbService, objectCache, halService);
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves the status of notify requests for a specific item.
|
||||
* @param itemUuid The UUID of the item.
|
||||
* @returns An Observable that emits the remote data containing the notify requests status.
|
||||
*/
|
||||
getNotifyRequestsStatus(itemUuid: string): Observable<RemoteData<NotifyRequestsStatus>> {
|
||||
const href$ = this.halService.getEndpoint(this.notifyRequestLink).pipe(
|
||||
tap((url: string) => console.log('url', url) ),
|
||||
map((url: string) => url + '/' + itemUuid),
|
||||
);
|
||||
|
||||
href$.pipe(take(1)).subscribe((url: string) => {
|
||||
const request = new GetRequest(this.requestService.generateRequestId(), url);
|
||||
this.requestService.send(request, true);
|
||||
});
|
||||
|
||||
return this.rdb.buildFromHref(href$);
|
||||
}
|
||||
}
|
@@ -61,6 +61,8 @@ import {
|
||||
ThemedFullFileSectionComponent
|
||||
} from './full/field-components/file-section/themed-full-file-section.component';
|
||||
import { QaEventNotificationComponent } from './simple/qa-event-notification/qa-event-notification.component';
|
||||
import { NotifyRequestsStatusComponent } from './simple/notify-requests-status/notify-requests-status-component/notify-requests-status.component';
|
||||
import { RequestStatusAlertBoxComponent } from './simple/notify-requests-status/request-status-alert-box/request-status-alert-box.component';
|
||||
|
||||
const ENTRY_COMPONENTS = [
|
||||
// put only entry components that use custom decorator
|
||||
@@ -104,7 +106,9 @@ const DECLARATIONS = [
|
||||
ItemAlertsComponent,
|
||||
ThemedItemAlertsComponent,
|
||||
BitstreamRequestACopyPageComponent,
|
||||
QaEventNotificationComponent
|
||||
QaEventNotificationComponent,
|
||||
NotifyRequestsStatusComponent,
|
||||
RequestStatusAlertBoxComponent
|
||||
];
|
||||
|
||||
@NgModule({
|
||||
|
@@ -3,6 +3,7 @@
|
||||
<div *ngIf="itemRD?.payload as item">
|
||||
<ds-themed-item-alerts [item]="item"></ds-themed-item-alerts>
|
||||
<ds-qa-event-notification [item]="item"></ds-qa-event-notification>
|
||||
<ds-notify-requests-status [itemUuid]="item.uuid"></ds-notify-requests-status>
|
||||
<ds-item-versions-notice [item]="item"></ds-item-versions-notice>
|
||||
<ds-view-tracker [object]="item"></ds-view-tracker>
|
||||
<ds-listable-object-component-loader *ngIf="!item.isWithdrawn || (isAdmin$|async)" [object]="item" [viewMode]="viewMode"></ds-listable-object-component-loader>
|
||||
|
@@ -0,0 +1,5 @@
|
||||
<ng-container *ngIf="statusMap.size > 0">
|
||||
<ng-container *ngFor="let entry of statusMap | keyvalue ">
|
||||
<ds-request-status-alert-box [status]="entry.key" [data]="entry.value"></ds-request-status-alert-box>
|
||||
</ng-container>
|
||||
</ng-container>
|
@@ -0,0 +1,108 @@
|
||||
import { ChangeDetectionStrategy, Component, Input } from '@angular/core';
|
||||
import { Observable, of } from 'rxjs';
|
||||
import { NotifyRequestsStatus, NotifyStatuses } from '../notify-requests-status.model';
|
||||
import { NotifyRequestsStatusDataService } from 'src/app/core/data/notify-services-status-data.service';
|
||||
import { RequestStatusEnum } from '../notify-status.enum';
|
||||
|
||||
@Component({
|
||||
selector: 'ds-notify-requests-status',
|
||||
templateUrl: './notify-requests-status.component.html',
|
||||
styleUrls: ['./notify-requests-status.component.scss'],
|
||||
changeDetection: ChangeDetectionStrategy.OnPush,
|
||||
})
|
||||
export class NotifyRequestsStatusComponent {
|
||||
|
||||
/**
|
||||
* The UUID of the item.
|
||||
*/
|
||||
@Input() itemUuid: string;
|
||||
|
||||
/**
|
||||
* Map that stores the status of requests and their corresponding notify statuses.
|
||||
* The keys of the map are instances of the RequestStatusEnum enum,
|
||||
* and the values are arrays of NotifyStatuses objects.
|
||||
*/
|
||||
statusMap: Map<RequestStatusEnum, NotifyStatuses[]> = new Map();
|
||||
|
||||
notifyRequestStatus$: Observable<NotifyRequestsStatus> = of( Object.assign(new NotifyRequestsStatus(), {
|
||||
notifyStatuses: [
|
||||
{
|
||||
serviceName: 'test',
|
||||
serviceUrl: 'test',
|
||||
status: RequestStatusEnum.ACCEPTED,
|
||||
},
|
||||
{
|
||||
serviceName: 'test1',
|
||||
serviceUrl: 'test',
|
||||
status: RequestStatusEnum.ACCEPTED,
|
||||
},
|
||||
{
|
||||
serviceName: 'Review Platform',
|
||||
serviceUrl: 'test',
|
||||
status: RequestStatusEnum.ACCEPTED,
|
||||
},
|
||||
{
|
||||
serviceName: 'Demo Environment',
|
||||
serviceUrl: 'test',
|
||||
status: RequestStatusEnum.ACCEPTED,
|
||||
},
|
||||
{
|
||||
serviceName: 'Additional Information',
|
||||
serviceUrl: 'test',
|
||||
status: RequestStatusEnum.ACCEPTED,
|
||||
},
|
||||
{
|
||||
serviceName: 'Notification Service',
|
||||
serviceUrl: 'test',
|
||||
status: RequestStatusEnum.ACCEPTED,
|
||||
},
|
||||
{
|
||||
serviceName: 'test2',
|
||||
serviceUrl: 'test',
|
||||
status: RequestStatusEnum.REJECTED,
|
||||
},
|
||||
{
|
||||
serviceName: 'test3',
|
||||
serviceUrl: 'test',
|
||||
status: RequestStatusEnum.REQUESTED,
|
||||
},
|
||||
{
|
||||
serviceName: 'test4',
|
||||
serviceUrl: 'test',
|
||||
status: RequestStatusEnum.REQUESTED,
|
||||
}
|
||||
],
|
||||
itemUuid: '8d5fda2d-f380-467e-a86b-0436ac699dab',
|
||||
}));
|
||||
|
||||
constructor(
|
||||
private notifyInfoService: NotifyRequestsStatusDataService,
|
||||
) { }
|
||||
|
||||
ngOnInit(): void {
|
||||
this.notifyInfoService.getNotifyRequestsStatus(this.itemUuid).subscribe((data) => {
|
||||
console.log(data, 'asdasdsa');
|
||||
});
|
||||
|
||||
this.notifyRequestStatus$.subscribe((data) => {
|
||||
this.groupDataByStatus(data);
|
||||
console.log(this.statusMap);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Groups the notify requests status data by status.
|
||||
* @param notifyRequestsStatus The notify requests status data.
|
||||
*/
|
||||
private groupDataByStatus(notifyRequestsStatus: NotifyRequestsStatus): void {
|
||||
notifyRequestsStatus.notifyStatuses.forEach((notifyStatus: NotifyStatuses) => {
|
||||
const status = notifyStatus.status;
|
||||
|
||||
if (!this.statusMap.has(status)) {
|
||||
this.statusMap.set(status, []);
|
||||
}
|
||||
|
||||
this.statusMap.get(status)?.push(notifyStatus);
|
||||
});
|
||||
}
|
||||
}
|
@@ -0,0 +1,68 @@
|
||||
// eslint-disable-next-line max-classes-per-file
|
||||
import { autoserialize, deserialize, inheritSerialization } from 'cerialize';
|
||||
import { typedObject } from '../../../core/cache/builders/build-decorators';
|
||||
import { CacheableObject } from '../../../core/cache/cacheable-object.model';
|
||||
import { ResourceType } from '../../../core/shared/resource-type';
|
||||
import { excludeFromEquals } from '../../../core/utilities/equals.decorators';
|
||||
import { NOTIFYREQUEST } from './notify-requests-status.resource-type';
|
||||
import { HALLink } from '../../../core/shared/hal-link.model';
|
||||
import { RequestStatusEnum } from './notify-status.enum';
|
||||
|
||||
/**
|
||||
* Represents the status of notify requests for an item.
|
||||
*/
|
||||
@typedObject
|
||||
@inheritSerialization(CacheableObject)
|
||||
export class NotifyRequestsStatus implements CacheableObject {
|
||||
static type = NOTIFYREQUEST;
|
||||
|
||||
/**
|
||||
* The object type.
|
||||
*/
|
||||
@excludeFromEquals
|
||||
@autoserialize
|
||||
type: ResourceType;
|
||||
|
||||
/**
|
||||
* The notify statuses.
|
||||
*/
|
||||
@autoserialize
|
||||
notifyStatuses: NotifyStatuses[];
|
||||
|
||||
/**
|
||||
* The UUID of the item.
|
||||
*/
|
||||
@autoserialize
|
||||
itemUuid: string;
|
||||
|
||||
/**
|
||||
* The links associated with the notify requests status.
|
||||
*/
|
||||
@deserialize
|
||||
_links: {
|
||||
self: HALLink;
|
||||
[k: string]: HALLink | HALLink[];
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Represents the status of a notification request.
|
||||
*/
|
||||
export class NotifyStatuses {
|
||||
/**
|
||||
* The name of the service.
|
||||
*/
|
||||
serviceName: string;
|
||||
|
||||
/**
|
||||
* The URL of the service.
|
||||
*/
|
||||
serviceUrl: string;
|
||||
|
||||
/**
|
||||
* The status of the notification request.
|
||||
*/
|
||||
status: RequestStatusEnum;
|
||||
}
|
||||
|
||||
|
@@ -0,0 +1,8 @@
|
||||
import {ResourceType} from '../../../core/shared/resource-type';
|
||||
/**
|
||||
* The resource type for the root endpoint
|
||||
*
|
||||
* Needs to be in a separate file to prevent circular
|
||||
* dependencies in webpack.
|
||||
*/
|
||||
export const NOTIFYREQUEST = new ResourceType('notifyrequest');
|
@@ -0,0 +1,5 @@
|
||||
export enum RequestStatusEnum {
|
||||
ACCEPTED = 'ACCEPTED',
|
||||
REJECTED = 'REJECTED',
|
||||
REQUESTED = 'REQUESTED',
|
||||
}
|
@@ -0,0 +1,32 @@
|
||||
<ng-container *ngIf="data?.length > 0 && displayOptions">
|
||||
<div
|
||||
[ngClass]="{'align-items-center': data.length == 1}"
|
||||
class="alert d-flex flex-row sections-gap {{
|
||||
displayOptions.alertType
|
||||
}}"
|
||||
>
|
||||
<img
|
||||
class="source-logo"
|
||||
src="assets/images/qa-coar-notify-logo.png"
|
||||
alt="notify logo"
|
||||
/>
|
||||
<ds-truncatable [id]="status">
|
||||
<ds-truncatable-part [id]="status" [minLines]="1">
|
||||
<div class="w-100 d-flex flex-column">
|
||||
<ng-container *ngFor="let request of data">
|
||||
<div
|
||||
[innerHTML]="
|
||||
displayOptions.text
|
||||
| translate
|
||||
: {
|
||||
serviceName: request.serviceName,
|
||||
serviceUrl: request.serviceUrl
|
||||
}
|
||||
"
|
||||
></div>
|
||||
</ng-container>
|
||||
</div>
|
||||
</ds-truncatable-part>
|
||||
</ds-truncatable>
|
||||
</div>
|
||||
</ng-container>
|
@@ -0,0 +1,7 @@
|
||||
.source-logo {
|
||||
max-height: var(--ds-header-logo-height);
|
||||
}
|
||||
|
||||
.sections-gap {
|
||||
gap: 1rem;
|
||||
}
|
@@ -0,0 +1,51 @@
|
||||
import { ComponentFixture, TestBed, fakeAsync } from '@angular/core/testing';
|
||||
import { RequestStatusAlertBoxComponent } from './request-status-alert-box.component';
|
||||
import { TranslateModule } from '@ngx-translate/core';
|
||||
import { RequestStatusEnum } from '../notify-status.enum';
|
||||
|
||||
describe('RequestStatusAlertBoxComponent', () => {
|
||||
let component: RequestStatusAlertBoxComponent;
|
||||
let componentAsAny: any;
|
||||
let fixture: ComponentFixture<RequestStatusAlertBoxComponent>;
|
||||
|
||||
const mockData = [
|
||||
{
|
||||
serviceName: 'test',
|
||||
serviceUrl: 'test',
|
||||
status: RequestStatusEnum.ACCEPTED,
|
||||
},
|
||||
{
|
||||
serviceName: 'test1',
|
||||
serviceUrl: 'test',
|
||||
status: RequestStatusEnum.REJECTED,
|
||||
},
|
||||
];
|
||||
|
||||
beforeEach(async () => {
|
||||
await TestBed.configureTestingModule({
|
||||
imports: [TranslateModule.forRoot()],
|
||||
declarations: [RequestStatusAlertBoxComponent],
|
||||
}).compileComponents();
|
||||
});
|
||||
|
||||
beforeEach(() => {
|
||||
fixture = TestBed.createComponent(RequestStatusAlertBoxComponent);
|
||||
component = fixture.componentInstance;
|
||||
component.data = mockData;
|
||||
component.displayOptions = {
|
||||
alertType: 'alert-danger',
|
||||
text: 'request-status-alert-box.rejected',
|
||||
};
|
||||
componentAsAny = component;
|
||||
fixture.detectChanges();
|
||||
});
|
||||
|
||||
it('should create the component', () => {
|
||||
expect(component).toBeTruthy();
|
||||
});
|
||||
|
||||
it('should display the alert box when data is available', fakeAsync(() => {
|
||||
const alertBoxElement = fixture.nativeElement.querySelector('.alert');
|
||||
expect(alertBoxElement).toBeTruthy();
|
||||
}));
|
||||
});
|
@@ -0,0 +1,82 @@
|
||||
import {
|
||||
ChangeDetectionStrategy,
|
||||
Component,
|
||||
Input,
|
||||
type OnInit,
|
||||
} from '@angular/core';
|
||||
import { NotifyStatuses } from '../notify-requests-status.model';
|
||||
import { RequestStatusEnum } from '../notify-status.enum';
|
||||
|
||||
@Component({
|
||||
selector: 'ds-request-status-alert-box',
|
||||
templateUrl: './request-status-alert-box.component.html',
|
||||
styleUrls: ['./request-status-alert-box.component.scss'],
|
||||
changeDetection: ChangeDetectionStrategy.OnPush,
|
||||
})
|
||||
/**
|
||||
* Represents a component that displays the status of a request.
|
||||
*/
|
||||
export class RequestStatusAlertBoxComponent implements OnInit {
|
||||
/**
|
||||
* The status of the request.
|
||||
*/
|
||||
@Input() status: RequestStatusEnum;
|
||||
|
||||
/**
|
||||
* The input data for the request status alert box component.
|
||||
* @type {NotifyStatuses[]}
|
||||
*/
|
||||
@Input() data: NotifyStatuses[] = [];
|
||||
|
||||
/**
|
||||
* The display options for the request status alert box.
|
||||
*/
|
||||
displayOptions: NotifyRequestDisplayOptions;
|
||||
|
||||
ngOnInit(): void {
|
||||
this.prepareDataToDisplay();
|
||||
}
|
||||
|
||||
/**
|
||||
* Prepares the data to be displayed based on the current status.
|
||||
*/
|
||||
private prepareDataToDisplay() {
|
||||
switch (this.status) {
|
||||
case RequestStatusEnum.ACCEPTED:
|
||||
this.displayOptions = {
|
||||
alertType: 'alert-info',
|
||||
text: 'request-status-alert-box.accepted',
|
||||
};
|
||||
break;
|
||||
|
||||
case RequestStatusEnum.REJECTED:
|
||||
this.displayOptions = {
|
||||
alertType: 'alert-danger',
|
||||
text: 'request-status-alert-box.rejected',
|
||||
};
|
||||
break;
|
||||
|
||||
case RequestStatusEnum.REQUESTED:
|
||||
this.displayOptions = {
|
||||
alertType: 'alert-warning',
|
||||
text: 'request-status-alert-box.requested',
|
||||
};
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Represents the display options for a notification request.
|
||||
*/
|
||||
export interface NotifyRequestDisplayOptions {
|
||||
/**
|
||||
* The type of alert to display.
|
||||
* Possible values are 'alert-danger', 'alert-warning', or 'alert-info'.
|
||||
*/
|
||||
alertType: 'alert-danger' | 'alert-warning' | 'alert-info';
|
||||
/**
|
||||
* The text to display in the notification.
|
||||
*/
|
||||
text: string;
|
||||
}
|
@@ -5697,4 +5697,10 @@
|
||||
|
||||
"access-control-option-end-date-note": "Select the date until which the related access condition is applied",
|
||||
|
||||
"request-status-alert-box.accepted": "The request for <a href='{{serviceUrl}}' target='_blank'> {{ serviceName }} </a> has been taken in charge.",
|
||||
|
||||
"request-status-alert-box.rejected": "The request for <a href='{{serviceUrl}}' target='_blank'> {{ serviceName }} </a> has been rejected.",
|
||||
|
||||
"request-status-alert-box.requested": "The request for <a href='{{serviceUrl}}' target='_blank'> {{ serviceName }} </a> is pending.",
|
||||
|
||||
}
|
||||
|
Reference in New Issue
Block a user