mirror of
https://github.com/DSpace/dspace-angular.git
synced 2025-10-07 01:54:15 +00:00
refactor, add detail mapping, add missing translation, optimize modal
This commit is contained in:
@@ -34,11 +34,27 @@ import {
|
||||
path: 'inbound',
|
||||
component: AdminNotifyIncomingComponent,
|
||||
canActivate: [SiteAdministratorGuard],
|
||||
resolve: {
|
||||
breadcrumb: I18nBreadcrumbResolver,
|
||||
},
|
||||
data: {
|
||||
title: 'admin.notify.dashboard.page.title',
|
||||
breadcrumbKey: 'admin.notify.dashboard',
|
||||
showBreadcrumbsFluid: false
|
||||
},
|
||||
},
|
||||
{
|
||||
path: 'outbound',
|
||||
component: AdminNotifyOutgoingComponent,
|
||||
canActivate: [SiteAdministratorGuard],
|
||||
resolve: {
|
||||
breadcrumb: I18nBreadcrumbResolver,
|
||||
},
|
||||
data: {
|
||||
title: 'admin.notify.dashboard.page.title',
|
||||
breadcrumbKey: 'admin.notify.dashboard',
|
||||
showBreadcrumbsFluid: false
|
||||
},
|
||||
}
|
||||
])
|
||||
],
|
||||
|
@@ -8,14 +8,13 @@ import { AdminNotifyIncomingComponent } from './admin-notify-logs/admin-notify-i
|
||||
import { SharedModule } from '../../shared/shared.module';
|
||||
import { SearchModule } from '../../shared/search/search.module';
|
||||
import { SearchPageModule } from '../../search-page/search-page.module';
|
||||
import { AdminNotifyIncomingSearchResultComponent } from './admin-notify-search-result/incoming/admin-notify-incoming-search-result.component';
|
||||
import {
|
||||
AdminNotifyOutgoingComponent
|
||||
} from './admin-notify-logs/admin-notify-outgoing/admin-notify-outgoing.component';
|
||||
import { AdminNotifyDetailModalComponent } from './admin-notify-detail-modal/admin-notify-detail-modal.component';
|
||||
import {
|
||||
AdminNotifyOutgoingSearchResultComponent
|
||||
} from "./admin-notify-search-result/outgoing/admin-notify-outgoing-search-result.component";
|
||||
AdminNotifySearchResultComponent
|
||||
} from "./admin-notify-search-result/admin-notify-search-result.component";
|
||||
import { AdminNotifyMessagesService } from "./services/admin-notify-messages.service";
|
||||
|
||||
|
||||
@@ -36,8 +35,7 @@ import { AdminNotifyMessagesService } from "./services/admin-notify-messages.ser
|
||||
AdminNotifyMetricsComponent,
|
||||
AdminNotifyIncomingComponent,
|
||||
AdminNotifyOutgoingComponent,
|
||||
AdminNotifyIncomingSearchResultComponent,
|
||||
AdminNotifyOutgoingSearchResultComponent,
|
||||
AdminNotifySearchResultComponent,
|
||||
AdminNotifyDetailModalComponent
|
||||
]
|
||||
})
|
||||
|
@@ -1,14 +1,14 @@
|
||||
<div class="modal-header">
|
||||
<h4 class="modal-title">Message Detail</h4>
|
||||
<h4 class="modal-title">{{'notify-message-modal.title' | translate}}</h4>
|
||||
<button type="button" class="close" aria-label="Close" (click)="activeModal.dismiss('Cross click')">
|
||||
<span aria-hidden="true">×</span>
|
||||
</button>
|
||||
</div>
|
||||
<div class="d-flex modal-body flex-column p-4">
|
||||
<div class="container p-4">
|
||||
<div *ngFor="let key of notifyMessageKeys">
|
||||
<div class="d-flex w-100 justify-content-between mb-4">
|
||||
<div class="font-weight-bold mr-5">{{ key }}</div>
|
||||
<div class="text-nowrap text-truncate">{{ notifyMessage[key] }}</div>
|
||||
<div class="row mb-4">
|
||||
<div class="font-weight-bold col-sm">{{ key + '.notify-detail-modal' | translate}}</div>
|
||||
<div class="text-nowrap col-sm text-right">{{ notifyMessage[key] }}</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
@@ -21,7 +21,6 @@
|
||||
[showViewModes]="false"
|
||||
[searchEnabled]="false"
|
||||
[context]="context"
|
||||
[useUniquePageId]="true"
|
||||
></ds-themed-search>
|
||||
</div>
|
||||
</div>
|
||||
|
@@ -16,7 +16,7 @@ import { SearchConfigurationService } from "../../../../core/shared/search/searc
|
||||
]
|
||||
})
|
||||
export class AdminNotifyIncomingComponent {
|
||||
protected readonly context = Context.CoarNotifyIncoming;
|
||||
protected readonly context = Context.CoarNotify;
|
||||
constructor(@Inject(SEARCH_CONFIG_SERVICE) public searchConfigService: SearchConfigurationService) {
|
||||
}
|
||||
}
|
||||
|
@@ -21,7 +21,6 @@
|
||||
[showViewModes]="false"
|
||||
[searchEnabled]="false"
|
||||
[context]="context"
|
||||
[useUniquePageId]="true"
|
||||
></ds-themed-search>
|
||||
</div>
|
||||
</div>
|
||||
|
@@ -16,7 +16,7 @@ import { SearchConfigurationService } from "../../../../core/shared/search/searc
|
||||
]
|
||||
})
|
||||
export class AdminNotifyOutgoingComponent {
|
||||
protected readonly context = Context.CoarNotifyOutgoing;
|
||||
protected readonly context = Context.CoarNotify;
|
||||
|
||||
constructor(@Inject(SEARCH_CONFIG_SERVICE) public searchConfigService: SearchConfigurationService) {
|
||||
}
|
||||
|
@@ -0,0 +1,43 @@
|
||||
<div class="table-responsive mt-2">
|
||||
<table class="table table-striped table-hover">
|
||||
<thead>
|
||||
<tr class="text-nowrap">
|
||||
<th scope="col">{{ 'notify-message-result.timestamp' | translate}}</th>
|
||||
<th scope="col">{{'notify-message-result.repositoryItem' | translate}}</th>
|
||||
<th scope="col">{{ 'notify-message-result.ldnService' | translate}}</th>
|
||||
<th scope="col">{{ 'notify-message-result.type' | translate }}</th>
|
||||
<th scope="col">{{ 'notify-message-result.status' | translate }}</th>
|
||||
<th scope="col">{{ 'notify-message-result.action' | translate }}</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr *ngFor="let message of (messagesSubject$ | async)">
|
||||
<td>
|
||||
<div>{{message.queueTimeout}}</div>
|
||||
</td>
|
||||
<td>
|
||||
<div *ngIf="isInbound">{{message.context}}</div>
|
||||
<div *ngIf="!isInbound">{{message.object}}</div>
|
||||
</td>
|
||||
<td>
|
||||
<div *ngIf="isInbound">{{message.origin}}</div>
|
||||
<div *ngIf="!isInbound">{{message.target}}</div>
|
||||
</td>
|
||||
<td>
|
||||
<div>{{message.coarNotifyType}}</div>
|
||||
</td>
|
||||
<td>
|
||||
<div>{{message.queueStatusLabel}}</div>
|
||||
</td>
|
||||
<td>
|
||||
<div class="d-flex flex-column">
|
||||
<button class="btn mb-2 btn-dark" (click)="openDetailModal(message)">{{ 'notify-message-result.detail' | translate }}</button>
|
||||
<button *ngIf="message.queueStatusLabel === reprocessStatus" (click)="reprocessMessage(message)" class="btn btn-warning">
|
||||
{{ 'notify-message-result.reprocess' | translate }}
|
||||
</button>
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
@@ -0,0 +1,22 @@
|
||||
import { ComponentFixture, TestBed } from '@angular/core/testing';
|
||||
import { AdminNotifySearchResultComponent } from './admin-notify-search-result.component';
|
||||
|
||||
describe('AdminNotifySearchResultComponent', () => {
|
||||
let component: AdminNotifySearchResultComponent;
|
||||
let fixture: ComponentFixture<AdminNotifySearchResultComponent>;
|
||||
|
||||
beforeEach(async () => {
|
||||
await TestBed.configureTestingModule({
|
||||
declarations: [ AdminNotifySearchResultComponent ]
|
||||
})
|
||||
.compileComponents();
|
||||
|
||||
fixture = TestBed.createComponent(AdminNotifySearchResultComponent);
|
||||
component = fixture.componentInstance;
|
||||
fixture.detectChanges();
|
||||
});
|
||||
|
||||
it('should create', () => {
|
||||
expect(component).toBeTruthy();
|
||||
});
|
||||
});
|
@@ -0,0 +1,122 @@
|
||||
import { ChangeDetectorRef, Component, Inject, OnDestroy, OnInit } from '@angular/core';
|
||||
import { AdminNotifySearchResult } from '../models/admin-notify-message-search-result.model';
|
||||
import { ViewMode } from '../../../core/shared/view-mode.model';
|
||||
import { Context } from '../../../core/shared/context.model';
|
||||
import { AdminNotifyMessage, QueueStatusMap } from '../models/admin-notify-message.model';
|
||||
import {
|
||||
tabulatableObjectsComponent
|
||||
} from '../../../shared/object-collection/shared/tabulatable-objects/tabulatable-objects.decorator';
|
||||
import {
|
||||
TabulatableResultListElementsComponent
|
||||
} from '../../../shared/object-list/search-result-list-element/tabulatable-search-result/tabulatable-result-list-elements.component';
|
||||
import { PaginatedList } from '../../../core/data/paginated-list.model';
|
||||
import { NgbModal } from '@ng-bootstrap/ng-bootstrap';
|
||||
import { AdminNotifyDetailModalComponent } from '../admin-notify-detail-modal/admin-notify-detail-modal.component';
|
||||
import { LdnServicesService } from "../../admin-ldn-services/ldn-services-data/ldn-services-data.service";
|
||||
import { BehaviorSubject, from, Observable, of, scan, Subscription, switchMap } from "rxjs";
|
||||
import { combineLatest, filter, map, mergeMap, tap } from "rxjs/operators";
|
||||
import { getAllSucceededRemoteDataPayload } from "../../../core/shared/operators";
|
||||
import { ItemDataService } from "../../../core/data/item-data.service";
|
||||
import { AdminNotifyMessagesService } from "../services/admin-notify-messages.service";
|
||||
import { SearchConfigurationService } from "../../../core/shared/search/search-configuration.service";
|
||||
import { SEARCH_CONFIG_SERVICE } from "../../../my-dspace-page/my-dspace-page.component";
|
||||
|
||||
@tabulatableObjectsComponent(PaginatedList<AdminNotifySearchResult>, ViewMode.Table, Context.CoarNotify)
|
||||
@Component({
|
||||
selector: 'ds-admin-notify-search-result',
|
||||
templateUrl: './admin-notify-search-result.component.html',
|
||||
styleUrls: ['./admin-notify-search-result.component.scss'],
|
||||
providers: [
|
||||
{
|
||||
provide: SEARCH_CONFIG_SERVICE,
|
||||
useClass: SearchConfigurationService
|
||||
}
|
||||
]
|
||||
})
|
||||
export class AdminNotifySearchResultComponent extends TabulatableResultListElementsComponent<PaginatedList<AdminNotifySearchResult>, AdminNotifySearchResult> implements OnInit, OnDestroy{
|
||||
public messagesSubject$: BehaviorSubject<AdminNotifyMessage[]> = new BehaviorSubject([]);
|
||||
public reprocessStatus = QueueStatusMap.QUEUE_STATUS_QUEUED_FOR_RETRY;
|
||||
//we check on one type of config to render specific table headers
|
||||
public isInbound: boolean;
|
||||
|
||||
/**
|
||||
* Array to track all subscriptions and unsubscribe them onDestroy
|
||||
* @type {Array}
|
||||
*/
|
||||
private subs: Subscription[] = [];
|
||||
|
||||
constructor(private modalService: NgbModal,
|
||||
private adminNotifyMessagesService: AdminNotifyMessagesService,
|
||||
@Inject(SEARCH_CONFIG_SERVICE) public searchConfigService: SearchConfigurationService) {
|
||||
super();
|
||||
}
|
||||
|
||||
/**
|
||||
* Map messages on init for readable representation
|
||||
*/
|
||||
ngOnInit() {
|
||||
this.mapDetailsToMessages()
|
||||
this.subs.push(this.searchConfigService.getCurrentConfiguration('')
|
||||
.subscribe(configuration => {
|
||||
this.isInbound = configuration === 'NOTIFY.incoming';
|
||||
})
|
||||
);
|
||||
}
|
||||
|
||||
ngOnDestroy() {
|
||||
this.subs.forEach(sub => sub.unsubscribe());
|
||||
}
|
||||
|
||||
/**
|
||||
* Open modal for details visualization
|
||||
* @param message the message to be displayed
|
||||
*/
|
||||
openDetailModal(message: AdminNotifyMessage) {
|
||||
const modalRef = this.modalService.open(AdminNotifyDetailModalComponent);
|
||||
const messageToOpen = {...message};
|
||||
// we delete not necessary or not readable keys
|
||||
if (this.isInbound) {
|
||||
delete messageToOpen.target;
|
||||
delete messageToOpen.object;
|
||||
} else {
|
||||
delete messageToOpen.context;
|
||||
delete messageToOpen.origin;
|
||||
}
|
||||
delete messageToOpen._links;
|
||||
delete messageToOpen.metadata;
|
||||
delete messageToOpen.thumbnail;
|
||||
delete messageToOpen.item;
|
||||
delete messageToOpen.accessStatus;
|
||||
delete messageToOpen.queueStatus;
|
||||
|
||||
const messageKeys = Object.keys(messageToOpen);
|
||||
modalRef.componentInstance.notifyMessage = messageToOpen;
|
||||
modalRef.componentInstance.notifyMessageKeys = messageKeys;
|
||||
}
|
||||
|
||||
/**
|
||||
* Reprocess message in status QUEUE_STATUS_QUEUED_FOR_RETRY and update results
|
||||
* @param message the message to be reprocessed
|
||||
*/
|
||||
reprocessMessage(message: AdminNotifyMessage) {
|
||||
this.subs.push(
|
||||
this.adminNotifyMessagesService.reprocessMessage(message, this.messagesSubject$)
|
||||
.subscribe(response => {
|
||||
this.messagesSubject$.next(response)
|
||||
}
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Map readable results to messages
|
||||
* @private
|
||||
*/
|
||||
private mapDetailsToMessages() {
|
||||
this.subs.push(this.adminNotifyMessagesService.getDetailedMessages(this.objects?.page.map(pageResult => pageResult.indexableObject))
|
||||
.subscribe(response => {
|
||||
this.messagesSubject$.next(response)
|
||||
}))
|
||||
}
|
||||
}
|
@@ -1,40 +0,0 @@
|
||||
|
||||
<div class="table-responsive mt-2">
|
||||
<table class="table table-striped table-hover">
|
||||
<thead>
|
||||
<tr>
|
||||
<th scope="col">Timestamp</th>
|
||||
<th scope="col">LDN Service</th>
|
||||
<th scope="col">Repository Item</th>
|
||||
<th scope="col">Type</th>
|
||||
<th scope="col">Status</th>
|
||||
<th scope="col">Action</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr *ngFor="let message of (notifyMessages$ | async)">
|
||||
<td>
|
||||
<div>{{message.queueTimeout}}</div>
|
||||
</td>
|
||||
<td>
|
||||
<div>{{message.origin}}</div>
|
||||
</td>
|
||||
<td>
|
||||
<div>{{message.context}}</div>
|
||||
</td>
|
||||
<td>
|
||||
<div>{{message.coarNotifyType}}</div>
|
||||
</td>
|
||||
<td>
|
||||
<div>{{message.queueStatusLabel}}</div>
|
||||
</td>
|
||||
<td>
|
||||
<div class="d-flex flex-column">
|
||||
<button class="btn mb-2 btn-dark" (click)="openDetailModal(message)">Detail</button>
|
||||
<button *ngIf="message.queueStatusLabel === reprocessStatus" (click)="reprocessMessage(message)" class="btn btn-warning">Reprocess</button>
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
@@ -1,22 +0,0 @@
|
||||
import { ComponentFixture, TestBed } from '@angular/core/testing';
|
||||
import { AdminNotifyIncomingSearchResultComponent } from './admin-notify-incoming-search-result.component';
|
||||
|
||||
describe('AdminNotifySearchResultComponent', () => {
|
||||
let component: AdminNotifyIncomingSearchResultComponent;
|
||||
let fixture: ComponentFixture<AdminNotifyIncomingSearchResultComponent>;
|
||||
|
||||
beforeEach(async () => {
|
||||
await TestBed.configureTestingModule({
|
||||
declarations: [ AdminNotifyIncomingSearchResultComponent ]
|
||||
})
|
||||
.compileComponents();
|
||||
|
||||
fixture = TestBed.createComponent(AdminNotifyIncomingSearchResultComponent);
|
||||
component = fixture.componentInstance;
|
||||
fixture.detectChanges();
|
||||
});
|
||||
|
||||
it('should create', () => {
|
||||
expect(component).toBeTruthy();
|
||||
});
|
||||
});
|
@@ -1,97 +0,0 @@
|
||||
import { Component, OnInit } from '@angular/core';
|
||||
import { AdminNotifySearchResult } from '../../models/admin-notify-message-search-result.model';
|
||||
import { ViewMode } from '../../../../core/shared/view-mode.model';
|
||||
import { Context } from '../../../../core/shared/context.model';
|
||||
import { AdminNotifyMessage, QueueStatusMap } from '../../models/admin-notify-message.model';
|
||||
import {
|
||||
tabulatableObjectsComponent
|
||||
} from '../../../../shared/object-collection/shared/tabulatable-objects/tabulatable-objects.decorator';
|
||||
import {
|
||||
TabulatableResultListElementsComponent
|
||||
} from '../../../../shared/object-list/search-result-list-element/tabulatable-search-result/tabulatable-result-list-elements.component';
|
||||
import { PaginatedList } from '../../../../core/data/paginated-list.model';
|
||||
import { NgbModal } from '@ng-bootstrap/ng-bootstrap';
|
||||
import { AdminNotifyDetailModalComponent } from '../../admin-notify-detail-modal/admin-notify-detail-modal.component';
|
||||
import { LdnServicesService } from "../../../admin-ldn-services/ldn-services-data/ldn-services-data.service";
|
||||
import { BehaviorSubject, concatMap, from, Observable, of, scan, switchMap } from "rxjs";
|
||||
import { RemoteData } from "../../../../core/data/remote-data";
|
||||
import { LdnService } from "../../../admin-ldn-services/ldn-services-model/ldn-services.model";
|
||||
import { filter, map, mergeMap, take, tap, toArray } from "rxjs/operators";
|
||||
import { getAllSucceededRemoteDataPayload } from "../../../../core/shared/operators";
|
||||
import { ItemDataService } from "../../../../core/data/item-data.service";
|
||||
import { AdminNotifyMessagesService } from "../../services/admin-notify-messages.service";
|
||||
|
||||
@tabulatableObjectsComponent(PaginatedList<AdminNotifySearchResult>, ViewMode.Table, Context.CoarNotifyIncoming)
|
||||
@Component({
|
||||
selector: 'ds-admin-notify-search-result',
|
||||
templateUrl: './admin-notify-incoming-search-result.component.html',
|
||||
styleUrls: ['./admin-notify-incoming-search-result.component.scss']
|
||||
})
|
||||
export class AdminNotifyIncomingSearchResultComponent extends TabulatableResultListElementsComponent<PaginatedList<AdminNotifySearchResult>, AdminNotifySearchResult> implements OnInit{
|
||||
public notifyMessages: AdminNotifyMessage[];
|
||||
public notifyMessages$: Observable<AdminNotifyMessage[]>;
|
||||
public reprocessStatus = QueueStatusMap.QUEUE_STATUS_QUEUED_FOR_RETRY;
|
||||
|
||||
|
||||
|
||||
constructor(private modalService: NgbModal,
|
||||
private ldnServicesService: LdnServicesService,
|
||||
private itemDataService: ItemDataService,
|
||||
private adminNotifyMessagesService: AdminNotifyMessagesService) {
|
||||
super();
|
||||
}
|
||||
|
||||
/**
|
||||
* Map messages on init for readable representation
|
||||
*/
|
||||
ngOnInit() {
|
||||
this.notifyMessages = this.objects?.page.map(object => {
|
||||
const indexableObject = object.indexableObject;
|
||||
indexableObject.coarNotifyType = indexableObject.coarNotifyType.split(':')[1];
|
||||
indexableObject.queueStatusLabel = QueueStatusMap[indexableObject.queueStatusLabel];
|
||||
return indexableObject;
|
||||
});
|
||||
|
||||
this.notifyMessages$ = from(this.notifyMessages).pipe(
|
||||
mergeMap(message => of(message)),
|
||||
mergeMap(message =>
|
||||
message.origin ? this.ldnServicesService.findById(message.origin.toString()).pipe(
|
||||
getAllSucceededRemoteDataPayload(),
|
||||
map(detail => ({...message, origin: detail.name}))
|
||||
) : of(message),
|
||||
),
|
||||
mergeMap(message =>
|
||||
message.context ? this.itemDataService.findById(message.context.toString()).pipe(
|
||||
getAllSucceededRemoteDataPayload(),
|
||||
map(detail => ({...message, context: detail.name}))
|
||||
) : of(message),
|
||||
),
|
||||
scan((acc: any, value: any) => [...acc, value], []),
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Open modal for details visualization
|
||||
* @param message the message to be displayed
|
||||
*/
|
||||
openDetailModal(message: AdminNotifyMessage) {
|
||||
const modalRef = this.modalService.open(AdminNotifyDetailModalComponent);
|
||||
const messageKeys = Object.keys(message);
|
||||
const keysToRead = [];
|
||||
messageKeys.forEach((key) => {
|
||||
if (typeof message[key] !== 'object') {
|
||||
keysToRead.push(key);
|
||||
}
|
||||
});
|
||||
modalRef.componentInstance.notifyMessage = message;
|
||||
modalRef.componentInstance.notifyMessageKeys = keysToRead;
|
||||
}
|
||||
|
||||
/**
|
||||
* Reprocess message in status QUEUE_STATUS_QUEUED_FOR_RETRY and update results
|
||||
* @param message
|
||||
*/
|
||||
reprocessMessage(message: AdminNotifyMessage) {
|
||||
// TODO implement reprocess
|
||||
}
|
||||
}
|
@@ -1,39 +0,0 @@
|
||||
<div class="table-responsive mt-2">
|
||||
<table class="table table-striped table-hover">
|
||||
<thead>
|
||||
<tr>
|
||||
<th scope="col">Timestamp</th>
|
||||
<th scope="col">Repository Item</th>
|
||||
<th scope="col">LDN Service</th>
|
||||
<th scope="col">Type</th>
|
||||
<th scope="col">Status</th>
|
||||
<th scope="col">Action</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr *ngFor="let message of (notifyMessages$ | async)">
|
||||
<td>
|
||||
<div>{{message.queueTimeout}}</div>
|
||||
</td>
|
||||
<td>
|
||||
<div>{{message.object}}</div>
|
||||
</td>
|
||||
<td>
|
||||
<div>{{message.target}}</div>
|
||||
</td>
|
||||
<td>
|
||||
<div>{{message.coarNotifyType}}</div>
|
||||
</td>
|
||||
<td>
|
||||
<div>{{message.queueStatusLabel}}</div>
|
||||
</td>
|
||||
<td>
|
||||
<div class="d-flex flex-column">
|
||||
<button class="btn mb-2 btn-dark" (click)="openDetailModal(message)">Detail</button>
|
||||
<button *ngIf="message.queueStatusLabel === reprocessStatus" (click)="reprocessMessage(message)" class="btn btn-warning">Reprocess</button>
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
@@ -1,22 +0,0 @@
|
||||
import { ComponentFixture, TestBed } from '@angular/core/testing';
|
||||
import { AdminNotifyOutgoingSearchResultComponent } from './admin-notify-outgoing-search-result.component';
|
||||
|
||||
describe('AdminNotifySearchResultComponent', () => {
|
||||
let component: AdminNotifyOutgoingSearchResultComponent;
|
||||
let fixture: ComponentFixture<AdminNotifyOutgoingSearchResultComponent>;
|
||||
|
||||
beforeEach(async () => {
|
||||
await TestBed.configureTestingModule({
|
||||
declarations: [ AdminNotifyOutgoingSearchResultComponent ]
|
||||
})
|
||||
.compileComponents();
|
||||
|
||||
fixture = TestBed.createComponent(AdminNotifyOutgoingSearchResultComponent);
|
||||
component = fixture.componentInstance;
|
||||
fixture.detectChanges();
|
||||
});
|
||||
|
||||
it('should create', () => {
|
||||
expect(component).toBeTruthy();
|
||||
});
|
||||
});
|
@@ -1,98 +0,0 @@
|
||||
import { Component, OnInit } from '@angular/core';
|
||||
import { AdminNotifySearchResult } from '../../models/admin-notify-message-search-result.model';
|
||||
import { ViewMode } from '../../../../core/shared/view-mode.model';
|
||||
import { Context } from '../../../../core/shared/context.model';
|
||||
import { AdminNotifyMessage, QueueStatusMap } from '../../models/admin-notify-message.model';
|
||||
import {
|
||||
tabulatableObjectsComponent
|
||||
} from '../../../../shared/object-collection/shared/tabulatable-objects/tabulatable-objects.decorator';
|
||||
import {
|
||||
TabulatableResultListElementsComponent
|
||||
} from '../../../../shared/object-list/search-result-list-element/tabulatable-search-result/tabulatable-result-list-elements.component';
|
||||
import { PaginatedList } from '../../../../core/data/paginated-list.model';
|
||||
import { NgbModal } from '@ng-bootstrap/ng-bootstrap';
|
||||
import { AdminNotifyDetailModalComponent } from '../../admin-notify-detail-modal/admin-notify-detail-modal.component';
|
||||
import { LdnServicesService } from "../../../admin-ldn-services/ldn-services-data/ldn-services-data.service";
|
||||
import { from, Observable, of, scan, switchMap } from "rxjs";
|
||||
import { combineLatest, filter, map, mergeMap } from "rxjs/operators";
|
||||
import { getAllSucceededRemoteDataPayload } from "../../../../core/shared/operators";
|
||||
import { ItemDataService } from "../../../../core/data/item-data.service";
|
||||
import { AdminNotifyMessagesService } from "../../services/admin-notify-messages.service";
|
||||
|
||||
@tabulatableObjectsComponent(PaginatedList<AdminNotifySearchResult>, ViewMode.Table, Context.CoarNotifyOutgoing)
|
||||
@Component({
|
||||
selector: 'ds-admin-notify-search-result',
|
||||
templateUrl: './admin-notify-outgoing-search-result.component.html',
|
||||
styleUrls: ['./admin-notify-outgoing-search-result.component.scss']
|
||||
})
|
||||
export class AdminNotifyOutgoingSearchResultComponent extends TabulatableResultListElementsComponent<PaginatedList<AdminNotifySearchResult>, AdminNotifySearchResult> implements OnInit{
|
||||
public notifyMessages: AdminNotifyMessage[];
|
||||
public notifyMessages$: Observable<AdminNotifyMessage[]>;
|
||||
public reprocessStatus = QueueStatusMap.QUEUE_STATUS_QUEUED_FOR_RETRY;
|
||||
|
||||
constructor(private modalService: NgbModal,
|
||||
private ldnServicesService: LdnServicesService,
|
||||
private itemDataService: ItemDataService,
|
||||
private adminNotifyMessagesService: AdminNotifyMessagesService) {
|
||||
super();
|
||||
}
|
||||
|
||||
/**
|
||||
* Map messages on init for readable representation
|
||||
*/
|
||||
ngOnInit() {
|
||||
this.mapDetailsToMessages()
|
||||
}
|
||||
|
||||
/**
|
||||
* Open modal for details visualization
|
||||
* @param message the message to be displayed
|
||||
*/
|
||||
openDetailModal(message: AdminNotifyMessage) {
|
||||
const modalRef = this.modalService.open(AdminNotifyDetailModalComponent);
|
||||
const messageKeys = Object.keys(message);
|
||||
modalRef.componentInstance.notifyMessage = message;
|
||||
modalRef.componentInstance.notifyMessageKeys = messageKeys;
|
||||
}
|
||||
|
||||
/**
|
||||
* Reprocess message in status QUEUE_STATUS_QUEUED_FOR_RETRY and update results
|
||||
* @param message
|
||||
*/
|
||||
reprocessMessage(message: AdminNotifyMessage) {
|
||||
this.adminNotifyMessagesService.findById(message.id).pipe(getAllSucceededRemoteDataPayload()).subscribe(response => {
|
||||
console.log(response);
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Map readable results to messages
|
||||
* @private
|
||||
*/
|
||||
private mapDetailsToMessages() {
|
||||
this.notifyMessages = this.objects?.page.map(object => {
|
||||
const indexableObject = object.indexableObject;
|
||||
indexableObject.coarNotifyType = indexableObject.coarNotifyType.split(':')[1];
|
||||
indexableObject.queueStatusLabel = QueueStatusMap[indexableObject.queueStatusLabel];
|
||||
return indexableObject;
|
||||
});
|
||||
|
||||
this.notifyMessages$ = from(this.notifyMessages).pipe(
|
||||
mergeMap(message => of(message)),
|
||||
mergeMap(message =>
|
||||
message.target ? this.ldnServicesService.findById(message.target.toString()).pipe(
|
||||
getAllSucceededRemoteDataPayload(),
|
||||
map(detail => ({...message, target: detail.name}))
|
||||
) : of(message),
|
||||
),
|
||||
mergeMap(message =>
|
||||
message.object ? this.itemDataService.findById(message.object.toString()).pipe(
|
||||
getAllSucceededRemoteDataPayload(),
|
||||
map(detail => ({...message, object: detail.name}))
|
||||
) : of(message),
|
||||
),
|
||||
scan((acc: any, value: any) => [...acc, value], []),
|
||||
)
|
||||
}
|
||||
}
|
@@ -1,10 +1,11 @@
|
||||
import { autoserialize, deserialize, inheritSerialization } from 'cerialize';
|
||||
import { autoserialize, autoserializeAs, deserialize, inheritSerialization } from 'cerialize';
|
||||
import { typedObject } from '../../../core/cache/builders/build-decorators';
|
||||
import { ADMIN_NOTIFY_MESSAGE } from './admin-notify-message.resource-type';
|
||||
import { excludeFromEquals } from '../../../core/utilities/equals.decorators';
|
||||
import { DSpaceObject } from '../../../core/shared/dspace-object.model';
|
||||
import { GenericConstructor } from '../../../core/shared/generic-constructor';
|
||||
import { ListableObject } from '../../../shared/object-collection/shared/listable-object.model';
|
||||
import { Observable } from "rxjs";
|
||||
|
||||
export enum QueueStatusMap {
|
||||
QUEUE_STATUS_PROCESSED = 'Processed',
|
||||
@@ -107,6 +108,25 @@ export class AdminNotifyMessage extends DSpaceObject {
|
||||
@autoserialize
|
||||
queueStatus: number;
|
||||
|
||||
/**
|
||||
* Thumbnail link used when browsing items with showThumbs config enabled.
|
||||
*/
|
||||
@autoserialize
|
||||
thumbnail: string;
|
||||
|
||||
/**
|
||||
* The observable pointing to the item itself
|
||||
*/
|
||||
@autoserialize
|
||||
item: Observable<AdminNotifyMessage>;
|
||||
|
||||
/**
|
||||
* The observable pointing to the access status of the item
|
||||
*/
|
||||
@autoserialize
|
||||
accessStatus: Observable<AdminNotifyMessage>;
|
||||
|
||||
|
||||
|
||||
@deserialize
|
||||
_links: {
|
||||
|
@@ -10,7 +10,7 @@ import {HALEndpointService} from '../../../core/shared/hal-endpoint.service';
|
||||
import {NotificationsService} from '../../../shared/notifications/notifications.service';
|
||||
import {FindListOptions} from '../../../core/data/find-list-options.model';
|
||||
import {FollowLinkConfig} from '../../../shared/utils/follow-link-config.model';
|
||||
import {Observable} from 'rxjs';
|
||||
import { BehaviorSubject, from, Observable, of, scan } from 'rxjs';
|
||||
import {RemoteData} from '../../../core/data/remote-data';
|
||||
import {PaginatedList} from '../../../core/data/paginated-list.model';
|
||||
import {NoContent} from '../../../core/shared/NoContent.model';
|
||||
@@ -21,7 +21,13 @@ import {RestRequestMethod} from '../../../core/data/rest-request-method';
|
||||
import {CreateData, CreateDataImpl} from '../../../core/data/base/create-data';
|
||||
import {SearchDataImpl} from '../../../core/data/base/search-data';
|
||||
import { ADMIN_NOTIFY_MESSAGE } from "../models/admin-notify-message.resource-type";
|
||||
import { AdminNotifyMessage } from "../models/admin-notify-message.model";
|
||||
import { AdminNotifyMessage, QueueStatusMap } from "../models/admin-notify-message.model";
|
||||
import { SearchResult } from "../../../shared/search/models/search-result.model";
|
||||
import { map, mergeMap } from "rxjs/operators";
|
||||
import { getAllSucceededRemoteDataPayload } from "../../../core/shared/operators";
|
||||
import { AdminNotifySearchResult } from "../models/admin-notify-message-search-result.model";
|
||||
import { LdnServicesService } from "../../admin-ldn-services/ldn-services-data/ldn-services-data.service";
|
||||
import { ItemDataService } from "../../../core/data/item-data.service";
|
||||
|
||||
/**
|
||||
* Injectable service responsible for fetching/sending data from/to the REST API on the messages endpoint.
|
||||
@@ -39,7 +45,77 @@ export class AdminNotifyMessagesService extends IdentifiableDataService<AdminNot
|
||||
protected objectCache: ObjectCacheService,
|
||||
protected halService: HALEndpointService,
|
||||
protected notificationsService: NotificationsService,
|
||||
private ldnServicesService: LdnServicesService,
|
||||
private itemDataService: ItemDataService,
|
||||
) {
|
||||
super('messages', requestService, rdbService, objectCache, halService);
|
||||
}
|
||||
|
||||
/**
|
||||
* Map labels to readable info for user
|
||||
* @param message the message to which map the labels
|
||||
*/
|
||||
public formatMessageLabels(message: AdminNotifyMessage) : AdminNotifyMessage {
|
||||
message.coarNotifyType = message.coarNotifyType?.split(':')[1];
|
||||
message.queueStatusLabel = QueueStatusMap[message.queueStatusLabel];
|
||||
return message;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add detailed information to each message
|
||||
* @param messages the messages to which add detailded info
|
||||
*/
|
||||
public getDetailedMessages(messages: AdminNotifyMessage[]) : Observable<AdminNotifyMessage[]> {
|
||||
return from(messages.map(message => this.formatMessageLabels(message))).pipe(
|
||||
mergeMap(message =>
|
||||
message.target ? this.ldnServicesService.findById(message.target.toString()).pipe(
|
||||
getAllSucceededRemoteDataPayload(),
|
||||
map(detail => ({...message, target: detail.name}))
|
||||
) : of(message),
|
||||
),
|
||||
mergeMap(message =>
|
||||
message.object ? this.itemDataService.findById(message.object.toString()).pipe(
|
||||
getAllSucceededRemoteDataPayload(),
|
||||
map(detail => ({...message, object: detail.name}))
|
||||
) : of(message),
|
||||
),
|
||||
mergeMap(message =>
|
||||
message.origin ? this.ldnServicesService.findById(message.origin.toString()).pipe(
|
||||
getAllSucceededRemoteDataPayload(),
|
||||
map(detail => ({...message, origin: detail.name}))
|
||||
) : of(message),
|
||||
),
|
||||
mergeMap(message =>
|
||||
message.context ? this.itemDataService.findById(message.context.toString()).pipe(
|
||||
getAllSucceededRemoteDataPayload(),
|
||||
map(detail => ({...message, context: detail.name}))
|
||||
) : of(message),
|
||||
),
|
||||
scan((acc: any, value: any) => [...acc, value], []),
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Reprocess message in status QUEUE_STATUS_QUEUED_FOR_RETRY and update results
|
||||
* @param message the message to reprocess
|
||||
* @param messageSubject the current visualised messages source
|
||||
*/
|
||||
public reprocessMessage(message: AdminNotifyMessage, messageSubject: BehaviorSubject<AdminNotifyMessage[]>) : Observable<AdminNotifyMessage[]> {
|
||||
return this.findById(message.id).pipe(
|
||||
getAllSucceededRemoteDataPayload(),
|
||||
map(reprocessedMessage => this.formatMessageLabels(reprocessedMessage)),
|
||||
mergeMap((newMessage) => messageSubject.pipe(
|
||||
map(messages => {
|
||||
const messageToUpdate = messages.find(currentMessage => currentMessage.id === message.id);
|
||||
const indexOfMessageToUpdate = messages.indexOf(messageToUpdate);
|
||||
newMessage.target = messageToUpdate.target;
|
||||
newMessage.object = messageToUpdate.object;
|
||||
newMessage.origin = messageToUpdate.origin;
|
||||
newMessage.context = messageToUpdate.context;
|
||||
messages[indexOfMessageToUpdate] = newMessage;
|
||||
return messages
|
||||
})
|
||||
)),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
@@ -40,6 +40,5 @@ export enum Context {
|
||||
|
||||
Bitstream = 'bitstream',
|
||||
|
||||
CoarNotifyIncoming = 'coarNotifyIncoming',
|
||||
CoarNotifyOutgoing = 'coarNotifyOutgoing',
|
||||
CoarNotify = 'coarNotify',
|
||||
}
|
||||
|
@@ -3529,7 +3529,51 @@
|
||||
|
||||
"sorting.queue_attempts.ASC": "Queue attempted Ascending",
|
||||
|
||||
"orgunit.listelement.badge": "Organizational Unit",
|
||||
"type.notify-detail-modal": "Type",
|
||||
|
||||
"id.notify-detail-modal": "Id",
|
||||
|
||||
"coarNotifyType.notify-detail-modal": "Coar Notify type",
|
||||
|
||||
"activityStreamType.notify-detail-modal": "Activity stream type",
|
||||
|
||||
"inReplyTo.notify-detail-modal": "In reply to",
|
||||
|
||||
"object.notify-detail-modal": "Repository Item",
|
||||
|
||||
"context.notify-detail-modal": "Repository Item",
|
||||
|
||||
"queueAttempts.notify-detail-modal": "Queue attempts",
|
||||
|
||||
"queueLastStartTime.notify-detail-modal": "Queue last started",
|
||||
|
||||
"origin.notify-detail-modal": "LDN Service",
|
||||
|
||||
"target.notify-detail-modal": "LDN Service",
|
||||
|
||||
"queueStatusLabel.notify-detail-modal": "Queue status",
|
||||
|
||||
"queueTimeout.notify-detail-modal": "Queue timeout",
|
||||
|
||||
"notify-message-modal.title": "Message Detail",
|
||||
|
||||
"notify-message-result.timestamp": "Timestamp",
|
||||
|
||||
"notify-message-result.repositoryItem": "Repository Item",
|
||||
|
||||
"notify-message-result.ldnService": "LDN Service",
|
||||
|
||||
"notify-message-result.type": "Type",
|
||||
|
||||
"notify-message-result.status": "Status",
|
||||
|
||||
"notify-message-result.action": "Action",
|
||||
|
||||
"notify-message-result.detail": "Detail",
|
||||
|
||||
"notify-message-result.reprocess": "Reprocess",
|
||||
|
||||
"orgunit.listelement.badge": "Repository Item",
|
||||
|
||||
"orgunit.listelement.no-title": "Untitled",
|
||||
|
||||
|
Reference in New Issue
Block a user