mirror of
https://github.com/DSpace/dspace-angular.git
synced 2025-10-17 23:13:04 +00:00
finished second selection tab
This commit is contained in:
@@ -524,6 +524,9 @@
|
||||
"search.filters.applied.f.namedresourcetype": "Status",
|
||||
"search.filters.applied.f.subject": "Subject",
|
||||
"search.filters.applied.f.submitter": "Submitter",
|
||||
"search.filters.applied.f.jobTitle": "Job Title",
|
||||
"search.filters.applied.f.birthDate.max": "End birth date",
|
||||
"search.filters.applied.f.birthDate.min": "Start birth date",
|
||||
"search.filters.filter.author.head": "Author",
|
||||
"search.filters.filter.author.placeholder": "Author name",
|
||||
"search.filters.filter.birthDate.head": "Birth Date",
|
||||
@@ -603,19 +606,30 @@
|
||||
"submission.general.save-later": "Save for later",
|
||||
"submission.mydspace": {},
|
||||
"submission.sections.describe.relationship-lookup.close": "Close",
|
||||
"submission.sections.describe.relationship-lookup.deselect-all": "Deselect all",
|
||||
"submission.sections.describe.relationship-lookup.deselect-page": "Deselect page",
|
||||
"submission.sections.describe.relationship-lookup.loading": "Loading...",
|
||||
"submission.sections.describe.relationship-lookup.placeholder": "Search query",
|
||||
"submission.sections.describe.relationship-lookup.search": "Go",
|
||||
"submission.sections.describe.relationship-lookup.select-all": "Select all",
|
||||
"submission.sections.describe.relationship-lookup.select-page": "Select page",
|
||||
"submission.sections.describe.relationship-lookup.search-tab.deselect-all": "Deselect all",
|
||||
"submission.sections.describe.relationship-lookup.search-tab.deselect-page": "Deselect page",
|
||||
"submission.sections.describe.relationship-lookup.search-tab.loading": "Loading...",
|
||||
"submission.sections.describe.relationship-lookup.search-tab.placeholder": "Search query",
|
||||
"submission.sections.describe.relationship-lookup.search-tab.search": "Go",
|
||||
"submission.sections.describe.relationship-lookup.search-tab.select-all": "Select all",
|
||||
"submission.sections.describe.relationship-lookup.search-tab.select-page": "Select page",
|
||||
"submission.sections.describe.relationship-lookup.selected": "Selected {{ size }} items",
|
||||
"submission.sections.describe.relationship-lookup.title.Journal Issue": "Select a Journal Issue",
|
||||
"submission.sections.describe.relationship-lookup.title.Journal Volume": "Select a Journal Volume",
|
||||
"submission.sections.describe.relationship-lookup.title.Journal": "Select a Journal",
|
||||
"submission.sections.describe.relationship-lookup.title.Author": "Select an Author",
|
||||
"submission.sections.describe.relationship-lookup.toggle-dropdown": "Toggle dropdown",
|
||||
"submission.sections.describe.relationship-lookup.search-tab.tab-title.Author": "Search for Authors",
|
||||
"submission.sections.describe.relationship-lookup.search-tab.tab-title.Journal": "Search for Journals",
|
||||
"submission.sections.describe.relationship-lookup.search-tab.tab-title.Journal Issue": "Search for Journal Issues",
|
||||
"submission.sections.describe.relationship-lookup.search-tab.tab-title.Journal Volume": "Search for Journal Volumes",
|
||||
"submission.sections.describe.relationship-lookup.selection-tab.tab-title": "Current Selection ({{ count }})",
|
||||
"submission.sections.describe.relationship-lookup.title.Journal Issue": "Journal Issues",
|
||||
"submission.sections.describe.relationship-lookup.title.Journal Volume": "Journal Volumes",
|
||||
"submission.sections.describe.relationship-lookup.title.Journal": "Journals",
|
||||
"submission.sections.describe.relationship-lookup.title.Author": "Authors",
|
||||
"submission.sections.describe.relationship-lookup.search-tab.toggle-dropdown": "Toggle dropdown",
|
||||
"submission.sections.describe.relationship-lookup.selection-tab.settings": "Settings",
|
||||
"submission.sections.describe.relationship-lookup.selection-tab.no-selection": "Your selection is currently empty.",
|
||||
"submission.sections.describe.relationship-lookup.selection-tab.title.Author": "Selected Authors",
|
||||
"submission.sections.describe.relationship-lookup.selection-tab.title.Journal": "Selected Journals",
|
||||
"submission.sections.describe.relationship-lookup.selection-tab.title.Journal Volume": "Selected Journal Volume",
|
||||
"submission.sections.describe.relationship-lookup.selection-tab.title.Journal Issue": "Selected Issue",
|
||||
"submission.sections.general.add-more": "Add more",
|
||||
"submission.sections.general.collection": "Collection",
|
||||
"submission.sections.general.deposit_error_notice": "There was an issue when submitting the item, please try again later.",
|
||||
|
@@ -11,7 +11,11 @@
|
||||
[scopes]="(scopeListRD$ | async)"
|
||||
[inPlaceSearch]="inPlaceSearch">
|
||||
</ds-search-form>
|
||||
<div class="row mb-3 mb-md-1">
|
||||
<div class="labels col-sm-9 offset-sm-3">
|
||||
<ds-search-labels *ngIf="searchEnabled" [inPlaceSearch]="inPlaceSearch"></ds-search-labels>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div id="search-body"
|
||||
class="row-offcanvas row-offcanvas-left"
|
||||
|
@@ -1,9 +1,26 @@
|
||||
import { autoserialize, autoserializeAs } from 'cerialize';
|
||||
import { hasValue } from '../../shared/empty.util';
|
||||
|
||||
/**
|
||||
* Represents the state of a paginated response
|
||||
*/
|
||||
export class PageInfo {
|
||||
constructor(
|
||||
options?: {
|
||||
elementsPerPage: number,
|
||||
totalElements: number,
|
||||
totalPages: number,
|
||||
currentPage: number
|
||||
}
|
||||
) {
|
||||
if (hasValue(options)) {
|
||||
this.elementsPerPage = options.elementsPerPage;
|
||||
this.totalElements = options.totalElements;
|
||||
this.totalPages = options.totalPages;
|
||||
this.currentPage = options.currentPage;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* The number of elements on a page
|
||||
*/
|
||||
|
@@ -20,7 +20,7 @@ function equalsByFields(object1, object2, fieldList): boolean {
|
||||
return !object1[key].equals(object2[key]);
|
||||
}
|
||||
if (typeof object1[key] === 'object') {
|
||||
equalsByFields(object1[key], object2[key], Object.keys(object1))
|
||||
return !equalsByFields(object1[key], object2[key], Object.keys(object1))
|
||||
}
|
||||
return object1[key] !== object2[key];
|
||||
});
|
||||
|
@@ -88,6 +88,9 @@ import { RemoteData } from '../../../../core/data/remote-data';
|
||||
import { Item } from '../../../../core/shared/item.model';
|
||||
import { Relationship } from '../../../../core/shared/item-relationships/relationship.model';
|
||||
import { ItemDataService } from '../../../../core/data/item-data.service';
|
||||
import { RemoveRelationshipAction } from './relation-lookup-modal/relationship.actions';
|
||||
import { Store } from '@ngrx/store';
|
||||
import { AppState } from '../../../../app.reducer';
|
||||
|
||||
export function dsDynamicFormControlMapFn(model: DynamicFormControlModel): Type<DynamicFormControl> | null {
|
||||
switch (model.type) {
|
||||
@@ -202,7 +205,8 @@ export class DsDynamicFormControlContainerComponent extends DynamicFormControlCo
|
||||
private selectableListService: SelectableListService,
|
||||
private itemService: ItemDataService,
|
||||
private relationshipService: RelationshipService,
|
||||
private zone: NgZone
|
||||
private zone: NgZone,
|
||||
private store: Store<AppState>
|
||||
) {
|
||||
super(componentFactoryResolver, layoutService, validationService);
|
||||
}
|
||||
@@ -279,11 +283,10 @@ export class DsDynamicFormControlContainerComponent extends DynamicFormControlCo
|
||||
removeSelection(object: SearchResult<Item>) {
|
||||
this.selectableListService.deselectSingle(this.listId, object);
|
||||
this.zone.runOutsideAngular(
|
||||
this.model.workspaceItem.item.pipe(
|
||||
() => this.model.workspaceItem.item.pipe(
|
||||
getSucceededRemoteData(),
|
||||
switchMap((itemRD: RemoteData<Item>) => this.relationshipService.getRelationshipByItemsAndLabel(itemRD.payload, object.indexableObject, this.model.relationship.relationshipType)),
|
||||
switchMap((relationship: Relationship) => this.relationshipService.deleteRelationship(relationship.id)),
|
||||
take(1)
|
||||
).subscribe());
|
||||
tap((itemRD: RemoteData<Item>) => this.store.dispatch(new RemoveRelationshipAction(itemRD.payload, object.indexableObject, this.model.relationship.relationshipType)))
|
||||
).subscribe()
|
||||
);
|
||||
}
|
||||
}
|
||||
|
@@ -7,28 +7,28 @@
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<ngb-tabset>
|
||||
<ngb-tab title="Search">
|
||||
<ngb-tab [title]="'submission.sections.describe.relationship-lookup.search-tab.tab-title.' + label | translate">
|
||||
<ng-template ngbTabContent>
|
||||
<ds-dynamic-lookup-relation-search-tab
|
||||
[label]="label"
|
||||
[itemRD$]="itemRD$"
|
||||
[selection$]="selection$"
|
||||
[listId]="listId"
|
||||
[relationship]="relationship"
|
||||
[repeatable]="repeatable"
|
||||
(selectObject)="select($event)"
|
||||
(deselectObject)="deselect($event)"
|
||||
class="d-block pt-3">
|
||||
</ds-dynamic-lookup-relation-search-tab>
|
||||
</ng-template>
|
||||
</ngb-tab>
|
||||
<ngb-tab title="Selection">
|
||||
<ngb-tab [title]="'submission.sections.describe.relationship-lookup.selection-tab.tab-title' | translate : {count: (selection$ | async)?.length}">
|
||||
<ng-template ngbTabContent>
|
||||
<ds-dynamic-lookup-relation-selection-tab
|
||||
[label]="label"
|
||||
[itemRD$]="itemRD$"
|
||||
[selection$]="selection$"
|
||||
[listId]="listId"
|
||||
[relationship]="relationship"
|
||||
[label]="label"
|
||||
[repeatable]="repeatable"
|
||||
(selectObject)="select($event)"
|
||||
(deselectObject)="deselect($event)"
|
||||
class="d-block pt-3">
|
||||
</ds-dynamic-lookup-relation-selection-tab>
|
||||
</ng-template>
|
||||
|
@@ -1,14 +1,23 @@
|
||||
import { Component, OnInit } from '@angular/core';
|
||||
import { Component, NgZone, OnInit } from '@angular/core';
|
||||
import { Observable } from 'rxjs';
|
||||
import { NgbActiveModal } from '@ng-bootstrap/ng-bootstrap';
|
||||
import { hasValue } from '../../../../empty.util';
|
||||
import { map } from 'rxjs/operators';
|
||||
import { map, tap } from 'rxjs/operators';
|
||||
import { SEARCH_CONFIG_SERVICE } from '../../../../../+my-dspace-page/my-dspace-page.component';
|
||||
import { SearchConfigurationService } from '../../../../../core/shared/search/search-configuration.service';
|
||||
import { SelectableListService } from '../../../../object-list/selectable-list/selectable-list.service';
|
||||
import { SelectableListState } from '../../../../object-list/selectable-list/selectable-list.reducer';
|
||||
import { ListableObject } from '../../../../object-collection/shared/listable-object.model';
|
||||
import { RelationshipOptions } from '../../models/relationship-options.model';
|
||||
import { SearchResult } from '../../../../search/search-result.model';
|
||||
import { Item } from '../../../../../core/shared/item.model';
|
||||
import { getSucceededRemoteData } from '../../../../../core/shared/operators';
|
||||
import { RemoteData } from '../../../../../core/data/remote-data';
|
||||
import { AddRelationshipAction, RemoveRelationshipAction } from './relationship.actions';
|
||||
import { RelationshipService } from '../../../../../core/data/relationship.service';
|
||||
import { RelationshipTypeService } from '../../../../../core/data/relationship-type.service';
|
||||
import { Store } from '@ngrx/store';
|
||||
import { AppState } from '../../../../../app.reducer';
|
||||
|
||||
@Component({
|
||||
selector: 'ds-dynamic-lookup-relation-modal',
|
||||
@@ -33,6 +42,10 @@ export class DsDynamicLookupRelationModalComponent implements OnInit {
|
||||
constructor(
|
||||
public modal: NgbActiveModal,
|
||||
private selectableListService: SelectableListService,
|
||||
private relationshipService: RelationshipService,
|
||||
private relationshipTypeService: RelationshipTypeService,
|
||||
private zone: NgZone,
|
||||
private store: Store<AppState>
|
||||
) {
|
||||
}
|
||||
|
||||
@@ -44,4 +57,32 @@ export class DsDynamicLookupRelationModalComponent implements OnInit {
|
||||
close() {
|
||||
this.modal.close();
|
||||
}
|
||||
|
||||
select(...selectableObjects: SearchResult<Item>[]) {
|
||||
this.zone.runOutsideAngular(
|
||||
() => this.itemRD$
|
||||
.pipe(
|
||||
getSucceededRemoteData(),
|
||||
tap((itemRD: RemoteData<Item>) => {
|
||||
return selectableObjects.forEach((object) =>
|
||||
this.store.dispatch(new AddRelationshipAction(itemRD.payload, object.indexableObject, this.relationship.relationshipType))
|
||||
);
|
||||
})
|
||||
).subscribe());
|
||||
}
|
||||
|
||||
|
||||
deselect(...selectableObjects: SearchResult<Item>[]) {
|
||||
this.zone.runOutsideAngular(
|
||||
() => this.itemRD$.pipe(
|
||||
getSucceededRemoteData(),
|
||||
tap((itemRD: RemoteData<Item>) => {
|
||||
return selectableObjects.forEach((object) =>
|
||||
this.store.dispatch(new RemoveRelationshipAction(itemRD.payload, object.indexableObject, this.relationship.relationshipType))
|
||||
);
|
||||
})
|
||||
).subscribe()
|
||||
);
|
||||
}
|
||||
|
||||
}
|
@@ -5,12 +5,15 @@
|
||||
<div class="col-8">
|
||||
<form class="input-group mb-3" #queryForm="ngForm"
|
||||
(ngSubmit)="search(queryForm.value.query)">
|
||||
<input type="text" class="form-control" name="query" [placeholder]="'submission.sections.describe.relationship-lookup.placeholder' | translate"
|
||||
<input type="text" class="form-control" name="query" [placeholder]="'submission.sections.describe.relationship-lookup.search-tab.placeholder' | translate"
|
||||
[ngModel]="searchQuery">
|
||||
<div class="input-group-append">
|
||||
<button class="btn btn-outline-secondary" type="submit">{{ ('submission.sections.describe.relationship-lookup.search' | translate) }}</button>
|
||||
<button class="btn btn-outline-secondary" type="submit">{{ ('submission.sections.describe.relationship-lookup.search-tab.search' | translate) }}</button>
|
||||
</div>
|
||||
</form>
|
||||
|
||||
<ds-search-labels [inPlaceSearch]="true"></ds-search-labels>
|
||||
|
||||
<div *ngIf="repeatable" class="position-absolute">
|
||||
<div class="input-group mb-3">
|
||||
<div class="input-group-prepend">
|
||||
@@ -38,7 +41,7 @@
|
||||
class="btn btn-outline-secondary rounded-right">
|
||||
<span class="spinner-border spinner-border-sm" role="status"
|
||||
aria-hidden="true"></span>
|
||||
<span class="sr-only">{{ ('submission.sections.describe.relationship-lookup.loading' | translate) }}</span>
|
||||
<span class="sr-only">{{ ('submission.sections.describe.relationship-lookup.search-tab.loading' | translate) }}</span>
|
||||
</button>
|
||||
<button id="resultdropdown" type="button"
|
||||
ngbDropdownToggle
|
||||
@@ -49,10 +52,12 @@
|
||||
<span class="sr-only">{{ ('submission.sections.describe.relationship-lookup.toggle-dropdown' | translate) }}</span>
|
||||
</button>
|
||||
<div ngbDropdownMenu aria-labelledby="resultdropdown">
|
||||
<button class="dropdown-item" (click)="selectPage(resultsRD?.payload?.page)">{{ ('submission.sections.describe.relationship-lookup.select-page' | translate) }}</button>
|
||||
<button class="dropdown-item" (click)="deselectPage(resultsRD?.payload?.page)">{{ ('submission.sections.describe.relationship-lookup.deselect-page' | translate) }}</button>
|
||||
<button class="dropdown-item" (click)="selectAll()">{{ ('submission.sections.describe.relationship-lookup.select-all' | translate) }}</button>
|
||||
<button class="dropdown-item" (click)="deselectAll()">{{ ('submission.sections.describe.relationship-lookup.deselect-all' | translate) }}</button>
|
||||
<button class="dropdown-item"
|
||||
(click)="selectPage(resultsRD?.payload?.page)">{{ ('submission.sections.describe.relationship-lookup.search-tab.select-page' | translate) }}</button>
|
||||
<button class="dropdown-item"
|
||||
(click)="deselectPage(resultsRD?.payload?.page)">{{ ('submission.sections.describe.relationship-lookup.search-tab.deselect-page' | translate) }}</button>
|
||||
<button class="dropdown-item" (click)="selectAll()">{{ ('submission.sections.describe.relationship-lookup.search-tab.select-all' | translate) }}</button>
|
||||
<button class="dropdown-item" (click)="deselectAll()">{{ ('submission.sections.describe.relationship-lookup.search-tab.deselect-all' | translate) }}</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -62,9 +67,8 @@
|
||||
[searchConfig]="this.searchConfig"
|
||||
[selectable]="true"
|
||||
[selectionConfig]="{ repeatable: repeatable, listId: listId }"
|
||||
(deselectObject)="deselect($event)"
|
||||
(selectObject)="select($event)"
|
||||
>
|
||||
(deselectObject)="deselectObject.emit($event)"
|
||||
(selectObject)="selectObject.emit($event)">
|
||||
</ds-search-results>
|
||||
</div>
|
||||
</div>
|
@@ -1,4 +1,4 @@
|
||||
import { Component, Input, NgZone, OnDestroy, OnInit } from '@angular/core';
|
||||
import { Component, EventEmitter, Input, OnDestroy, OnInit, Output } from '@angular/core';
|
||||
import { SEARCH_CONFIG_SERVICE } from '../../../../../../+my-dspace-page/my-dspace-page.component';
|
||||
import { SearchConfigurationService } from '../../../../../../core/shared/search/search-configuration.service';
|
||||
import { Item } from '../../../../../../core/shared/item.model';
|
||||
@@ -14,16 +14,11 @@ import { SearchService } from '../../../../../../core/shared/search/search.servi
|
||||
import { Router } from '@angular/router';
|
||||
import { SelectableListService } from '../../../../../object-list/selectable-list/selectable-list.service';
|
||||
import { RouteService } from '../../../../../services/route.service';
|
||||
import { RelationshipService } from '../../../../../../core/data/relationship.service';
|
||||
import { RelationshipTypeService } from '../../../../../../core/data/relationship-type.service';
|
||||
import { Store } from '@ngrx/store';
|
||||
import { AppState } from '../../../../../../app.reducer';
|
||||
import { SelectableListState } from '../../../../../object-list/selectable-list/selectable-list.reducer';
|
||||
import { hasValue, isNotEmpty } from '../../../../../empty.util';
|
||||
import { concat, map, multicast, switchMap, take, takeWhile, tap } from 'rxjs/operators';
|
||||
import { DSpaceObject } from '../../../../../../core/shared/dspace-object.model';
|
||||
import { getSucceededRemoteData } from '../../../../../../core/shared/operators';
|
||||
import { AddRelationshipAction, RemoveRelationshipAction } from '../relationship.actions';
|
||||
|
||||
@Component({
|
||||
selector: 'ds-dynamic-lookup-relation-search-tab',
|
||||
@@ -38,12 +33,12 @@ import { AddRelationshipAction, RemoveRelationshipAction } from '../relationship
|
||||
})
|
||||
|
||||
export class DsDynamicLookupRelationSearchTabComponent implements OnInit, OnDestroy {
|
||||
@Input() label: string;
|
||||
@Input() relationship: RelationshipOptions;
|
||||
@Input() listId: string;
|
||||
@Input() itemRD$;
|
||||
@Input() repeatable: boolean;
|
||||
@Input() selection$: Observable<ListableObject[]>;
|
||||
@Output() deselectObject: EventEmitter<ListableObject> = new EventEmitter<ListableObject>();
|
||||
@Output() selectObject: EventEmitter<ListableObject> = new EventEmitter<ListableObject>();
|
||||
resultsRD$: Observable<RemoteData<PaginatedList<SearchResult<Item>>>>;
|
||||
searchConfig: PaginatedSearchOptions;
|
||||
searchQuery;
|
||||
@@ -62,10 +57,6 @@ export class DsDynamicLookupRelationSearchTabComponent implements OnInit, OnDest
|
||||
private selectableListService: SelectableListService,
|
||||
private searchConfigService: SearchConfigurationService,
|
||||
private routeService: RouteService,
|
||||
private relationshipService: RelationshipService,
|
||||
private relationshipTypeService: RelationshipTypeService,
|
||||
private zone: NgZone,
|
||||
private store: Store<AppState>
|
||||
) {
|
||||
}
|
||||
|
||||
@@ -74,13 +65,13 @@ export class DsDynamicLookupRelationSearchTabComponent implements OnInit, OnDest
|
||||
this.routeService.setParameter('fixedFilterQuery', this.relationship.filter);
|
||||
this.routeService.setParameter('configuration', this.relationship.searchConfiguration);
|
||||
|
||||
this.selection$ = this.selectableListService.getSelectableList(this.listId).pipe(map((listState: SelectableListState) => hasValue(listState) && hasValue(listState.selection) ? listState.selection : []));
|
||||
this.someSelected$ = this.selection$.pipe(map((selection) => isNotEmpty(selection)));
|
||||
this.resultsRD$ = this.searchConfigService.paginatedSearchOptions.pipe(
|
||||
map((options) => {
|
||||
return Object.assign(new PaginatedSearchOptions({}), options, { fixedFilter: this.relationship.filter, configuration: this.relationship.searchConfiguration })
|
||||
}),
|
||||
switchMap((options) => {
|
||||
this.searchQuery = options.query;
|
||||
this.searchConfig = options;
|
||||
return this.searchService.search(options).pipe(
|
||||
/* Make sure to only listen to the first x results, until loading is finished */
|
||||
@@ -96,6 +87,7 @@ export class DsDynamicLookupRelationSearchTabComponent implements OnInit, OnDest
|
||||
)
|
||||
})
|
||||
);
|
||||
this.resultsRD$.subscribe((t) => console.log(t));
|
||||
|
||||
}
|
||||
|
||||
@@ -116,7 +108,7 @@ export class DsDynamicLookupRelationSearchTabComponent implements OnInit, OnDest
|
||||
.pipe(take(1))
|
||||
.subscribe((selection: SearchResult<Item>[]) => {
|
||||
const filteredPage = page.filter((pageItem) => selection.findIndex((selected) => selected.equals(pageItem)) < 0)
|
||||
this.select(...filteredPage);
|
||||
this.selectObject.emit(...filteredPage);
|
||||
});
|
||||
this.selectableListService.select(this.listId, page);
|
||||
}
|
||||
@@ -127,7 +119,7 @@ export class DsDynamicLookupRelationSearchTabComponent implements OnInit, OnDest
|
||||
.pipe(take(1))
|
||||
.subscribe((selection: SearchResult<Item>[]) => {
|
||||
const filteredPage = page.filter((pageItem) => selection.findIndex((selected) => selected.equals(pageItem)) >= 0)
|
||||
this.deselect(...filteredPage);
|
||||
this.deselectObject.emit(...filteredPage);
|
||||
});
|
||||
this.selectableListService.deselect(this.listId, page);
|
||||
}
|
||||
@@ -151,7 +143,7 @@ export class DsDynamicLookupRelationSearchTabComponent implements OnInit, OnDest
|
||||
.pipe(take(1))
|
||||
.subscribe((selection: SearchResult<Item>[]) => {
|
||||
const filteredResults = results.filter((pageItem) => selection.findIndex((selected) => selected.equals(pageItem)) < 0);
|
||||
this.select(...filteredResults);
|
||||
this.selectObject.emit(...filteredResults);
|
||||
});
|
||||
this.selectableListService.select(this.listId, results);
|
||||
}
|
||||
@@ -162,38 +154,10 @@ export class DsDynamicLookupRelationSearchTabComponent implements OnInit, OnDest
|
||||
this.allSelected = false;
|
||||
this.selection$
|
||||
.pipe(take(1))
|
||||
.subscribe((selection: SearchResult<Item>[]) => this.deselect(...selection));
|
||||
.subscribe((selection: SearchResult<Item>[]) => this.deselectObject.emit(...selection));
|
||||
this.selectableListService.deselectAll(this.listId);
|
||||
}
|
||||
|
||||
|
||||
select(...selectableObjects: SearchResult<Item>[]) {
|
||||
this.zone.runOutsideAngular(
|
||||
() => this.itemRD$
|
||||
.pipe(
|
||||
getSucceededRemoteData(),
|
||||
tap((itemRD: RemoteData<Item>) => {
|
||||
return selectableObjects.forEach((object) =>
|
||||
this.store.dispatch(new AddRelationshipAction(itemRD.payload, object.indexableObject, this.relationship.relationshipType))
|
||||
);
|
||||
})
|
||||
).subscribe());
|
||||
}
|
||||
|
||||
|
||||
deselect(...selectableObjects: SearchResult<Item>[]) {
|
||||
this.zone.runOutsideAngular(
|
||||
() => this.itemRD$.pipe(
|
||||
getSucceededRemoteData(),
|
||||
tap((itemRD: RemoteData<Item>) => {
|
||||
return selectableObjects.forEach((object) =>
|
||||
this.store.dispatch(new RemoveRelationshipAction(itemRD.payload, object.indexableObject, this.relationship.relationshipType))
|
||||
);
|
||||
})
|
||||
).subscribe()
|
||||
);
|
||||
}
|
||||
|
||||
ngOnDestroy(): void {
|
||||
if (hasValue(this.subscription)
|
||||
) {
|
||||
|
@@ -1,10 +1,22 @@
|
||||
<ds-search-sidebar class="col-4" id="search-sidebar"
|
||||
[resultCount]=""
|
||||
[inPlaceSearch]="true" [showViewModes]="false"></ds-search-sidebar>
|
||||
<div class="row">
|
||||
<div class="col-4">
|
||||
<h3>{{ 'submission.sections.describe.relationship-lookup.selection-tab.settings' | translate}}</h3>
|
||||
<ds-page-size-selector></ds-page-size-selector>
|
||||
</div>
|
||||
<div class="col-8">
|
||||
<div *ngIf="(selectionRD$ | async)?.payload.page < 1">
|
||||
{{'submission.sections.describe.relationship-lookup.selection-tab.no-selection' | translate}}
|
||||
</div>
|
||||
<div *ngIf="(selectionRD$ | async)?.payload.page.length >= 1">
|
||||
<h3>{{ 'submission.sections.describe.relationship-lookup.selection-tab.title.' + label | translate}}</h3>
|
||||
<ds-viewable-collection [objects]="selectionRD$ | async"
|
||||
[selectable]="true"
|
||||
[selectionConfig]="{ repeatable: repeatable, listId: listId }"
|
||||
[config]="initialPagination"
|
||||
[hideGear]="true"
|
||||
(deselectObject)="deselectObject.emit($event)"
|
||||
(selectObject)="selectObject.emit($event)"
|
||||
></ds-viewable-collection>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
@@ -1,14 +1,20 @@
|
||||
import { Component, Input } from '@angular/core';
|
||||
import { Component, EventEmitter, Input, Output } from '@angular/core';
|
||||
import { SEARCH_CONFIG_SERVICE } from '../../../../../../+my-dspace-page/my-dspace-page.component';
|
||||
import { SearchConfigurationService } from '../../../../../../core/shared/search/search-configuration.service';
|
||||
import { Observable } from 'rxjs';
|
||||
import { RelationshipOptions } from '../../../models/relationship-options.model';
|
||||
import { ListableObject } from '../../../../../object-collection/shared/listable-object.model';
|
||||
import { RemoteData } from '../../../../../../core/data/remote-data';
|
||||
import { map, take } from 'rxjs/operators';
|
||||
import { map, switchMap, take } from 'rxjs/operators';
|
||||
import { createSuccessfulRemoteDataObject } from '../../../../../testing/utils';
|
||||
import { PaginationComponentOptions } from '../../../../../pagination/pagination-component-options.model';
|
||||
import { PaginatedList } from '../../../../../../core/data/paginated-list';
|
||||
import { Router } from '@angular/router';
|
||||
import { SelectableListService } from '../../../../../object-list/selectable-list/selectable-list.service';
|
||||
import { RouteService } from '../../../../../services/route.service';
|
||||
import { PaginatedSearchOptions } from '../../../../../search/paginated-search-options.model';
|
||||
import { size } from 'memory-cache';
|
||||
import { PageInfo } from '../../../../../../core/shared/page-info.model';
|
||||
|
||||
@Component({
|
||||
selector: 'ds-dynamic-lookup-relation-selection-tab',
|
||||
@@ -24,24 +30,54 @@ import { PaginatedList } from '../../../../../../core/data/paginated-list';
|
||||
|
||||
export class DsDynamicLookupRelationSelectionTabComponent {
|
||||
@Input() label: string;
|
||||
@Input() relationship: RelationshipOptions;
|
||||
@Input() listId: string;
|
||||
@Input() itemRD$;
|
||||
@Input() repeatable: boolean;
|
||||
@Input() selection$: Observable<ListableObject[]>;
|
||||
@Input() selectionRD$: Observable<RemoteData<PaginatedList<ListableObject>>>;
|
||||
@Output() deselectObject: EventEmitter<ListableObject> = new EventEmitter<ListableObject>();
|
||||
@Output() selectObject: EventEmitter<ListableObject> = new EventEmitter<ListableObject>();
|
||||
|
||||
initialPagination = Object.assign(new PaginationComponentOptions(), {
|
||||
id: 'submission-relation-list',
|
||||
pageSize: 5
|
||||
});
|
||||
|
||||
constructor() {
|
||||
constructor(private router: Router,
|
||||
private searchConfigService: SearchConfigurationService) {
|
||||
}
|
||||
|
||||
ngOnInit() {
|
||||
this.selectionRD$ = this.selection$.pipe(
|
||||
this.resetRoute();
|
||||
this.selectionRD$ = this.searchConfigService.paginatedSearchOptions
|
||||
.pipe(
|
||||
map((options: PaginatedSearchOptions) => options.pagination),
|
||||
switchMap((pagination: PaginationComponentOptions) => {
|
||||
return this.selection$.pipe(
|
||||
take(1),
|
||||
map((selection) => createSuccessfulRemoteDataObject(new PaginatedList({} as any, selection)))
|
||||
map((selected) => {
|
||||
const offset = (pagination.currentPage - 1) * pagination.pageSize;
|
||||
const end = (offset + pagination.pageSize) > selected.length ? selected.length : offset + pagination.pageSize;
|
||||
const selection = selected.slice(offset, end);
|
||||
const pageInfo = new PageInfo(
|
||||
{
|
||||
elementsPerPage: pagination.pageSize,
|
||||
totalElements: selected.length,
|
||||
currentPage: pagination.currentPage,
|
||||
totalPages: Math.ceil(selected.length / pagination.pageSize)
|
||||
});
|
||||
return createSuccessfulRemoteDataObject(new PaginatedList(pageInfo, selection))
|
||||
})
|
||||
);
|
||||
})
|
||||
)
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
resetRoute() {
|
||||
this.router.navigate([], {
|
||||
queryParams: Object.assign({}, { page: 1, pageSize: this.initialPagination.pageSize }),
|
||||
});
|
||||
}
|
||||
}
|
@@ -0,0 +1,10 @@
|
||||
<div class="setting-option page-size-settings mb-3 p-3">
|
||||
<h5>{{ 'search.sidebar.settings.rpp' | translate}}</h5>
|
||||
<select class="form-control" (change)="reloadRPP($event)">
|
||||
<option *ngFor="let pageSizeOption of (paginationOptions$ | async).pageSizeOptions"
|
||||
[value]="pageSizeOption"
|
||||
[selected]="pageSizeOption === +(paginationOptions$ | async).pageSize ? 'selected': null">
|
||||
{{pageSizeOption}}
|
||||
</option>
|
||||
</select>
|
||||
</div>
|
@@ -0,0 +1,3 @@
|
||||
.setting-option {
|
||||
border: 1px solid map-get($theme-colors, light);
|
||||
}
|
@@ -0,0 +1,52 @@
|
||||
import { Component, Inject, Input, OnInit } from '@angular/core';
|
||||
import { PaginationComponentOptions } from '../pagination/pagination-component-options.model';
|
||||
import { Observable } from 'rxjs';
|
||||
import { ActivatedRoute, NavigationExtras, Router } from '@angular/router';
|
||||
import { SEARCH_CONFIG_SERVICE } from '../../+my-dspace-page/my-dspace-page.component';
|
||||
import { SearchConfigurationService } from '../../core/shared/search/search-configuration.service';
|
||||
import { PaginatedSearchOptions } from '../search/paginated-search-options.model';
|
||||
import { map } from 'rxjs/operators';
|
||||
|
||||
@Component({
|
||||
selector: 'ds-page-size-selector',
|
||||
styleUrls: ['./page-size-selector.component.scss'],
|
||||
templateUrl: './page-size-selector.component.html'
|
||||
})
|
||||
|
||||
/**
|
||||
* This component represents the part of the search sidebar that contains the general search settings.
|
||||
*/
|
||||
export class PageSizeSelectorComponent implements OnInit {
|
||||
/**
|
||||
* The configuration for the current paginated search results
|
||||
*/
|
||||
paginationOptions$: Observable<PaginationComponentOptions>;
|
||||
|
||||
constructor(private route: ActivatedRoute,
|
||||
private router: Router,
|
||||
@Inject(SEARCH_CONFIG_SERVICE) public searchConfigurationService: SearchConfigurationService) {
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize paginated search options
|
||||
*/
|
||||
ngOnInit(): void {
|
||||
this.paginationOptions$ = this.searchConfigurationService.paginatedSearchOptions.pipe(map((options: PaginatedSearchOptions) => options.pagination));
|
||||
}
|
||||
|
||||
/**
|
||||
* Method to change the current page size (results per page)
|
||||
* @param {Event} event Change event containing the new page size value
|
||||
*/
|
||||
reloadRPP(event: Event) {
|
||||
const value = (event.target as HTMLInputElement).value;
|
||||
const navigationExtras: NavigationExtras = {
|
||||
queryParams: {
|
||||
pageSize: value,
|
||||
page: 1
|
||||
},
|
||||
queryParamsHandling: 'merge'
|
||||
};
|
||||
this.router.navigate([], navigationExtras);
|
||||
}
|
||||
}
|
@@ -1,5 +1,3 @@
|
||||
<div class="row mb-3 mb-md-1">
|
||||
<div class="labels col-sm-9 offset-sm-3">
|
||||
<ng-container *ngFor="let key of ((appliedFilters | async) | dsObjectKeys)"><!--Do not remove this to prevent uneven spacing
|
||||
--><a *ngFor="let values of (appliedFilters | async)[key]"
|
||||
class="badge badge-primary mr-1 mb-1 text-capitalize"
|
||||
@@ -9,5 +7,3 @@
|
||||
<span> ×</span>
|
||||
</a><!--Do not remove this to prevent uneven spacing
|
||||
--></ng-container>
|
||||
</div>
|
||||
</div>
|
||||
|
@@ -10,15 +10,5 @@
|
||||
</option>
|
||||
</select>
|
||||
</div>
|
||||
|
||||
<div class="setting-option page-size-settings mb-3 p-3">
|
||||
<h5>{{ 'search.sidebar.settings.rpp' | translate}}</h5>
|
||||
<select class="form-control" (change)="reloadRPP($event)">
|
||||
<option *ngFor="let pageSizeOption of config?.pagination.pageSizeOptions"
|
||||
[value]="pageSizeOption"
|
||||
[selected]="pageSizeOption === +config?.pagination.pageSize ? 'selected': null">
|
||||
{{pageSizeOption}}
|
||||
</option>
|
||||
</select>
|
||||
</div>
|
||||
<ds-page-size-selector></ds-page-size-selector>
|
||||
</ng-container>
|
@@ -18,12 +18,6 @@ import { currentPath } from '../../utils/route.utils';
|
||||
* This component represents the part of the search sidebar that contains the general search settings.
|
||||
*/
|
||||
export class SearchSettingsComponent implements OnInit {
|
||||
|
||||
/**
|
||||
* True when the search component should show results on the current page
|
||||
*/
|
||||
@Input() inPlaceSearch;
|
||||
|
||||
/**
|
||||
* The configuration for the current paginated search results
|
||||
*/
|
||||
@@ -47,22 +41,6 @@ export class SearchSettingsComponent implements OnInit {
|
||||
this.searchOptions$ = this.searchConfigurationService.paginatedSearchOptions;
|
||||
}
|
||||
|
||||
/**
|
||||
* Method to change the current page size (results per page)
|
||||
* @param {Event} event Change event containing the new page size value
|
||||
*/
|
||||
reloadRPP(event: Event) {
|
||||
const value = (event.target as HTMLInputElement).value;
|
||||
const navigationExtras: NavigationExtras = {
|
||||
queryParams: {
|
||||
pageSize: value,
|
||||
page: 1
|
||||
},
|
||||
queryParamsHandling: 'merge'
|
||||
};
|
||||
this.router.navigate(this.getSearchLinkParts(), navigationExtras);
|
||||
}
|
||||
|
||||
/**
|
||||
* Method to change the current sort field and direction
|
||||
* @param {Event} event Change event containing the sort direction and sort field
|
||||
@@ -77,26 +55,6 @@ export class SearchSettingsComponent implements OnInit {
|
||||
},
|
||||
queryParamsHandling: 'merge'
|
||||
};
|
||||
this.router.navigate(this.getSearchLinkParts(), navigationExtras);
|
||||
}
|
||||
|
||||
/**
|
||||
* @returns {string} The base path to the search page, or the current page when inPlaceSearch is true
|
||||
*/
|
||||
public getSearchLink(): string {
|
||||
if (this.inPlaceSearch) {
|
||||
return currentPath(this.router);
|
||||
}
|
||||
return this.service.getSearchLink();
|
||||
}
|
||||
|
||||
/**
|
||||
* @returns {string[]} The base path to the search page, or the current page when inPlaceSearch is true, split in separate pieces
|
||||
*/
|
||||
public getSearchLinkParts(): string[] {
|
||||
if (this.service) {
|
||||
return [];
|
||||
}
|
||||
return this.getSearchLink().split('/');
|
||||
this.router.navigate([], navigationExtras);
|
||||
}
|
||||
}
|
||||
|
@@ -12,7 +12,7 @@
|
||||
<div class="sidebar-content">
|
||||
<ds-search-switch-configuration [inPlaceSearch]="inPlaceSearch" *ngIf="configurationList" [configurationList]="configurationList"></ds-search-switch-configuration>
|
||||
<ds-search-filters [inPlaceSearch]="inPlaceSearch"></ds-search-filters>
|
||||
<ds-search-settings [inPlaceSearch]="inPlaceSearch"></ds-search-settings>
|
||||
<ds-search-settings></ds-search-settings>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
@@ -162,6 +162,7 @@ import { SearchAuthorityFilterComponent } from './search/search-filters/search-f
|
||||
import { DsDynamicDisabledComponent } from './form/builder/ds-dynamic-form-ui/models/disabled/dynamic-disabled.component';
|
||||
import { DsDynamicLookupRelationSearchTabComponent } from './form/builder/ds-dynamic-form-ui/relation-lookup-modal/search-tab/dynamic-lookup-relation-search-tab.component';
|
||||
import { DsDynamicLookupRelationSelectionTabComponent } from './form/builder/ds-dynamic-form-ui/relation-lookup-modal/selection-tab/dynamic-lookup-relation-selection-tab.component';
|
||||
import { PageSizeSelectorComponent } from './page-size-selector/page-size-selector.component';
|
||||
|
||||
const MODULES = [
|
||||
// Do NOT include UniversalModule, HttpModule, or JsonpModule here
|
||||
@@ -305,6 +306,7 @@ const COMPONENTS = [
|
||||
SearchFacetRangeOptionComponent,
|
||||
SearchSwitchConfigurationComponent,
|
||||
SearchAuthorityFilterComponent,
|
||||
PageSizeSelectorComponent
|
||||
];
|
||||
|
||||
const ENTRY_COMPONENTS = [
|
||||
|
Reference in New Issue
Block a user