5590: Item move component

This commit is contained in:
Yana De Pauw
2018-10-25 18:14:22 +02:00
parent 8570ff2578
commit d26bba8e14
15 changed files with 351 additions and 140 deletions

View File

@@ -103,6 +103,16 @@
"curate": { "curate": {
"head": "Curate" "head": "Curate"
} }
},
"move": {
"head":"Move item: {{id}}",
"description": "Select the collection you wish to move this item to. To narrow down the list of displayed collections, you can enter a search query in the box.",
"inheritpolicies": {
"description": "Inherit the default policies of the destination collection",
"checkbox": "Inherit policies"
},
"move": "Move",
"cancel": "Cancel"
} }
} }
}, },

View File

@@ -4,15 +4,21 @@ import { SharedModule } from '../../shared/shared.module';
import { EditItemPageRoutingModule } from './edit-item-page.routing.module'; import { EditItemPageRoutingModule } from './edit-item-page.routing.module';
import { EditItemPageComponent } from './edit-item-page.component'; import { EditItemPageComponent } from './edit-item-page.component';
import { ItemStatusComponent } from './item-status/item-status.component'; import { ItemStatusComponent } from './item-status/item-status.component';
import {ItemOperationComponent} from './item-operation/item-operation.component';
import {ItemMoveComponent} from './item-move/item-move.component';
import {SearchPageModule} from '../../+search-page/search-page.module';
@NgModule({ @NgModule({
imports: [ imports: [
CommonModule, CommonModule,
SharedModule, SharedModule,
EditItemPageRoutingModule EditItemPageRoutingModule,
SearchPageModule.forRoot(),
], ],
declarations: [ declarations: [
EditItemPageComponent, EditItemPageComponent,
ItemOperationComponent,
ItemMoveComponent,
ItemStatusComponent ItemStatusComponent
] ]
}) })

View File

@@ -1,7 +1,16 @@
import { ItemPageResolver } from '../item-page.resolver'; import {ItemPageResolver} from '../item-page.resolver';
import { NgModule } from '@angular/core'; import {NgModule} from '@angular/core';
import { RouterModule } from '@angular/router'; import {RouterModule} from '@angular/router';
import { EditItemPageComponent } from './edit-item-page.component'; import {EditItemPageComponent} from './edit-item-page.component';
import {ItemMoveComponent} from './item-move/item-move.component';
import {URLCombiner} from '../../core/url-combiner/url-combiner';
import {getItemEditPath} from '../item-page-routing.module';
const ITEM_EDIT_MOVE_PATH = 'move';
export function getItemEditMovePath(id: string) {
return new URLCombiner(getItemEditPath(id), ITEM_EDIT_MOVE_PATH);
}
@NgModule({ @NgModule({
imports: [ imports: [
@@ -12,6 +21,13 @@ import { EditItemPageComponent } from './edit-item-page.component';
resolve: { resolve: {
item: ItemPageResolver item: ItemPageResolver
} }
},
{
path: ITEM_EDIT_MOVE_PATH,
component: ItemMoveComponent,
resolve: {
item: ItemPageResolver
}
} }
]) ])
], ],

View File

@@ -1,51 +1,41 @@
import {Component, OnInit} from '@angular/core'; <div class="container">
import {Collection} from '../../../core/shared/collection.model'; <div class="row">
import {RemoteData} from '../../../core/data/remote-data'; <div class="col-12">
import {Item} from '../../../core/shared/item.model'; <h2>{{'item.edit.move.head' | translate: { id: (itemRD$ | async)?.payload?.id} }}</h2>
import {getSucceededRemoteData} from '../../../core/shared/operators'; <p>{{'item.edit.move.description' | translate}}</p>
import {Observable} from 'rxjs'; <div class="row">
import {PaginatedList} from '../../../core/data/paginated-list'; <div class="col-12">
import {TranslateService} from '@ngx-translate/core'; <ds-input-suggestions #f id="search-form"
import {NotificationsService} from '../../../shared/notifications/notifications.service'; [suggestions]="(filterSearchResults | async)"
import {SearchService} from '../../../+search-page/search-service/search.service'; [placeholder]="'item.move.search.placeholder'| translate"
import {SearchConfigurationService} from '../../../+search-page/search-service/search-configuration.service'; [action]="getCurrentUrl()"
import {ActivatedRoute, Router} from '@angular/router'; [name]="'item-move'"
import {CollectionDataService} from '../../../core/data/collection-data.service'; [(ngModel)]="selectedCollection"
(clickSuggestion)="onClick($event)"
(findSuggestions)="findSuggestions($event)"
(click)="f.open()"
ngDefaultControl>
</ds-input-suggestions>
</div>
</div>
<div class="row">
<div class="col-12">
<p>
<input type="checkbox" name="tc" [(ngModel)]="inheritPolicies" id="inheritPoliciesCheckbox">
<label for="inheritPoliciesCheckbox">{{'item.edit.move.inheritpolicies.checkbox' |
translate}}</label>
</p>
<p>
{{'item.edit.move.inheritpolicies.description' | translate}}
</p>
</div>
</div>
@Component({ <button (click)="moveCollection()" class="btn btn-outline-secondary">{{'item.edit.move.move' | translate}}
selector: 'ds-item-move', </button>
templateUrl: './item-move.component.html' <button [routerLink]="['/items/', (itemRD$ | async)?.payload?.id]" class="btn btn-outline-secondary">
}) {{'item.edit.move.cancel' | translate}}
export class ItemMoveComponent implements OnInit { </button>
inheritPolicies: boolean; </div>
</div>
itemRD$: Observable<RemoteData<Item>>; </div>
/**
* List of collections to show under the "Browse" tab
* Collections that are mapped to the item
*/
itemCollectionsRD$: Observable<RemoteData<PaginatedList<Collection>>>;
constructor(private route: ActivatedRoute,
private router: Router,
private searchConfigService: SearchConfigurationService,
private searchService: SearchService,
private notificationsService: NotificationsService,
private collectionDataService: CollectionDataService,
private translateService: TranslateService) {
}
ngOnInit(): void {
this.itemRD$ = this.route.data.map((data) => data.item).pipe(getSucceededRemoteData()) as Observable<RemoteData<Item>>;
this.loadCollectionLists();
}
/**
* Load all available collections to move the item to.
* TODO: When the API support it, only fetch collections where user has ADD rights to.
*/
loadCollectionLists() {
this.itemCollectionsRD$ = this.collectionDataService.findAll();
}
}

View File

@@ -0,0 +1,111 @@
import {Component, OnInit} from '@angular/core';
import {SearchService} from '../../../+search-page/search-service/search.service';
import {Observable} from 'rxjs/Observable';
import {map} from 'rxjs/operators';
import {DSpaceObjectType} from '../../../core/shared/dspace-object-type.model';
import {SearchOptions} from '../../../+search-page/search-options.model';
import {RemoteData} from '../../../core/data/remote-data';
import {DSpaceObject} from '../../../core/shared/dspace-object.model';
import {PaginatedList} from '../../../core/data/paginated-list';
import {SearchResult} from '../../../+search-page/search-result.model';
import {PaginatedSearchOptions} from '../../../+search-page/paginated-search-options.model';
import {Item} from '../../../core/shared/item.model';
import {ActivatedRoute, Router} from '@angular/router';
import {NotificationsService} from '../../../shared/notifications/notifications.service';
import {CollectionDataService} from '../../../core/data/collection-data.service';
import {SearchConfigurationService} from '../../../+search-page/search-service/search-configuration.service';
import {TranslateService} from '@ngx-translate/core';
import {getSucceededRemoteData} from '../../../core/shared/operators';
import {ItemDataService} from '../../../core/data/item-data.service';
import {RestResponse} from '../../../core/cache/response-cache.models';
import {getItemEditPath} from '../../item-page-routing.module';
@Component({
selector: 'ds-item-move',
templateUrl: './item-move.component.html'
})
export class ItemMoveComponent implements OnInit {
inheritPolicies = false;
itemRD$: Observable<RemoteData<Item>>;
/**
* Search options
*/
searchOptions$: Observable<PaginatedSearchOptions>;
filterSearchResults: Observable<any[]> = Observable.of([]);
selectedCollection: string;
selectedCollectionId: string;
itemId: string;
constructor(private route: ActivatedRoute,
private router: Router,
private notificationsService: NotificationsService,
private collectionDataService: CollectionDataService,
private itemDataService: ItemDataService,
private searchConfigService: SearchConfigurationService,
private searchService: SearchService,
private translateService: TranslateService) {
}
ngOnInit(): void {
this.itemRD$ = this.route.data.map((data) => data.item).pipe(getSucceededRemoteData()) as Observable<RemoteData<Item>>;
this.itemRD$.first().subscribe((rd) => {
this.itemId = rd.payload.id;
}
);
this.searchOptions$ = this.searchConfigService.paginatedSearchOptions;
this.loadSuggestions('');
}
findSuggestions(query): void {
this.loadSuggestions(query);
}
/**
* Load all available collections to move the item to.
* TODO: When the API support it, only fetch collections where user has ADD rights to.
*/
loadSuggestions(query): void {
this.filterSearchResults = this.searchService.search(new SearchOptions({
dsoType: DSpaceObjectType.COLLECTION,
query: query
})).first().pipe(
map((rd: RemoteData<PaginatedList<SearchResult<DSpaceObject>>>) => {
return rd.payload.page.map((searchResult) => {
return {
displayValue: searchResult.dspaceObject.name,
value: {name: searchResult.dspaceObject.name, id: searchResult.dspaceObject.uuid}
};
});
})
);
}
onClick(data: any): void {
this.selectedCollection = data.name;
this.selectedCollectionId = data.id;
}
/**
* @returns {string} the current URL
*/
getCurrentUrl() {
return this.router.url;
}
moveCollection() {
this.itemDataService.moveToCollection(this.itemId, this.selectedCollectionId).first().subscribe(
(response: RestResponse) => {
this.router.navigate([getItemEditPath(this.itemId)]);
if (response.isSuccessful) {
this.notificationsService.success(this.translateService.get('item.move.success'));
} else {
this.notificationsService.error(this.translateService.get('item.move.error'));
}
}
);
}
}

View File

@@ -1,10 +1,15 @@
import {Component} from '@angular/core'; <div class="col-3 float-left d-flex h-100 action-label">
<span class="justify-content-center align-self-center">
@Component({ {{'item.edit.tabs.status.buttons.' + operation.operationKey + '.label' | translate}}
selector: 'ds-item-operation', </span>
templateUrl: './ds-item-operation.html' </div>
}) <div *ngIf="!operation.disabled" class="col-9 float-left action-button">
<a class="btn btn-outline-secondary" href="{{operation.operationUrl}}">
export class ItemOperationComponent { {{'item.edit.tabs.status.buttons.' + operation.operationKey + '.button' | translate}}
</a>
} </div>
<div *ngIf="operation.disabled" class="col-9 float-left action-button">
<span class="btn btn-danger">
{{'item.edit.tabs.status.buttons.' + operation.operationKey + '.button' | translate}}
</span>
</div>

View File

@@ -0,0 +1,13 @@
import {Component, Input} from '@angular/core';
import {ItemOperation} from './itemOperation.model';
@Component({
selector: 'ds-item-operation',
templateUrl: './item-operation.component.html'
})
export class ItemOperationComponent {
@Input() operation: ItemOperation;
}

View File

@@ -0,0 +1,12 @@
export class ItemOperation {
operationKey: string;
operationUrl: string;
disabled: boolean;
constructor(operationKey: string, operationUrl: string) {
this.operationKey = operationKey;
this.operationUrl = operationUrl;
}
}

View File

@@ -15,16 +15,7 @@
<a href="{{getItemPage()}}">{{getItemPage()}}</a> <a href="{{getItemPage()}}">{{getItemPage()}}</a>
</div> </div>
<div *ngFor="let actionKey of actionsKeys" class="w-100 pt-3"> <div *ngFor="let operation of operations" class="w-100 pt-3">
<div class="col-3 float-left d-flex h-100 action-label"> <ds-item-operation [operation]="operation"></ds-item-operation>
<span class="justify-content-center align-self-center">
{{'item.edit.tabs.status.buttons.' + actionKey + '.label' | translate}}
</span>
</div>
<div class="col-9 float-left action-button">
<a class="btn btn-outline-secondary" href="{{actions[actionKey]}}">
{{'item.edit.tabs.status.buttons.' + actionKey + '.button' | translate}}
</a>
</div>
</div> </div>
</div> </div>

View File

@@ -2,6 +2,7 @@ import { ChangeDetectionStrategy, Component, Input, OnInit } from '@angular/core
import { fadeIn, fadeInOut } from '../../../shared/animations/fade'; import { fadeIn, fadeInOut } from '../../../shared/animations/fade';
import { Item } from '../../../core/shared/item.model'; import { Item } from '../../../core/shared/item.model';
import { Router } from '@angular/router'; import { Router } from '@angular/router';
import {ItemOperation} from '../item-operation/itemOperation.model';
@Component({ @Component({
selector: 'ds-item-status', selector: 'ds-item-status',
@@ -35,7 +36,7 @@ export class ItemStatusComponent implements OnInit {
* The possible actions that can be performed on the item * The possible actions that can be performed on the item
* key: id value: url to action's component * key: id value: url to action's component
*/ */
actions: any; operations: ItemOperation[];
/** /**
* The keys of the actions (to loop over) * The keys of the actions (to loop over)
*/ */
@@ -57,11 +58,10 @@ export class ItemStatusComponent implements OnInit {
i18n example: 'item.edit.tabs.status.buttons.<key>.label' i18n example: 'item.edit.tabs.status.buttons.<key>.label'
The value is supposed to be a href for the button The value is supposed to be a href for the button
*/ */
this.actions = Object.assign({ this.operations = [
// TODO: Create mapping component on item level new ItemOperation('mappedCollections',this.getCurrentUrl() + '/'),
mappedCollections: this.getCurrentUrl() + '/' new ItemOperation('move', this.getCurrentUrl() + '/move'),
}); ]
this.actionsKeys = Object.keys(this.actions);
} }
/** /**

View File

@@ -1,10 +1,21 @@
import { NgModule } from '@angular/core'; import {NgModule} from '@angular/core';
import { RouterModule } from '@angular/router'; import {RouterModule} from '@angular/router';
import { ItemPageComponent } from './simple/item-page.component'; import {ItemPageComponent} from './simple/item-page.component';
import { FullItemPageComponent } from './full/full-item-page.component'; import {FullItemPageComponent} from './full/full-item-page.component';
import { ItemPageResolver } from './item-page.resolver'; import {ItemPageResolver} from './item-page.resolver';
import { AuthenticatedGuard } from '../core/auth/authenticated.guard'; import {AuthenticatedGuard} from '../core/auth/authenticated.guard';
import {URLCombiner} from '../core/url-combiner/url-combiner';
import {getItemModulePath} from '../app-routing.module';
export function getItemPageRoute(itemId: string) {
return new URLCombiner(getItemModulePath(), itemId).toString();
}
export function getItemEditPath(id: string) {
return new URLCombiner(getItemModulePath(),ITEM_EDIT_PATH.replace(/:id/, id)).toString()
}
const ITEM_EDIT_PATH = ':id/edit';
@NgModule({ @NgModule({
imports: [ imports: [
@@ -25,7 +36,7 @@ import { AuthenticatedGuard } from '../core/auth/authenticated.guard';
} }
}, },
{ {
path: ':id/edit', path: ITEM_EDIT_PATH,
loadChildren: './edit-item-page/edit-item-page.module#EditItemPageModule', loadChildren: './edit-item-page/edit-item-page.module#EditItemPageModule',
canActivate: [AuthenticatedGuard] canActivate: [AuthenticatedGuard]
} }

View File

@@ -1,38 +1,45 @@
import { NgModule } from '@angular/core'; import {ModuleWithProviders, NgModule} from '@angular/core';
import { CommonModule } from '@angular/common'; import {CommonModule} from '@angular/common';
import { CoreModule } from '../core/core.module'; import {CoreModule} from '../core/core.module';
import { SharedModule } from '../shared/shared.module'; import {SharedModule} from '../shared/shared.module';
import { SearchPageRoutingModule } from './search-page-routing.module'; import {SearchPageRoutingModule} from './search-page-routing.module';
import { SearchPageComponent } from './search-page.component'; import {SearchPageComponent} from './search-page.component';
import { SearchResultsComponent } from './search-results/search-results.component'; import {SearchResultsComponent} from './search-results/search-results.component';
import { ItemSearchResultListElementComponent } from '../shared/object-list/search-result-list-element/item-search-result/item-search-result-list-element.component'; import {ItemSearchResultListElementComponent} from '../shared/object-list/search-result-list-element/item-search-result/item-search-result-list-element.component';
import { CollectionSearchResultListElementComponent } from '../shared/object-list/search-result-list-element/collection-search-result/collection-search-result-list-element.component'; import {CollectionSearchResultListElementComponent} from '../shared/object-list/search-result-list-element/collection-search-result/collection-search-result-list-element.component';
import { CommunitySearchResultListElementComponent } from '../shared/object-list/search-result-list-element/community-search-result/community-search-result-list-element.component'; import {CommunitySearchResultListElementComponent} from '../shared/object-list/search-result-list-element/community-search-result/community-search-result-list-element.component';
import { ItemSearchResultGridElementComponent } from '../shared/object-grid/search-result-grid-element/item-search-result/item-search-result-grid-element.component'; import {ItemSearchResultGridElementComponent} from '../shared/object-grid/search-result-grid-element/item-search-result/item-search-result-grid-element.component';
import { CommunitySearchResultGridElementComponent } from '../shared/object-grid/search-result-grid-element/community-search-result/community-search-result-grid-element.component' import {CommunitySearchResultGridElementComponent} from '../shared/object-grid/search-result-grid-element/community-search-result/community-search-result-grid-element.component';
import { CollectionSearchResultGridElementComponent } from '../shared/object-grid/search-result-grid-element/collection-search-result/collection-search-result-grid-element.component'; import {CollectionSearchResultGridElementComponent} from '../shared/object-grid/search-result-grid-element/collection-search-result/collection-search-result-grid-element.component';
import { SearchService } from './search-service/search.service'; import {SearchService} from './search-service/search.service';
import { SearchSidebarComponent } from './search-sidebar/search-sidebar.component'; import {SearchSidebarComponent} from './search-sidebar/search-sidebar.component';
import { SearchSidebarService } from './search-sidebar/search-sidebar.service'; import {SearchSidebarService} from './search-sidebar/search-sidebar.service';
import { SearchSidebarEffects } from './search-sidebar/search-sidebar.effects'; import {SearchSidebarEffects} from './search-sidebar/search-sidebar.effects';
import { SearchSettingsComponent } from './search-settings/search-settings.component'; import {SearchSettingsComponent} from './search-settings/search-settings.component';
import { EffectsModule } from '@ngrx/effects'; import {EffectsModule} from '@ngrx/effects';
import { SearchFiltersComponent } from './search-filters/search-filters.component'; import {SearchFiltersComponent} from './search-filters/search-filters.component';
import { SearchFilterComponent } from './search-filters/search-filter/search-filter.component'; import {SearchFilterComponent} from './search-filters/search-filter/search-filter.component';
import { SearchFacetFilterComponent } from './search-filters/search-filter/search-facet-filter/search-facet-filter.component'; import {SearchFacetFilterComponent} from './search-filters/search-filter/search-facet-filter/search-facet-filter.component';
import { SearchFilterService } from './search-filters/search-filter/search-filter.service'; import {SearchFilterService} from './search-filters/search-filter/search-filter.service';
import { SearchLabelsComponent } from './search-labels/search-labels.component'; import {SearchLabelsComponent} from './search-labels/search-labels.component';
import { SearchRangeFilterComponent } from './search-filters/search-filter/search-range-filter/search-range-filter.component'; import {SearchRangeFilterComponent} from './search-filters/search-filter/search-range-filter/search-range-filter.component';
import { SearchTextFilterComponent } from './search-filters/search-filter/search-text-filter/search-text-filter.component'; import {SearchTextFilterComponent} from './search-filters/search-filter/search-text-filter/search-text-filter.component';
import { SearchFacetFilterWrapperComponent } from './search-filters/search-filter/search-facet-filter-wrapper/search-facet-filter-wrapper.component'; import {SearchFacetFilterWrapperComponent} from './search-filters/search-filter/search-facet-filter-wrapper/search-facet-filter-wrapper.component';
import { SearchBooleanFilterComponent } from './search-filters/search-filter/search-boolean-filter/search-boolean-filter.component'; import {SearchBooleanFilterComponent} from './search-filters/search-filter/search-boolean-filter/search-boolean-filter.component';
import { SearchHierarchyFilterComponent } from './search-filters/search-filter/search-hierarchy-filter/search-hierarchy-filter.component'; import {SearchHierarchyFilterComponent} from './search-filters/search-filter/search-hierarchy-filter/search-hierarchy-filter.component';
import { SearchConfigurationService } from './search-service/search-configuration.service'; import {SearchConfigurationService} from './search-service/search-configuration.service';
const effects = [ const effects = [
SearchSidebarEffects SearchSidebarEffects
]; ];
const PROVIDERS = [
SearchService,
SearchSidebarService,
SearchFilterService,
SearchConfigurationService
];
@NgModule({ @NgModule({
imports: [ imports: [
SearchPageRoutingModule, SearchPageRoutingModule,
@@ -65,10 +72,7 @@ const effects = [
SearchBooleanFilterComponent, SearchBooleanFilterComponent,
], ],
providers: [ providers: [
SearchService, ...PROVIDERS
SearchSidebarService,
SearchFilterService,
SearchConfigurationService
], ],
entryComponents: [ entryComponents: [
ItemSearchResultListElementComponent, ItemSearchResultListElementComponent,
@@ -89,4 +93,12 @@ const effects = [
* This module handles all components and pipes that are necessary for the search page * This module handles all components and pipes that are necessary for the search page
*/ */
export class SearchPageModule { export class SearchPageModule {
static forRoot(): ModuleWithProviders {
return {
ngModule: CoreModule,
providers: [
...PROVIDERS
]
};
}
} }

View File

@@ -3,6 +3,10 @@ import { RouterModule } from '@angular/router';
import { PageNotFoundComponent } from './pagenotfound/pagenotfound.component'; import { PageNotFoundComponent } from './pagenotfound/pagenotfound.component';
const ITEM_MODULE_PATH = 'items';
export function getItemModulePath() {
return `/${ITEM_MODULE_PATH}`;
}
@NgModule({ @NgModule({
imports: [ imports: [
RouterModule.forRoot([ RouterModule.forRoot([
@@ -10,7 +14,7 @@ import { PageNotFoundComponent } from './pagenotfound/pagenotfound.component';
{ path: 'home', loadChildren: './+home-page/home-page.module#HomePageModule' }, { path: 'home', loadChildren: './+home-page/home-page.module#HomePageModule' },
{ path: 'communities', loadChildren: './+community-page/community-page.module#CommunityPageModule' }, { path: 'communities', loadChildren: './+community-page/community-page.module#CommunityPageModule' },
{ path: 'collections', loadChildren: './+collection-page/collection-page.module#CollectionPageModule' }, { path: 'collections', loadChildren: './+collection-page/collection-page.module#CollectionPageModule' },
{ path: 'items', loadChildren: './+item-page/item-page.module#ItemPageModule' }, { path: ITEM_MODULE_PATH, loadChildren: './+item-page/item-page.module#ItemPageModule' },
{ path: 'search', loadChildren: './+search-page/search-page.module#SearchPageModule' }, { path: 'search', loadChildren: './+search-page/search-page.module#SearchPageModule' },
{ path: 'browse', loadChildren: './+browse-by/browse-by.module#BrowseByModule' }, { path: 'browse', loadChildren: './+browse-by/browse-by.module#BrowseByModule' },
{ path: 'admin', loadChildren: './+admin/admin.module#AdminModule' }, { path: 'admin', loadChildren: './+admin/admin.module#AdminModule' },

View File

@@ -1,21 +1,24 @@
import { Inject, Injectable } from '@angular/core'; import {Injectable} from '@angular/core';
import { Store } from '@ngrx/store'; import {Store} from '@ngrx/store';
import { Observable } from 'rxjs/Observable'; import {Observable} from 'rxjs/Observable';
import { GLOBAL_CONFIG, GlobalConfig } from '../../../config'; import {isNotEmpty, isNotEmptyOperator} from '../../shared/empty.util';
import { isEmpty, isNotEmpty } from '../../shared/empty.util'; import {BrowseService} from '../browse/browse.service';
import { BrowseService } from '../browse/browse.service'; import {RemoteDataBuildService} from '../cache/builders/remote-data-build.service';
import { RemoteDataBuildService } from '../cache/builders/remote-data-build.service'; import {NormalizedItem} from '../cache/models/normalized-item.model';
import { NormalizedItem } from '../cache/models/normalized-item.model'; import {ResponseCacheService} from '../cache/response-cache.service';
import { ResponseCacheService } from '../cache/response-cache.service'; import {CoreState} from '../core.reducers';
import { CoreState } from '../core.reducers'; import {Item} from '../shared/item.model';
import { Item } from '../shared/item.model'; import {URLCombiner} from '../url-combiner/url-combiner';
import { URLCombiner } from '../url-combiner/url-combiner';
import { DataService } from './data.service'; import {DataService} from './data.service';
import { RequestService } from './request.service'; import {RequestService} from './request.service';
import { HALEndpointService } from '../shared/hal-endpoint.service'; import {HALEndpointService} from '../shared/hal-endpoint.service';
import { FindAllOptions } from './request.models'; import {FindAllOptions, PostRequest, RestRequest} from './request.models';
import {distinctUntilChanged, map} from 'rxjs/operators';
import {RestResponse} from '../cache/response-cache.models';
import {configureRequest, getResponseFromSelflink} from '../shared/operators';
import {ResponseCacheEntry} from '../cache/response-cache.reducer';
@Injectable() @Injectable()
export class ItemDataService extends DataService<NormalizedItem, Item> { export class ItemDataService extends DataService<NormalizedItem, Item> {
@@ -48,4 +51,22 @@ export class ItemDataService extends DataService<NormalizedItem, Item> {
.distinctUntilChanged(); .distinctUntilChanged();
} }
public getMoveItemEndpoint(itemId: string, collectionId?: string): Observable<string> {
return this.halService.getEndpoint(this.linkPath).pipe(
map((endpoint: string) => this.getFindByIDHref(endpoint, itemId)),
map((endpoint: string) => `${endpoint}/owningCollection/move/${collectionId ? `/${collectionId}` : ''}`)
);
}
public moveToCollection(itemId: string, collectionId: string): Observable<RestResponse> {
return this.getMoveItemEndpoint(itemId, collectionId).pipe(
// isNotEmptyOperator(),
distinctUntilChanged(),
map((endpointURL: string) => new PostRequest(this.requestService.generateRequestId(), endpointURL)),
configureRequest(this.requestService),
map((request: RestRequest) => request.href),
getResponseFromSelflink(this.responseCache),
map((responseCacheEntry: ResponseCacheEntry) => responseCacheEntry.response)
);
}
} }

View File

@@ -159,6 +159,15 @@ export class InputSuggestionsComponent {
this.show.next(false); this.show.next(false);
} }
/**
* Changes the show variable so the suggestion dropdown opens
*/
open() {
if (!this.blockReopen) {
this.show.next(true);
}
}
/** /**
* For usage of the isNotEmpty function in the template * For usage of the isNotEmpty function in the template
*/ */