mirror of
https://github.com/DSpace/dspace-angular.git
synced 2025-10-17 06:53:03 +00:00
55946: Intermediate commit
This commit is contained in:
@@ -5,11 +5,13 @@ import { EditItemPageRoutingModule } from './edit-item-page.routing.module';
|
||||
import { EditItemPageComponent } from './edit-item-page.component';
|
||||
import { ItemCollectionMapperComponent } from './item-collection-mapper/item-collection-mapper.component';
|
||||
import { ItemStatusComponent } from './item-status/item-status.component';
|
||||
import { SearchPageModule } from '../../+search-page/search-page.module';
|
||||
|
||||
@NgModule({
|
||||
imports: [
|
||||
CommonModule,
|
||||
SharedModule,
|
||||
SearchPageModule,
|
||||
EditItemPageRoutingModule
|
||||
],
|
||||
declarations: [
|
||||
|
@@ -15,7 +15,7 @@ import { ItemCollectionMapperComponent } from './item-collection-mapper/item-col
|
||||
}
|
||||
},
|
||||
{
|
||||
path: 'map',
|
||||
path: 'mapper',
|
||||
component: ItemCollectionMapperComponent,
|
||||
resolve: {
|
||||
item: ItemPageResolver
|
||||
|
@@ -1,7 +1,38 @@
|
||||
<div class="container">
|
||||
<div class="row">
|
||||
<div class="col-12">
|
||||
<p>It works!</p>
|
||||
<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>{{'item.edit.item-mapper.description' | translate}}</p>
|
||||
|
||||
<div class="row">
|
||||
<div class="col-12 col-lg-6">
|
||||
<ds-search-form id="search-form"
|
||||
[query]="(searchOptions$ | async)?.query"
|
||||
[scope]="(searchOptions$ | async)?.scope"
|
||||
[currentUrl]="getCurrentUrl()">
|
||||
</ds-search-form>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<ngb-tabset (tabChange)="tabChange($event)">
|
||||
<ngb-tab title="{{'item.edit.item-mapper.tabs.browse' | translate}}">
|
||||
<ng-template ngbTabContent>
|
||||
<div class="mt-2">
|
||||
<div *ngFor="let col of (itemCollectionsRD$ | async)?.payload">{{col.name}}</div>
|
||||
</div>
|
||||
</ng-template>
|
||||
</ngb-tab>
|
||||
<ngb-tab title="{{'item.edit.item-mapper.tabs.map' | translate}}">
|
||||
<ng-template ngbTabContent>
|
||||
<div class="mt-2">
|
||||
|
||||
</div>
|
||||
</ng-template>
|
||||
</ngb-tab>
|
||||
</ngb-tabset>
|
||||
|
||||
<button [routerLink]="['/items/', (itemRD$ | async)?.payload?.id]" class="btn btn-outline-secondary">{{'item.edit.item-mapper.return' | translate}}</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
@@ -1,5 +1,20 @@
|
||||
import { ChangeDetectionStrategy, Component } from '@angular/core';
|
||||
import { ChangeDetectionStrategy, Component, OnInit } from '@angular/core';
|
||||
import { fadeIn, fadeInOut } from '../../../shared/animations/fade';
|
||||
import { Observable } from 'rxjs/Observable';
|
||||
import { PaginatedSearchOptions } from '../../../+search-page/paginated-search-options.model';
|
||||
import { DSpaceObject } from '../../../core/shared/dspace-object.model';
|
||||
import { SortDirection, SortOptions } from '../../../core/cache/models/sort-options.model';
|
||||
import { RemoteData } from '../../../core/data/remote-data';
|
||||
import { PaginatedList } from '../../../core/data/paginated-list';
|
||||
import { Collection } from '../../../core/shared/collection.model';
|
||||
import { Item } from '../../../core/shared/item.model';
|
||||
import { getSucceededRemoteData } from '../../../core/shared/operators';
|
||||
import { ActivatedRoute, Router } from '@angular/router';
|
||||
import { SearchService } from '../../../+search-page/search-service/search.service';
|
||||
import { SearchConfigurationService } from '../../../+search-page/search-service/search-configuration.service';
|
||||
import { map, switchMap } from 'rxjs/operators';
|
||||
import { CollectionDataService } from '../../../core/data/collection-data.service';
|
||||
import { ItemDataService } from '../../../core/data/item-data.service';
|
||||
|
||||
@Component({
|
||||
selector: 'ds-item-collection-mapper',
|
||||
@@ -14,6 +29,81 @@ import { fadeIn, fadeInOut } from '../../../shared/animations/fade';
|
||||
/**
|
||||
* Component for mapping collections to an item
|
||||
*/
|
||||
export class ItemCollectionMapperComponent {
|
||||
export class ItemCollectionMapperComponent implements OnInit {
|
||||
/**
|
||||
* The item to map to collections
|
||||
*/
|
||||
itemRD$: Observable<RemoteData<Item>>;
|
||||
|
||||
/**
|
||||
* Search options
|
||||
*/
|
||||
searchOptions$: Observable<PaginatedSearchOptions>;
|
||||
|
||||
/**
|
||||
* List of collections to show under the "Browse" tab
|
||||
* Collections that are mapped to the item
|
||||
*/
|
||||
itemCollectionsRD$: Observable<RemoteData<Collection[]>>;
|
||||
|
||||
/**
|
||||
* List of collections to show under the "Map" tab
|
||||
* Collections that are not mapped to the item
|
||||
*/
|
||||
mappingCollectionsRD$: Observable<RemoteData<PaginatedList<Collection>>>;
|
||||
|
||||
/**
|
||||
* Sort on title ASC by default
|
||||
* @type {SortOptions}
|
||||
*/
|
||||
defaultSortOptions: SortOptions = new SortOptions('dc.title', SortDirection.ASC);
|
||||
|
||||
constructor(private route: ActivatedRoute,
|
||||
private router: Router,
|
||||
private searchConfigService: SearchConfigurationService,
|
||||
private searchService: SearchService,
|
||||
private collectionDataService: CollectionDataService,
|
||||
private itemDataService: ItemDataService) {
|
||||
}
|
||||
|
||||
ngOnInit(): void {
|
||||
this.itemRD$ = this.route.data.map((data) => data.item).pipe(getSucceededRemoteData()) as Observable<RemoteData<Item>>;
|
||||
this.searchOptions$ = this.searchConfigService.paginatedSearchOptions;
|
||||
this.loadCollectionLists();
|
||||
}
|
||||
|
||||
/**
|
||||
* Load itemCollectionsRD$ with a fixed scope to only obtain the collections that own this item
|
||||
* Load mappingCollectionsRD$ to only obtain collections that don't own this item
|
||||
* TODO: When the API support it, fetch collections excluding the item's scope (currently fetches all collections)
|
||||
*/
|
||||
loadCollectionLists() {
|
||||
this.itemCollectionsRD$ = this.itemRD$.pipe(
|
||||
map((itemRD: RemoteData<Item>) => itemRD.payload),
|
||||
switchMap((item: Item) => this.itemDataService.getMappedCollections(item.id))
|
||||
);
|
||||
this.mappingCollectionsRD$ = this.collectionDataService.findAll();
|
||||
}
|
||||
|
||||
/**
|
||||
* Clear url parameters on tab change (temporary fix until pagination is improved)
|
||||
* @param event
|
||||
*/
|
||||
tabChange(event) {
|
||||
// TODO: Fix tabs to maintain their own pagination options (once the current pagination system is improved)
|
||||
// Temporary solution: Clear url params when changing tabs
|
||||
this.router.navigateByUrl(this.getCurrentUrl());
|
||||
}
|
||||
|
||||
/**
|
||||
* Get current url without parameters
|
||||
* @returns {string}
|
||||
*/
|
||||
getCurrentUrl(): string {
|
||||
if (this.router.url.indexOf('?') > -1) {
|
||||
return this.router.url.substring(0, this.router.url.indexOf('?'));
|
||||
}
|
||||
return this.router.url;
|
||||
}
|
||||
|
||||
}
|
||||
|
@@ -54,7 +54,7 @@ export class ItemStatusComponent implements OnInit {
|
||||
this.statusDataKeys = Object.keys(this.statusData);
|
||||
|
||||
this.actions = Object.assign({
|
||||
mappedCollections: this.getCurrentUrl() + '/map'
|
||||
mappedCollections: this.getCurrentUrl() + '/mapper'
|
||||
});
|
||||
this.actionsKeys = Object.keys(this.actions);
|
||||
}
|
||||
|
@@ -65,6 +65,7 @@ import { UploaderService } from '../shared/uploader/uploader.service';
|
||||
import { BrowseItemsResponseParsingService } from './data/browse-items-response-parsing-service';
|
||||
import { DSpaceObjectDataService } from './data/dspace-object-data.service';
|
||||
import { ItemSelectService } from '../shared/item-select/item-select.service';
|
||||
import { MappingCollectionsReponseParsingService } from './data/mapping-collections-reponse-parsing.service';
|
||||
|
||||
const IMPORTS = [
|
||||
CommonModule,
|
||||
@@ -111,6 +112,7 @@ const PROVIDERS = [
|
||||
RegistryMetadataschemasResponseParsingService,
|
||||
RegistryMetadatafieldsResponseParsingService,
|
||||
RegistryBitstreamformatsResponseParsingService,
|
||||
MappingCollectionsReponseParsingService,
|
||||
MetadataschemaParsingService,
|
||||
DebugResponseParsingService,
|
||||
SearchResponseParsingService,
|
||||
|
@@ -3,7 +3,7 @@ import { Inject, Injectable } from '@angular/core';
|
||||
import { Store } from '@ngrx/store';
|
||||
import { Observable } from 'rxjs/Observable';
|
||||
import { GLOBAL_CONFIG, GlobalConfig } from '../../../config';
|
||||
import { isEmpty, isNotEmpty, isNotEmptyOperator } from '../../shared/empty.util';
|
||||
import { ensureArrayHasValue, isEmpty, isNotEmpty, isNotEmptyOperator } from '../../shared/empty.util';
|
||||
import { BrowseService } from '../browse/browse.service';
|
||||
import { RemoteDataBuildService } from '../cache/builders/remote-data-build.service';
|
||||
import { NormalizedItem } from '../cache/models/normalized-item.model';
|
||||
@@ -15,11 +15,21 @@ import { URLCombiner } from '../url-combiner/url-combiner';
|
||||
import { DataService } from './data.service';
|
||||
import { RequestService } from './request.service';
|
||||
import { HALEndpointService } from '../shared/hal-endpoint.service';
|
||||
import { FindAllOptions, PostRequest, RestRequest } from './request.models';
|
||||
import { FindAllOptions, GetRequest, MappingCollectionsRequest, PostRequest, RestRequest } from './request.models';
|
||||
import { distinctUntilChanged, map } from 'rxjs/operators';
|
||||
import { configureRequest, getResponseFromSelflink } from '../shared/operators';
|
||||
import {
|
||||
configureRequest,
|
||||
filterSuccessfulResponses,
|
||||
getRequestFromSelflink,
|
||||
getResponseFromSelflink
|
||||
} from '../shared/operators';
|
||||
import { ResponseCacheEntry } from '../cache/response-cache.reducer';
|
||||
import { RestResponse } from '../cache/response-cache.models';
|
||||
import { DSOSuccessResponse, GenericSuccessResponse, RestResponse } from '../cache/response-cache.models';
|
||||
import { BrowseDefinition } from '../shared/browse-definition.model';
|
||||
import { Collection } from '../shared/collection.model';
|
||||
import { NormalizedCollection } from '../cache/models/normalized-collection.model';
|
||||
import { RemoteData } from './remote-data';
|
||||
import { PaginatedList } from './paginated-list';
|
||||
|
||||
@Injectable()
|
||||
export class ItemDataService extends DataService<NormalizedItem, Item> {
|
||||
@@ -71,4 +81,16 @@ export class ItemDataService extends DataService<NormalizedItem, Item> {
|
||||
);
|
||||
}
|
||||
|
||||
public getMappedCollections(itemId: string): Observable<RemoteData<Collection[]>> {
|
||||
const request$ = this.getMappingCollectionsEndpoint(itemId).pipe(
|
||||
isNotEmptyOperator(),
|
||||
distinctUntilChanged(),
|
||||
map((endpointURL: string) => new MappingCollectionsRequest(this.requestService.generateRequestId(), endpointURL)),
|
||||
configureRequest(this.requestService)
|
||||
);
|
||||
|
||||
// TODO: Create a remotedata object
|
||||
return undefined;
|
||||
}
|
||||
|
||||
}
|
||||
|
@@ -0,0 +1,24 @@
|
||||
import { Injectable } from '@angular/core';
|
||||
import { ResponseParsingService } from './parsing.service';
|
||||
import { RestRequest } from './request.models';
|
||||
import { DSpaceRESTV2Response } from '../dspace-rest-v2/dspace-rest-v2-response.model';
|
||||
import { ErrorResponse, GenericSuccessResponse, RestResponse } from '../cache/response-cache.models';
|
||||
|
||||
@Injectable()
|
||||
export class MappingCollectionsReponseParsingService implements ResponseParsingService {
|
||||
parse(request: RestRequest, data: DSpaceRESTV2Response): RestResponse {
|
||||
const payload = data.payload;
|
||||
|
||||
if (payload._embedded && payload._embedded.mappingCollections) {
|
||||
const mappingCollections = payload._embedded.mappingCollections;
|
||||
return new GenericSuccessResponse(mappingCollections, data.statusCode);
|
||||
} else {
|
||||
return new ErrorResponse(
|
||||
Object.assign(
|
||||
new Error('Unexpected response from mappingCollections endpoint'),
|
||||
{ statusText: data.statusCode }
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
@@ -13,6 +13,7 @@ import { HttpOptions } from '../dspace-rest-v2/dspace-rest-v2.service';
|
||||
import { HttpHeaders } from '@angular/common/http';
|
||||
import { IntegrationResponseParsingService } from '../integration/integration-response-parsing.service';
|
||||
import { BrowseItemsResponseParsingService } from './browse-items-response-parsing-service';
|
||||
import { MappingCollectionsReponseParsingService } from './mapping-collections-reponse-parsing.service';
|
||||
|
||||
/* tslint:disable:max-classes-per-file */
|
||||
|
||||
@@ -191,6 +192,12 @@ export class BrowseItemsRequest extends GetRequest {
|
||||
}
|
||||
}
|
||||
|
||||
export class MappingCollectionsRequest extends GetRequest {
|
||||
getResponseParser(): GenericConstructor<ResponseParsingService> {
|
||||
return MappingCollectionsReponseParsingService;
|
||||
}
|
||||
}
|
||||
|
||||
export class ConfigRequest extends GetRequest {
|
||||
constructor(uuid: string, href: string) {
|
||||
super(uuid, href);
|
||||
|
Reference in New Issue
Block a user