trying to clean up namevariant code

This commit is contained in:
lotte
2019-11-05 16:33:39 +01:00
parent 2e50d99fc4
commit 5a6a0eac6f
8 changed files with 148 additions and 134 deletions

View File

@@ -32,7 +32,7 @@ import {
BitstreamFormatRegistryState BitstreamFormatRegistryState
} from './+admin/admin-registries/bitstream-formats/bitstream-format.reducers'; } from './+admin/admin-registries/bitstream-formats/bitstream-format.reducers';
import { ObjectSelectionListState, objectSelectionReducer } from './shared/object-select/object-select.reducer'; import { ObjectSelectionListState, objectSelectionReducer } from './shared/object-select/object-select.reducer';
import { relationshipListReducer, RelationshipListsState } from './shared/form/builder/ds-dynamic-form-ui/relation-lookup-modal/relationship.reducer'; import { nameVariantReducer, NameVariantListsState } from './shared/form/builder/ds-dynamic-form-ui/relation-lookup-modal/name-variant.reducer';
export interface AppState { export interface AppState {
router: fromRouter.RouterReducerState; router: fromRouter.RouterReducerState;
@@ -49,7 +49,7 @@ export interface AppState {
menus: MenusState; menus: MenusState;
objectSelection: ObjectSelectionListState; objectSelection: ObjectSelectionListState;
selectableLists: SelectableListsState; selectableLists: SelectableListsState;
relationshipLists: RelationshipListsState; relationshipLists: NameVariantListsState;
} }
export const appReducers: ActionReducerMap<AppState> = { export const appReducers: ActionReducerMap<AppState> = {
@@ -67,7 +67,7 @@ export const appReducers: ActionReducerMap<AppState> = {
menus: menusReducer, menus: menusReducer,
objectSelection: objectSelectionReducer, objectSelection: objectSelectionReducer,
selectableLists: selectableListReducer, selectableLists: selectableListReducer,
relationshipLists: relationshipListReducer relationshipLists: nameVariantReducer
}; };
export const routerStateSelector = (state: AppState) => state.router; export const routerStateSelector = (state: AppState) => state.router;

View File

@@ -28,13 +28,13 @@ import { SearchParam } from '../cache/models/search-param.model';
import { HttpOptions } from '../dspace-rest-v2/dspace-rest-v2.service'; import { HttpOptions } from '../dspace-rest-v2/dspace-rest-v2.service';
import { RemoveNameVariantAction, SetNameVariantAction } from '../../shared/form/builder/ds-dynamic-form-ui/relation-lookup-modal/relationship.actions'; import { RemoveNameVariantAction, SetNameVariantAction } from '../../shared/form/builder/ds-dynamic-form-ui/relation-lookup-modal/relationship.actions';
import { AppState, keySelector } from '../../app.reducer'; import { AppState, keySelector } from '../../app.reducer';
import { RelationshipListState, RelationshipState } from '../../shared/form/builder/ds-dynamic-form-ui/relation-lookup-modal/relationship.reducer'; import { NameVariantListState, RelationshipState } from '../../shared/form/builder/ds-dynamic-form-ui/relation-lookup-modal/name-variant.reducer';
const relationshipListsStateSelector = (state: AppState) => state.relationshipLists; const relationshipListsStateSelector = (state: AppState) => state.relationshipLists;
const relationshipListStateSelector = (listID: string): MemoizedSelector<AppState, RelationshipListState> => { const relationshipListStateSelector = (listID: string): MemoizedSelector<AppState, NameVariantListState> => {
return keySelector<RelationshipListState>(listID, relationshipListsStateSelector); return keySelector<NameVariantListState>(listID, relationshipListsStateSelector);
}; };
const relationshipStateSelector = (listID: string, itemID: string): MemoizedSelector<AppState, RelationshipState> => { const relationshipStateSelector = (listID: string, itemID: string): MemoizedSelector<AppState, RelationshipState> => {

View File

@@ -82,7 +82,7 @@ import { DsDynamicDisabledComponent } from './models/disabled/dynamic-disabled.c
import { DYNAMIC_FORM_CONTROL_TYPE_DISABLED } from './models/disabled/dynamic-disabled.model'; import { DYNAMIC_FORM_CONTROL_TYPE_DISABLED } from './models/disabled/dynamic-disabled.model';
import { DsDynamicLookupRelationModalComponent } from './relation-lookup-modal/dynamic-lookup-relation-modal.component'; import { DsDynamicLookupRelationModalComponent } from './relation-lookup-modal/dynamic-lookup-relation-modal.component';
import { ItemMetadataRepresentation } from '../../../../core/shared/metadata-representation/item/item-metadata-representation.model'; import { ItemMetadataRepresentation } from '../../../../core/shared/metadata-representation/item/item-metadata-representation.model';
import { getSucceededRemoteData } from '../../../../core/shared/operators'; import { getRemoteDataPayload, getSucceededRemoteData } from '../../../../core/shared/operators';
import { RemoteData } from '../../../../core/data/remote-data'; import { RemoteData } from '../../../../core/data/remote-data';
import { Item } from '../../../../core/shared/item.model'; import { Item } from '../../../../core/shared/item.model';
import { ItemDataService } from '../../../../core/data/item-data.service'; import { ItemDataService } from '../../../../core/data/item-data.service';
@@ -269,14 +269,17 @@ export class DsDynamicFormControlContainerComponent extends DynamicFormControlCo
} }
openLookup() { openLookup() {
this.modalRef = this.modalService.open(DsDynamicLookupRelationModalComponent, { size: 'lg' }); this.model.workspaceItem.item.pipe(getSucceededRemoteData(), getRemoteDataPayload())
const modalComp = this.modalRef.componentInstance; .subscribe((item: Item) => {
modalComp.repeatable = this.model.repeatable; this.modalRef = this.modalService.open(DsDynamicLookupRelationModalComponent, { size: 'lg' });
modalComp.listId = this.listId; const modalComp = this.modalRef.componentInstance;
modalComp.relationshipOptions = this.model.relationship; modalComp.repeatable = this.model.repeatable;
modalComp.label = this.model.label; modalComp.listId = this.listId;
modalComp.itemRD$ = this.model.workspaceItem.item; modalComp.relationshipOptions = this.model.relationship;
modalComp.metadataFields = this.model.metadataFields; modalComp.label = this.model.label;
modalComp.item = item;
modalComp.metadataFields = this.model.metadataFields;
})
} }
removeSelection(object: SearchResult<Item>) { removeSelection(object: SearchResult<Item>) {

View File

@@ -2,7 +2,7 @@ import { Component, NgZone, OnInit } from '@angular/core';
import { combineLatest, Observable, Subscription } from 'rxjs'; import { combineLatest, Observable, Subscription } from 'rxjs';
import { NgbActiveModal } from '@ng-bootstrap/ng-bootstrap'; import { NgbActiveModal } from '@ng-bootstrap/ng-bootstrap';
import { hasValue, hasValueOperator } from '../../../../empty.util'; import { hasValue, hasValueOperator } from '../../../../empty.util';
import { map, switchMap, take, tap } from 'rxjs/operators'; import { map, skip, switchMap, take, tap } from 'rxjs/operators';
import { SEARCH_CONFIG_SERVICE } from '../../../../../+my-dspace-page/my-dspace-page.component'; import { SEARCH_CONFIG_SERVICE } from '../../../../../+my-dspace-page/my-dspace-page.component';
import { SearchConfigurationService } from '../../../../../core/shared/search/search-configuration.service'; import { SearchConfigurationService } from '../../../../../core/shared/search/search-configuration.service';
import { SelectableListService } from '../../../../object-list/selectable-list/selectable-list.service'; import { SelectableListService } from '../../../../object-list/selectable-list/selectable-list.service';
@@ -22,7 +22,7 @@ import { Context } from '../../../../../core/shared/context.model';
import { Relationship } from '../../../../../core/shared/item-relationships/relationship.model'; import { Relationship } from '../../../../../core/shared/item-relationships/relationship.model';
import { MetadataValue } from '../../../../../core/shared/metadata.models'; import { MetadataValue } from '../../../../../core/shared/metadata.models';
import { ItemSearchResult } from '../../../../object-collection/shared/item-search-result.model'; import { ItemSearchResult } from '../../../../object-collection/shared/item-search-result.model';
import { RelationshipListState } from './relationship.reducer'; import { NameVariantListState } from './name-variant.reducer';
@Component({ @Component({
selector: 'ds-dynamic-lookup-relation-modal', selector: 'ds-dynamic-lookup-relation-modal',
@@ -40,11 +40,14 @@ export class DsDynamicLookupRelationModalComponent implements OnInit {
label: string; label: string;
relationshipOptions: RelationshipOptions; relationshipOptions: RelationshipOptions;
listId: string; listId: string;
itemRD$; item;
repeatable: boolean; repeatable: boolean;
selection$: Observable<ListableObject[]>; selection$: Observable<ListableObject[]>;
context: Context; context: Context;
metadataFields: string; metadataFields: string;
subMap: {
[uuid: string]: Subscription
};
constructor( constructor(
public modal: NgbActiveModal, public modal: NgbActiveModal,
@@ -61,8 +64,6 @@ export class DsDynamicLookupRelationModalComponent implements OnInit {
if (this.relationshipOptions.nameVariants) { if (this.relationshipOptions.nameVariants) {
this.context = Context.Submission; this.context = Context.Submission;
} }
this.itemRD$.subscribe((r) => console.log(r));
this.setExistingNameVariants();
} }
close() { close() {
@@ -73,8 +74,16 @@ export class DsDynamicLookupRelationModalComponent implements OnInit {
this.zone.runOutsideAngular( this.zone.runOutsideAngular(
() => { () => {
const obs: Observable<any[]> = combineLatest(...selectableObjects.map((sri: SearchResult<Item>) => { const obs: Observable<any[]> = combineLatest(...selectableObjects.map((sri: SearchResult<Item>) => {
return this.relationshipService.getNameVariant(this.listId, sri.indexableObject.uuid) const nameVariant$ = this.relationshipService.getNameVariant(this.listId, sri.indexableObject.uuid);
.pipe(map((nameVariant: string) => { this.subMap[sri.indexableObject.uuid] = nameVariant$
.pipe(skip(1))
.subscribe((nameVariant: string) =>
this.relationshipService.updateNameVariant(this.item, sri.indexableObject, this.relationshipOptions.relationshipType, nameVariant)
);
return nameVariant$
.pipe(
take(1),
map((nameVariant: string) => {
return { return {
item: sri.indexableObject, item: sri.indexableObject,
nameVariant nameVariant
@@ -84,10 +93,10 @@ export class DsDynamicLookupRelationModalComponent implements OnInit {
}) })
); );
combineLatest(this.itemRD$.pipe(getSucceededRemoteData()), obs) obs
.subscribe(([itemRD, obs]: [RemoteData<Item>, any[]]) => { .subscribe((obs: any[]) => {
return obs.forEach((object: any) => { return obs.forEach((object: any) => {
this.store.dispatch(new AddRelationshipAction(itemRD.payload, object.item, this.relationshipOptions.relationshipType, object.nameVariant)); this.store.dispatch(new AddRelationshipAction(this.item, object.item, this.relationshipOptions.relationshipType, object.nameVariant));
this.addSelectSubscription(object); this.addSelectSubscription(object);
} }
); );
@@ -97,28 +106,22 @@ export class DsDynamicLookupRelationModalComponent implements OnInit {
deselect(...selectableObjects: SearchResult<Item>[]) { deselect(...selectableObjects: SearchResult<Item>[]) {
this.zone.runOutsideAngular( this.zone.runOutsideAngular(
() => this.itemRD$.pipe( () => selectableObjects.forEach((object) => {
getSucceededRemoteData(), this.store.dispatch(new RemoveRelationshipAction(this.item, object.indexableObject, this.relationshipOptions.relationshipType));
tap((itemRD: RemoteData<Item>) => { this.addSelectSubscription(object);
return selectableObjects.forEach((object) => { })
this.store.dispatch(new RemoveRelationshipAction(itemRD.payload, object.indexableObject, this.relationshipOptions.relationshipType)); )
this.addSelectSubscription(object); ;
});
}
)
).subscribe()
);
} }
subscriptions = new Map<string, Subscription>(); subscriptions = new Map<string, Subscription>();
addSelectSubscription(itemSR: SearchResult<Item>) { addSelectSubscription(itemSR: SearchResult<Item>) {
const item$ = this.itemRD$.pipe(getSucceededRemoteData(), getRemoteDataPayload());
const nameVariant$ = this.relationshipService.getNameVariant(this.listId, itemSR.indexableObject.uuid).pipe(hasValueOperator()); const nameVariant$ = this.relationshipService.getNameVariant(this.listId, itemSR.indexableObject.uuid).pipe(hasValueOperator());
const subscription = combineLatest(item$, nameVariant$) const subscription = nameVariant$
.pipe( .pipe(
switchMap(([item, nameVariant]: [Item, string]) => { switchMap((nameVariant: string) => {
return this.relationshipService.getRelationshipByItemsAndLabel(item, itemSR.indexableObject, this.relationshipOptions.relationshipType) return this.relationshipService.getRelationshipByItemsAndLabel(this.item, itemSR.indexableObject, this.relationshipOptions.relationshipType)
.pipe(map((relationship: Relationship) => Object.assign(new Relationship(), relationship, { leftwardValue: nameVariant }))) .pipe(map((relationship: Relationship) => Object.assign(new Relationship(), relationship, { leftwardValue: nameVariant })))
}), }),
switchMap((updatedRelation: Relationship) => this.relationshipService.update(updatedRelation)) switchMap((updatedRelation: Relationship) => this.relationshipService.update(updatedRelation))
@@ -139,10 +142,7 @@ export class DsDynamicLookupRelationModalComponent implements OnInit {
} }
setExistingNameVariants() { setExistingNameVariants() {
const virtualMDs$: Observable<MetadataValue[]> = this.itemRD$.pipe( const virtualMDs$: Observable<MetadataValue[]> = this.item.allMetadata(this.metadataFields).filter((mdValue) => mdValue.isVirtual);
getSucceededRemoteData(),
getRemoteDataPayload(),
map((item: Item) => item.allMetadata(this.metadataFields).filter((mdValue) => mdValue.isVirtual)));
const relatedItemPairs$: Observable<[Item, Item][]> = virtualMDs$.pipe( const relatedItemPairs$: Observable<[Item, Item][]> = virtualMDs$.pipe(
switchMap((mds: MetadataValue[]) => combineLatest(mds.map((md: MetadataValue) => this.relationshipService.findById(md.virtualValue).pipe(getSucceededRemoteData(), getRemoteDataPayload())))), switchMap((mds: MetadataValue[]) => combineLatest(mds.map((md: MetadataValue) => this.relationshipService.findById(md.virtualValue).pipe(getSucceededRemoteData(), getRemoteDataPayload())))),
@@ -155,8 +155,8 @@ export class DsDynamicLookupRelationModalComponent implements OnInit {
) )
); );
const relatedItems$: Observable<Item[]> = combineLatest(relatedItemPairs$, this.itemRD$).pipe( const relatedItems$: Observable<Item[]> = relatedItemPairs$.pipe(
map(([relatedItemPairs, itemRD]: [[Item, Item][], RemoteData<Item>]) => relatedItemPairs.map(([left, right]: [Item, Item]) => left.uuid === itemRD.payload.uuid ? left : right)) map(([relatedItemPairs,]: [[Item, Item][]]) => relatedItemPairs.map(([left, right]: [Item, Item]) => left.uuid === this.item.uuid ? left : right))
); );
combineLatest(virtualMDs$, relatedItems$).pipe(take(1)).subscribe(([virtualMDs, relatedItems]) => { combineLatest(virtualMDs$, relatedItems$).pipe(take(1)).subscribe(([virtualMDs, relatedItems]) => {

View File

@@ -0,0 +1,54 @@
/**
* The list of NameVariantAction type definitions
*/
import { type } from '../../../../ngrx/type';
import { Action } from '@ngrx/store';
import { Item } from '../../../../../core/shared/item.model';
export const NameVariantActionTypes = {
SET_NAME_VARIANT: type('dspace/name-variant/SET_NAME_VARIANT'),
REMOVE_NAME_VARIANT: type('dspace/name-variant/REMOVE_NAME_VARIANT'),
};
/* tslint:disable:max-classes-per-file */
export abstract class NameVariantListAction implements Action {
type;
payload: {
listID: string;
itemID: string;
};
constructor(listID: string, itemID: string) {
this.payload = { listID, itemID };
}
}
export class SetNameVariantAction extends NameVariantListAction {
type = NameVariantActionTypes.SET_NAME_VARIANT;
payload: {
listID: string;
itemID: string;
nameVariant: string;
};
constructor(listID: string, itemID: string, nameVariant: string) {
super(listID, itemID);
this.payload.nameVariant = nameVariant;
}
}
export class RemoveNameVariantAction extends NameVariantListAction {
type = NameVariantActionTypes.REMOVE_NAME_VARIANT;
constructor(listID: string, itemID: string) {
super(listID, itemID);
}
}
/* tslint:enable:max-classes-per-file */
/**
* A type to encompass all RelationshipActions
*/
export type NameVariantAction
= SetNameVariantAction
| RemoveNameVariantAction

View File

@@ -0,0 +1,45 @@
/**
* Represents the state of all lists containing name variants in the store
*/
import { NameVariantAction, NameVariantActionTypes, SetNameVariantAction } from './name-variant.actions';
export type NameVariantListsState = {
[listID: string]: NameVariantListState;
}
/**
* Represents the state of a single list containing nameVariants in the store
*/
export type NameVariantListState = {
[itemID: string]: string;
}
/**
* Reducer that handles NameVariantAction to update the NameVariantListsState
* @param {NameVariantListsState} state The initial NameVariantListsState
* @param {NameVariantAction} action The Action to be performed on the state
* @returns {NameVariantListsState} The new, reduced NameVariantListsState
*/
export function nameVariantReducer(state: NameVariantListsState = {}, action: NameVariantAction): NameVariantListsState {
switch (action.type) {
case NameVariantActionTypes.SET_NAME_VARIANT: {
const listState: NameVariantListState = state[action.payload.listID] || {};
const nameVariant = (action as SetNameVariantAction).payload.nameVariant;
const newListState = setNameVariant(listState, action.payload.itemID, nameVariant);
return Object.assign({}, state, { [action.payload.listID]: newListState });
}
case NameVariantActionTypes.REMOVE_NAME_VARIANT: {
const listState: NameVariantListState = state[action.payload.listID] || {};
const newListState = setNameVariant(listState, action.payload.itemID, undefined);
return Object.assign({}, state, { [action.payload.listID]: newListState });
}
default: {
return state;
}
}
}
function setNameVariant(state: NameVariantListState, itemID: string, nameVariant: string) {
return Object.assign({}, state, { [itemID]: { nameVariant } });
}

View File

@@ -8,46 +8,9 @@ import { Item } from '../../../../../core/shared/item.model';
export const RelationshipActionTypes = { export const RelationshipActionTypes = {
ADD_RELATIONSHIP: type('dspace/relationship/ADD_RELATIONSHIP'), ADD_RELATIONSHIP: type('dspace/relationship/ADD_RELATIONSHIP'),
REMOVE_RELATIONSHIP: type('dspace/relationship/REMOVE_RELATIONSHIP'), REMOVE_RELATIONSHIP: type('dspace/relationship/REMOVE_RELATIONSHIP'),
SET_NAME_VARIANT: type('dspace/relationship/SET_NAME_VARIANT'),
REMOVE_NAME_VARIANT: type('dspace/relationship/REMOVE_NAME_VARIANT'),
}; };
/* tslint:disable:max-classes-per-file */ /* tslint:disable:max-classes-per-file */
export abstract class RelationshipListAction implements Action {
type;
payload: {
listID: string;
itemID: string;
};
constructor(listID: string, itemID: string) {
this.payload = { listID, itemID };
}
}
export class SetNameVariantAction extends RelationshipListAction {
type = RelationshipActionTypes.SET_NAME_VARIANT;
payload: {
listID: string;
itemID: string;
nameVariant: string;
};
constructor(listID: string, itemID: string, nameVariant: string) {
super(listID, itemID);
this.payload.nameVariant = nameVariant;
}
}
export class RemoveNameVariantAction extends RelationshipListAction {
type = RelationshipActionTypes.REMOVE_NAME_VARIANT;
constructor(listID: string, itemID: string, ) {
super(listID, itemID);
}
}
/** /**
* An ngrx action to create a new relationship * An ngrx action to create a new relationship
*/ */

View File

@@ -1,51 +0,0 @@
/**
* Represents the state of all lists containing relationships in the store
*/
import { RelationshipActionTypes, RelationshipListAction, SetNameVariantAction } from './relationship.actions';
export type RelationshipListsState = {
[listID: string]: RelationshipListState;
}
/**
* Represents the state of a single list containing relationships in the store
*/
export type RelationshipListState = {
[itemID: string]: RelationshipState;
}
/**
* Represents the state of a relationship in a list in the store
*/
export type RelationshipState = {
nameVariant: string;
}
/**
* Reducer that handles RelationshipListAction to update the RelationshipListsState
* @param {RelationshipListsState} state The initial RelationshipListsState
* @param {RelationshipListAction} action The Action to be performed on the state
* @returns {RelationshipListsState} The new, reduced RelationshipListsState
*/
export function relationshipListReducer(state: RelationshipListsState = {}, action: RelationshipListAction): RelationshipListsState {
switch (action.type) {
case RelationshipActionTypes.SET_NAME_VARIANT: {
const listState: RelationshipListState = state[action.payload.listID] || {};
const nameVariant = (action as SetNameVariantAction).payload.nameVariant;
const newListState = setNameVariant(listState, action.payload.itemID, nameVariant);
return Object.assign({}, state, { [action.payload.listID]: newListState });
}
case RelationshipActionTypes.REMOVE_NAME_VARIANT: {
const listState: RelationshipListState = state[action.payload.listID] || {};
const newListState = setNameVariant(listState, action.payload.itemID, undefined);
return Object.assign({}, state, { [action.payload.listID]: newListState });
}
default: {
return state;
}
}
}
function setNameVariant(state: RelationshipListState, itemID: string, nameVariant: string) {
return Object.assign({}, state, { [itemID]: { nameVariant } });
}