74199: Admin search dialogs - Current DSO + context for new item/collection

This commit is contained in:
Kristof De Langhe
2020-10-23 17:29:10 +02:00
parent ade5eb53cc
commit 40891a3c35
10 changed files with 52 additions and 9 deletions

View File

@@ -20,6 +20,7 @@
</button> </button>
<button *ngFor="let listEntry of listEntries" <button *ngFor="let listEntry of listEntries"
class="list-group-item list-group-item-action border-0 list-entry" class="list-group-item list-group-item-action border-0 list-entry"
[ngClass]="{'current': listEntry.indexableObject.id === currentDSOId}"
title="{{ listEntry.indexableObject.name }}" title="{{ listEntry.indexableObject.name }}"
(click)="onSelect.emit(listEntry.indexableObject)" #listEntryElement> (click)="onSelect.emit(listEntry.indexableObject)" #listEntryElement>
<ds-listable-object-component-loader [object]="listEntry" [viewMode]="viewMode" <ds-listable-object-component-loader [object]="listEntry" [viewMode]="viewMode"

View File

@@ -3,3 +3,10 @@
max-height: $dso-selector-list-max-height; max-height: $dso-selector-list-max-height;
overflow-x: hidden; overflow-x: hidden;
} }
.current {
background-color: $dso-selector-current-background-color;
&:hover {
background-color: $dso-selector-current-background-hover-color;
}
}

View File

@@ -10,7 +10,7 @@ import {
ViewChildren ViewChildren
} from '@angular/core'; } from '@angular/core';
import { FormControl } from '@angular/forms'; import { FormControl } from '@angular/forms';
import { debounceTime, startWith, switchMap, tap } from 'rxjs/operators'; import { debounceTime, map, startWith, switchMap, tap } from 'rxjs/operators';
import { SearchService } from '../../../core/shared/search/search.service'; import { SearchService } from '../../../core/shared/search/search.service';
import { CollectionElementLinkType } from '../../object-collection/collection-element-link.type'; import { CollectionElementLinkType } from '../../object-collection/collection-element-link.type';
import { PaginatedSearchOptions } from '../../search/paginated-search-options.model'; import { PaginatedSearchOptions } from '../../search/paginated-search-options.model';
@@ -21,8 +21,8 @@ import { Context } from '../../../core/shared/context.model';
import { BehaviorSubject } from 'rxjs/internal/BehaviorSubject'; import { BehaviorSubject } from 'rxjs/internal/BehaviorSubject';
import { getFirstSucceededRemoteDataPayload } from '../../../core/shared/operators'; import { getFirstSucceededRemoteDataPayload } from '../../../core/shared/operators';
import { Subscription } from 'rxjs/internal/Subscription'; import { Subscription } from 'rxjs/internal/Subscription';
import { hasValue } from '../../empty.util'; import { hasValue, isEmpty, isNotEmpty } from '../../empty.util';
import { combineLatest as observableCombineLatest } from 'rxjs'; import { combineLatest as observableCombineLatest, of as observableOf } from 'rxjs';
import { Observable } from 'rxjs/internal/Observable'; import { Observable } from 'rxjs/internal/Observable';
import { PaginatedList } from '../../../core/data/paginated-list'; import { PaginatedList } from '../../../core/data/paginated-list';
import { SearchResult } from '../../search/search-result.model'; import { SearchResult } from '../../search/search-result.model';
@@ -126,23 +126,42 @@ export class DSOSelectorComponent implements OnInit, OnDestroy {
* The search will always start with the initial currentDSOId value * The search will always start with the initial currentDSOId value
*/ */
ngOnInit(): void { ngOnInit(): void {
this.input.setValue(this.currentDSOId);
this.typesString = this.types.map((type: string) => type.toString().toLowerCase()).join(', '); this.typesString = this.types.map((type: string) => type.toString().toLowerCase()).join(', ');
// Create an observable searching for the current DSO (return empty list if there's no current DSO)
let currentDSOResult$;
if (isNotEmpty(this.currentDSOId)) {
currentDSOResult$ = this.search(`search.resourceid:${this.currentDSOId}`, 1);
} else {
currentDSOResult$ = observableOf(new PaginatedList(undefined, []));
}
// Combine current DSO, query and page
this.subs.push(observableCombineLatest( this.subs.push(observableCombineLatest(
currentDSOResult$,
this.input.valueChanges.pipe( this.input.valueChanges.pipe(
debounceTime(this.debounceTime), debounceTime(this.debounceTime),
startWith(this.currentDSOId), startWith(''),
tap(() => this.currentPage$.next(1)) tap(() => this.currentPage$.next(1))
), ),
this.currentPage$ this.currentPage$
).pipe( ).pipe(
switchMap(([query, page]: [string, number]) => { switchMap(([currentDSOResult, query, page]: [PaginatedList<SearchResult<DSpaceObject>>, string, number]) => {
if (page === 1) { if (page === 1) {
// The first page is loading, this means we should reset the list instead of adding to it // The first page is loading, this means we should reset the list instead of adding to it
this.resetList = true; this.resetList = true;
} }
return this.search(query, page); return this.search(query, page).pipe(
map((list) => {
// If it's the first page and no query is entered, add the current DSO to the start of the list
// If no query is entered, filter out the current DSO from the results, as it'll be displayed at the start of the list already
list.page = [
...((isEmpty(query) && page === 1) ? currentDSOResult.page : []),
...list.page.filter((result) => isNotEmpty(query) || result.indexableObject.id !== this.currentDSOId)
];
return list;
})
);
}) })
).subscribe((list) => { ).subscribe((list) => {
if (this.resetList) { if (this.resetList) {

View File

@@ -22,6 +22,7 @@ export class CreateCollectionParentSelectorComponent extends DSOSelectorModalWra
objectType = DSpaceObjectType.COLLECTION; objectType = DSpaceObjectType.COLLECTION;
selectorTypes = [DSpaceObjectType.COMMUNITY]; selectorTypes = [DSpaceObjectType.COMMUNITY];
action = SelectorActionType.CREATE; action = SelectorActionType.CREATE;
header = 'dso-selector.create.collection.sub-level';
constructor(protected activeModal: NgbActiveModal, protected route: ActivatedRoute, private router: Router) { constructor(protected activeModal: NgbActiveModal, protected route: ActivatedRoute, private router: Router) {
super(activeModal, route); super(activeModal, route);

View File

@@ -5,6 +5,7 @@
</button> </button>
</div> </div>
<div class="modal-body"> <div class="modal-body">
<ds-authorized-collection-selector [currentDSOId]="dsoRD?.payload.uuid ? 'search.resourceid:' + dsoRD?.payload.uuid : null" [types]="selectorTypes" (onSelect)="selectObject($event)"></ds-authorized-collection-selector> <h5 *ngIf="header" class="px-2">{{header | translate}}</h5>
<ds-authorized-collection-selector [currentDSOId]="dsoRD?.payload.uuid" [types]="selectorTypes" (onSelect)="selectObject($event)"></ds-authorized-collection-selector>
</div> </div>
</div> </div>

View File

@@ -20,6 +20,7 @@ export class CreateItemParentSelectorComponent extends DSOSelectorModalWrapperCo
objectType = DSpaceObjectType.ITEM; objectType = DSpaceObjectType.ITEM;
selectorTypes = [DSpaceObjectType.COLLECTION]; selectorTypes = [DSpaceObjectType.COLLECTION];
action = SelectorActionType.CREATE; action = SelectorActionType.CREATE;
header = 'dso-selector.create.item.sub-level';
constructor(protected activeModal: NgbActiveModal, protected route: ActivatedRoute, private router: Router) { constructor(protected activeModal: NgbActiveModal, protected route: ActivatedRoute, private router: Router) {
super(activeModal, route); super(activeModal, route);

View File

@@ -5,6 +5,7 @@
</button> </button>
</div> </div>
<div class="modal-body"> <div class="modal-body">
<ds-dso-selector [currentDSOId]="dsoRD?.payload.uuid ? 'search.resourceid:' + dsoRD?.payload.uuid : null" [types]="selectorTypes" (onSelect)="selectObject($event)"></ds-dso-selector> <h5 *ngIf="header" class="px-2">{{header | translate}}</h5>
<ds-dso-selector [currentDSOId]="dsoRD?.payload.uuid" [types]="selectorTypes" (onSelect)="selectObject($event)"></ds-dso-selector>
</div> </div>
</div> </div>

View File

@@ -23,6 +23,12 @@ export abstract class DSOSelectorModalWrapperComponent implements OnInit {
*/ */
@Input() dsoRD: RemoteData<DSpaceObject>; @Input() dsoRD: RemoteData<DSpaceObject>;
/**
* Optional header to display above the selection list
* Supports i18n keys
*/
@Input() header: string;
/** /**
* The type of the DSO that's being edited, created or exported * The type of the DSO that's being edited, created or exported
*/ */

View File

@@ -1037,6 +1037,8 @@
"dso-selector.create.collection.head": "New collection", "dso-selector.create.collection.head": "New collection",
"dso-selector.create.collection.sub-level": "Create a new collection in",
"dso-selector.create.community.head": "New community", "dso-selector.create.community.head": "New community",
"dso-selector.create.community.sub-level": "Create a new community in", "dso-selector.create.community.sub-level": "Create a new community in",
@@ -1045,6 +1047,8 @@
"dso-selector.create.item.head": "New item", "dso-selector.create.item.head": "New item",
"dso-selector.create.item.sub-level": "Create a new item in",
"dso-selector.create.submission.head": "New submission", "dso-selector.create.submission.head": "New submission",
"dso-selector.edit.collection.head": "Edit collection", "dso-selector.edit.collection.head": "Edit collection",

View File

@@ -39,3 +39,5 @@ $edit-item-language-field-width: 43px !default;
$thumbnail-max-width: 175px !default; $thumbnail-max-width: 175px !default;
$dso-selector-list-max-height: 475px !default; $dso-selector-list-max-height: 475px !default;
$dso-selector-current-background-color: #eeeeee;
$dso-selector-current-background-hover-color: darken($dso-selector-current-background-color, 10%);