mirror of
https://github.com/DSpace/dspace-angular.git
synced 2025-10-07 01:54:15 +00:00
Merge pull request #983 from atmire/collection-mapper
Collection mapper
This commit is contained in:
@@ -2,7 +2,7 @@
|
|||||||
<div class="row">
|
<div class="row">
|
||||||
<div class="col-12">
|
<div class="col-12">
|
||||||
<h2>{{'collection.edit.item-mapper.head' | translate}}</h2>
|
<h2>{{'collection.edit.item-mapper.head' | translate}}</h2>
|
||||||
<p [innerHTML]="'collection.edit.item-mapper.collection' | translate:{ name: (collectionRD$ | async)?.payload?.name }" id="collection-name"></p>
|
<p [innerHTML]="'collection.edit.item-mapper.collection' | translate:{ name: (collectionName$ |async) }" id="collection-name"></p>
|
||||||
<p>{{'collection.edit.item-mapper.description' | translate}}</p>
|
<p>{{'collection.edit.item-mapper.description' | translate}}</p>
|
||||||
|
|
||||||
<ngb-tabset (tabChange)="tabChange($event)" [destroyOnHide]="true" #tabs="ngbTabset">
|
<ngb-tabset (tabChange)="tabChange($event)" [destroyOnHide]="true" #tabs="ngbTabset">
|
||||||
|
@@ -6,7 +6,6 @@ import { CommonModule } from '@angular/common';
|
|||||||
import { TranslateModule, TranslateService } from '@ngx-translate/core';
|
import { TranslateModule, TranslateService } from '@ngx-translate/core';
|
||||||
import { SearchFormComponent } from '../../shared/search-form/search-form.component';
|
import { SearchFormComponent } from '../../shared/search-form/search-form.component';
|
||||||
import { ActivatedRoute, Router } from '@angular/router';
|
import { ActivatedRoute, Router } from '@angular/router';
|
||||||
import { ActivatedRouteStub } from '../../shared/testing/active-router.stub';
|
|
||||||
import { RouterStub } from '../../shared/testing/router.stub';
|
import { RouterStub } from '../../shared/testing/router.stub';
|
||||||
import { SearchServiceStub } from '../../shared/testing/search-service.stub';
|
import { SearchServiceStub } from '../../shared/testing/search-service.stub';
|
||||||
import { NotificationsService } from '../../shared/notifications/notifications.service';
|
import { NotificationsService } from '../../shared/notifications/notifications.service';
|
||||||
@@ -28,7 +27,7 @@ import { ItemSelectComponent } from '../../shared/object-select/item-select/item
|
|||||||
import { ObjectSelectService } from '../../shared/object-select/object-select.service';
|
import { ObjectSelectService } from '../../shared/object-select/object-select.service';
|
||||||
import { ObjectSelectServiceStub } from '../../shared/testing/object-select-service.stub';
|
import { ObjectSelectServiceStub } from '../../shared/testing/object-select-service.stub';
|
||||||
import { VarDirective } from '../../shared/utils/var.directive';
|
import { VarDirective } from '../../shared/utils/var.directive';
|
||||||
import { of as observableOf, of } from 'rxjs';
|
import { of as observableOf } from 'rxjs/internal/observable/of';
|
||||||
import { RouteService } from '../../core/services/route.service';
|
import { RouteService } from '../../core/services/route.service';
|
||||||
import { ErrorComponent } from '../../shared/error/error.component';
|
import { ErrorComponent } from '../../shared/error/error.component';
|
||||||
import { LoadingComponent } from '../../shared/loading/loading.component';
|
import { LoadingComponent } from '../../shared/loading/loading.component';
|
||||||
@@ -66,7 +65,7 @@ describe('CollectionItemMapperComponent', () => {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
const mockCollectionRD: RemoteData<Collection> = createSuccessfulRemoteDataObject(mockCollection);
|
const mockCollectionRD: RemoteData<Collection> = createSuccessfulRemoteDataObject(mockCollection);
|
||||||
const mockSearchOptions = of(new PaginatedSearchOptions({
|
const mockSearchOptions = observableOf(new PaginatedSearchOptions({
|
||||||
pagination: Object.assign(new PaginationComponentOptions(), {
|
pagination: Object.assign(new PaginationComponentOptions(), {
|
||||||
id: 'search-page-configuration',
|
id: 'search-page-configuration',
|
||||||
pageSize: 10,
|
pageSize: 10,
|
||||||
@@ -88,23 +87,34 @@ describe('CollectionItemMapperComponent', () => {
|
|||||||
const emptyList = createSuccessfulRemoteDataObject(createPaginatedList([]));
|
const emptyList = createSuccessfulRemoteDataObject(createPaginatedList([]));
|
||||||
const itemDataServiceStub = {
|
const itemDataServiceStub = {
|
||||||
mapToCollection: () => createSuccessfulRemoteDataObject$({}),
|
mapToCollection: () => createSuccessfulRemoteDataObject$({}),
|
||||||
findAllByHref: () => of(emptyList)
|
findAllByHref: () => observableOf(emptyList)
|
||||||
|
};
|
||||||
|
const activatedRouteStub = {
|
||||||
|
parent: {
|
||||||
|
data: observableOf({
|
||||||
|
dso: mockCollectionRD
|
||||||
|
})
|
||||||
|
},
|
||||||
|
snapshot: {
|
||||||
|
queryParamMap: new Map([
|
||||||
|
['query', 'test'],
|
||||||
|
])
|
||||||
|
}
|
||||||
};
|
};
|
||||||
const activatedRouteStub = new ActivatedRouteStub({}, { dso: mockCollectionRD });
|
|
||||||
const translateServiceStub = {
|
const translateServiceStub = {
|
||||||
get: () => of('test-message of collection ' + mockCollection.name),
|
get: () => observableOf('test-message of collection ' + mockCollection.name),
|
||||||
onLangChange: new EventEmitter(),
|
onLangChange: new EventEmitter(),
|
||||||
onTranslationChange: new EventEmitter(),
|
onTranslationChange: new EventEmitter(),
|
||||||
onDefaultLangChange: new EventEmitter()
|
onDefaultLangChange: new EventEmitter()
|
||||||
};
|
};
|
||||||
const searchServiceStub = Object.assign(new SearchServiceStub(), {
|
const searchServiceStub = Object.assign(new SearchServiceStub(), {
|
||||||
search: () => of(emptyList),
|
search: () => observableOf(emptyList),
|
||||||
/* tslint:disable:no-empty */
|
/* tslint:disable:no-empty */
|
||||||
clearDiscoveryRequests: () => {}
|
clearDiscoveryRequests: () => {}
|
||||||
/* tslint:enable:no-empty */
|
/* tslint:enable:no-empty */
|
||||||
});
|
});
|
||||||
const collectionDataServiceStub = {
|
const collectionDataServiceStub = {
|
||||||
getMappedItems: () => of(emptyList),
|
getMappedItems: () => observableOf(emptyList),
|
||||||
/* tslint:disable:no-empty */
|
/* tslint:disable:no-empty */
|
||||||
clearMappedItemsRequests: () => {}
|
clearMappedItemsRequests: () => {}
|
||||||
/* tslint:enable:no-empty */
|
/* tslint:enable:no-empty */
|
||||||
|
@@ -1,6 +1,7 @@
|
|||||||
import { BehaviorSubject, combineLatest as observableCombineLatest, Observable } from 'rxjs';
|
import { BehaviorSubject, combineLatest as observableCombineLatest, Observable } from 'rxjs';
|
||||||
|
|
||||||
import { ChangeDetectionStrategy, Component, Inject, OnInit, ViewChild } from '@angular/core';
|
import { ChangeDetectionStrategy, Component, Inject, OnInit, ViewChild } from '@angular/core';
|
||||||
|
import { DSONameService } from '../../core/breadcrumbs/dso-name.service';
|
||||||
import { fadeIn, fadeInOut } from '../../shared/animations/fade';
|
import { fadeIn, fadeInOut } from '../../shared/animations/fade';
|
||||||
import { ActivatedRoute, Router } from '@angular/router';
|
import { ActivatedRoute, Router } from '@angular/router';
|
||||||
import { RemoteData } from '../../core/data/remote-data';
|
import { RemoteData } from '../../core/data/remote-data';
|
||||||
@@ -8,9 +9,10 @@ import { Collection } from '../../core/shared/collection.model';
|
|||||||
import { PaginatedList } from '../../core/data/paginated-list.model';
|
import { PaginatedList } from '../../core/data/paginated-list.model';
|
||||||
import { map, startWith, switchMap, take } from 'rxjs/operators';
|
import { map, startWith, switchMap, take } from 'rxjs/operators';
|
||||||
import {
|
import {
|
||||||
getRemoteDataPayload,
|
getRemoteDataPayload,
|
||||||
getFirstSucceededRemoteData,
|
getFirstSucceededRemoteData,
|
||||||
toDSpaceObjectListRD
|
toDSpaceObjectListRD,
|
||||||
|
getFirstCompletedRemoteData, getAllSucceededRemoteData
|
||||||
} from '../../core/shared/operators';
|
} from '../../core/shared/operators';
|
||||||
import { DSpaceObject } from '../../core/shared/dspace-object.model';
|
import { DSpaceObject } from '../../core/shared/dspace-object.model';
|
||||||
import { DSpaceObjectType } from '../../core/shared/dspace-object-type.model';
|
import { DSpaceObjectType } from '../../core/shared/dspace-object-type.model';
|
||||||
@@ -52,12 +54,13 @@ export class CollectionItemMapperComponent implements OnInit {
|
|||||||
* A view on the tabset element
|
* A view on the tabset element
|
||||||
* Used to switch tabs programmatically
|
* Used to switch tabs programmatically
|
||||||
*/
|
*/
|
||||||
@ViewChild('tabs') tabs;
|
@ViewChild('tabs', {static: false}) tabs;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The collection to map items to
|
* The collection to map items to
|
||||||
*/
|
*/
|
||||||
collectionRD$: Observable<RemoteData<Collection>>;
|
collectionRD$: Observable<RemoteData<Collection>>;
|
||||||
|
collectionName$: Observable<string>;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Search options
|
* Search options
|
||||||
@@ -101,11 +104,21 @@ export class CollectionItemMapperComponent implements OnInit {
|
|||||||
private notificationsService: NotificationsService,
|
private notificationsService: NotificationsService,
|
||||||
private itemDataService: ItemDataService,
|
private itemDataService: ItemDataService,
|
||||||
private collectionDataService: CollectionDataService,
|
private collectionDataService: CollectionDataService,
|
||||||
private translateService: TranslateService) {
|
private translateService: TranslateService,
|
||||||
|
private dsoNameService: DSONameService) {
|
||||||
}
|
}
|
||||||
|
|
||||||
ngOnInit(): void {
|
ngOnInit(): void {
|
||||||
this.collectionRD$ = this.route.data.pipe(map((data) => data.dso)).pipe(getFirstSucceededRemoteData()) as Observable<RemoteData<Collection>>;
|
this.collectionRD$ = this.route.parent.data.pipe(
|
||||||
|
map((data) => data.dso as RemoteData<Collection>),
|
||||||
|
getFirstSucceededRemoteData()
|
||||||
|
);
|
||||||
|
|
||||||
|
this.collectionName$ = this.collectionRD$.pipe(
|
||||||
|
map((rd: RemoteData<Collection>) => {
|
||||||
|
return this.dsoNameService.getName(rd.payload);
|
||||||
|
})
|
||||||
|
);
|
||||||
this.searchOptions$ = this.searchConfigService.paginatedSearchOptions;
|
this.searchOptions$ = this.searchConfigService.paginatedSearchOptions;
|
||||||
this.loadItemLists();
|
this.loadItemLists();
|
||||||
}
|
}
|
||||||
@@ -123,27 +136,27 @@ export class CollectionItemMapperComponent implements OnInit {
|
|||||||
);
|
);
|
||||||
this.collectionItemsRD$ = collectionAndOptions$.pipe(
|
this.collectionItemsRD$ = collectionAndOptions$.pipe(
|
||||||
switchMap(([collectionRD, options, shouldUpdate]) => {
|
switchMap(([collectionRD, options, shouldUpdate]) => {
|
||||||
if (shouldUpdate) {
|
if (shouldUpdate === true) {
|
||||||
this.shouldUpdate$.next(false);
|
this.shouldUpdate$.next(false);
|
||||||
}
|
}
|
||||||
return this.itemDataService.findAllByHref(collectionRD.payload._links.mappedItems.href, Object.assign(options, {
|
return this.itemDataService.findAllByHref(collectionRD.payload._links.mappedItems.href, Object.assign(options, {
|
||||||
sort: this.defaultSortOptions
|
sort: this.defaultSortOptions
|
||||||
}),!shouldUpdate, true, followLink('owningCollection'));
|
}),!shouldUpdate, false, followLink('owningCollection')).pipe(
|
||||||
|
getAllSucceededRemoteData()
|
||||||
|
);
|
||||||
})
|
})
|
||||||
);
|
);
|
||||||
this.mappedItemsRD$ = collectionAndOptions$.pipe(
|
this.mappedItemsRD$ = collectionAndOptions$.pipe(
|
||||||
switchMap(([collectionRD, options, shouldUpdate]) => {
|
switchMap(([collectionRD, options, shouldUpdate]) => {
|
||||||
if (shouldUpdate) {
|
return this.searchService.search(Object.assign(new PaginatedSearchOptions(options), {
|
||||||
return this.searchService.search(Object.assign(new PaginatedSearchOptions(options), {
|
query: this.buildQuery(collectionRD.payload.id, options.query),
|
||||||
query: this.buildQuery(collectionRD.payload.id, options.query),
|
scope: undefined,
|
||||||
scope: undefined,
|
dsoTypes: [DSpaceObjectType.ITEM],
|
||||||
dsoTypes: [DSpaceObjectType.ITEM],
|
sort: this.defaultSortOptions
|
||||||
sort: this.defaultSortOptions
|
}), 10000).pipe(
|
||||||
}), 10000).pipe(
|
toDSpaceObjectListRD(),
|
||||||
toDSpaceObjectListRD(),
|
startWith(undefined)
|
||||||
startWith(undefined)
|
);
|
||||||
);
|
|
||||||
}
|
|
||||||
})
|
})
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@@ -158,8 +171,17 @@ export class CollectionItemMapperComponent implements OnInit {
|
|||||||
getFirstSucceededRemoteData(),
|
getFirstSucceededRemoteData(),
|
||||||
map((collectionRD: RemoteData<Collection>) => collectionRD.payload),
|
map((collectionRD: RemoteData<Collection>) => collectionRD.payload),
|
||||||
switchMap((collection: Collection) =>
|
switchMap((collection: Collection) =>
|
||||||
observableCombineLatest(ids.map((id: string) =>
|
observableCombineLatest(ids.map((id: string) => {
|
||||||
remove ? this.itemDataService.removeMappingFromCollection(id, collection.id) : this.itemDataService.mapToCollection(id, collection._links.self.href)
|
if (remove) {
|
||||||
|
return this.itemDataService.removeMappingFromCollection(id, collection.id).pipe(
|
||||||
|
getFirstCompletedRemoteData()
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
return this.itemDataService.mapToCollection(id, collection._links.self.href).pipe(
|
||||||
|
getFirstCompletedRemoteData()
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
))
|
))
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
@@ -187,6 +209,7 @@ export class CollectionItemMapperComponent implements OnInit {
|
|||||||
successMessages.subscribe(([head, content]) => {
|
successMessages.subscribe(([head, content]) => {
|
||||||
this.notificationsService.success(head, content);
|
this.notificationsService.success(head, content);
|
||||||
});
|
});
|
||||||
|
this.shouldUpdate$.next(true);
|
||||||
}
|
}
|
||||||
if (unsuccessful.length > 0) {
|
if (unsuccessful.length > 0) {
|
||||||
const unsuccessMessages = observableCombineLatest(
|
const unsuccessMessages = observableCombineLatest(
|
||||||
@@ -198,8 +221,6 @@ export class CollectionItemMapperComponent implements OnInit {
|
|||||||
this.notificationsService.error(head, content);
|
this.notificationsService.error(head, content);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
// Force an update on all lists and switch back to the first tab
|
|
||||||
this.shouldUpdate$.next(true);
|
|
||||||
this.switchToFirstTab();
|
this.switchToFirstTab();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@@ -9,7 +9,6 @@ import { CreateCollectionPageGuard } from './create-collection-page/create-colle
|
|||||||
import { DeleteCollectionPageComponent } from './delete-collection-page/delete-collection-page.component';
|
import { DeleteCollectionPageComponent } from './delete-collection-page/delete-collection-page.component';
|
||||||
import { EditItemTemplatePageComponent } from './edit-item-template-page/edit-item-template-page.component';
|
import { EditItemTemplatePageComponent } from './edit-item-template-page/edit-item-template-page.component';
|
||||||
import { ItemTemplatePageResolver } from './edit-item-template-page/item-template-page.resolver';
|
import { ItemTemplatePageResolver } from './edit-item-template-page/item-template-page.resolver';
|
||||||
import { CollectionItemMapperComponent } from './collection-item-mapper/collection-item-mapper.component';
|
|
||||||
import { CollectionBreadcrumbResolver } from '../core/breadcrumbs/collection-breadcrumb.resolver';
|
import { CollectionBreadcrumbResolver } from '../core/breadcrumbs/collection-breadcrumb.resolver';
|
||||||
import { DSOBreadcrumbsService } from '../core/breadcrumbs/dso-breadcrumbs.service';
|
import { DSOBreadcrumbsService } from '../core/breadcrumbs/dso-breadcrumbs.service';
|
||||||
import { LinkService } from '../core/cache/builders/link.service';
|
import { LinkService } from '../core/cache/builders/link.service';
|
||||||
@@ -65,12 +64,6 @@ import { LinkMenuItemModel } from '../shared/menu/menu-item/models/link.model';
|
|||||||
path: '',
|
path: '',
|
||||||
component: CollectionPageComponent,
|
component: CollectionPageComponent,
|
||||||
pathMatch: 'full',
|
pathMatch: 'full',
|
||||||
},
|
|
||||||
{
|
|
||||||
path: '/edit/mapper',
|
|
||||||
component: CollectionItemMapperComponent,
|
|
||||||
pathMatch: 'full',
|
|
||||||
canActivate: [AuthenticatedGuard]
|
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
data: {
|
data: {
|
||||||
|
@@ -1,5 +1,6 @@
|
|||||||
import { RouterModule } from '@angular/router';
|
import { RouterModule } from '@angular/router';
|
||||||
import { NgModule } from '@angular/core';
|
import { NgModule } from '@angular/core';
|
||||||
|
import { CollectionItemMapperComponent } from '../collection-item-mapper/collection-item-mapper.component';
|
||||||
import { EditCollectionPageComponent } from './edit-collection-page.component';
|
import { EditCollectionPageComponent } from './edit-collection-page.component';
|
||||||
import { CollectionMetadataComponent } from './collection-metadata/collection-metadata.component';
|
import { CollectionMetadataComponent } from './collection-metadata/collection-metadata.component';
|
||||||
import { CollectionRolesComponent } from './collection-roles/collection-roles.component';
|
import { CollectionRolesComponent } from './collection-roles/collection-roles.component';
|
||||||
@@ -86,7 +87,12 @@ import { ResourcePolicyEditComponent } from '../../shared/resource-policies/edit
|
|||||||
data: { title: 'collection.edit.tabs.authorizations.title', showBreadcrumbs: true }
|
data: { title: 'collection.edit.tabs.authorizations.title', showBreadcrumbs: true }
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
},
|
||||||
|
{
|
||||||
|
path: 'mapper',
|
||||||
|
component: CollectionItemMapperComponent,
|
||||||
|
data: { title: 'collection.edit.tabs.item-mapper.title', showBreadcrumbs: true }
|
||||||
|
},
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
])
|
])
|
||||||
|
@@ -90,6 +90,11 @@ import { ItemPageWithdrawGuard } from './item-page-withdraw.guard';
|
|||||||
path: 'versionhistory',
|
path: 'versionhistory',
|
||||||
component: ItemVersionHistoryComponent,
|
component: ItemVersionHistoryComponent,
|
||||||
data: { title: 'item.edit.tabs.versionhistory.title', showBreadcrumbs: true }
|
data: { title: 'item.edit.tabs.versionhistory.title', showBreadcrumbs: true }
|
||||||
|
},
|
||||||
|
{
|
||||||
|
path: 'mapper',
|
||||||
|
component: ItemCollectionMapperComponent,
|
||||||
|
data: { title: 'item.edit.tabs.item-mapper.title', showBreadcrumbs: true }
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
@@ -2,7 +2,7 @@
|
|||||||
<div class="row">
|
<div class="row">
|
||||||
<div class="col-12">
|
<div class="col-12">
|
||||||
<h2>{{'item.edit.item-mapper.head' | translate}}</h2>
|
<h2>{{'item.edit.item-mapper.head' | translate}}</h2>
|
||||||
<p [innerHTML]="'item.edit.item-mapper.item' | translate:{ name: (itemRD$ | async)?.payload?.name }" id="item-name"></p>
|
<p [innerHTML]="'item.edit.item-mapper.item' | translate:{ name: (itemName$ | async) }" id="item-name"></p>
|
||||||
<p>{{'item.edit.item-mapper.description' | translate}}</p>
|
<p>{{'item.edit.item-mapper.description' | translate}}</p>
|
||||||
|
|
||||||
<ngb-tabset (tabChange)="tabChange($event)" [destroyOnHide]="true" #tabs="ngbTabset">
|
<ngb-tabset (tabChange)="tabChange($event)" [destroyOnHide]="true" #tabs="ngbTabset">
|
||||||
|
@@ -7,7 +7,7 @@ import { ActivatedRoute, Router } from '@angular/router';
|
|||||||
import { RouterTestingModule } from '@angular/router/testing';
|
import { RouterTestingModule } from '@angular/router/testing';
|
||||||
import { NgbModule } from '@ng-bootstrap/ng-bootstrap';
|
import { NgbModule } from '@ng-bootstrap/ng-bootstrap';
|
||||||
import { TranslateModule, TranslateService } from '@ngx-translate/core';
|
import { TranslateModule, TranslateService } from '@ngx-translate/core';
|
||||||
import { of } from 'rxjs';
|
import { of as observableOf } from 'rxjs/internal/observable/of';
|
||||||
import { SortDirection, SortOptions } from '../../../core/cache/models/sort-options.model';
|
import { SortDirection, SortOptions } from '../../../core/cache/models/sort-options.model';
|
||||||
import { CollectionDataService } from '../../../core/data/collection-data.service';
|
import { CollectionDataService } from '../../../core/data/collection-data.service';
|
||||||
import { ItemDataService } from '../../../core/data/item-data.service';
|
import { ItemDataService } from '../../../core/data/item-data.service';
|
||||||
@@ -26,7 +26,6 @@ import { PaginationComponentOptions } from '../../../shared/pagination/paginatio
|
|||||||
import { PaginationComponent } from '../../../shared/pagination/pagination.component';
|
import { PaginationComponent } from '../../../shared/pagination/pagination.component';
|
||||||
import { SearchFormComponent } from '../../../shared/search-form/search-form.component';
|
import { SearchFormComponent } from '../../../shared/search-form/search-form.component';
|
||||||
import { PaginatedSearchOptions } from '../../../shared/search/paginated-search-options.model';
|
import { PaginatedSearchOptions } from '../../../shared/search/paginated-search-options.model';
|
||||||
import { ActivatedRouteStub } from '../../../shared/testing/active-router.stub';
|
|
||||||
import { HostWindowServiceStub } from '../../../shared/testing/host-window-service.stub';
|
import { HostWindowServiceStub } from '../../../shared/testing/host-window-service.stub';
|
||||||
import { NotificationsServiceStub } from '../../../shared/testing/notifications-service.stub';
|
import { NotificationsServiceStub } from '../../../shared/testing/notifications-service.stub';
|
||||||
import { ObjectSelectServiceStub } from '../../../shared/testing/object-select-service.stub';
|
import { ObjectSelectServiceStub } from '../../../shared/testing/object-select-service.stub';
|
||||||
@@ -59,7 +58,7 @@ describe('ItemCollectionMapperComponent', () => {
|
|||||||
name: 'test-item'
|
name: 'test-item'
|
||||||
});
|
});
|
||||||
const mockItemRD: RemoteData<Item> = createSuccessfulRemoteDataObject(mockItem);
|
const mockItemRD: RemoteData<Item> = createSuccessfulRemoteDataObject(mockItem);
|
||||||
const mockSearchOptions = of(new PaginatedSearchOptions({
|
const mockSearchOptions = observableOf(new PaginatedSearchOptions({
|
||||||
pagination: Object.assign(new PaginationComponentOptions(), {
|
pagination: Object.assign(new PaginationComponentOptions(), {
|
||||||
id: 'search-page-configuration',
|
id: 'search-page-configuration',
|
||||||
pageSize: 10,
|
pageSize: 10,
|
||||||
@@ -81,24 +80,30 @@ describe('ItemCollectionMapperComponent', () => {
|
|||||||
const itemDataServiceStub = {
|
const itemDataServiceStub = {
|
||||||
mapToCollection: () => createSuccessfulRemoteDataObject$({}),
|
mapToCollection: () => createSuccessfulRemoteDataObject$({}),
|
||||||
removeMappingFromCollection: () => createSuccessfulRemoteDataObject$({}),
|
removeMappingFromCollection: () => createSuccessfulRemoteDataObject$({}),
|
||||||
getMappedCollectionsEndpoint: () => of('rest/api/mappedCollectionsEndpoint'),
|
getMappedCollectionsEndpoint: () => observableOf('rest/api/mappedCollectionsEndpoint'),
|
||||||
getMappedCollections: () => of(mockCollectionsRD),
|
getMappedCollections: () => observableOf(mockCollectionsRD),
|
||||||
/* tslint:disable:no-empty */
|
/* tslint:disable:no-empty */
|
||||||
clearMappedCollectionsRequests: () => {}
|
clearMappedCollectionsRequests: () => {}
|
||||||
/* tslint:enable:no-empty */
|
/* tslint:enable:no-empty */
|
||||||
};
|
};
|
||||||
const collectionDataServiceStub = {
|
const collectionDataServiceStub = {
|
||||||
findAllByHref: () => of(mockCollectionsRD)
|
findAllByHref: () => observableOf(mockCollectionsRD)
|
||||||
};
|
};
|
||||||
const searchServiceStub = Object.assign(new SearchServiceStub(), {
|
const searchServiceStub = Object.assign(new SearchServiceStub(), {
|
||||||
search: () => of(mockCollectionsRD),
|
search: () => observableOf(mockCollectionsRD),
|
||||||
/* tslint:disable:no-empty */
|
/* tslint:disable:no-empty */
|
||||||
clearDiscoveryRequests: () => {}
|
clearDiscoveryRequests: () => {}
|
||||||
/* tslint:enable:no-empty */
|
/* tslint:enable:no-empty */
|
||||||
});
|
});
|
||||||
const activatedRouteStub = new ActivatedRouteStub({}, { dso: mockItemRD });
|
const activatedRouteStub = {
|
||||||
|
parent: {
|
||||||
|
data: observableOf({
|
||||||
|
dso: mockItemRD
|
||||||
|
})
|
||||||
|
}
|
||||||
|
};
|
||||||
const translateServiceStub = {
|
const translateServiceStub = {
|
||||||
get: () => of('test-message of item ' + mockItem.name),
|
get: () => observableOf('test-message of item ' + mockItem.name),
|
||||||
onLangChange: new EventEmitter(),
|
onLangChange: new EventEmitter(),
|
||||||
onTranslationChange: new EventEmitter(),
|
onTranslationChange: new EventEmitter(),
|
||||||
onDefaultLangChange: new EventEmitter()
|
onDefaultLangChange: new EventEmitter()
|
||||||
|
@@ -1,6 +1,7 @@
|
|||||||
import { BehaviorSubject, combineLatest as observableCombineLatest, Observable } from 'rxjs';
|
import { BehaviorSubject, combineLatest as observableCombineLatest, Observable } from 'rxjs';
|
||||||
|
|
||||||
import { ChangeDetectionStrategy, Component, OnInit, ViewChild } from '@angular/core';
|
import { ChangeDetectionStrategy, Component, OnInit, ViewChild } from '@angular/core';
|
||||||
|
import { DSONameService } from '../../../core/breadcrumbs/dso-name.service';
|
||||||
import { CollectionDataService } from '../../../core/data/collection-data.service';
|
import { CollectionDataService } from '../../../core/data/collection-data.service';
|
||||||
import { fadeIn, fadeInOut } from '../../../shared/animations/fade';
|
import { fadeIn, fadeInOut } from '../../../shared/animations/fade';
|
||||||
import { RemoteData } from '../../../core/data/remote-data';
|
import { RemoteData } from '../../../core/data/remote-data';
|
||||||
@@ -12,15 +13,15 @@ import {
|
|||||||
getRemoteDataPayload,
|
getRemoteDataPayload,
|
||||||
getFirstSucceededRemoteData,
|
getFirstSucceededRemoteData,
|
||||||
toDSpaceObjectListRD,
|
toDSpaceObjectListRD,
|
||||||
getAllSucceededRemoteData
|
getAllSucceededRemoteData, getFirstCompletedRemoteData
|
||||||
} from '../../../core/shared/operators';
|
} from '../../../core/shared/operators';
|
||||||
import { ActivatedRoute, Router } from '@angular/router';
|
import { ActivatedRoute, Router } from '@angular/router';
|
||||||
import { map, startWith, switchMap, take } from 'rxjs/operators';
|
import { filter, map, startWith, switchMap, take } from 'rxjs/operators';
|
||||||
import { ItemDataService } from '../../../core/data/item-data.service';
|
import { ItemDataService } from '../../../core/data/item-data.service';
|
||||||
import { TranslateService } from '@ngx-translate/core';
|
import { TranslateService } from '@ngx-translate/core';
|
||||||
import { NotificationsService } from '../../../shared/notifications/notifications.service';
|
import { NotificationsService } from '../../../shared/notifications/notifications.service';
|
||||||
import { DSpaceObjectType } from '../../../core/shared/dspace-object-type.model';
|
import { DSpaceObjectType } from '../../../core/shared/dspace-object-type.model';
|
||||||
import { isNotEmpty } from '../../../shared/empty.util';
|
import { hasValue, isNotEmpty } from '../../../shared/empty.util';
|
||||||
import { PaginatedSearchOptions } from '../../../shared/search/paginated-search-options.model';
|
import { PaginatedSearchOptions } from '../../../shared/search/paginated-search-options.model';
|
||||||
import { SearchConfigurationService } from '../../../core/shared/search/search-configuration.service';
|
import { SearchConfigurationService } from '../../../core/shared/search/search-configuration.service';
|
||||||
import { SearchService } from '../../../core/shared/search/search.service';
|
import { SearchService } from '../../../core/shared/search/search.service';
|
||||||
@@ -51,6 +52,7 @@ export class ItemCollectionMapperComponent implements OnInit {
|
|||||||
* The item to map to collections
|
* The item to map to collections
|
||||||
*/
|
*/
|
||||||
itemRD$: Observable<RemoteData<Item>>;
|
itemRD$: Observable<RemoteData<Item>>;
|
||||||
|
itemName$: Observable<string>;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Search options
|
* Search options
|
||||||
@@ -88,11 +90,22 @@ export class ItemCollectionMapperComponent implements OnInit {
|
|||||||
private notificationsService: NotificationsService,
|
private notificationsService: NotificationsService,
|
||||||
private itemDataService: ItemDataService,
|
private itemDataService: ItemDataService,
|
||||||
private collectionDataService: CollectionDataService,
|
private collectionDataService: CollectionDataService,
|
||||||
private translateService: TranslateService) {
|
private translateService: TranslateService,
|
||||||
|
private dsoNameService: DSONameService) {
|
||||||
}
|
}
|
||||||
|
|
||||||
ngOnInit(): void {
|
ngOnInit(): void {
|
||||||
this.itemRD$ = this.route.data.pipe(map((data) => data.dso)).pipe(getFirstSucceededRemoteData()) as Observable<RemoteData<Item>>;
|
this.itemRD$ = this.route.parent.data.pipe(
|
||||||
|
take(1),
|
||||||
|
map((data) => data.dso),
|
||||||
|
);
|
||||||
|
|
||||||
|
this.itemName$ = this.itemRD$.pipe(
|
||||||
|
filter((rd: RemoteData<Item>) => hasValue(rd)),
|
||||||
|
map((rd: RemoteData<Item>) => {
|
||||||
|
return this.dsoNameService.getName(rd.payload);
|
||||||
|
})
|
||||||
|
);
|
||||||
this.searchOptions$ = this.searchConfigService.paginatedSearchOptions;
|
this.searchOptions$ = this.searchConfigService.paginatedSearchOptions;
|
||||||
this.loadCollectionLists();
|
this.loadCollectionLists();
|
||||||
}
|
}
|
||||||
@@ -122,7 +135,8 @@ export class ItemCollectionMapperComponent implements OnInit {
|
|||||||
|
|
||||||
const owningCollectionRD$ = this.itemRD$.pipe(
|
const owningCollectionRD$ = this.itemRD$.pipe(
|
||||||
getFirstSucceededRemoteDataPayload(),
|
getFirstSucceededRemoteDataPayload(),
|
||||||
switchMap((item: Item) => this.collectionDataService.findOwningCollectionFor(item))
|
switchMap((item: Item) => this.collectionDataService.findOwningCollectionFor(item)),
|
||||||
|
getAllSucceededRemoteData(),
|
||||||
);
|
);
|
||||||
const itemCollectionsAndOptions$ = observableCombineLatest(
|
const itemCollectionsAndOptions$ = observableCombineLatest(
|
||||||
this.itemCollectionsRD$,
|
this.itemCollectionsRD$,
|
||||||
@@ -162,7 +176,12 @@ export class ItemCollectionMapperComponent implements OnInit {
|
|||||||
|
|
||||||
// Map the item to the collections found in ids, excluding the collections the item is already mapped to
|
// Map the item to the collections found in ids, excluding the collections the item is already mapped to
|
||||||
const responses$ = itemIdAndExcludingIds$.pipe(
|
const responses$ = itemIdAndExcludingIds$.pipe(
|
||||||
switchMap(([itemId, excludingIds]) => observableCombineLatest(this.filterIds(ids, excludingIds).map((id: string) => this.itemDataService.mapToCollection(itemId, id))))
|
switchMap(([itemId, excludingIds]) =>
|
||||||
|
observableCombineLatest(
|
||||||
|
this.filterIds(ids, excludingIds).map((id: string) =>
|
||||||
|
this.itemDataService.mapToCollection(itemId, id).pipe(getFirstCompletedRemoteData())
|
||||||
|
))
|
||||||
|
)
|
||||||
);
|
);
|
||||||
|
|
||||||
this.showNotifications(responses$, 'item.edit.item-mapper.notifications.add');
|
this.showNotifications(responses$, 'item.edit.item-mapper.notifications.add');
|
||||||
@@ -176,7 +195,11 @@ export class ItemCollectionMapperComponent implements OnInit {
|
|||||||
const responses$ = this.itemRD$.pipe(
|
const responses$ = this.itemRD$.pipe(
|
||||||
getFirstSucceededRemoteData(),
|
getFirstSucceededRemoteData(),
|
||||||
map((itemRD: RemoteData<Item>) => itemRD.payload.id),
|
map((itemRD: RemoteData<Item>) => itemRD.payload.id),
|
||||||
switchMap((itemId: string) => observableCombineLatest(ids.map((id: string) => this.itemDataService.removeMappingFromCollection(itemId, id))))
|
switchMap((itemId: string) => observableCombineLatest(
|
||||||
|
ids.map((id: string) =>
|
||||||
|
this.itemDataService.removeMappingFromCollection(itemId, id).pipe(getFirstCompletedRemoteData())
|
||||||
|
))
|
||||||
|
)
|
||||||
);
|
);
|
||||||
|
|
||||||
this.showNotifications(responses$, 'item.edit.item-mapper.notifications.remove');
|
this.showNotifications(responses$, 'item.edit.item-mapper.notifications.remove');
|
||||||
|
@@ -649,6 +649,10 @@
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
"collection.edit.tabs.mapper.head": "Item Mapper",
|
||||||
|
|
||||||
|
"collection.edit.tabs.item-mapper.title": "Collection Edit - Item Mapper",
|
||||||
|
|
||||||
"collection.edit.item-mapper.cancel": "Cancel",
|
"collection.edit.item-mapper.cancel": "Cancel",
|
||||||
|
|
||||||
"collection.edit.item-mapper.collection": "Collection: \"<b>{{name}}</b>\"",
|
"collection.edit.item-mapper.collection": "Collection: \"<b>{{name}}</b>\"",
|
||||||
@@ -1462,6 +1466,9 @@
|
|||||||
"item.edit.breadcrumbs": "Edit Item",
|
"item.edit.breadcrumbs": "Edit Item",
|
||||||
|
|
||||||
|
|
||||||
|
"item.edit.tabs.mapper.head": "Collection Mapper",
|
||||||
|
|
||||||
|
"item.edit.tabs.item-mapper.title": "Item Edit - Collection Mapper",
|
||||||
|
|
||||||
"item.edit.item-mapper.buttons.add": "Map item to selected collections",
|
"item.edit.item-mapper.buttons.add": "Map item to selected collections",
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user