diff --git a/src/app/+admin/admin-sidebar/admin-sidebar.component.ts b/src/app/+admin/admin-sidebar/admin-sidebar.component.ts index 3ad1bd4272..185d083764 100644 --- a/src/app/+admin/admin-sidebar/admin-sidebar.component.ts +++ b/src/app/+admin/admin-sidebar/admin-sidebar.component.ts @@ -13,7 +13,6 @@ import { combineLatest as combineLatestObservable } from 'rxjs'; import { NgbModal } from '@ng-bootstrap/ng-bootstrap'; import { OnClickMenuItemModel } from '../../shared/menu/menu-item/models/onclick.model'; import { CreateCommunityParentSelectorComponent } from '../../shared/dso-selector/modal-wrappers/create-community-parent-selector/create-community-parent-selector.component'; -import { CreateItemParentSelectorComponent } from '../../shared/dso-selector/modal-wrappers/create-item-parent-selector/create-item-parent-selector.component'; import { CreateCollectionParentSelectorComponent } from '../../shared/dso-selector/modal-wrappers/create-collection-parent-selector/create-collection-parent-selector.component'; import { EditItemSelectorComponent } from '../../shared/dso-selector/modal-wrappers/edit-item-selector/edit-item-selector.component'; import { EditCommunitySelectorComponent } from '../../shared/dso-selector/modal-wrappers/edit-community-selector/edit-community-selector.component'; diff --git a/src/app/core/data/base-response-parsing.service.ts b/src/app/core/data/base-response-parsing.service.ts index 4ede02778c..0929b057db 100644 --- a/src/app/core/data/base-response-parsing.service.ts +++ b/src/app/core/data/base-response-parsing.service.ts @@ -44,7 +44,6 @@ export abstract class BaseResponseParsingService { } }); } - this.cache(object, requestUUID); return object; } diff --git a/src/app/core/data/relationship.service.ts b/src/app/core/data/relationship.service.ts index fca5074a88..81d9ed443e 100644 --- a/src/app/core/data/relationship.service.ts +++ b/src/app/core/data/relationship.service.ts @@ -10,7 +10,7 @@ import { getRemoteDataPayload, getResponseFromEntry, getSucceededRemoteData } from '../shared/operators'; -import { DeleteRequest, RestRequest } from './request.models'; +import { DeleteRequest, PostRequest, RestRequest } from './request.models'; import { Observable } from 'rxjs/internal/Observable'; import { RestResponse } from '../cache/response.models'; import { Item } from '../shared/item.model'; @@ -64,6 +64,22 @@ export class RelationshipService { ); } + /** + * Send a post request for a relationship by ID + * @param item1 + * @param item2 + */ + addRelationship(item1: Item, item2: Item): Observable { + return this.halService.getEndpoint(this.linkPath).pipe( + isNotEmptyOperator(), + distinctUntilChanged(), + map((endpointURL: string) => new PostRequest(this.requestService.generateRequestId(), endpointURL, `${item1.self} ${item2.self}`)), + configureRequest(this.requestService), + switchMap((restRequest: RestRequest) => this.requestService.getByUUID(restRequest.uuid)), + getResponseFromEntry() + ); + } + /** * Get a combined observable containing an array of all relationships in an item, as well as an array of the relationships their types * This is used for easier access of a relationship's type because they exist as observables diff --git a/src/app/core/shared/operators.ts b/src/app/core/shared/operators.ts index ae46691e39..3118549169 100644 --- a/src/app/core/shared/operators.ts +++ b/src/app/core/shared/operators.ts @@ -10,7 +10,6 @@ import { BrowseDefinition } from './browse-definition.model'; import { DSpaceObject } from './dspace-object.model'; import { PaginatedList } from '../data/paginated-list'; import { SearchResult } from '../../+search-page/search-result.model'; -import { Item } from './item.model'; import { Router } from '@angular/router'; /** diff --git a/src/app/shared/form/builder/ds-dynamic-form-ui/ds-dynamic-form-control-container.component.ts b/src/app/shared/form/builder/ds-dynamic-form-ui/ds-dynamic-form-control-container.component.ts index 0b81a5c7ab..37e83c7657 100644 --- a/src/app/shared/form/builder/ds-dynamic-form-ui/ds-dynamic-form-control-container.component.ts +++ b/src/app/shared/form/builder/ds-dynamic-form-ui/ds-dynamic-form-control-container.component.ts @@ -72,7 +72,6 @@ import { DYNAMIC_FORM_CONTROL_TYPE_LOOKUP_RELATION } from './models/lookup-relat import { DsDynamicLookupRelationComponent } from './models/lookup-relation/dynamic-lookup-relation.component'; export function dsDynamicFormControlMapFn(model: DynamicFormControlModel): Type | null { - console.log(model.type); switch (model.type) { case DYNAMIC_FORM_CONTROL_TYPE_ARRAY: return DsDynamicFormArrayComponent; diff --git a/src/app/shared/form/builder/ds-dynamic-form-ui/models/lookup-relation/dynamic-lookup-relation-modal.component.html b/src/app/shared/form/builder/ds-dynamic-form-ui/models/lookup-relation/dynamic-lookup-relation-modal.component.html index 593f4e543c..90f45547c6 100644 --- a/src/app/shared/form/builder/ds-dynamic-form-ui/models/lookup-relation/dynamic-lookup-relation-modal.component.html +++ b/src/app/shared/form/builder/ds-dynamic-form-ui/models/lookup-relation/dynamic-lookup-relation-modal.component.html @@ -1,26 +1,88 @@ -
-
-
-
-
-
- -
    -
  • - - -
  • -
-
+ + + \ No newline at end of file diff --git a/src/app/shared/form/builder/ds-dynamic-form-ui/models/lookup-relation/dynamic-lookup-relation-modal.component.scss b/src/app/shared/form/builder/ds-dynamic-form-ui/models/lookup-relation/dynamic-lookup-relation-modal.component.scss index 9e748833f9..337568b127 100644 --- a/src/app/shared/form/builder/ds-dynamic-form-ui/models/lookup-relation/dynamic-lookup-relation-modal.component.scss +++ b/src/app/shared/form/builder/ds-dynamic-form-ui/models/lookup-relation/dynamic-lookup-relation-modal.component.scss @@ -1,3 +1,7 @@ .result-list-element { flex: 1; +} + +.modal-footer { + justify-content: space-between; } \ No newline at end of file diff --git a/src/app/shared/form/builder/ds-dynamic-form-ui/models/lookup-relation/dynamic-lookup-relation-modal.component.ts b/src/app/shared/form/builder/ds-dynamic-form-ui/models/lookup-relation/dynamic-lookup-relation-modal.component.ts index 0834696641..a13b42d634 100644 --- a/src/app/shared/form/builder/ds-dynamic-form-ui/models/lookup-relation/dynamic-lookup-relation-modal.component.ts +++ b/src/app/shared/form/builder/ds-dynamic-form-ui/models/lookup-relation/dynamic-lookup-relation-modal.component.ts @@ -2,11 +2,16 @@ import { Component, OnInit } from '@angular/core'; import { PaginatedList } from '../../../../../../core/data/paginated-list'; import { SearchResult } from '../../../../../../+search-page/search-result.model'; import { RemoteData } from '../../../../../../core/data/remote-data'; -import { Observable } from 'rxjs'; +import { asyncScheduler, Observable, ReplaySubject } from 'rxjs'; import { SearchService } from '../../../../../../+search-page/search-service/search.service'; import { PaginatedSearchOptions } from '../../../../../../+search-page/paginated-search-options.model'; import { DSpaceObject } from '../../../../../../core/shared/dspace-object.model'; import { PaginationComponentOptions } from '../../../../../pagination/pagination-component-options.model'; +import { NgbActiveModal } from '@ng-bootstrap/ng-bootstrap'; +import { hasNoValue, hasValue, isNotEmpty } from '../../../../../empty.util'; +import { getSucceededRemoteData } from '../../../../../../core/shared/operators'; +import { finalize, map, takeUntil, takeWhile } from 'rxjs/operators'; +import { concat, multicast, take } from 'rxjs/operators'; const RELATION_TYPE_FILTER_PREFIX = 'f.entityType='; @@ -20,20 +25,111 @@ const RELATION_TYPE_METADATA_PREFIX = 'relation.isPublicationOf'; }) export class DsDynamicLookupRelationModalComponent implements OnInit { relationKey: string; + fieldName: string; resultsRD$: Observable>>>; searchConfig: PaginatedSearchOptions; + repeatable: boolean = true; + selection: DSpaceObject[] = []; + allSelected = false; - constructor(private searchService: SearchService) { + constructor(protected modal: NgbActiveModal, private searchService: SearchService) { } ngOnInit(): void { - const pagination = Object.assign(new PaginationComponentOptions(), { pageSize: 5 }); - this.searchConfig = new PaginatedSearchOptions({ - pagination: pagination, - fixedFilter: RELATION_TYPE_FILTER_PREFIX + this.relationKey.substring(RELATION_TYPE_METADATA_PREFIX.length) + this.fieldName = this.relationKey.substring(RELATION_TYPE_METADATA_PREFIX.length); + const pagination = Object.assign(new PaginationComponentOptions(), { + id: 'submission-relation-list', + pageSize: 5 }); - this.resultsRD$ = this.searchService.search(this.searchConfig); + this.onPaginationChange(pagination); } - onPaginationChange() {} + onPaginationChange(pagination: PaginationComponentOptions) { + this.searchConfig = new PaginatedSearchOptions({ + pagination: pagination, + fixedFilter: RELATION_TYPE_FILTER_PREFIX + this.fieldName + }); + this.resultsRD$ = this.searchService.search(this.searchConfig).pipe( + /* Make sure to only listen to the first x results, until loading is finished */ + /* TODO: in Rxjs 6.4.0 and up, we can replace this by takeWhile(predicate, true) - see https://stackoverflow.com/a/44644237 */ + multicast( + () => new ReplaySubject(1), + subject => subject.pipe( + takeWhile((rd: RemoteData>>) => rd.isLoading), + concat(subject.pipe(take(1)) + ) + ) + ) as any + ) + } + + close() { + this.modal.close(this.selection); + } + + isSelected(dso: DSpaceObject): boolean { + return hasValue(this.selection.find((selected) => selected.uuid === dso.uuid)); + } + + selectCheckbox(value: boolean, dso: DSpaceObject) { + if (value) { + this.selection = [...this.selection, dso]; + } else { + this.allSelected = false; + this.selection = this.selection.filter((selected) => { + return selected.uuid !== dso.uuid + }); + } + } + + selectRadio(value: boolean, dso: DSpaceObject) { + if (value) { + this.selection = [dso]; + } + } + + selectPage(page: SearchResult[]) { + const newObjects: DSpaceObject[] = page + .map((searchResult) => searchResult.indexableObject) + .filter((dso) => hasNoValue(this.selection.find((selected) => selected.uuid === dso.uuid))); + this.selection = [...this.selection, ...newObjects] + } + + deselectPage(page: SearchResult[]) { + this.allSelected = false; + const objects: DSpaceObject[] = page + .map((searchResult) => searchResult.indexableObject); + this.selection = this.selection.filter((selected) => hasNoValue(objects.find((object) => object.uuid === selected.uuid))); + } + + selectAll() { + this.allSelected = true; + const fullPagination = Object.assign(new PaginationComponentOptions(), { + currentPage: 1, + pageSize: Number.POSITIVE_INFINITY + }); + const fullSearchConfig = Object.assign(this.searchConfig, { pagination: fullPagination }); + const results = this.searchService.search(fullSearchConfig); + results.pipe( + getSucceededRemoteData(), + map((resultsRD) => resultsRD.payload.page) + ) + .subscribe((results) => + this.selection = [...this.selection, ...results.map((searchResult) => searchResult.indexableObject)] + ); + } + + deselectAll() { + this.allSelected = false; + this.selection = []; + } + + + isAllSelected() { + return this.allSelected; + } + + isSomeSelected() { + return isNotEmpty(this.selection); + } } \ No newline at end of file diff --git a/src/app/shared/form/builder/ds-dynamic-form-ui/models/lookup-relation/dynamic-lookup-relation.component.html b/src/app/shared/form/builder/ds-dynamic-form-ui/models/lookup-relation/dynamic-lookup-relation.component.html index 91b655ccc9..9911074e09 100644 --- a/src/app/shared/form/builder/ds-dynamic-form-ui/models/lookup-relation/dynamic-lookup-relation.component.html +++ b/src/app/shared/form/builder/ds-dynamic-form-ui/models/lookup-relation/dynamic-lookup-relation.component.html @@ -3,15 +3,20 @@
+ + +