mirror of
https://github.com/DSpace/dspace-angular.git
synced 2025-10-08 02:24:11 +00:00
62849: fixed issues with multiple selections, improved UX, updating to use new REST response
This commit is contained in:
@@ -431,7 +431,6 @@
|
|||||||
"volume-title": "Volume Title",
|
"volume-title": "Volume Title",
|
||||||
"publisher": "Publisher",
|
"publisher": "Publisher",
|
||||||
"description": "Description"
|
"description": "Description"
|
||||||
|
|
||||||
},
|
},
|
||||||
"listelement": {
|
"listelement": {
|
||||||
"badge": "Publication"
|
"badge": "Publication"
|
||||||
@@ -570,7 +569,7 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"switch-configuration": {
|
"switch-configuration": {
|
||||||
"title":"Show"
|
"title": "Show"
|
||||||
},
|
},
|
||||||
"view-switch": {
|
"view-switch": {
|
||||||
"show-list": "Show as list",
|
"show-list": "Show as list",
|
||||||
@@ -1016,7 +1015,7 @@
|
|||||||
"no-results": "No {{ type }} found"
|
"no-results": "No {{ type }} found"
|
||||||
},
|
},
|
||||||
"submission": {
|
"submission": {
|
||||||
"general":{
|
"general": {
|
||||||
"cannot_submit": "You have not the privilege to make a new submission.",
|
"cannot_submit": "You have not the privilege to make a new submission.",
|
||||||
"deposit": "Deposit",
|
"deposit": "Deposit",
|
||||||
"discard": {
|
"discard": {
|
||||||
@@ -1038,10 +1037,8 @@
|
|||||||
"title": "Edit Submission"
|
"title": "Edit Submission"
|
||||||
},
|
},
|
||||||
"mydspace": {
|
"mydspace": {
|
||||||
|
|
||||||
},
|
},
|
||||||
"sections": {
|
"sections": {
|
||||||
|
|
||||||
"general": {
|
"general": {
|
||||||
"add-more": "Add more",
|
"add-more": "Add more",
|
||||||
"no-sections": "No options available",
|
"no-sections": "No options available",
|
||||||
@@ -1066,7 +1063,6 @@
|
|||||||
"submit.progressbar.license": "Deposit license",
|
"submit.progressbar.license": "Deposit license",
|
||||||
"submit.progressbar.cclicense": "Creative commons license",
|
"submit.progressbar.cclicense": "Creative commons license",
|
||||||
"submit.progressbar.detect-duplicate": "Potential duplicates",
|
"submit.progressbar.detect-duplicate": "Potential duplicates",
|
||||||
|
|
||||||
"upload": {
|
"upload": {
|
||||||
"no-entry": "No",
|
"no-entry": "No",
|
||||||
"no-file-uploaded": "No file uploaded yet.",
|
"no-file-uploaded": "No file uploaded yet.",
|
||||||
@@ -1097,6 +1093,21 @@
|
|||||||
"info": "This operation can't be undone. Are you sure?"
|
"info": "This operation can't be undone. Are you sure?"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
"describe": {
|
||||||
|
"relationship-lookup": {
|
||||||
|
"search": "Go",
|
||||||
|
"loading": "Loading...",
|
||||||
|
"title": "Select a {{ label }}",
|
||||||
|
"toggle-dropdown": "Toggle dropdown",
|
||||||
|
"select-page": "Select page",
|
||||||
|
"deselect-page": "Deselect page",
|
||||||
|
"select-all": "Select all",
|
||||||
|
"deselect-all": "Deselect all",
|
||||||
|
"close": "Close",
|
||||||
|
"selected": "Selected {{ size }} items",
|
||||||
|
"placeholder": "Search query"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"workflow": {
|
"workflow": {
|
||||||
@@ -1132,7 +1143,6 @@
|
|||||||
"reject_help": "If you have reviewed the item and found it is <strong>not</strong> suitable for inclusion in the collection, select \"Reject\". You will then be asked to enter a message indicating why the item is unsuitable, and whether the submitter should change something and resubmit.",
|
"reject_help": "If you have reviewed the item and found it is <strong>not</strong> suitable for inclusion in the collection, select \"Reject\". You will then be asked to enter a message indicating why the item is unsuitable, and whether the submitter should change something and resubmit.",
|
||||||
"return": "Return to pool",
|
"return": "Return to pool",
|
||||||
"return_help": "Return the task to the pool so that another user may perform the task."
|
"return_help": "Return the task to the pool so that another user may perform the task."
|
||||||
|
|
||||||
},
|
},
|
||||||
"pool": {
|
"pool": {
|
||||||
"claim": "Claim",
|
"claim": "Claim",
|
||||||
|
@@ -8,39 +8,24 @@
|
|||||||
"input": {
|
"input": {
|
||||||
"type": "lookup-relation"
|
"type": "lookup-relation"
|
||||||
},
|
},
|
||||||
"label": "Journal Issue",
|
"label": "Author",
|
||||||
"mandatory": true,
|
"mandatory": true,
|
||||||
"repeatable": true,
|
"repeatable": true,
|
||||||
"mandatoryMessage": "Required field!",
|
"mandatoryMessage": "At least one author (plain text or relationship) is required",
|
||||||
"hints": "Select a journal issue for this publication.",
|
"hints": "Add an author",
|
||||||
"selectableMetadata": [
|
"selectableRelationships": [
|
||||||
{
|
{
|
||||||
"metadata": "relation.isPublicationOfJournalIssue",
|
"relationshipType": "isAuthorOfPublication",
|
||||||
"label": null,
|
"filter": null,
|
||||||
"authority": null,
|
"searchConfiguration": "personConfiguration"
|
||||||
"closed": null
|
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"languageCodes": []
|
|
||||||
}
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"fields": [
|
|
||||||
{
|
|
||||||
"input": {
|
|
||||||
"type": "name"
|
|
||||||
},
|
|
||||||
"label": "Authors",
|
|
||||||
"mandatory": false,
|
|
||||||
"repeatable": true,
|
|
||||||
"hints": "Enter the names of the authors of this item.",
|
|
||||||
"selectableMetadata": [
|
"selectableMetadata": [
|
||||||
{
|
{
|
||||||
"metadata": "dc.contributor.author",
|
"metadata": "dc.contributor.author",
|
||||||
"label": null,
|
"label": null,
|
||||||
"authority": null,
|
"authority": null,
|
||||||
"closed": null
|
"closed": false
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"languageCodes": []
|
"languageCodes": []
|
||||||
|
@@ -206,7 +206,7 @@ export class SearchConfigurationService implements OnDestroy {
|
|||||||
* @returns {Observable<string>} Emits the current fixed filter as a string
|
* @returns {Observable<string>} Emits the current fixed filter as a string
|
||||||
*/
|
*/
|
||||||
getCurrentFixedFilter(): Observable<string> {
|
getCurrentFixedFilter(): Observable<string> {
|
||||||
return this.routeService.getRouteParameterValue('fixedFilterQuery').pipe(tap((t) => console.log(t)));
|
return this.routeService.getRouteParameterValue('fixedFilterQuery');
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@@ -1,8 +1,26 @@
|
|||||||
import { isEmpty } from '../../shared/empty.util';
|
import { isEmpty } from '../../shared/empty.util';
|
||||||
|
import { GenericConstructor } from '../shared/generic-constructor';
|
||||||
|
import { EquatableObject } from './equatable';
|
||||||
|
|
||||||
const excludedFromEquals = new Map();
|
const excludedFromEquals = new Map();
|
||||||
const fieldsForEqualsMap = new Map();
|
const fieldsForEqualsMap = new Map();
|
||||||
|
|
||||||
|
export function inheritEquatable(parentCo: GenericConstructor<EquatableObject<any>>) {
|
||||||
|
return function decorator(childCo: GenericConstructor<EquatableObject<any>>) {
|
||||||
|
const parentExcludedFields = getExcludedFromEqualsFor(parentCo) || [];
|
||||||
|
const excludedFields = getExcludedFromEqualsFor(childCo) || [];
|
||||||
|
excludedFromEquals.set(childCo, [...excludedFields, ...parentExcludedFields]);
|
||||||
|
|
||||||
|
const mappedFields = fieldsForEqualsMap.get(childCo) || new Map();
|
||||||
|
const parentMappedFields = fieldsForEqualsMap.get(parentCo) || new Map();
|
||||||
|
Array.from(parentMappedFields.keys())
|
||||||
|
.filter((key) => !Array.from(mappedFields.keys()).includes(key))
|
||||||
|
.forEach((key) => {
|
||||||
|
fieldsForEquals(...parentMappedFields.get(key))(new childCo(), key);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
export function excludeFromEquals(object: any, propertyName: string): any {
|
export function excludeFromEquals(object: any, propertyName: string): any {
|
||||||
if (!object) {
|
if (!object) {
|
||||||
return;
|
return;
|
||||||
@@ -14,7 +32,7 @@ export function excludeFromEquals(object: any, propertyName: string): any {
|
|||||||
excludedFromEquals.set(object.constructor, [...list, propertyName]);
|
excludedFromEquals.set(object.constructor, [...list, propertyName]);
|
||||||
}
|
}
|
||||||
|
|
||||||
export function getExcludedFromEqualsFor(constructor: Function) {
|
export function getExcludedFromEqualsFor(constructor: Function): string[] {
|
||||||
return excludedFromEquals.get(constructor) || [];
|
return excludedFromEquals.get(constructor) || [];
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -33,7 +51,7 @@ export function fieldsForEquals(...fields: string[]): any {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
export function getFieldsForEquals(constructor: Function, field: string) {
|
export function getFieldsForEquals(constructor: Function, field: string): string[] {
|
||||||
const fieldMap = fieldsForEqualsMap.get(constructor) || new Map();
|
const fieldMap = fieldsForEqualsMap.get(constructor) || new Map();
|
||||||
return fieldMap.get(field);
|
return fieldMap.get(field);
|
||||||
}
|
}
|
@@ -1,5 +1,5 @@
|
|||||||
<div class="modal-header">
|
<div class="modal-header">
|
||||||
<h4 class="modal-title" id="modal-title">Choose a {{fieldName}}</h4>
|
<h4 class="modal-title" id="modal-title">{{ ('submission.sections.describe.relationship-lookup.title' | translate:{label: label}) }}</h4>
|
||||||
<button type="button" class="close" aria-label="Close button" aria-describedby="modal-title"
|
<button type="button" class="close" aria-label="Close button" aria-describedby="modal-title"
|
||||||
(click)="modal.dismiss()">
|
(click)="modal.dismiss()">
|
||||||
<span aria-hidden="true">×</span>
|
<span aria-hidden="true">×</span>
|
||||||
@@ -13,10 +13,10 @@
|
|||||||
<div class="col-8">
|
<div class="col-8">
|
||||||
<form class="input-group mb-3" #queryForm="ngForm"
|
<form class="input-group mb-3" #queryForm="ngForm"
|
||||||
(ngSubmit)="search(queryForm.value.query)">
|
(ngSubmit)="search(queryForm.value.query)">
|
||||||
<input type="text" class="form-control" name="query" placeholder="Search query"
|
<input type="text" class="form-control" name="query" [placeholder]="'submission.sections.describe.relationship-lookup.placeholder' | translate"
|
||||||
[ngModel]="searchQuery">
|
[ngModel]="searchQuery">
|
||||||
<div class="input-group-append">
|
<div class="input-group-append">
|
||||||
<button class="btn btn-outline-secondary" type="submit">Go</button>
|
<button class="btn btn-outline-secondary" type="submit">{{ ('submission.sections.describe.relationship-lookup.search' | translate) }}</button>
|
||||||
</div>
|
</div>
|
||||||
</form>
|
</form>
|
||||||
<div *ngIf="repeatable" class="position-absolute">
|
<div *ngIf="repeatable" class="position-absolute">
|
||||||
@@ -46,20 +46,20 @@
|
|||||||
class="btn btn-outline-secondary rounded-right">
|
class="btn btn-outline-secondary rounded-right">
|
||||||
<span class="spinner-border spinner-border-sm" role="status"
|
<span class="spinner-border spinner-border-sm" role="status"
|
||||||
aria-hidden="true"></span>
|
aria-hidden="true"></span>
|
||||||
<span class="sr-only">Loading...</span>
|
<span class="sr-only">{{ ('submission.sections.describe.relationship-lookup.loading' | translate) }}</span>
|
||||||
</button>
|
</button>
|
||||||
<button *ngIf="!selectAllLoading" id="resultdropdown" type="button"
|
<button *ngIf="!selectAllLoading" id="resultdropdown" type="button"
|
||||||
ngbDropdownToggle
|
ngbDropdownToggle
|
||||||
class="btn btn-outline-secondary dropdown-toggle-split"
|
class="btn btn-outline-secondary dropdown-toggle-split"
|
||||||
data-toggle="dropdown" aria-haspopup="true"
|
data-toggle="dropdown" aria-haspopup="true"
|
||||||
aria-expanded="false">
|
aria-expanded="false">
|
||||||
<span class="sr-only">Toggle Dropdown</span>
|
<span class="sr-only">{{ ('submission.sections.describe.relationship-lookup.toggle-dropdown' | translate) }}</span>
|
||||||
</button>
|
</button>
|
||||||
<div ngbDropdownMenu aria-labelledby="resultdropdown">
|
<div ngbDropdownMenu aria-labelledby="resultdropdown">
|
||||||
<button class="dropdown-item" (click)="selectPage(resultsRD?.payload?.page)">Select page</button>
|
<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)">Deselect page</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()">Select all</button>
|
<button class="dropdown-item" (click)="selectAll()">{{ ('submission.sections.describe.relationship-lookup.select-all' | translate) }}</button>
|
||||||
<button class="dropdown-item" (click)="deselectAll()">Deselect all</button>
|
<button class="dropdown-item" (click)="deselectAll()">{{ ('submission.sections.describe.relationship-lookup.deselect-all' | translate) }}</button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -68,15 +68,16 @@
|
|||||||
[sortConfig]="this.searchConfig?.sort"
|
[sortConfig]="this.searchConfig?.sort"
|
||||||
[searchConfig]="this.searchConfig"
|
[searchConfig]="this.searchConfig"
|
||||||
[selectable]="true"
|
[selectable]="true"
|
||||||
[selectionConfig]="{ repeatable: repeatable, listId: listId }">
|
[selectionConfig]="{ repeatable: repeatable, listId: listId }"
|
||||||
|
(deselectObject)="allSelected = false"
|
||||||
|
>
|
||||||
</ds-search-results>
|
</ds-search-results>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="modal-footer">
|
<div class="modal-footer">
|
||||||
<small>Selected {{(selection$ | async)?.length || 0}} items</small>
|
<small>{{ ('submission.sections.describe.relationship-lookup.selected' | translate:{size: (selection$ | async)?.length || 0}) }}</small>
|
||||||
<div>
|
<div>
|
||||||
<button type="button" class="btn btn-outline-secondary" (click)="modal.dismiss()">Cancel</button>
|
<button type="button" class="btn btn-danger" (click)="close()">{{ ('submission.sections.describe.relationship-lookup.close' | translate) }}</button>
|
||||||
<button type="button" class="btn btn-danger" (click)="close()">Ok</button>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
@@ -35,7 +35,9 @@ const RELATION_TYPE_FILTER_PREFIX = 'f.entityType=';
|
|||||||
})
|
})
|
||||||
export class DsDynamicLookupRelationModalComponent implements OnInit {
|
export class DsDynamicLookupRelationModalComponent implements OnInit {
|
||||||
relationKey: string;
|
relationKey: string;
|
||||||
fieldName: string;
|
label: string;
|
||||||
|
filter: string;
|
||||||
|
searchConfiguration: string;
|
||||||
listId: string;
|
listId: string;
|
||||||
resultsRD$: Observable<RemoteData<PaginatedList<SearchResult<DSpaceObject>>>>;
|
resultsRD$: Observable<RemoteData<PaginatedList<SearchResult<DSpaceObject>>>>;
|
||||||
searchConfig: PaginatedSearchOptions;
|
searchConfig: PaginatedSearchOptions;
|
||||||
@@ -49,21 +51,20 @@ export class DsDynamicLookupRelationModalComponent implements OnInit {
|
|||||||
pageSize: 10
|
pageSize: 10
|
||||||
});
|
});
|
||||||
selection$: Observable<ListableObject[]>;
|
selection$: Observable<ListableObject[]>;
|
||||||
fixedFilter: string;
|
|
||||||
|
|
||||||
constructor(public modal: NgbActiveModal, private searchService: SearchService, private router: Router, private selectableListService: SelectableListService, private searchConfigService: SearchConfigurationService, private routeService: RouteService) {
|
constructor(public modal: NgbActiveModal, private searchService: SearchService, private router: Router, private selectableListService: SelectableListService, private searchConfigService: SearchConfigurationService, private routeService: RouteService) {
|
||||||
}
|
}
|
||||||
|
|
||||||
ngOnInit(): void {
|
ngOnInit(): void {
|
||||||
this.resetRoute();
|
this.resetRoute();
|
||||||
this.fixedFilter = RELATION_TYPE_FILTER_PREFIX + this.fieldName;
|
this.routeService.setParameter('fixedFilterQuery', this.filter);
|
||||||
this.routeService.setParameter('fixedFilterQuery', this.fixedFilter);
|
this.routeService.setParameter('configuration', this.searchConfiguration);
|
||||||
|
|
||||||
this.selection$ = this.selectableListService.getSelectableList(this.listId).pipe(map((listState: SelectableListState) => hasValue(listState) && hasValue(listState.selection) ? listState.selection : []));
|
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.someSelected$ = this.selection$.pipe(map((selection) => isNotEmpty(selection)));
|
||||||
this.resultsRD$ = this.searchConfigService.paginatedSearchOptions.pipe(
|
this.resultsRD$ = this.searchConfigService.paginatedSearchOptions.pipe(
|
||||||
map((options) => {
|
map((options) => {
|
||||||
return Object.assign(new PaginatedSearchOptions({}), options, { fixedFilter: RELATION_TYPE_FILTER_PREFIX + this.fieldName })
|
return Object.assign(new PaginatedSearchOptions({}), options, { fixedFilter: this.filter, configuration: this.searchConfiguration })
|
||||||
}),
|
}),
|
||||||
switchMap((options) => {
|
switchMap((options) => {
|
||||||
this.searchConfig = options;
|
this.searchConfig = options;
|
||||||
@@ -85,9 +86,9 @@ export class DsDynamicLookupRelationModalComponent implements OnInit {
|
|||||||
}
|
}
|
||||||
|
|
||||||
search(query: string) {
|
search(query: string) {
|
||||||
|
this.allSelected = false;
|
||||||
this.searchQuery = query;
|
this.searchQuery = query;
|
||||||
this.resetRoute();
|
this.resetRoute();
|
||||||
this.selectableListService.deselectAll(this.listId);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
close() {
|
close() {
|
||||||
@@ -100,7 +101,6 @@ export class DsDynamicLookupRelationModalComponent implements OnInit {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
selectPage(page: SearchResult<DSpaceObject>[]) {
|
selectPage(page: SearchResult<DSpaceObject>[]) {
|
||||||
this.selectableListService.select(this.listId, page);
|
this.selectableListService.select(this.listId, page);
|
||||||
}
|
}
|
||||||
|
@@ -1,4 +1,3 @@
|
|||||||
<script src="dynamic-lookup-relation.component.ts"></script>
|
|
||||||
<div>
|
<div>
|
||||||
<div *ngIf="model.repeatable || !((model.value | async) && (model.value | async).length > 0)" class="form-row align-items-center">
|
<div *ngIf="model.repeatable || !((model.value | async) && (model.value | async).length > 0)" class="form-row align-items-center">
|
||||||
<div class="col">
|
<div class="col">
|
||||||
@@ -12,29 +11,19 @@
|
|||||||
</div>
|
</div>
|
||||||
<div class="col-auto text-center">
|
<div class="col-auto text-center">
|
||||||
<button class="btn btn-secondary"
|
<button class="btn btn-secondary"
|
||||||
type="button"
|
type="submit"
|
||||||
ngbTooltip="{{'form.lookup-help' | translate}}"
|
ngbTooltip="{{'form.lookup-help' | translate}}"
|
||||||
placement="top"
|
placement="top"
|
||||||
(click)="openLookup(); $event.stopPropagation();">{{'form.lookup' | translate}}
|
(click)="openLookup(); $event.stopPropagation();">{{'form.lookup' | translate}}
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
<!--<div class="col-auto text-center">-->
|
|
||||||
<!--<button class="btn btn-secondary"-->
|
|
||||||
<!--type="button"-->
|
|
||||||
<!--ngbTooltip="{{'form.add-help' | translate}}"-->
|
|
||||||
<!--#tooltip = ngbTooltip-->
|
|
||||||
<!--placement="top"-->
|
|
||||||
<!--[disabled]="!hasResultsSelected()"-->
|
|
||||||
<!--(click)="add(); tooltip.close(); $event.stopPropagation();">{{'form.add' | translate}}-->
|
|
||||||
<!--</button>-->
|
|
||||||
<!--</div>-->
|
|
||||||
</div>
|
</div>
|
||||||
<div class="mt-3">
|
<div class="mt-3">
|
||||||
<ul class="list-unstyled">
|
<ul class="list-unstyled">
|
||||||
<li *ngFor="let result of (model.value | async)">
|
<li *ngFor="let result of (model.value | async)">
|
||||||
<ng-container *ngVar="result.indexableObject as value">
|
<ng-container *ngVar="result.indexableObject as value">
|
||||||
<button type="button" class="close float-left" aria-label="Close button"
|
<button type="button" class="close float-left" aria-label="Close button"
|
||||||
(click)="removeSelection(value)">
|
(click)="removeSelection(result)">
|
||||||
<span aria-hidden="true">×</span>
|
<span aria-hidden="true">×</span>
|
||||||
</button>
|
</button>
|
||||||
<span class="d-inline-block align-middle ml-1">{{value.name}}</span>
|
<span class="d-inline-block align-middle ml-1">{{value.name}}</span>
|
||||||
|
@@ -1,10 +1,6 @@
|
|||||||
import { Component, EventEmitter, Input, OnInit, Output } from '@angular/core';
|
import { Component, EventEmitter, Input, OnInit, Output } from '@angular/core';
|
||||||
|
|
||||||
import {
|
import { DynamicFormControlComponent, DynamicFormLayoutService, DynamicFormValidationService } from '@ng-dynamic-forms/core';
|
||||||
DynamicFormControlComponent,
|
|
||||||
DynamicFormLayoutService,
|
|
||||||
DynamicFormValidationService
|
|
||||||
} from '@ng-dynamic-forms/core';
|
|
||||||
import { FormGroup } from '@angular/forms';
|
import { FormGroup } from '@angular/forms';
|
||||||
import { hasValue, isNotEmpty } from '../../../../../empty.util';
|
import { hasValue, isNotEmpty } from '../../../../../empty.util';
|
||||||
import { NgbModal, NgbModalRef } from '@ng-bootstrap/ng-bootstrap';
|
import { NgbModal, NgbModalRef } from '@ng-bootstrap/ng-bootstrap';
|
||||||
@@ -12,11 +8,9 @@ import { DsDynamicLookupRelationModalComponent } from './dynamic-lookup-relation
|
|||||||
import { DynamicLookupRelationModel } from './dynamic-lookup-relation.model';
|
import { DynamicLookupRelationModel } from './dynamic-lookup-relation.model';
|
||||||
import { DSpaceObject } from '../../../../../../core/shared/dspace-object.model';
|
import { DSpaceObject } from '../../../../../../core/shared/dspace-object.model';
|
||||||
import { RelationshipService } from '../../../../../../core/data/relationship.service';
|
import { RelationshipService } from '../../../../../../core/data/relationship.service';
|
||||||
import { Item } from '../../../../../../core/shared/item.model';
|
|
||||||
import { SelectableListService } from '../../../../../object-list/selectable-list/selectable-list.service';
|
import { SelectableListService } from '../../../../../object-list/selectable-list/selectable-list.service';
|
||||||
import { SelectableListState } from '../../../../../object-list/selectable-list/selectable-list.reducer';
|
import { SelectableListState } from '../../../../../object-list/selectable-list/selectable-list.reducer';
|
||||||
import { Observable } from 'rxjs';
|
import { Observable } from 'rxjs';
|
||||||
import { ListableObject } from '../../../../../object-collection/shared/listable-object.model';
|
|
||||||
import { map } from 'rxjs/operators';
|
import { map } from 'rxjs/operators';
|
||||||
import { SearchResult } from '../../../../../search/search-result.model';
|
import { SearchResult } from '../../../../../search/search-result.model';
|
||||||
|
|
||||||
@@ -39,8 +33,10 @@ export class DsDynamicLookupRelationComponent extends DynamicFormControlComponen
|
|||||||
|
|
||||||
modalRef: NgbModalRef;
|
modalRef: NgbModalRef;
|
||||||
modalValuesString = '';
|
modalValuesString = '';
|
||||||
fieldName: string;
|
|
||||||
listId: string;
|
listId: string;
|
||||||
|
filter: string;
|
||||||
|
searchConfig: string;
|
||||||
|
|
||||||
|
|
||||||
constructor(private modalService: NgbModal,
|
constructor(private modalService: NgbModal,
|
||||||
protected layoutService: DynamicFormLayoutService,
|
protected layoutService: DynamicFormLayoutService,
|
||||||
@@ -52,8 +48,9 @@ export class DsDynamicLookupRelationComponent extends DynamicFormControlComponen
|
|||||||
}
|
}
|
||||||
|
|
||||||
ngOnInit(): void {
|
ngOnInit(): void {
|
||||||
this.fieldName = this.model.name.substring(RELATION_TYPE_METADATA_PREFIX.length);
|
this.filter = this.model.relationship.filter;
|
||||||
this.listId = 'list-' + this.fieldName;
|
this.searchConfig = this.model.relationship.searchConfiguration;
|
||||||
|
this.listId = 'list-' + this.model.relationship.relationshipType;
|
||||||
this.model.value = this.selectableListService.getSelectableList(this.listId).pipe(
|
this.model.value = this.selectableListService.getSelectableList(this.listId).pipe(
|
||||||
map((listState: SelectableListState) => hasValue(listState) && hasValue(listState.selection) ? listState.selection : []),
|
map((listState: SelectableListState) => hasValue(listState) && hasValue(listState.selection) ? listState.selection : []),
|
||||||
);
|
);
|
||||||
@@ -69,27 +66,15 @@ export class DsDynamicLookupRelationComponent extends DynamicFormControlComponen
|
|||||||
modalComp.repeatable = this.model.repeatable;
|
modalComp.repeatable = this.model.repeatable;
|
||||||
modalComp.relationKey = this.model.name;
|
modalComp.relationKey = this.model.name;
|
||||||
modalComp.listId = this.listId;
|
modalComp.listId = this.listId;
|
||||||
modalComp.fieldName = this.fieldName;
|
modalComp.filter = this.filter;
|
||||||
|
modalComp.fieldName = this.searchConfig;
|
||||||
|
modalComp.label = this.model.label;
|
||||||
|
|
||||||
this.modalRef.result.then((resultString = '') => {
|
this.modalRef.result.then((resultString = '') => {
|
||||||
this.modalValuesString = resultString;
|
this.modalValuesString = resultString;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
// add() {
|
|
||||||
// if (isNotEmpty(this.model.value)) {
|
|
||||||
// this.model.value = [...this.model.value, ...this.selectedResults];
|
|
||||||
// } else {
|
|
||||||
// this.model.value = this.selectedResults;
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// this.modalValuesString = '';
|
|
||||||
// this.selectedResults = [];
|
|
||||||
// this.selectedResults.forEach((item: Item) => {
|
|
||||||
// this.relationService.addRelationship(this.model.item, item);
|
|
||||||
// })
|
|
||||||
// }
|
|
||||||
|
|
||||||
removeSelection(object: SearchResult<DSpaceObject>) {
|
removeSelection(object: SearchResult<DSpaceObject>) {
|
||||||
this.selectableListService.deselectSingle(this.listId, object);
|
this.selectableListService.deselectSingle(this.listId, object);
|
||||||
}
|
}
|
||||||
|
@@ -1,6 +1,7 @@
|
|||||||
import { DynamicFormControlLayout, serializable } from '@ng-dynamic-forms/core';
|
import { DynamicFormControlLayout, serializable } from '@ng-dynamic-forms/core';
|
||||||
import { DsDynamicInputModel, DsDynamicInputModelConfig } from '../ds-dynamic-input.model';
|
import { DsDynamicInputModel, DsDynamicInputModelConfig } from '../ds-dynamic-input.model';
|
||||||
import { Item } from '../../../../../../core/shared/item.model';
|
import { Item } from '../../../../../../core/shared/item.model';
|
||||||
|
import { RelationshipOptions } from './model/relationship-options.model';
|
||||||
|
|
||||||
export const DYNAMIC_FORM_CONTROL_TYPE_LOOKUP_RELATION = 'LOOKUP_RELATION';
|
export const DYNAMIC_FORM_CONTROL_TYPE_LOOKUP_RELATION = 'LOOKUP_RELATION';
|
||||||
|
|
||||||
@@ -8,6 +9,7 @@ export interface DynamicLookupRelationModelConfig extends DsDynamicInputModelCon
|
|||||||
value?: any;
|
value?: any;
|
||||||
repeatable: boolean;
|
repeatable: boolean;
|
||||||
item: Item;
|
item: Item;
|
||||||
|
relationship: RelationshipOptions;
|
||||||
}
|
}
|
||||||
|
|
||||||
export class DynamicLookupRelationModel extends DsDynamicInputModel {
|
export class DynamicLookupRelationModel extends DsDynamicInputModel {
|
||||||
@@ -15,6 +17,7 @@ export class DynamicLookupRelationModel extends DsDynamicInputModel {
|
|||||||
@serializable() readonly type: string = DYNAMIC_FORM_CONTROL_TYPE_LOOKUP_RELATION;
|
@serializable() readonly type: string = DYNAMIC_FORM_CONTROL_TYPE_LOOKUP_RELATION;
|
||||||
@serializable() value: any;
|
@serializable() value: any;
|
||||||
@serializable() repeatable: boolean;
|
@serializable() repeatable: boolean;
|
||||||
|
relationship: RelationshipOptions;
|
||||||
item: Item;
|
item: Item;
|
||||||
|
|
||||||
constructor(config: DynamicLookupRelationModelConfig, layout?: DynamicFormControlLayout) {
|
constructor(config: DynamicLookupRelationModelConfig, layout?: DynamicFormControlLayout) {
|
||||||
@@ -25,6 +28,7 @@ export class DynamicLookupRelationModel extends DsDynamicInputModel {
|
|||||||
this.disabled = true;
|
this.disabled = true;
|
||||||
this.repeatable = config.repeatable;
|
this.repeatable = config.repeatable;
|
||||||
this.item = config.item;
|
this.item = config.item;
|
||||||
|
this.relationship = config.relationship;
|
||||||
this.valueUpdates.next(config.value);
|
this.valueUpdates.next(config.value);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -0,0 +1,5 @@
|
|||||||
|
export interface RelationshipOptions {
|
||||||
|
relationshipType: string;
|
||||||
|
filter: string;
|
||||||
|
searchConfiguration: string;
|
||||||
|
}
|
@@ -2,6 +2,7 @@ import { autoserialize } from 'cerialize';
|
|||||||
import { FormRowModel } from '../../../../core/config/models/config-submission-forms.model';
|
import { FormRowModel } from '../../../../core/config/models/config-submission-forms.model';
|
||||||
import { LanguageCode } from './form-field-language-value.model';
|
import { LanguageCode } from './form-field-language-value.model';
|
||||||
import { FormFieldMetadataValueObject } from './form-field-metadata-value.model';
|
import { FormFieldMetadataValueObject } from './form-field-metadata-value.model';
|
||||||
|
import { RelationshipOptions } from '../ds-dynamic-form-ui/models/lookup-relation/model/relationship-options.model';
|
||||||
|
|
||||||
export class FormFieldModel {
|
export class FormFieldModel {
|
||||||
|
|
||||||
@@ -32,6 +33,9 @@ export class FormFieldModel {
|
|||||||
@autoserialize
|
@autoserialize
|
||||||
selectableMetadata: FormFieldMetadataValueObject[];
|
selectableMetadata: FormFieldMetadataValueObject[];
|
||||||
|
|
||||||
|
@autoserialize
|
||||||
|
selectableRelationships: RelationshipOptions[];
|
||||||
|
|
||||||
@autoserialize
|
@autoserialize
|
||||||
rows: FormRowModel[];
|
rows: FormRowModel[];
|
||||||
|
|
||||||
|
@@ -1,20 +1,14 @@
|
|||||||
import { FieldParser } from './field-parser';
|
import { FieldParser } from './field-parser';
|
||||||
import {
|
|
||||||
DynamicLookupModel,
|
|
||||||
DynamicLookupModelConfig
|
|
||||||
} from '../ds-dynamic-form-ui/models/lookup/dynamic-lookup.model';
|
|
||||||
import { FormFieldMetadataValueObject } from '../models/form-field-metadata-value.model';
|
import { FormFieldMetadataValueObject } from '../models/form-field-metadata-value.model';
|
||||||
import {
|
import { DynamicLookupRelationModel, DynamicLookupRelationModelConfig } from '../ds-dynamic-form-ui/models/lookup-relation/dynamic-lookup-relation.model';
|
||||||
DynamicLookupRelationModel,
|
|
||||||
DynamicLookupRelationModelConfig
|
|
||||||
} from '../ds-dynamic-form-ui/models/lookup-relation/dynamic-lookup-relation.model';
|
|
||||||
|
|
||||||
export class LookupRelationFieldParser extends FieldParser {
|
export class LookupRelationFieldParser extends FieldParser {
|
||||||
|
|
||||||
public modelFactory(fieldValue?: FormFieldMetadataValueObject | any, label?: boolean): any {
|
public modelFactory(fieldValue?: FormFieldMetadataValueObject | any, label?: boolean): any {
|
||||||
const lookupModelConfig: DynamicLookupRelationModelConfig = this.initModel(null, label);
|
const lookupModelConfig: DynamicLookupRelationModelConfig = this.initModel(null, label);
|
||||||
lookupModelConfig.repeatable = this.configData.repeatable;
|
lookupModelConfig.repeatable = this.configData.repeatable;
|
||||||
|
/* TODO what to do with multiple relationships? */
|
||||||
|
lookupModelConfig.relationship = this.configData.selectableRelationships[0];
|
||||||
return new DynamicLookupRelationModel(lookupModelConfig);
|
return new DynamicLookupRelationModel(lookupModelConfig);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -7,6 +7,8 @@
|
|||||||
(pageChange)="onPageChange($event)"
|
(pageChange)="onPageChange($event)"
|
||||||
(pageSizeChange)="onPageSizeChange($event)"
|
(pageSizeChange)="onPageSizeChange($event)"
|
||||||
(sortDirectionChange)="onSortDirectionChange($event)"
|
(sortDirectionChange)="onSortDirectionChange($event)"
|
||||||
|
(deselectObject)="deselectObject.emit($event)"
|
||||||
|
(selectObject)="selectObject.emit($event)"
|
||||||
(sortFieldChange)="onSortFieldChange($event)"
|
(sortFieldChange)="onSortFieldChange($event)"
|
||||||
[selectable]="selectable"
|
[selectable]="selectable"
|
||||||
[selectionConfig]="selectionConfig"
|
[selectionConfig]="selectionConfig"
|
||||||
|
@@ -35,6 +35,8 @@ export class ObjectCollectionComponent implements OnChanges, OnInit {
|
|||||||
@Input() hideGear = false;
|
@Input() hideGear = false;
|
||||||
@Input() selectable = false;
|
@Input() selectable = false;
|
||||||
@Input() selectionConfig: {repeatable: boolean, listId: string};
|
@Input() selectionConfig: {repeatable: boolean, listId: string};
|
||||||
|
@Output() deselectObject: EventEmitter<ListableObject> = new EventEmitter<ListableObject>();
|
||||||
|
@Output() selectObject: EventEmitter<ListableObject> = new EventEmitter<ListableObject>();
|
||||||
|
|
||||||
pageInfo: Observable<PageInfo>;
|
pageInfo: Observable<PageInfo>;
|
||||||
private sub;
|
private sub;
|
||||||
|
@@ -1,7 +1,9 @@
|
|||||||
import { SearchResult } from '../../search/search-result.model';
|
import { SearchResult } from '../../search/search-result.model';
|
||||||
import { Item } from '../../../core/shared/item.model';
|
import { Item } from '../../../core/shared/item.model';
|
||||||
import { searchResultFor } from '../../search/search-result-element-decorator';
|
import { searchResultFor } from '../../search/search-result-element-decorator';
|
||||||
|
import { inheritEquatable } from '../../../core/utilities/equals.decorators';
|
||||||
|
|
||||||
@searchResultFor(Item)
|
@searchResultFor(Item)
|
||||||
|
@inheritEquatable(SearchResult)
|
||||||
export class ItemSearchResult extends SearchResult<Item> {
|
export class ItemSearchResult extends SearchResult<Item> {
|
||||||
}
|
}
|
||||||
|
@@ -79,8 +79,11 @@ export class ObjectListComponent {
|
|||||||
*/
|
*/
|
||||||
@Output() sortDirectionChange: EventEmitter<SortDirection> = new EventEmitter<SortDirection>();
|
@Output() sortDirectionChange: EventEmitter<SortDirection> = new EventEmitter<SortDirection>();
|
||||||
|
|
||||||
@Output() paginationChange: EventEmitter<SortDirection> = new EventEmitter<any>();
|
@Output() paginationChange: EventEmitter<any> = new EventEmitter<any>();
|
||||||
|
|
||||||
|
@Output() deselectObject: EventEmitter<ListableObject> = new EventEmitter<ListableObject>();
|
||||||
|
|
||||||
|
@Output() selectObject: EventEmitter<ListableObject> = new EventEmitter<ListableObject>();
|
||||||
/**
|
/**
|
||||||
* An event fired when the sort field is changed.
|
* An event fired when the sort field is changed.
|
||||||
* Event's payload equals to the newly selected sort field.
|
* Event's payload equals to the newly selected sort field.
|
||||||
@@ -108,66 +111,24 @@ export class ObjectListComponent {
|
|||||||
this.paginationChange.emit(event);
|
this.paginationChange.emit(event);
|
||||||
}
|
}
|
||||||
|
|
||||||
// isDisabled(object: ListableObject): boolean {
|
|
||||||
// return hasValue(this.previousSelection.find((selected) => selected === object));
|
|
||||||
// }
|
|
||||||
|
|
||||||
selectCheckbox(value: boolean, object: ListableObject) {
|
selectCheckbox(value: boolean, object: ListableObject) {
|
||||||
if (value) {
|
if (value) {
|
||||||
this.selectionService.selectSingle(this.selectionConfig.listId, object);
|
this.selectionService.selectSingle(this.selectionConfig.listId, object);
|
||||||
|
this.selectObject.emit(object);
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
this.selectionService.deselectSingle(this.selectionConfig.listId, object);
|
this.selectionService.deselectSingle(this.selectionConfig.listId, object);
|
||||||
|
this.deselectObject.emit(object);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
selectRadio(value: boolean, object: ListableObject) {
|
selectRadio(value: boolean, object: ListableObject) {
|
||||||
if (value) {
|
if (value) {
|
||||||
this.selectionService.selectSingle(this.selectionConfig.listId, object, false);
|
this.selectionService.selectSingle(this.selectionConfig.listId, object, false);
|
||||||
|
this.selectObject.emit(object);
|
||||||
|
} else {
|
||||||
|
this.selectionService.deselectSingle(this.selectionConfig.listId, object);
|
||||||
|
this.deselectObject.emit(object);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
selectPage(page: SearchResult<DSpaceObject>[]) {
|
|
||||||
this.selectionService.select(this.selectionConfig.listId, this.objects.payload.page);
|
|
||||||
}
|
|
||||||
|
|
||||||
deselectPage(page: SearchResult<DSpaceObject>[]) {
|
|
||||||
this.selectionService.deselect(this.selectionConfig.listId, this.objects.payload.page);
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
deselectAll() {
|
|
||||||
this.selectionService.deselectAll(this.selectionConfig.listId);
|
|
||||||
}
|
|
||||||
|
|
||||||
// isAllSelected() {
|
|
||||||
// return this.allSelected;
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// isSomeSelected() {
|
|
||||||
// return isNotEmpty(this.selection);
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
//
|
|
||||||
// selectAll() {
|
|
||||||
// this.allSelected = true;
|
|
||||||
// this.selectAllLoading = true;
|
|
||||||
// const fullPagination = Object.assign(new PaginationComponentOptions(), {
|
|
||||||
// query: this.searchQuery,
|
|
||||||
// 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),
|
|
||||||
// tap(() => this.selectAllLoading = false)
|
|
||||||
// )
|
|
||||||
// .subscribe((results) =>
|
|
||||||
// this.selection = results
|
|
||||||
// .map((searchResult) => searchResult.indexableObject)
|
|
||||||
// .filter((dso) => hasNoValue(this.previousSelection.find((object) => object === dso)))
|
|
||||||
// );
|
|
||||||
// }
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@@ -71,10 +71,12 @@ function select(state: SelectableListState, action: SelectableListSelectAction)
|
|||||||
|
|
||||||
function selectSingle(state: SelectableListState, action: SelectableListSelectSingleAction) {
|
function selectSingle(state: SelectableListState, action: SelectableListSelectSingleAction) {
|
||||||
let newSelection;
|
let newSelection;
|
||||||
if (action.payload.multipleSelectionsAllowed && !isObjectInSelection(state.selection, action.payload.object)) {
|
if (!isObjectInSelection(state.selection, action.payload.object)) {
|
||||||
newSelection = [...state.selection, action.payload.object];
|
if (action.payload.multipleSelectionsAllowed) {
|
||||||
} else {
|
newSelection = [...state.selection, action.payload.object];
|
||||||
newSelection = [action.payload.object];
|
} else {
|
||||||
|
newSelection = [action.payload.object];
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return Object.assign({}, state, { selection: newSelection });
|
return Object.assign({}, state, { selection: newSelection });
|
||||||
}
|
}
|
||||||
|
@@ -37,8 +37,9 @@ export class SelectableListService {
|
|||||||
* Select an object in a specific list in the store
|
* Select an object in a specific list in the store
|
||||||
* @param {string} id The id of the list on which the object should be selected
|
* @param {string} id The id of the list on which the object should be selected
|
||||||
* @param {ListableObject} object The object to select
|
* @param {ListableObject} object The object to select
|
||||||
|
* @param {boolean} multipleSelectionsAllowed Defines if the multiple selections are allowed for this selectable list
|
||||||
*/
|
*/
|
||||||
selectSingle(id: string, object: ListableObject, multipleSelectionsAllowed?) {
|
selectSingle(id: string, object: ListableObject, multipleSelectionsAllowed?: boolean) {
|
||||||
this.store.dispatch(new SelectableListSelectSingleAction(id, object, multipleSelectionsAllowed));
|
this.store.dispatch(new SelectableListSelectSingleAction(id, object, multipleSelectionsAllowed));
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -86,7 +87,7 @@ export class SelectableListService {
|
|||||||
isObjectSelected(id: string, object: ListableObject): Observable<boolean> {
|
isObjectSelected(id: string, object: ListableObject): Observable<boolean> {
|
||||||
return this.getSelectableList(id).pipe(
|
return this.getSelectableList(id).pipe(
|
||||||
filter((state: SelectableListState) => hasValue(state)),
|
filter((state: SelectableListState) => hasValue(state)),
|
||||||
map((state: SelectableListState) => isNotEmpty(state.selection) && hasValue(state.selection.find((selected) => selected === object))),
|
map((state: SelectableListState) => isNotEmpty(state.selection) && hasValue(state.selection.find((selected) => selected.equals(object)))),
|
||||||
startWith(false),
|
startWith(false),
|
||||||
distinctUntilChanged()
|
distinctUntilChanged()
|
||||||
);
|
);
|
||||||
|
@@ -7,6 +7,8 @@
|
|||||||
[hideGear]="true"
|
[hideGear]="true"
|
||||||
[selectable]="selectable"
|
[selectable]="selectable"
|
||||||
[selectionConfig]="selectionConfig"
|
[selectionConfig]="selectionConfig"
|
||||||
|
(deselectObject)="deselectObject.emit($event)"
|
||||||
|
(selectObject)="selectObject.emit($event)"
|
||||||
>
|
>
|
||||||
</ds-viewable-collection>
|
</ds-viewable-collection>
|
||||||
</div>
|
</div>
|
||||||
|
@@ -1,4 +1,4 @@
|
|||||||
import { Component, Input } from '@angular/core';
|
import { Component, EventEmitter, Input, Output } from '@angular/core';
|
||||||
import { RemoteData } from '../../../core/data/remote-data';
|
import { RemoteData } from '../../../core/data/remote-data';
|
||||||
import { DSpaceObject } from '../../../core/shared/dspace-object.model';
|
import { DSpaceObject } from '../../../core/shared/dspace-object.model';
|
||||||
import { fadeIn, fadeInOut } from '../../animations/fade';
|
import { fadeIn, fadeInOut } from '../../animations/fade';
|
||||||
@@ -8,6 +8,7 @@ import { SearchResult } from '../search-result.model';
|
|||||||
import { PaginatedList } from '../../../core/data/paginated-list';
|
import { PaginatedList } from '../../../core/data/paginated-list';
|
||||||
import { hasNoValue, isNotEmpty } from '../../empty.util';
|
import { hasNoValue, isNotEmpty } from '../../empty.util';
|
||||||
import { SortOptions } from '../../../core/cache/models/sort-options.model';
|
import { SortOptions } from '../../../core/cache/models/sort-options.model';
|
||||||
|
import { ListableObject } from '../../object-collection/shared/listable-object.model';
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'ds-search-results',
|
selector: 'ds-search-results',
|
||||||
@@ -58,6 +59,11 @@ export class SearchResultsComponent {
|
|||||||
@Input() selectable = false;
|
@Input() selectable = false;
|
||||||
|
|
||||||
@Input() selectionConfig: {repeatable: boolean, listId: string};
|
@Input() selectionConfig: {repeatable: boolean, listId: string};
|
||||||
|
|
||||||
|
@Output() deselectObject: EventEmitter<ListableObject> = new EventEmitter<ListableObject>();
|
||||||
|
|
||||||
|
@Output() selectObject: EventEmitter<ListableObject> = new EventEmitter<ListableObject>();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Method to change the given string by surrounding it by quotes if not already present.
|
* Method to change the given string by surrounding it by quotes if not already present.
|
||||||
*/
|
*/
|
||||||
|
Reference in New Issue
Block a user