67611: External-Source-Entry import window

This commit is contained in:
Kristof De Langhe
2019-12-04 17:54:01 +01:00
parent e9a8a25116
commit 0210be1a53
14 changed files with 306 additions and 6 deletions

View File

@@ -1525,6 +1525,32 @@
"submission.sections.describe.relationship-lookup.close": "Close",
"submission.sections.describe.relationship-lookup.external-source.import-button-title": "Import remote entry",
"submission.sections.describe.relationship-lookup.external-source.import-modal.authority": "Authority",
"submission.sections.describe.relationship-lookup.external-source.import-modal.authority.new": "Import as a new local authority entry",
"submission.sections.describe.relationship-lookup.external-source.import-modal.cancel": "Cancel",
"submission.sections.describe.relationship-lookup.external-source.import-modal.entities": "Entities",
"submission.sections.describe.relationship-lookup.external-source.import-modal.entities.new": "Import as a new local entity",
"submission.sections.describe.relationship-lookup.external-source.import-modal.head.lcname": "Importing from LC Name",
"submission.sections.describe.relationship-lookup.external-source.import-modal.head.orcidV2": "Importing from ORCID",
"submission.sections.describe.relationship-lookup.external-source.import-modal.head.sherpaJournal": "Importing from Sherpa Journal",
"submission.sections.describe.relationship-lookup.external-source.import-modal.head.sherpaPublisher": "Importing from Sherpa Publisher",
"submission.sections.describe.relationship-lookup.external-source.import-modal.import": "Import",
"submission.sections.describe.relationship-lookup.external-source.import-modal.select": "Select a local match:",
"submission.sections.describe.relationship-lookup.external-source.import-modal.title": "Import Remote Entry",
"submission.sections.describe.relationship-lookup.search-tab.deselect-all": "Deselect all",
"submission.sections.describe.relationship-lookup.search-tab.deselect-page": "Deselect page",

View File

@@ -25,6 +25,12 @@ export class NormalizedExternalSourceEntry extends NormalizedObject<ExternalSour
@autoserialize
value: string;
/**
* The ID of the external source this entry originates from
*/
@autoserialize
externalSource: string;
/**
* Metadata of the entry
*/

View File

@@ -24,6 +24,11 @@ export class ExternalSourceEntry extends ListableObject {
*/
value: string;
/**
* The ID of the external source this entry originates from
*/
externalSource: string;
/**
* Metadata of the entry
*/

View File

@@ -1,2 +1,11 @@
<div class="d-inline-block">
<button (click)="import()"
class="btn btn-outline-primary btn-sm float-left"
title="{{'submission.sections.describe.relationship-lookup.external-source.import-button-title' | translate}}">
<i class="fas fa-cloud-download-alt fa-fw"></i>
</button>
</div>
<div class="d-inline-block ml-2">
<div>{{object.display}}</div>
<div *ngIf="uri"><a [href]="uri.value">{{uri.value}}</a></div>
</div>

View File

@@ -3,9 +3,13 @@ import { ExternalSourceEntry } from '../../../../../core/shared/external-source-
import { listableObjectComponent } from '../../../../../shared/object-collection/shared/listable-object/listable-object.decorator';
import { ViewMode } from '../../../../../core/shared/view-mode.model';
import { Context } from '../../../../../core/shared/context.model';
import { Component, OnInit } from '@angular/core';
import { Component, Inject, OnInit } from '@angular/core';
import { Metadata } from '../../../../../core/shared/metadata.utils';
import { MetadataValue } from '../../../../../core/shared/metadata.models';
import { NgbModal, NgbModalRef } from '@ng-bootstrap/ng-bootstrap';
import { ExternalSourceEntryImportModalComponent } from '../../../../../shared/form/builder/ds-dynamic-form-ui/relation-lookup-modal/external-source-tab/external-source-entry-import-modal/external-source-entry-import-modal.component';
import { DsDynamicLookupRelationExternalSourceTabComponent } from '../../../../../shared/form/builder/ds-dynamic-form-ui/relation-lookup-modal/external-source-tab/dynamic-lookup-relation-external-source-tab.component';
import { hasValue } from '../../../../../shared/empty.util';
@listableObjectComponent(ExternalSourceEntry, ViewMode.ListElement, Context.SubmissionModal)
@Component({
@@ -19,7 +23,29 @@ export class ExternalSourceEntryListSubmissionElementComponent extends AbstractL
*/
uri: MetadataValue;
/**
* The modal for importing the entry
*/
modalRef: NgbModalRef;
constructor(@Inject(DsDynamicLookupRelationExternalSourceTabComponent) private externalSourceTab: DsDynamicLookupRelationExternalSourceTabComponent,
private modalService: NgbModal) {
super();
}
ngOnInit(): void {
this.uri = Metadata.first(this.object.metadata, 'dc.identifier.uri');
}
import(): void {
this.modalRef = this.modalService.open(ExternalSourceEntryImportModalComponent, {
size: 'lg',
container: 'ds-dynamic-lookup-relation-modal'
});
const modalComp = this.modalRef.componentInstance;
modalComp.externalSourceEntry = this.object;
if (hasValue(this.externalSourceTab) && hasValue(this.externalSourceTab.relationship)) {
modalComp.relationship = this.externalSourceTab.relationship;
}
}
}

View File

@@ -26,6 +26,7 @@
<ng-template ngbTabContent>
<ds-dynamic-lookup-relation-external-source-tab
[listId]="listId"
[relationship]="relationshipOptions"
[repeatable]="repeatable"
[context]="context"
[externalSource]="source"

View File

@@ -1,3 +1,11 @@
.modal-footer {
justify-content: space-between;
}
/* Render child-modals slightly smaller than this modal to avoid complete overlap */
:host {
::ng-deep .modal-content {
width: 90%;
margin: 5%;
}
}

View File

@@ -10,7 +10,6 @@
<ng-container *ngVar="(entriesRD$ | async) as entriesRD">
<ds-viewable-collection *ngIf="entriesRD?.hasSucceeded && !entriesRD?.isLoading && entriesRD?.payload?.page?.length > 0" @fadeIn
[objects]="entriesRD"
[selectable]="true"
[selectionConfig]="{ repeatable: repeatable, listId: listId }"
[config]="initialPagination"
[hideGear]="true"

View File

@@ -14,6 +14,7 @@ import { Context } from '../../../../../../core/shared/context.model';
import { ListableObject } from '../../../../../object-collection/shared/listable-object.model';
import { fadeIn, fadeInOut } from '../../../../../animations/fade';
import { PaginationComponentOptions } from '../../../../../pagination/pagination-component-options.model';
import { RelationshipOptions } from '../../../models/relationship-options.model';
@Component({
selector: 'ds-dynamic-lookup-relation-external-source-tab',
@@ -34,6 +35,7 @@ import { PaginationComponentOptions } from '../../../../../pagination/pagination
export class DsDynamicLookupRelationExternalSourceTabComponent implements OnInit {
@Input() label: string;
@Input() listId: string;
@Input() relationship: RelationshipOptions;
@Input() repeatable: boolean;
@Input() context: Context;
@Output() deselectObject: EventEmitter<ListableObject> = new EventEmitter<ListableObject>();

View File

@@ -0,0 +1,50 @@
<div class="modal-header">
<h4 class="modal-title" id="modal-title">{{ ('submission.sections.describe.relationship-lookup.external-source.import-modal.title') | translate }}</h4>
<button type="button" class="close" aria-label="Close button" aria-describedby="modal-title"
(click)="modal.dismiss()">
<span aria-hidden="true">&times;</span>
</button>
</div>
<div class="modal-body">
<h4>{{ ('submission.sections.describe.relationship-lookup.external-source.import-modal.head.' + externalSourceEntry.externalSource | translate) }}</h4>
<div id="external-source-entry-information" class="mb-3">
<div><span>{{externalSourceEntry.display}}</span></div>
<div *ngIf="uri"><a href="{{uri.value}}">{{uri.value}}</a></div>
</div>
<h4>{{ ('submission.sections.describe.relationship-lookup.external-source.import-modal.select' | translate) }}</h4>
<div id="external-source-entry-entities" class="mb-2">
<h5 class="font-weight-bold">{{ ('submission.sections.describe.relationship-lookup.external-source.import-modal.entities' | translate) }}</h5>
<ds-search-results [searchResults]="(localEntitiesRD$ | async)"
[sortConfig]="this.lookupRelationService.searchConfig?.sort"
[searchConfig]="this.lookupRelationService.searchConfig"
[selectable]="true"
[selectionConfig]="{ repeatable: false, listId: entityListId }"
[linkType]="linkTypes.ExternalLink"
[context]="context"
(deselectObject)="deselectEntity($event)"
(selectObject)="selectEntity($event)">
</ds-search-results>
<div class="form-check">
<input class="form-check-input" type="radio" name="new-entity" id="new-entity" value="new-entity" (click)="selectNewEntity()" [checked]="selectedImportType === importType.NewEntity" />
<label class="form-check-label" for="new-entity">{{ ('submission.sections.describe.relationship-lookup.external-source.import-modal.entities.new' | translate) }}</label>
</div>
</div>
<div id="external-source-entry-authority">
<h5 class="font-weight-bold">{{ ('submission.sections.describe.relationship-lookup.external-source.import-modal.authority' | translate) }}</h5>
<div class="form-check">
<input class="form-check-input" type="radio" name="new-authority" id="new-authority" value="new-authority" (click)="selectNewAuthority()" [checked]="selectedImportType === importType.NewAuthority" />
<label class="form-check-label" for="new-authority">{{ ('submission.sections.describe.relationship-lookup.external-source.import-modal.authority.new' | translate) }}</label>
</div>
</div>
</div>
<div class="modal-footer">
<div>
<button type="button" class="btn btn-outline-secondary" (click)="close()">{{ ('submission.sections.describe.relationship-lookup.external-source.import-modal.cancel' | translate) }}</button>
</div>
<div>
<button type="button" class="btn btn-primary" [disabled]="selectedImportType === importType.None" (click)="import()">{{ ('submission.sections.describe.relationship-lookup.external-source.import-modal.import' | translate) }}</button>
</div>
</div>

View File

@@ -0,0 +1,162 @@
import { Component, OnInit } from '@angular/core';
import { NgbActiveModal } from '@ng-bootstrap/ng-bootstrap';
import { ExternalSourceEntry } from '../../../../../../../core/shared/external-source-entry.model';
import { MetadataValue } from '../../../../../../../core/shared/metadata.models';
import { Metadata } from '../../../../../../../core/shared/metadata.utils';
import { Observable } from 'rxjs/internal/Observable';
import { RemoteData } from '../../../../../../../core/data/remote-data';
import { PaginatedList } from '../../../../../../../core/data/paginated-list';
import { SearchResult } from '../../../../../../search/search-result.model';
import { Item } from '../../../../../../../core/shared/item.model';
import { RelationshipOptions } from '../../../../models/relationship-options.model';
import { LookupRelationService } from '../../../../../../../core/data/lookup-relation.service';
import { PaginatedSearchOptions } from '../../../../../../search/paginated-search-options.model';
import { CollectionElementLinkType } from '../../../../../../object-collection/collection-element-link.type';
import { Context } from '../../../../../../../core/shared/context.model';
import { SelectableListService } from '../../../../../../object-list/selectable-list/selectable-list.service';
/**
* The possible types of import for the external entry
*/
export enum ImportType {
None = 'None',
LocalEntity = 'LocalEntity',
LocalAuthority = 'LocalAuthority',
NewEntity = 'NewEntity',
NewAuthority = 'NewAuthority'
}
@Component({
selector: 'ds-external-source-entry-import-modal',
styleUrls: ['./external-source-entry-import-modal.component.scss'],
templateUrl: './external-source-entry-import-modal.component.html'
})
export class ExternalSourceEntryImportModalComponent implements OnInit {
/**
* The external source entry
*/
externalSourceEntry: ExternalSourceEntry;
/**
* The current relationship-options used for filtering results
*/
relationship: RelationshipOptions;
/**
* The metadata value for the entry's uri
*/
uri: MetadataValue;
/**
* Local entities with a similar name
*/
localEntitiesRD$: Observable<RemoteData<PaginatedList<SearchResult<Item>>>>;
/**
* Search options to use for fetching similar results
*/
searchOptions: PaginatedSearchOptions;
/**
* The type of link to render in listable elements
*/
linkTypes = CollectionElementLinkType;
/**
* The context we're currently in (submission)
*/
context = Context.SubmissionModal;
/**
* List ID for selecting local entities
*/
entityListId = 'external-source-import-entity';
/**
* List ID for selecting local authorities
*/
authorityListId = 'external-source-import-authority';
/**
* ImportType enum
*/
importType = ImportType;
/**
* The type of import the user currently has selected
*/
selectedImportType = ImportType.None;
constructor(public modal: NgbActiveModal,
public lookupRelationService: LookupRelationService,
private selectService: SelectableListService) {
}
ngOnInit(): void {
this.uri = Metadata.first(this.externalSourceEntry.metadata, 'dc.identifier.uri');
this.searchOptions = Object.assign(new PaginatedSearchOptions({ query: this.externalSourceEntry.value }));
this.localEntitiesRD$ = this.lookupRelationService.getLocalResults(this.relationship, this.searchOptions);
}
/**
* Close the window
*/
close() {
this.modal.close();
}
/**
* Perform the import of the external entry
*/
import() {
console.log('TODO: Import');
}
/**
* Deselected a local entity
* @param event
*/
deselectEntity(event) {
this.selectedImportType = ImportType.None;
}
/**
* Selected a local entity
* @param event
*/
selectEntity(event) {
this.selectedImportType = ImportType.LocalEntity;
}
/**
* Selected/deselected the new entity option
*/
selectNewEntity() {
if (this.selectedImportType === ImportType.NewEntity) {
this.selectedImportType = ImportType.None;
} else {
this.selectedImportType = ImportType.NewEntity;
this.deselectAllLists();
}
}
/**
* Selected/deselected the new authority option
*/
selectNewAuthority() {
if (this.selectedImportType === ImportType.NewAuthority) {
this.selectedImportType = ImportType.None;
} else {
this.selectedImportType = ImportType.NewAuthority;
this.deselectAllLists();
}
}
/**
* Deselect every element from both entity and authority lists
*/
deselectAllLists() {
this.selectService.deselectAll(this.entityListId);
this.selectService.deselectAll(this.authorityListId);
}
}

View File

@@ -175,6 +175,7 @@ import { SidebarFilterSelectedOptionComponent } from './sidebar/filter/sidebar-f
import { MetadataRepresentationListComponent } from '../+item-page/simple/metadata-representation-list/metadata-representation-list.component';
import { SelectableListItemControlComponent } from './object-collection/shared/selectable-list-item-control/selectable-list-item-control.component';
import { DsDynamicLookupRelationExternalSourceTabComponent } from './form/builder/ds-dynamic-form-ui/relation-lookup-modal/external-source-tab/dynamic-lookup-relation-external-source-tab.component';
import { ExternalSourceEntryImportModalComponent } from './form/builder/ds-dynamic-form-ui/relation-lookup-modal/external-source-tab/external-source-entry-import-modal/external-source-entry-import-modal.component';
const MODULES = [
// Do NOT include UniversalModule, HttpModule, or JsonpModule here
@@ -331,7 +332,8 @@ const COMPONENTS = [
ItemSelectComponent,
CollectionSelectComponent,
MetadataRepresentationLoaderComponent,
SelectableListItemControlComponent
SelectableListItemControlComponent,
ExternalSourceEntryImportModalComponent
];
const ENTRY_COMPONENTS = [
@@ -393,7 +395,8 @@ const ENTRY_COMPONENTS = [
SearchAuthorityFilterComponent,
DsDynamicLookupRelationSearchTabComponent,
DsDynamicLookupRelationSelectionTabComponent,
DsDynamicLookupRelationExternalSourceTabComponent
DsDynamicLookupRelationExternalSourceTabComponent,
ExternalSourceEntryImportModalComponent
];
const SHARED_ITEM_PAGE_COMPONENTS = [