mirror of
https://github.com/DSpace/dspace-angular.git
synced 2025-10-07 01:54:15 +00:00
65711: name variants in store
This commit is contained in:
@@ -32,6 +32,7 @@ import {
|
||||
BitstreamFormatRegistryState
|
||||
} from './+admin/admin-registries/bitstream-formats/bitstream-format.reducers';
|
||||
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';
|
||||
|
||||
export interface AppState {
|
||||
router: fromRouter.RouterReducerState;
|
||||
@@ -48,6 +49,7 @@ export interface AppState {
|
||||
menus: MenusState;
|
||||
objectSelection: ObjectSelectionListState;
|
||||
selectableLists: SelectableListsState;
|
||||
relationshipLists: RelationshipListsState;
|
||||
}
|
||||
|
||||
export const appReducers: ActionReducerMap<AppState> = {
|
||||
@@ -64,7 +66,8 @@ export const appReducers: ActionReducerMap<AppState> = {
|
||||
cssVariables: cssVariablesReducer,
|
||||
menus: menusReducer,
|
||||
objectSelection: objectSelectionReducer,
|
||||
selectableLists: selectableListReducer
|
||||
selectableLists: selectableListReducer,
|
||||
relationshipLists: relationshipListReducer
|
||||
};
|
||||
|
||||
export const routerStateSelector = (state: AppState) => state.router;
|
||||
|
@@ -19,13 +19,27 @@ import { compareArraysUsingIds, paginatedRelationsToItems, relationsToItems } fr
|
||||
import { ObjectCacheService } from '../cache/object-cache.service';
|
||||
import { DataService } from './data.service';
|
||||
import { NormalizedObjectBuildService } from '../cache/builders/normalized-object-build.service';
|
||||
import { Store } from '@ngrx/store';
|
||||
import { MemoizedSelector, select, Store } from '@ngrx/store';
|
||||
import { CoreState } from '../core.reducers';
|
||||
import { NotificationsService } from '../../shared/notifications/notifications.service';
|
||||
import { HttpClient, HttpHeaders } from '@angular/common/http';
|
||||
import { DefaultChangeAnalyzer } from './default-change-analyzer.service';
|
||||
import { SearchParam } from '../cache/models/search-param.model';
|
||||
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 { AppState, keySelector } from '../../app.reducer';
|
||||
import { RelationshipListState, RelationshipState } from '../../shared/form/builder/ds-dynamic-form-ui/relation-lookup-modal/relationship.reducer';
|
||||
|
||||
|
||||
const relationshipListsStateSelector = (state: AppState) => state.relationshipLists;
|
||||
|
||||
const relationshipListStateSelector = (listID: string): MemoizedSelector<AppState, RelationshipListState> => {
|
||||
return keySelector<RelationshipListState>(listID, relationshipListsStateSelector);
|
||||
};
|
||||
|
||||
const relationshipStateSelector = (listID: string, itemID: string): MemoizedSelector<AppState, RelationshipState> => {
|
||||
return keySelector<RelationshipState>(itemID, relationshipListStateSelector(listID));
|
||||
};
|
||||
|
||||
/**
|
||||
* The service handling all relationship requests
|
||||
@@ -44,7 +58,8 @@ export class RelationshipService extends DataService<Relationship> {
|
||||
protected objectCache: ObjectCacheService,
|
||||
protected notificationsService: NotificationsService,
|
||||
protected http: HttpClient,
|
||||
protected comparator: DefaultChangeAnalyzer<Relationship>) {
|
||||
protected comparator: DefaultChangeAnalyzer<Relationship>,
|
||||
protected appStore: Store<AppState>) {
|
||||
super();
|
||||
}
|
||||
|
||||
@@ -204,7 +219,7 @@ export class RelationshipService extends DataService<Relationship> {
|
||||
if (options) {
|
||||
findAllOptions = Object.assign(new FindAllOptions(), options);
|
||||
}
|
||||
const searchParams = [ new SearchParam('label', label), new SearchParam('dso', item.id) ];
|
||||
const searchParams = [new SearchParam('label', label), new SearchParam('dso', item.id)];
|
||||
if (findAllOptions.searchParams) {
|
||||
findAllOptions.searchParams = [...findAllOptions.searchParams, ...searchParams];
|
||||
} else {
|
||||
@@ -272,4 +287,17 @@ export class RelationshipService extends DataService<Relationship> {
|
||||
);
|
||||
}
|
||||
|
||||
public setNameVariant(listID: string, itemID: string, nameVariant: string) {
|
||||
this.appStore.dispatch(new SetNameVariantAction(listID, itemID, nameVariant));
|
||||
}
|
||||
|
||||
public getNameVariant(listID: string, itemID: string): Observable<string> {
|
||||
return this.appStore.pipe(
|
||||
select(relationshipStateSelector(listID, itemID)), map((state: RelationshipState) => hasValue(state) ? state.nameVariant : undefined)
|
||||
);
|
||||
}
|
||||
|
||||
public removeNameVariant(listID: string, itemID: string) {
|
||||
this.appStore.dispatch(new RemoveNameVariantAction(listID, itemID));
|
||||
}
|
||||
}
|
||||
|
@@ -1,6 +1,6 @@
|
||||
<ds-item-type-badge [object]="dso"></ds-item-type-badge>
|
||||
<ds-truncatable [id]="dso.id">
|
||||
<ds-person-input-suggestions [suggestions]="suggestions" (typeSuggestion)="filter($event)"></ds-person-input-suggestions>
|
||||
<ds-person-input-suggestions [suggestions]="suggestions" (typeSuggestion)="filter($event)" [(ngModel)]="selected" (clickSuggestion)="select($event)" (submitSuggestion)="select($event)"></ds-person-input-suggestions>
|
||||
<!-- <select>-->
|
||||
<!-- <option [value]="firstMetadataValue('person.familyName') + ', ' + firstMetadataValue('person.givenName')" [innerHTML]="firstMetadataValue('person.familyName') + ', ' + firstMetadataValue('person.givenName')"></option>-->
|
||||
<!-- <option *ngFor="let value of allMetadataValues('dc.title.alternative')" [value]="value" [innerHTML]="value"></option>-->
|
||||
|
@@ -5,6 +5,9 @@ import { listableObjectComponent } from '../../../../../shared/object-collection
|
||||
import { ViewMode } from '../../../../../core/shared/view-mode.model';
|
||||
import { Item } from '../../../../../core/shared/item.model';
|
||||
import { Context } from '../../../../../core/shared/context.model';
|
||||
import { RelationshipService } from '../../../../../core/data/relationship.service';
|
||||
import { TruncatableService } from '../../../../../shared/truncatable/truncatable.service';
|
||||
import { take } from 'rxjs/operators';
|
||||
|
||||
@listableObjectComponent('PersonSearchResult', ViewMode.ListElement, Context.Submission)
|
||||
@Component({
|
||||
@@ -18,16 +21,31 @@ import { Context } from '../../../../../core/shared/context.model';
|
||||
export class PersonSearchResultListSubmissionElementComponent extends SearchResultListElementComponent<ItemSearchResult, Item> implements OnInit {
|
||||
suggestions: string[];
|
||||
allSuggestions: string[];
|
||||
selected: string;
|
||||
|
||||
constructor(protected truncatableService: TruncatableService, private relationshipService: RelationshipService) {
|
||||
super(truncatableService);
|
||||
}
|
||||
|
||||
ngOnInit() {
|
||||
super.ngOnInit();
|
||||
const defaultValue = this.firstMetadataValue('person.familyName') + ', ' + this.firstMetadataValue('person.givenName')
|
||||
const defaultValue = this.firstMetadataValue('person.familyName') + ', ' + this.firstMetadataValue('person.givenName');
|
||||
const alternatives = this.allMetadataValues('dc.title.alternative');
|
||||
this.allSuggestions = [defaultValue, ...alternatives];
|
||||
this.suggestions = this.allSuggestions;
|
||||
|
||||
this.relationshipService.getNameVariant(this.listID, this.dso.uuid)
|
||||
.pipe(take(1))
|
||||
.subscribe((nameVariant: string) => {
|
||||
this.selected = nameVariant || defaultValue;
|
||||
});
|
||||
}
|
||||
|
||||
filter(query) {
|
||||
this.suggestions = this.allSuggestions.filter((suggestion) => suggestion.includes(query));
|
||||
}
|
||||
|
||||
select(value) {
|
||||
this.relationshipService.setNameVariant(this.listID, this.dso.uuid, value);
|
||||
}
|
||||
}
|
||||
|
@@ -1,8 +1,8 @@
|
||||
import { Component, NgZone, OnInit } from '@angular/core';
|
||||
import { Observable } from 'rxjs';
|
||||
import { combineLatest, Observable } from 'rxjs';
|
||||
import { NgbActiveModal } from '@ng-bootstrap/ng-bootstrap';
|
||||
import { hasValue } from '../../../../empty.util';
|
||||
import { map, tap } from 'rxjs/operators';
|
||||
import { map, switchMap, take, 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';
|
||||
@@ -11,7 +11,7 @@ import { ListableObject } from '../../../../object-collection/shared/listable-ob
|
||||
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 { getRemoteDataPayload, 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';
|
||||
@@ -19,6 +19,8 @@ import { RelationshipTypeService } from '../../../../../core/data/relationship-t
|
||||
import { Store } from '@ngrx/store';
|
||||
import { AppState } from '../../../../../app.reducer';
|
||||
import { Context } from '../../../../../core/shared/context.model';
|
||||
import { Relationship } from '../../../../../core/shared/item-relationships/relationship.model';
|
||||
import { PaginatedList } from '../../../../../core/data/paginated-list';
|
||||
|
||||
@Component({
|
||||
selector: 'ds-dynamic-lookup-relation-modal',
|
||||
@@ -56,6 +58,27 @@ export class DsDynamicLookupRelationModalComponent implements OnInit {
|
||||
if (this.relationship.nameVariants) {
|
||||
this.context = Context.Submission;
|
||||
}
|
||||
this.itemRD$.pipe(
|
||||
switchMap((itemRD: RemoteData<Item>) => this.relationshipService.getItemRelationshipsByLabel(itemRD.payload, this.relationship.relationshipType)),
|
||||
getSucceededRemoteData(),
|
||||
getRemoteDataPayload(),
|
||||
map((relationships: PaginatedList<Relationship>) => relationships.page.)
|
||||
);
|
||||
combineLatest(this.itemRD$, this.selection$)
|
||||
.pipe(
|
||||
take(1),
|
||||
switchMap(([itemRD, objects]: [RemoteData<Item>, ListableObject[]]) => {
|
||||
return combineLatest(objects.map((obj: Item) => this.relationshipService.getRelationshipsByRelatedItemIds(itemRD.payload, [obj.uuid])
|
||||
.pipe(take(1), map((rels: Relationship[]) => [rels[0], obj.uuid] as [Relationship, string])))
|
||||
)
|
||||
}
|
||||
)
|
||||
).subscribe((relations: [Relationship, string][]) => {
|
||||
relations.forEach((([rel, id]: [Relationship, string]) => {
|
||||
this.relationshipService.setNameVariant(this.listId, id, rel.)
|
||||
}))
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
close() {
|
||||
|
@@ -8,10 +8,46 @@ import { Item } from '../../../../../core/shared/item.model';
|
||||
export const RelationshipActionTypes = {
|
||||
ADD_RELATIONSHIP: type('dspace/relationship/ADD_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 */
|
||||
|
||||
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
|
||||
*/
|
||||
|
@@ -3,7 +3,7 @@ import { Actions, Effect, ofType } from '@ngrx/effects';
|
||||
import { debounceTime, map, mergeMap, take, tap } from 'rxjs/operators';
|
||||
import { BehaviorSubject } from 'rxjs';
|
||||
import { RelationshipService } from '../../../../../core/data/relationship.service';
|
||||
import { AddRelationshipAction, RelationshipAction, RelationshipActionTypes } from './relationship.actions';
|
||||
import { AddRelationshipAction, RelationshipAction, RelationshipActionTypes, RemoveRelationshipAction } from './relationship.actions';
|
||||
import { Item } from '../../../../../core/shared/item.model';
|
||||
import { hasNoValue, hasValueOperator } from '../../../../empty.util';
|
||||
import { Relationship } from '../../../../../core/shared/item-relationships/relationship.model';
|
||||
@@ -34,7 +34,7 @@ export class RelationshipEffects {
|
||||
*/
|
||||
@Effect({ dispatch: false }) mapLastActions$ = this.actions$
|
||||
.pipe(
|
||||
ofType(...Object.values(RelationshipActionTypes)),
|
||||
ofType(RelationshipActionTypes.ADD_RELATIONSHIP, RelationshipActionTypes.REMOVE_RELATIONSHIP),
|
||||
map((action: RelationshipAction) => {
|
||||
const { item1, item2, relationshipType } = action.payload;
|
||||
const identifier: string = this.createIdentifier(item1, item2, relationshipType);
|
||||
@@ -74,7 +74,6 @@ export class RelationshipEffects {
|
||||
|
||||
private addRelationship(item1: Item, item2: Item, relationshipType: string, nameVariant?: string) {
|
||||
const type1: string = item1.firstMetadataValue('relationship.type');
|
||||
// const type1: string = 'JournalVolume';
|
||||
const type2: string = item2.firstMetadataValue('relationship.type');
|
||||
return this.relationshipTypeService.getRelationshipTypeByLabelAndTypes(relationshipType, type1, type2)
|
||||
.pipe(
|
||||
|
@@ -0,0 +1,51 @@
|
||||
/**
|
||||
* 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 } });
|
||||
}
|
@@ -41,6 +41,11 @@ export class ListableObjectComponentLoaderComponent implements OnInit {
|
||||
*/
|
||||
@Input() linkType: CollectionElementLinkType;
|
||||
|
||||
/**
|
||||
* The identifier of the list this element resides in
|
||||
*/
|
||||
@Input() listID: string;
|
||||
|
||||
/**
|
||||
* Directive hook used to place the dynamic child component
|
||||
*/
|
||||
@@ -62,6 +67,7 @@ export class ListableObjectComponentLoaderComponent implements OnInit {
|
||||
(componentRef.instance as any).object = this.object;
|
||||
(componentRef.instance as any).index = this.index;
|
||||
(componentRef.instance as any).linkType = this.linkType;
|
||||
(componentRef.instance as any).listID = this.listID;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@@ -17,6 +17,11 @@ export class AbstractListableElementComponent<T extends ListableObject> {
|
||||
*/
|
||||
@Input() linkType: CollectionElementLinkType;
|
||||
|
||||
/**
|
||||
* The identifier of the list this element resides in
|
||||
*/
|
||||
@Input() listID: string;
|
||||
|
||||
/**
|
||||
* The available link types
|
||||
*/
|
||||
|
@@ -26,7 +26,7 @@
|
||||
(click)="selectRadio(!checked, object)">
|
||||
</ng-container>
|
||||
</span>
|
||||
<ds-listable-object-component-loader [object]="object" [viewMode]="viewMode" [index]="i" [context]="context" [linkType]="linkType"></ds-listable-object-component-loader>
|
||||
<ds-listable-object-component-loader [object]="object" [viewMode]="viewMode" [index]="i" [context]="context" [linkType]="linkType" [listID]="selectionConfig?.listId"></ds-listable-object-component-loader>
|
||||
</li>
|
||||
</ul>
|
||||
</ds-pagination>
|
||||
|
Reference in New Issue
Block a user