From 0210be1a53faeaef1fb93d886b29db94ebe682be Mon Sep 17 00:00:00 2001 From: Kristof De Langhe Date: Wed, 4 Dec 2019 17:54:01 +0100 Subject: [PATCH 01/12] 67611: External-Source-Entry import window --- resources/i18n/en.json5 | 26 +++ .../normalized-external-source-entry.model.ts | 6 + .../shared/external-source-entry.model.ts | 5 + ...try-list-submission-element.component.html | 13 +- ...entry-list-submission-element.component.ts | 28 ++- ...namic-lookup-relation-modal.component.html | 1 + ...namic-lookup-relation-modal.component.scss | 8 + ...elation-external-source-tab.component.html | 1 - ...-relation-external-source-tab.component.ts | 2 + ...l-source-entry-import-modal.component.html | 50 ++++++ ...l-source-entry-import-modal.component.scss | 3 + ...ource-entry-import-modal.component.spec.ts | 0 ...nal-source-entry-import-modal.component.ts | 162 ++++++++++++++++++ src/app/shared/shared.module.ts | 7 +- 14 files changed, 306 insertions(+), 6 deletions(-) create mode 100644 src/app/shared/form/builder/ds-dynamic-form-ui/relation-lookup-modal/external-source-tab/external-source-entry-import-modal/external-source-entry-import-modal.component.html create mode 100644 src/app/shared/form/builder/ds-dynamic-form-ui/relation-lookup-modal/external-source-tab/external-source-entry-import-modal/external-source-entry-import-modal.component.scss create mode 100644 src/app/shared/form/builder/ds-dynamic-form-ui/relation-lookup-modal/external-source-tab/external-source-entry-import-modal/external-source-entry-import-modal.component.spec.ts create mode 100644 src/app/shared/form/builder/ds-dynamic-form-ui/relation-lookup-modal/external-source-tab/external-source-entry-import-modal/external-source-entry-import-modal.component.ts diff --git a/resources/i18n/en.json5 b/resources/i18n/en.json5 index df0d9b27f0..fe7949d8b1 100644 --- a/resources/i18n/en.json5 +++ b/resources/i18n/en.json5 @@ -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", diff --git a/src/app/core/cache/models/normalized-external-source-entry.model.ts b/src/app/core/cache/models/normalized-external-source-entry.model.ts index 02abbb32d8..d09d1fe7ea 100644 --- a/src/app/core/cache/models/normalized-external-source-entry.model.ts +++ b/src/app/core/cache/models/normalized-external-source-entry.model.ts @@ -25,6 +25,12 @@ export class NormalizedExternalSourceEntry extends NormalizedObject{{object.display}} -
{{uri.value}}
+
+ +
+
+
{{object.display}}
+
{{uri.value}}
+
diff --git a/src/app/entity-groups/research-entities/submission/item-list-elements/external-source-entry/external-source-entry-list-submission-element.component.ts b/src/app/entity-groups/research-entities/submission/item-list-elements/external-source-entry/external-source-entry-list-submission-element.component.ts index 673370cc2c..07d691a5cb 100644 --- a/src/app/entity-groups/research-entities/submission/item-list-elements/external-source-entry/external-source-entry-list-submission-element.component.ts +++ b/src/app/entity-groups/research-entities/submission/item-list-elements/external-source-entry/external-source-entry-list-submission-element.component.ts @@ -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; + } + } } diff --git a/src/app/shared/form/builder/ds-dynamic-form-ui/relation-lookup-modal/dynamic-lookup-relation-modal.component.html b/src/app/shared/form/builder/ds-dynamic-form-ui/relation-lookup-modal/dynamic-lookup-relation-modal.component.html index 46620aa00b..4c87ac8bdb 100644 --- a/src/app/shared/form/builder/ds-dynamic-form-ui/relation-lookup-modal/dynamic-lookup-relation-modal.component.html +++ b/src/app/shared/form/builder/ds-dynamic-form-ui/relation-lookup-modal/dynamic-lookup-relation-modal.component.html @@ -26,6 +26,7 @@ = new EventEmitter(); diff --git a/src/app/shared/form/builder/ds-dynamic-form-ui/relation-lookup-modal/external-source-tab/external-source-entry-import-modal/external-source-entry-import-modal.component.html b/src/app/shared/form/builder/ds-dynamic-form-ui/relation-lookup-modal/external-source-tab/external-source-entry-import-modal/external-source-entry-import-modal.component.html new file mode 100644 index 0000000000..d2ad3d403d --- /dev/null +++ b/src/app/shared/form/builder/ds-dynamic-form-ui/relation-lookup-modal/external-source-tab/external-source-entry-import-modal/external-source-entry-import-modal.component.html @@ -0,0 +1,50 @@ + + + diff --git a/src/app/shared/form/builder/ds-dynamic-form-ui/relation-lookup-modal/external-source-tab/external-source-entry-import-modal/external-source-entry-import-modal.component.scss b/src/app/shared/form/builder/ds-dynamic-form-ui/relation-lookup-modal/external-source-tab/external-source-entry-import-modal/external-source-entry-import-modal.component.scss new file mode 100644 index 0000000000..7db9839e38 --- /dev/null +++ b/src/app/shared/form/builder/ds-dynamic-form-ui/relation-lookup-modal/external-source-tab/external-source-entry-import-modal/external-source-entry-import-modal.component.scss @@ -0,0 +1,3 @@ +.modal-footer { + justify-content: space-between; +} diff --git a/src/app/shared/form/builder/ds-dynamic-form-ui/relation-lookup-modal/external-source-tab/external-source-entry-import-modal/external-source-entry-import-modal.component.spec.ts b/src/app/shared/form/builder/ds-dynamic-form-ui/relation-lookup-modal/external-source-tab/external-source-entry-import-modal/external-source-entry-import-modal.component.spec.ts new file mode 100644 index 0000000000..e69de29bb2 diff --git a/src/app/shared/form/builder/ds-dynamic-form-ui/relation-lookup-modal/external-source-tab/external-source-entry-import-modal/external-source-entry-import-modal.component.ts b/src/app/shared/form/builder/ds-dynamic-form-ui/relation-lookup-modal/external-source-tab/external-source-entry-import-modal/external-source-entry-import-modal.component.ts new file mode 100644 index 0000000000..6a65ec9b05 --- /dev/null +++ b/src/app/shared/form/builder/ds-dynamic-form-ui/relation-lookup-modal/external-source-tab/external-source-entry-import-modal/external-source-entry-import-modal.component.ts @@ -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>>>; + + /** + * 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); + } +} diff --git a/src/app/shared/shared.module.ts b/src/app/shared/shared.module.ts index 903083e931..230bb1f073 100644 --- a/src/app/shared/shared.module.ts +++ b/src/app/shared/shared.module.ts @@ -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 = [ From 6ada3fae5b5288f5e321ece59bf71fc5ae1ec462 Mon Sep 17 00:00:00 2001 From: Kristof De Langhe Date: Thu, 5 Dec 2019 10:58:38 +0100 Subject: [PATCH 02/12] 67611: Fixed radio button bug + hide pagintion details --- .../external-source-entry-import-modal.component.html | 5 ++++- .../external-source-entry-import-modal.component.ts | 6 ++++-- .../object-collection/object-collection.component.html | 3 +++ .../shared/object-collection/object-collection.component.ts | 5 +++++ src/app/shared/object-detail/object-detail.component.ts | 2 +- src/app/shared/object-grid/object-grid.component.html | 1 + src/app/shared/object-grid/object-grid.component.ts | 5 +++++ src/app/shared/object-list/object-list.component.html | 1 + src/app/shared/object-list/object-list.component.ts | 5 +++++ src/app/shared/pagination/pagination.component.html | 2 +- .../search/search-results/search-results.component.html | 1 + .../search/search-results/search-results.component.ts | 5 +++++ 12 files changed, 36 insertions(+), 5 deletions(-) diff --git a/src/app/shared/form/builder/ds-dynamic-form-ui/relation-lookup-modal/external-source-tab/external-source-entry-import-modal/external-source-entry-import-modal.component.html b/src/app/shared/form/builder/ds-dynamic-form-ui/relation-lookup-modal/external-source-tab/external-source-entry-import-modal/external-source-entry-import-modal.component.html index d2ad3d403d..f055e617e3 100644 --- a/src/app/shared/form/builder/ds-dynamic-form-ui/relation-lookup-modal/external-source-tab/external-source-entry-import-modal/external-source-entry-import-modal.component.html +++ b/src/app/shared/form/builder/ds-dynamic-form-ui/relation-lookup-modal/external-source-tab/external-source-entry-import-modal/external-source-entry-import-modal.component.html @@ -16,10 +16,13 @@
{{ ('submission.sections.describe.relationship-lookup.external-source.import-modal.entities' | translate) }}
- diff --git a/src/app/shared/object-collection/object-collection.component.ts b/src/app/shared/object-collection/object-collection.component.ts index f09ba3953e..58de49ba40 100644 --- a/src/app/shared/object-collection/object-collection.component.ts +++ b/src/app/shared/object-collection/object-collection.component.ts @@ -63,6 +63,11 @@ export class ObjectCollectionComponent implements OnInit { */ @Input() context: Context; + /** + * Option for hiding the pagination detail + */ + @Input() hidePaginationDetail = false; + /** * the page info of the list */ diff --git a/src/app/shared/object-detail/object-detail.component.ts b/src/app/shared/object-detail/object-detail.component.ts index fb68316251..45efb4a0b7 100644 --- a/src/app/shared/object-detail/object-detail.component.ts +++ b/src/app/shared/object-detail/object-detail.component.ts @@ -89,7 +89,7 @@ export class ObjectDetailComponent { /** * Option for hiding the pagination detail */ - public hidePaginationDetail = true; + @Input() hidePaginationDetail = true; /** * An event fired when the page is changed. diff --git a/src/app/shared/object-grid/object-grid.component.html b/src/app/shared/object-grid/object-grid.component.html index 348536bfed..0afd623d86 100644 --- a/src/app/shared/object-grid/object-grid.component.html +++ b/src/app/shared/object-grid/object-grid.component.html @@ -5,6 +5,7 @@ [sortOptions]="sortConfig" [hideGear]="hideGear" [hidePagerWhenSinglePage]="hidePagerWhenSinglePage" + [hidePaginationDetail]="hidePaginationDetail" (pageChange)="onPageChange($event)" (pageSizeChange)="onPageSizeChange($event)" (sortDirectionChange)="onSortDirectionChange($event)" diff --git a/src/app/shared/object-grid/object-grid.component.ts b/src/app/shared/object-grid/object-grid.component.ts index 2da4abe13b..c6f8347217 100644 --- a/src/app/shared/object-grid/object-grid.component.ts +++ b/src/app/shared/object-grid/object-grid.component.ts @@ -69,6 +69,11 @@ export class ObjectGridComponent implements OnInit { */ @Input() context: Context; + /** + * Option for hiding the pagination detail + */ + @Input() hidePaginationDetail = false; + /** * Behavior subject to output the current listable objects */ diff --git a/src/app/shared/object-list/object-list.component.html b/src/app/shared/object-list/object-list.component.html index 887be96785..d0cfb1a9d8 100644 --- a/src/app/shared/object-list/object-list.component.html +++ b/src/app/shared/object-list/object-list.component.html @@ -5,6 +5,7 @@ [sortOptions]="sortConfig" [hideGear]="hideGear" [hidePagerWhenSinglePage]="hidePagerWhenSinglePage" + [hidePaginationDetail]="hidePaginationDetail" (pageChange)="onPageChange($event)" (pageSizeChange)="onPageSizeChange($event)" (sortDirectionChange)="onSortDirectionChange($event)" diff --git a/src/app/shared/object-list/object-list.component.ts b/src/app/shared/object-list/object-list.component.ts index 1be0f69106..1efd715084 100644 --- a/src/app/shared/object-list/object-list.component.ts +++ b/src/app/shared/object-list/object-list.component.ts @@ -74,6 +74,11 @@ export class ObjectListComponent { */ @Input() context: Context; + /** + * Option for hiding the pagination detail + */ + @Input() hidePaginationDetail = false; + /** * The current listable objects */ diff --git a/src/app/shared/pagination/pagination.component.html b/src/app/shared/pagination/pagination.component.html index c16a153026..649fe686ff 100644 --- a/src/app/shared/pagination/pagination.component.html +++ b/src/app/shared/pagination/pagination.component.html @@ -1,5 +1,5 @@
-
+
{{ 'pagination.showing.label' | translate }} diff --git a/src/app/shared/search/search-results/search-results.component.html b/src/app/shared/search/search-results/search-results.component.html index ab1e96c58f..cbc56d1080 100644 --- a/src/app/shared/search/search-results/search-results.component.html +++ b/src/app/shared/search/search-results/search-results.component.html @@ -8,6 +8,7 @@ [selectable]="selectable" [selectionConfig]="selectionConfig" [context]="context" + [hidePaginationDetail]="hidePaginationDetail" (deselectObject)="deselectObject.emit($event)" (selectObject)="selectObject.emit($event)" > diff --git a/src/app/shared/search/search-results/search-results.component.ts b/src/app/shared/search/search-results/search-results.component.ts index f245b5f9ae..b094e69a57 100644 --- a/src/app/shared/search/search-results/search-results.component.ts +++ b/src/app/shared/search/search-results/search-results.component.ts @@ -67,6 +67,11 @@ export class SearchResultsComponent { @Input() context: Context; + /** + * Option for hiding the pagination detail + */ + @Input() hidePaginationDetail = false; + @Input() selectionConfig: {repeatable: boolean, listId: string}; @Output() deselectObject: EventEmitter = new EventEmitter(); From 7a904f9bf7ec11ea5daf9586bcc3ca7ff71f63e7 Mon Sep 17 00:00:00 2001 From: Kristof De Langhe Date: Thu, 5 Dec 2019 14:06:29 +0100 Subject: [PATCH 03/12] 67611: Refactored import button to separate component within object-collection + moved calling of import modal to external-source tab --- ...try-list-submission-element.component.html | 7 -- ...entry-list-submission-element.component.ts | 26 ----- ...elation-external-source-tab.component.html | 5 +- ...-relation-external-source-tab.component.ts | 54 +++++++++- ...l-source-entry-import-modal.component.html | 2 +- ...nal-source-entry-import-modal.component.ts | 99 +++++++++++++++++-- .../object-collection.component.html | 3 + .../object-collection.component.ts | 15 +++ ...mportable-list-item-control.component.html | 7 ++ .../importable-list-item-control.component.ts | 26 +++++ .../object-list/object-list.component.html | 5 + .../object-list/object-list.component.ts | 16 +++ src/app/shared/shared.module.ts | 4 +- 13 files changed, 223 insertions(+), 46 deletions(-) create mode 100644 src/app/shared/object-collection/shared/importable-list-item-control/importable-list-item-control.component.html create mode 100644 src/app/shared/object-collection/shared/importable-list-item-control/importable-list-item-control.component.ts diff --git a/src/app/entity-groups/research-entities/submission/item-list-elements/external-source-entry/external-source-entry-list-submission-element.component.html b/src/app/entity-groups/research-entities/submission/item-list-elements/external-source-entry/external-source-entry-list-submission-element.component.html index 4df06bc0e6..5f34d8ccd0 100644 --- a/src/app/entity-groups/research-entities/submission/item-list-elements/external-source-entry/external-source-entry-list-submission-element.component.html +++ b/src/app/entity-groups/research-entities/submission/item-list-elements/external-source-entry/external-source-entry-list-submission-element.component.html @@ -1,11 +1,4 @@
- -
-
{{object.display}}
diff --git a/src/app/entity-groups/research-entities/submission/item-list-elements/external-source-entry/external-source-entry-list-submission-element.component.ts b/src/app/entity-groups/research-entities/submission/item-list-elements/external-source-entry/external-source-entry-list-submission-element.component.ts index 07d691a5cb..8891a179c3 100644 --- a/src/app/entity-groups/research-entities/submission/item-list-elements/external-source-entry/external-source-entry-list-submission-element.component.ts +++ b/src/app/entity-groups/research-entities/submission/item-list-elements/external-source-entry/external-source-entry-list-submission-element.component.ts @@ -6,10 +6,6 @@ import { Context } from '../../../../../core/shared/context.model'; 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({ @@ -23,29 +19,7 @@ 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; - } - } } diff --git a/src/app/shared/form/builder/ds-dynamic-form-ui/relation-lookup-modal/external-source-tab/dynamic-lookup-relation-external-source-tab.component.html b/src/app/shared/form/builder/ds-dynamic-form-ui/relation-lookup-modal/external-source-tab/dynamic-lookup-relation-external-source-tab.component.html index a9ae77a9f5..04737c44e4 100644 --- a/src/app/shared/form/builder/ds-dynamic-form-ui/relation-lookup-modal/external-source-tab/dynamic-lookup-relation-external-source-tab.component.html +++ b/src/app/shared/form/builder/ds-dynamic-form-ui/relation-lookup-modal/external-source-tab/dynamic-lookup-relation-external-source-tab.component.html @@ -14,8 +14,9 @@ [config]="initialPagination" [hideGear]="true" [context]="context" - (deselectObject)="deselectObject.emit($event)" - (selectObject)="selectObject.emit($event)"> + [importable]="true" + [importConfig]="importConfig" + (importObject)="import($event)"> diff --git a/src/app/shared/form/builder/ds-dynamic-form-ui/relation-lookup-modal/external-source-tab/dynamic-lookup-relation-external-source-tab.component.ts b/src/app/shared/form/builder/ds-dynamic-form-ui/relation-lookup-modal/external-source-tab/dynamic-lookup-relation-external-source-tab.component.ts index d884f5f63d..18dfa4277f 100644 --- a/src/app/shared/form/builder/ds-dynamic-form-ui/relation-lookup-modal/external-source-tab/dynamic-lookup-relation-external-source-tab.component.ts +++ b/src/app/shared/form/builder/ds-dynamic-form-ui/relation-lookup-modal/external-source-tab/dynamic-lookup-relation-external-source-tab.component.ts @@ -1,4 +1,4 @@ -import { Component, EventEmitter, Input, OnInit, Output } from '@angular/core'; +import { Component, EventEmitter, Input, OnDestroy, OnInit, Output } from '@angular/core'; import { SEARCH_CONFIG_SERVICE } from '../../../../../../+my-dspace-page/my-dspace-page.component'; import { SearchConfigurationService } from '../../../../../../core/shared/search/search-configuration.service'; import { Router } from '@angular/router'; @@ -15,6 +15,11 @@ import { ListableObject } from '../../../../../object-collection/shared/listable import { fadeIn, fadeInOut } from '../../../../../animations/fade'; import { PaginationComponentOptions } from '../../../../../pagination/pagination-component-options.model'; import { RelationshipOptions } from '../../../models/relationship-options.model'; +import { NgbModal, NgbModalRef } from '@ng-bootstrap/ng-bootstrap'; +import { ExternalSourceEntryImportModalComponent } from './external-source-entry-import-modal/external-source-entry-import-modal.component'; +import { Subscription } from 'rxjs/internal/Subscription'; +import { hasValue } from '../../../../../empty.util'; +import { SelectableListService } from '../../../../../object-list/selectable-list/selectable-list.service'; @Component({ selector: 'ds-dynamic-lookup-relation-external-source-tab', @@ -32,7 +37,7 @@ import { RelationshipOptions } from '../../../models/relationship-options.model' ] }) -export class DsDynamicLookupRelationExternalSourceTabComponent implements OnInit { +export class DsDynamicLookupRelationExternalSourceTabComponent implements OnInit, OnDestroy { @Input() label: string; @Input() listId: string; @Input() relationship: RelationshipOptions; @@ -56,9 +61,28 @@ export class DsDynamicLookupRelationExternalSourceTabComponent implements OnInit */ entriesRD$: Observable>>; + /** + * Config to use for the import buttons + */ + importConfig = { + buttonLabel: 'submission.sections.describe.relationship-lookup.external-source.import-button-title' + }; + + /** + * The modal for importing the entry + */ + modalRef: NgbModalRef; + + /** + * Subscription to the modal's importedObject event-emitter + */ + importObjectSub: Subscription; + constructor(private router: Router, public searchConfigService: SearchConfigurationService, - private externalSourceService: ExternalSourceService) { + private externalSourceService: ExternalSourceService, + private modalService: NgbModal, + private selectableListService: SelectableListService) { } ngOnInit(): void { @@ -67,4 +91,28 @@ export class DsDynamicLookupRelationExternalSourceTabComponent implements OnInit this.externalSourceService.getExternalSourceEntries(this.externalSource.id, searchOptions)) ) } + + /** + * Start the import of an entry by opening up an import modal window + * @param entry The entry to import + */ + import(entry) { + this.modalRef = this.modalService.open(ExternalSourceEntryImportModalComponent, { + size: 'lg', + container: 'ds-dynamic-lookup-relation-modal' + }); + const modalComp = this.modalRef.componentInstance; + modalComp.externalSourceEntry = entry; + modalComp.relationship = this.relationship; + this.importObjectSub = modalComp.importedObject.subscribe((object) => { + this.selectableListService.selectSingle(this.listId, object); + this.selectObject.emit(object); + }); + } + + ngOnDestroy(): void { + if (hasValue(this.importObjectSub)) { + this.importObjectSub.unsubscribe(); + } + } } diff --git a/src/app/shared/form/builder/ds-dynamic-form-ui/relation-lookup-modal/external-source-tab/external-source-entry-import-modal/external-source-entry-import-modal.component.html b/src/app/shared/form/builder/ds-dynamic-form-ui/relation-lookup-modal/external-source-tab/external-source-entry-import-modal/external-source-entry-import-modal.component.html index f055e617e3..348b7eae18 100644 --- a/src/app/shared/form/builder/ds-dynamic-form-ui/relation-lookup-modal/external-source-tab/external-source-entry-import-modal/external-source-entry-import-modal.component.html +++ b/src/app/shared/form/builder/ds-dynamic-form-ui/relation-lookup-modal/external-source-tab/external-source-entry-import-modal/external-source-entry-import-modal.component.html @@ -26,7 +26,7 @@ [selectionConfig]="{ repeatable: false, listId: entityListId }" [linkType]="linkTypes.ExternalLink" [context]="context" - (deselectObject)="deselectEntity($event)" + (deselectObject)="deselectEntity()" (selectObject)="selectEntity($event)">
diff --git a/src/app/shared/form/builder/ds-dynamic-form-ui/relation-lookup-modal/external-source-tab/external-source-entry-import-modal/external-source-entry-import-modal.component.ts b/src/app/shared/form/builder/ds-dynamic-form-ui/relation-lookup-modal/external-source-tab/external-source-entry-import-modal/external-source-entry-import-modal.component.ts index 6f17ddc529..f8b7b07184 100644 --- a/src/app/shared/form/builder/ds-dynamic-form-ui/relation-lookup-modal/external-source-tab/external-source-entry-import-modal/external-source-entry-import-modal.component.ts +++ b/src/app/shared/form/builder/ds-dynamic-form-ui/relation-lookup-modal/external-source-tab/external-source-entry-import-modal/external-source-entry-import-modal.component.ts @@ -1,4 +1,4 @@ -import { Component, OnInit } from '@angular/core'; +import { Component, EventEmitter, 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'; @@ -14,6 +14,8 @@ import { PaginatedSearchOptions } from '../../../../../../search/paginated-searc 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'; +import { ListableObject } from '../../../../../../object-collection/shared/listable-object.model'; +import { take } from 'rxjs/operators'; /** * The possible types of import for the external entry @@ -87,6 +89,21 @@ export class ExternalSourceEntryImportModalComponent implements OnInit { */ selectedImportType = ImportType.None; + /** + * The selected local entity + */ + selectedEntity: ListableObject; + + /** + * The selected local authority + */ + selectedAuthority: ListableObject; + + /** + * An object has been imported, send it to the parent component + */ + importedObject: EventEmitter = new EventEmitter(); + constructor(public modal: NgbActiveModal, public lookupRelationService: LookupRelationService, private selectService: SelectableListService) { @@ -109,14 +126,64 @@ export class ExternalSourceEntryImportModalComponent implements OnInit { * Perform the import of the external entry */ import() { - console.log('TODO: Import'); + switch (this.selectedImportType) { + case ImportType.LocalEntity : { + this.importLocalEntity(); + break; + } + case ImportType.NewEntity : { + this.importNewEntity(); + break; + } + case ImportType.LocalAuthority : { + this.importLocalAuthority(); + break; + } + case ImportType.NewAuthority : { + this.importNewAuthority(); + break; + } + } + this.selectedImportType = ImportType.None; + this.deselectAllLists(); + this.close(); + } + + /** + * Import the selected local entity + */ + importLocalEntity() { + if (this.selectedEntity !== undefined) { + this.importedObject.emit(this.selectedEntity); + } + } + + /** + * Create and import a new entity from the external entry + */ + importNewEntity() { + this.importedObject.emit(this.externalSourceEntry); + } + + /** + * Import the selected local authority + */ + importLocalAuthority() { + // TODO: Implement ability to import local authorities + } + + /** + * Create and import a new authority from the external entry + */ + importNewAuthority() { + // TODO: Implement ability to import new authorities } /** * Deselected a local entity - * @param event */ - deselectEntity(event) { + deselectEntity() { + this.selectedEntity = undefined; if (this.selectedImportType === ImportType.LocalEntity) { this.selectedImportType = ImportType.None; } @@ -124,9 +191,10 @@ export class ExternalSourceEntryImportModalComponent implements OnInit { /** * Selected a local entity - * @param event + * @param entity */ - selectEntity(event) { + selectEntity(entity) { + this.selectedEntity = entity; this.selectedImportType = ImportType.LocalEntity; } @@ -142,6 +210,25 @@ export class ExternalSourceEntryImportModalComponent implements OnInit { } } + /** + * Deselected a local authority + */ + deselectAuthority() { + this.selectedAuthority = undefined; + if (this.selectedImportType === ImportType.LocalAuthority) { + this.selectedImportType = ImportType.None; + } + } + + /** + * Selected a local authority + * @param authority + */ + selectAuthority(authority) { + this.selectedAuthority = authority; + this.selectedImportType = ImportType.LocalAuthority; + } + /** * Selected/deselected the new authority option */ diff --git a/src/app/shared/object-collection/object-collection.component.html b/src/app/shared/object-collection/object-collection.component.html index 499b8e03c9..e696170a6f 100644 --- a/src/app/shared/object-collection/object-collection.component.html +++ b/src/app/shared/object-collection/object-collection.component.html @@ -15,6 +15,9 @@ (sortFieldChange)="onSortFieldChange($event)" [selectable]="selectable" [selectionConfig]="selectionConfig" + [importable]="importable" + [importConfig]="importConfig" + (importObject)="importObject.emit($event)" *ngIf="(currentMode$ | async) === viewModeEnum.ListElement"> diff --git a/src/app/shared/object-collection/object-collection.component.ts b/src/app/shared/object-collection/object-collection.component.ts index 58de49ba40..f39bf07123 100644 --- a/src/app/shared/object-collection/object-collection.component.ts +++ b/src/app/shared/object-collection/object-collection.component.ts @@ -53,6 +53,21 @@ export class ObjectCollectionComponent implements OnInit { @Output() deselectObject: EventEmitter = new EventEmitter(); @Output() selectObject: EventEmitter = new EventEmitter(); + /** + * Whether or not to add an import button to the object elements + */ + @Input() importable = false; + + /** + * The config to use for the import button + */ + @Input() importConfig: { buttonLabel: string }; + + /** + * Send an import event to the parent component + */ + @Output() importObject: EventEmitter = new EventEmitter(); + /** * The link type of the rendered list elements */ diff --git a/src/app/shared/object-collection/shared/importable-list-item-control/importable-list-item-control.component.html b/src/app/shared/object-collection/shared/importable-list-item-control/importable-list-item-control.component.html new file mode 100644 index 0000000000..ca3b086653 --- /dev/null +++ b/src/app/shared/object-collection/shared/importable-list-item-control/importable-list-item-control.component.html @@ -0,0 +1,7 @@ +
+ +
diff --git a/src/app/shared/object-collection/shared/importable-list-item-control/importable-list-item-control.component.ts b/src/app/shared/object-collection/shared/importable-list-item-control/importable-list-item-control.component.ts new file mode 100644 index 0000000000..f381a02d86 --- /dev/null +++ b/src/app/shared/object-collection/shared/importable-list-item-control/importable-list-item-control.component.ts @@ -0,0 +1,26 @@ +import { Component, EventEmitter, Input, Output } from '@angular/core'; +import { ListableObject } from '../listable-object.model'; + +@Component({ + selector: 'ds-importable-list-item-control', + templateUrl: './importable-list-item-control.component.html' +}) +/** + * Component adding an import button to a list item + */ +export class ImportableListItemControlComponent { + /** + * The item or metadata to determine the component for + */ + @Input() object: ListableObject; + + /** + * Extra configuration for the import button + */ + @Input() importConfig: { buttonLabel: string }; + + /** + * Output the object to import + */ + @Output() importObject: EventEmitter = new EventEmitter(); +} diff --git a/src/app/shared/object-list/object-list.component.html b/src/app/shared/object-list/object-list.component.html index d0cfb1a9d8..5f6b1d1ec8 100644 --- a/src/app/shared/object-list/object-list.component.html +++ b/src/app/shared/object-list/object-list.component.html @@ -20,6 +20,11 @@ (deselectObject)="deselectObject.emit($event)" (selectObject)="selectObject.emit($event)"> + + + diff --git a/src/app/shared/object-list/object-list.component.ts b/src/app/shared/object-list/object-list.component.ts index 1efd715084..5ebaae668c 100644 --- a/src/app/shared/object-list/object-list.component.ts +++ b/src/app/shared/object-list/object-list.component.ts @@ -79,6 +79,16 @@ export class ObjectListComponent { */ @Input() hidePaginationDetail = false; + /** + * Whether or not to add an import button to the object + */ + @Input() importable = false; + + /** + * Config used for the import button + */ + @Input() importConfig: { importLabel: string }; + /** * The current listable objects */ @@ -137,6 +147,12 @@ export class ObjectListComponent { @Output() deselectObject: EventEmitter = new EventEmitter(); @Output() selectObject: EventEmitter = new EventEmitter(); + + /** + * Send an import event to the parent component + */ + @Output() importObject: EventEmitter = new EventEmitter(); + /** * An event fired when the sort field is changed. * Event's payload equals to the newly selected sort field. diff --git a/src/app/shared/shared.module.ts b/src/app/shared/shared.module.ts index 230bb1f073..6afa15d0f7 100644 --- a/src/app/shared/shared.module.ts +++ b/src/app/shared/shared.module.ts @@ -176,6 +176,7 @@ import { MetadataRepresentationListComponent } from '../+item-page/simple/metada 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'; +import { ImportableListItemControlComponent } from './object-collection/shared/importable-list-item-control/importable-list-item-control.component'; const MODULES = [ // Do NOT include UniversalModule, HttpModule, or JsonpModule here @@ -333,7 +334,8 @@ const COMPONENTS = [ CollectionSelectComponent, MetadataRepresentationLoaderComponent, SelectableListItemControlComponent, - ExternalSourceEntryImportModalComponent + ExternalSourceEntryImportModalComponent, + ImportableListItemControlComponent ]; const ENTRY_COMPONENTS = [ From fda083137a2854daaf780a523d39a3fb699937c8 Mon Sep 17 00:00:00 2001 From: Kristof De Langhe Date: Thu, 5 Dec 2019 15:48:54 +0100 Subject: [PATCH 04/12] 67611: Import external entry as new entity pt1 --- resources/i18n/en.json5 | 2 ++ src/app/core/data/item-data.service.ts | 29 +++++++++++++++++++ ...ynamic-form-control-container.component.ts | 14 +++++++-- ...namic-lookup-relation-modal.component.html | 2 ++ ...dynamic-lookup-relation-modal.component.ts | 1 + ...-relation-external-source-tab.component.ts | 6 ++++ ...l-source-entry-import-modal.component.html | 12 ++++++-- ...nal-source-entry-import-modal.component.ts | 27 +++++++++++++++-- 8 files changed, 84 insertions(+), 9 deletions(-) diff --git a/resources/i18n/en.json5 b/resources/i18n/en.json5 index fe7949d8b1..16d5d64bd9 100644 --- a/resources/i18n/en.json5 +++ b/resources/i18n/en.json5 @@ -1533,6 +1533,8 @@ "submission.sections.describe.relationship-lookup.external-source.import-modal.cancel": "Cancel", + "submission.sections.describe.relationship-lookup.external-source.import-modal.collection": "Select a collection to import new entries to", + "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", diff --git a/src/app/core/data/item-data.service.ts b/src/app/core/data/item-data.service.ts index e616cb8020..b5f16227a8 100644 --- a/src/app/core/data/item-data.service.ts +++ b/src/app/core/data/item-data.service.ts @@ -37,6 +37,7 @@ import { HttpOptions } from '../dspace-rest-v2/dspace-rest-v2.service'; import { Collection } from '../shared/collection.model'; import { RemoteData } from './remote-data'; import { PaginatedList } from './paginated-list'; +import { ExternalSourceEntry } from '../shared/external-source-entry.model'; @Injectable() export class ItemDataService extends DataService { @@ -247,4 +248,32 @@ export class ItemDataService extends DataService { map((request: RequestEntry) => request.response) ); } + + /** + * Import an external source entry into a collection + * @param externalSourceEntry + * @param collectionId + */ + public importExternalSourceEntry(externalSourceEntry: ExternalSourceEntry, collectionId: string): Observable { + const options: HttpOptions = Object.create({}); + let headers = new HttpHeaders(); + headers = headers.append('Content-Type', 'text/uri-list'); + options.headers = headers; + + const requestId = this.requestService.generateRequestId(); + const href$ = this.halService.getEndpoint(this.linkPath).pipe(map((href) => `${href}?owningCollection=${collectionId}`)); + + href$.pipe( + find((href: string) => hasValue(href)), + map((href: string) => { + const request = new PostRequest(requestId, href, externalSourceEntry.self, options); + this.requestService.configure(request); + }) + ).subscribe(); + + return this.requestService.getByUUID(requestId).pipe( + find((request: RequestEntry) => request.completed), + map((request: RequestEntry) => request.response) + ); + } } diff --git a/src/app/shared/form/builder/ds-dynamic-form-ui/ds-dynamic-form-control-container.component.ts b/src/app/shared/form/builder/ds-dynamic-form-ui/ds-dynamic-form-control-container.component.ts index b78385dc62..d6e3a97a11 100644 --- a/src/app/shared/form/builder/ds-dynamic-form-ui/ds-dynamic-form-control-container.component.ts +++ b/src/app/shared/form/builder/ds-dynamic-form-ui/ds-dynamic-form-control-container.component.ts @@ -101,6 +101,7 @@ import { ItemSearchResult } from '../../../object-collection/shared/item-search- import { ItemMetadataRepresentation } from '../../../../core/shared/metadata-representation/item/item-metadata-representation.model'; import { MetadataValue } from '../../../../core/shared/metadata.models'; import * as uuidv4 from 'uuid/v4'; +import { Collection } from '../../../../core/shared/collection.model'; export function dsDynamicFormControlMapFn(model: DynamicFormControlModel): Type | null { switch (model.type) { @@ -188,6 +189,7 @@ export class DsDynamicFormControlContainerComponent extends DynamicFormControlCo hasRelationLookup: boolean; modalRef: NgbModalRef; item: Item; + collection: Collection; listId: string; searchConfig: string; selectedValues$: Observable (submissionObject.item as Observable>).pipe(getAllSucceededRemoteData(), getRemoteDataPayload()))); + getRemoteDataPayload() + ); + + const item$ = submissionObject$.pipe(switchMap((submissionObject: SubmissionObject) => (submissionObject.item as Observable>).pipe(getAllSucceededRemoteData(), getRemoteDataPayload()))); + const collection$ = submissionObject$.pipe(switchMap((submissionObject: SubmissionObject) => (submissionObject.collection as Observable>).pipe(getAllSucceededRemoteData(), getRemoteDataPayload()))); this.subs.push(item$.subscribe((item) => this.item = item)); + this.subs.push(collection$.subscribe((collection) => this.collection = collection)); this.relationService.getRelatedItemsByLabel(this.item, this.model.relationship.relationshipType).pipe( map((items: RemoteData>) => items.payload.page.map((item) => Object.assign(new ItemSearchResult(), { indexableObject: item }))), @@ -325,6 +332,7 @@ export class DsDynamicFormControlContainerComponent extends DynamicFormControlCo modalComp.label = this.model.label; modalComp.metadataFields = this.model.metadataFields; modalComp.item = this.item; + modalComp.collection = this.collection; } removeSelection(object: SearchResult) { diff --git a/src/app/shared/form/builder/ds-dynamic-form-ui/relation-lookup-modal/dynamic-lookup-relation-modal.component.html b/src/app/shared/form/builder/ds-dynamic-form-ui/relation-lookup-modal/dynamic-lookup-relation-modal.component.html index 4c87ac8bdb..1773661486 100644 --- a/src/app/shared/form/builder/ds-dynamic-form-ui/relation-lookup-modal/dynamic-lookup-relation-modal.component.html +++ b/src/app/shared/form/builder/ds-dynamic-form-ui/relation-lookup-modal/dynamic-lookup-relation-modal.component.html @@ -26,6 +26,8 @@ ; context: Context; diff --git a/src/app/shared/form/builder/ds-dynamic-form-ui/relation-lookup-modal/external-source-tab/dynamic-lookup-relation-external-source-tab.component.ts b/src/app/shared/form/builder/ds-dynamic-form-ui/relation-lookup-modal/external-source-tab/dynamic-lookup-relation-external-source-tab.component.ts index 18dfa4277f..dfdb1508fc 100644 --- a/src/app/shared/form/builder/ds-dynamic-form-ui/relation-lookup-modal/external-source-tab/dynamic-lookup-relation-external-source-tab.component.ts +++ b/src/app/shared/form/builder/ds-dynamic-form-ui/relation-lookup-modal/external-source-tab/dynamic-lookup-relation-external-source-tab.component.ts @@ -20,6 +20,8 @@ import { ExternalSourceEntryImportModalComponent } from './external-source-entry import { Subscription } from 'rxjs/internal/Subscription'; import { hasValue } from '../../../../../empty.util'; import { SelectableListService } from '../../../../../object-list/selectable-list/selectable-list.service'; +import { Item } from '../../../../../../core/shared/item.model'; +import { Collection } from '../../../../../../core/shared/collection.model'; @Component({ selector: 'ds-dynamic-lookup-relation-external-source-tab', @@ -40,6 +42,8 @@ import { SelectableListService } from '../../../../../object-list/selectable-lis export class DsDynamicLookupRelationExternalSourceTabComponent implements OnInit, OnDestroy { @Input() label: string; @Input() listId: string; + @Input() item: Item; + @Input() collection: Collection; @Input() relationship: RelationshipOptions; @Input() repeatable: boolean; @Input() context: Context; @@ -103,6 +107,8 @@ export class DsDynamicLookupRelationExternalSourceTabComponent implements OnInit }); const modalComp = this.modalRef.componentInstance; modalComp.externalSourceEntry = entry; + modalComp.item = this.item; + modalComp.collection = this.collection; modalComp.relationship = this.relationship; this.importObjectSub = modalComp.importedObject.subscribe((object) => { this.selectableListService.selectSingle(this.listId, object); diff --git a/src/app/shared/form/builder/ds-dynamic-form-ui/relation-lookup-modal/external-source-tab/external-source-entry-import-modal/external-source-entry-import-modal.component.html b/src/app/shared/form/builder/ds-dynamic-form-ui/relation-lookup-modal/external-source-tab/external-source-entry-import-modal/external-source-entry-import-modal.component.html index 348b7eae18..ffb3aabde8 100644 --- a/src/app/shared/form/builder/ds-dynamic-form-ui/relation-lookup-modal/external-source-tab/external-source-entry-import-modal/external-source-entry-import-modal.component.html +++ b/src/app/shared/form/builder/ds-dynamic-form-ui/relation-lookup-modal/external-source-tab/external-source-entry-import-modal/external-source-entry-import-modal.component.html @@ -13,7 +13,13 @@

{{ ('submission.sections.describe.relationship-lookup.external-source.import-modal.select' | translate) }}

-
+
+
+ + +
+
+
{{ ('submission.sections.describe.relationship-lookup.external-source.import-modal.entities' | translate) }}
-
+
@@ -37,7 +43,7 @@
{{ ('submission.sections.describe.relationship-lookup.external-source.import-modal.authority' | translate) }}
-
+
diff --git a/src/app/shared/form/builder/ds-dynamic-form-ui/relation-lookup-modal/external-source-tab/external-source-entry-import-modal/external-source-entry-import-modal.component.ts b/src/app/shared/form/builder/ds-dynamic-form-ui/relation-lookup-modal/external-source-tab/external-source-entry-import-modal/external-source-entry-import-modal.component.ts index f8b7b07184..acd1fa59ea 100644 --- a/src/app/shared/form/builder/ds-dynamic-form-ui/relation-lookup-modal/external-source-tab/external-source-entry-import-modal/external-source-entry-import-modal.component.ts +++ b/src/app/shared/form/builder/ds-dynamic-form-ui/relation-lookup-modal/external-source-tab/external-source-entry-import-modal/external-source-entry-import-modal.component.ts @@ -15,7 +15,8 @@ import { CollectionElementLinkType } from '../../../../../../object-collection/c import { Context } from '../../../../../../../core/shared/context.model'; import { SelectableListService } from '../../../../../../object-list/selectable-list/selectable-list.service'; import { ListableObject } from '../../../../../../object-collection/shared/listable-object.model'; -import { take } from 'rxjs/operators'; +import { Collection } from '../../../../../../../core/shared/collection.model'; +import { ItemDataService } from '../../../../../../../core/data/item-data.service'; /** * The possible types of import for the external entry @@ -39,6 +40,21 @@ export class ExternalSourceEntryImportModalComponent implements OnInit { */ externalSourceEntry: ExternalSourceEntry; + /** + * The item in submission + */ + item: Item; + + /** + * The collection the user is submitting in + */ + collection: Collection; + + /** + * The ID of the collection to import entries to + */ + collectionId: string; + /** * The current relationship-options used for filtering results */ @@ -106,13 +122,15 @@ export class ExternalSourceEntryImportModalComponent implements OnInit { constructor(public modal: NgbActiveModal, public lookupRelationService: LookupRelationService, - private selectService: SelectableListService) { + private selectService: SelectableListService, + private itemService: ItemDataService) { } ngOnInit(): void { this.uri = Metadata.first(this.externalSourceEntry.metadata, 'dc.identifier.uri'); this.searchOptions = Object.assign(new PaginatedSearchOptions({ query: 'sarah' })); this.localEntitiesRD$ = this.lookupRelationService.getLocalResults(this.relationship, this.searchOptions); + this.collectionId = this.collection.id; } /** @@ -162,7 +180,10 @@ export class ExternalSourceEntryImportModalComponent implements OnInit { * Create and import a new entity from the external entry */ importNewEntity() { - this.importedObject.emit(this.externalSourceEntry); + console.log(this.collection); + this.itemService.importExternalSourceEntry(this.externalSourceEntry, this.collectionId).subscribe((response) => { + console.log(response); + }); } /** From f0e38e9e8c7085fc2ec25a000651811bf92984fb Mon Sep 17 00:00:00 2001 From: Kristof De Langhe Date: Thu, 5 Dec 2019 17:31:13 +0100 Subject: [PATCH 05/12] 67611: Console error fix, notification on adding local entity and JSDocs --- resources/i18n/en.json5 | 3 ++ ...namic-lookup-relation-modal.component.html | 1 - ...-relation-external-source-tab.component.ts | 50 +++++++++++++++++-- ...nal-source-entry-import-modal.component.ts | 11 +++- 4 files changed, 58 insertions(+), 7 deletions(-) diff --git a/resources/i18n/en.json5 b/resources/i18n/en.json5 index 16d5d64bd9..7fa9c96010 100644 --- a/resources/i18n/en.json5 +++ b/resources/i18n/en.json5 @@ -1523,8 +1523,11 @@ "submission.general.save-later": "Save for later", + "submission.sections.describe.relationship-lookup.close": "Close", + "submission.sections.describe.relationship-lookup.external-source.added": "Successfully added local entry to the selection", + "submission.sections.describe.relationship-lookup.external-source.import-button-title": "Import remote entry", "submission.sections.describe.relationship-lookup.external-source.import-modal.authority": "Authority", diff --git a/src/app/shared/form/builder/ds-dynamic-form-ui/relation-lookup-modal/dynamic-lookup-relation-modal.component.html b/src/app/shared/form/builder/ds-dynamic-form-ui/relation-lookup-modal/dynamic-lookup-relation-modal.component.html index 1773661486..06e45ecb92 100644 --- a/src/app/shared/form/builder/ds-dynamic-form-ui/relation-lookup-modal/dynamic-lookup-relation-modal.component.html +++ b/src/app/shared/form/builder/ds-dynamic-form-ui/relation-lookup-modal/dynamic-lookup-relation-modal.component.html @@ -29,7 +29,6 @@ [item]="item" [collection]="collection" [relationship]="relationshipOptions" - [repeatable]="repeatable" [context]="context" [externalSource]="source" (selectObject)="select($event)" diff --git a/src/app/shared/form/builder/ds-dynamic-form-ui/relation-lookup-modal/external-source-tab/dynamic-lookup-relation-external-source-tab.component.ts b/src/app/shared/form/builder/ds-dynamic-form-ui/relation-lookup-modal/external-source-tab/dynamic-lookup-relation-external-source-tab.component.ts index dfdb1508fc..54cd4e2f86 100644 --- a/src/app/shared/form/builder/ds-dynamic-form-ui/relation-lookup-modal/external-source-tab/dynamic-lookup-relation-external-source-tab.component.ts +++ b/src/app/shared/form/builder/ds-dynamic-form-ui/relation-lookup-modal/external-source-tab/dynamic-lookup-relation-external-source-tab.component.ts @@ -22,6 +22,8 @@ import { hasValue } from '../../../../../empty.util'; import { SelectableListService } from '../../../../../object-list/selectable-list/selectable-list.service'; import { Item } from '../../../../../../core/shared/item.model'; import { Collection } from '../../../../../../core/shared/collection.model'; +import { NotificationsService } from '../../../../../notifications/notifications.service'; +import { TranslateService } from '@ngx-translate/core'; @Component({ selector: 'ds-dynamic-lookup-relation-external-source-tab', @@ -38,18 +40,49 @@ import { Collection } from '../../../../../../core/shared/collection.model'; fadeInOut ] }) - +/** + * Component rendering the tab content of an external source during submission lookup + * Shows a list of entries matching the current search query with the option to import them into the repository + */ export class DsDynamicLookupRelationExternalSourceTabComponent implements OnInit, OnDestroy { - @Input() label: string; + /** + * The ID of the list of selected entries + */ @Input() listId: string; + + /** + * The item in submission + */ @Input() item: Item; + + /** + * The collection the user is submitting an item into + */ @Input() collection: Collection; + + /** + * The relationship-options for the current lookup + */ @Input() relationship: RelationshipOptions; - @Input() repeatable: boolean; + + /** + * The context to displaying lists for + */ @Input() context: Context; + + /** + * Emit an event when an object has been deselected + */ @Output() deselectObject: EventEmitter = new EventEmitter(); + + /** + * Emit an event when an object has been selected (or imported) + */ @Output() selectObject: EventEmitter = new EventEmitter(); + /** + * The initial pagination options + */ initialPagination = Object.assign(new PaginationComponentOptions(), { id: 'submission-external-source-relation-list', pageSize: 5 @@ -86,9 +119,14 @@ export class DsDynamicLookupRelationExternalSourceTabComponent implements OnInit public searchConfigService: SearchConfigurationService, private externalSourceService: ExternalSourceService, private modalService: NgbModal, - private selectableListService: SelectableListService) { + private selectableListService: SelectableListService, + private notificationsService: NotificationsService, + private translateService: TranslateService) { } + /** + * Get the entries for the selected external source + */ ngOnInit(): void { this.entriesRD$ = this.searchConfigService.paginatedSearchOptions.pipe( switchMap((searchOptions: PaginatedSearchOptions) => @@ -112,10 +150,14 @@ export class DsDynamicLookupRelationExternalSourceTabComponent implements OnInit modalComp.relationship = this.relationship; this.importObjectSub = modalComp.importedObject.subscribe((object) => { this.selectableListService.selectSingle(this.listId, object); + this.notificationsService.success(this.translateService.get('submission.sections.describe.relationship-lookup.external-source.added')); this.selectObject.emit(object); }); } + /** + * Unsubscribe from open subscriptions + */ ngOnDestroy(): void { if (hasValue(this.importObjectSub)) { this.importObjectSub.unsubscribe(); diff --git a/src/app/shared/form/builder/ds-dynamic-form-ui/relation-lookup-modal/external-source-tab/external-source-entry-import-modal/external-source-entry-import-modal.component.ts b/src/app/shared/form/builder/ds-dynamic-form-ui/relation-lookup-modal/external-source-tab/external-source-entry-import-modal/external-source-entry-import-modal.component.ts index acd1fa59ea..2107021d40 100644 --- a/src/app/shared/form/builder/ds-dynamic-form-ui/relation-lookup-modal/external-source-tab/external-source-entry-import-modal/external-source-entry-import-modal.component.ts +++ b/src/app/shared/form/builder/ds-dynamic-form-ui/relation-lookup-modal/external-source-tab/external-source-entry-import-modal/external-source-entry-import-modal.component.ts @@ -17,6 +17,7 @@ import { SelectableListService } from '../../../../../../object-list/selectable- import { ListableObject } from '../../../../../../object-collection/shared/listable-object.model'; import { Collection } from '../../../../../../../core/shared/collection.model'; import { ItemDataService } from '../../../../../../../core/data/item-data.service'; +import { PaginationComponentOptions } from '../../../../../../pagination/pagination-component-options.model'; /** * The possible types of import for the external entry @@ -34,6 +35,12 @@ export enum ImportType { styleUrls: ['./external-source-entry-import-modal.component.scss'], templateUrl: './external-source-entry-import-modal.component.html' }) +/** + * Component to display a modal window for importing an external source entry + * Shows information about the selected entry and a selectable list of local entities and authorities with similar names + * and the ability to add one of those results to the selection instead of the external entry. + * The other option is to import the external entry as a new entity or authority into the repository. + */ export class ExternalSourceEntryImportModalComponent implements OnInit { /** * The external source entry @@ -128,7 +135,8 @@ export class ExternalSourceEntryImportModalComponent implements OnInit { ngOnInit(): void { this.uri = Metadata.first(this.externalSourceEntry.metadata, 'dc.identifier.uri'); - this.searchOptions = Object.assign(new PaginatedSearchOptions({ query: 'sarah' })); + const pagination = Object.assign(new PaginationComponentOptions(), { id: 'external-entry-import', pageSize: 5 }); + this.searchOptions = Object.assign(new PaginatedSearchOptions({ query: this.externalSourceEntry.value, pagination: pagination })); this.localEntitiesRD$ = this.lookupRelationService.getLocalResults(this.relationship, this.searchOptions); this.collectionId = this.collection.id; } @@ -180,7 +188,6 @@ export class ExternalSourceEntryImportModalComponent implements OnInit { * Create and import a new entity from the external entry */ importNewEntity() { - console.log(this.collection); this.itemService.importExternalSourceEntry(this.externalSourceEntry, this.collectionId).subscribe((response) => { console.log(response); }); From 1402dd9129156dddaa86f8421ccddcc8db2f5cc8 Mon Sep 17 00:00:00 2001 From: Kristof De Langhe Date: Fri, 6 Dec 2019 16:52:30 +0100 Subject: [PATCH 06/12] 67611: Import new external entity and add to selection + message changes/refactoring --- resources/i18n/en.json5 | 34 +++++++++++++++++-- src/app/core/data/item-data.service.ts | 10 ++++-- src/app/core/data/lookup-relation.service.ts | 11 +++++- ...namic-lookup-relation-modal.component.html | 4 +-- ...dynamic-lookup-relation-modal.component.ts | 9 +++++ ...-relation-external-source-tab.component.ts | 33 ++++++++---------- ...l-source-entry-import-modal.component.html | 22 ++++++------ ...nal-source-entry-import-modal.component.ts | 33 ++++++++++++++++-- 8 files changed, 116 insertions(+), 40 deletions(-) diff --git a/resources/i18n/en.json5 b/resources/i18n/en.json5 index 76ffe955a7..cee53de8ec 100644 --- a/resources/i18n/en.json5 +++ b/resources/i18n/en.json5 @@ -1546,7 +1546,19 @@ "submission.sections.describe.relationship-lookup.external-source.added": "Successfully added local entry to the selection", - "submission.sections.describe.relationship-lookup.external-source.import-button-title": "Import remote entry", + "submission.sections.describe.relationship-lookup.external-source.import-button-title.Author": "Import remote author", + + "submission.sections.describe.relationship-lookup.external-source.import-button-title.Journal": "Import remote journal", + + "submission.sections.describe.relationship-lookup.external-source.import-button-title.Journal Issue": "Import remote journal issue", + + "submission.sections.describe.relationship-lookup.external-source.import-button-title.Journal Volume": "Import remote journal volume", + + "submission.sections.describe.relationship-lookup.external-source.import-modal.Author.title": "Import Remote Author", + + "submission.sections.describe.relationship-lookup.external-source.import-modal.Author.added.local-entity": "Successfully added local author to the selection", + + "submission.sections.describe.relationship-lookup.external-source.import-modal.Author.added.new-entity": "Successfully imported and added external author to the selection", "submission.sections.describe.relationship-lookup.external-source.import-modal.authority": "Authority", @@ -1570,9 +1582,25 @@ "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.Journal.title": "Import Remote Journal", - "submission.sections.describe.relationship-lookup.external-source.import-modal.title": "Import Remote Entry", + "submission.sections.describe.relationship-lookup.external-source.import-modal.Journal.added.local-entity": "Successfully added local journal to the selection", + + "submission.sections.describe.relationship-lookup.external-source.import-modal.Journal.added.new-entity": "Successfully imported and added external journal to the selection", + + "submission.sections.describe.relationship-lookup.external-source.import-modal.Journal Issue.title": "Import Remote Journal Issue", + + "submission.sections.describe.relationship-lookup.external-source.import-modal.Journal Issue.added.local-entity": "Successfully added local journal issue to the selection", + + "submission.sections.describe.relationship-lookup.external-source.import-modal.Journal Issue.added.new-entity": "Successfully imported and added external journal issue to the selection", + + "submission.sections.describe.relationship-lookup.external-source.import-modal.Journal Volume.title": "Import Remote Journal Volume", + + "submission.sections.describe.relationship-lookup.external-source.import-modal.Journal Volume.added.local-entity": "Successfully added local journal volume to the selection", + + "submission.sections.describe.relationship-lookup.external-source.import-modal.Journal Volume.added.new-entity": "Successfully imported and added external journal volume to the selection", + + "submission.sections.describe.relationship-lookup.external-source.import-modal.select": "Select a local match:", "submission.sections.describe.relationship-lookup.search-tab.deselect-all": "Deselect all", diff --git a/src/app/core/data/item-data.service.ts b/src/app/core/data/item-data.service.ts index b71b778993..cd7e70dc32 100644 --- a/src/app/core/data/item-data.service.ts +++ b/src/app/core/data/item-data.service.ts @@ -254,7 +254,7 @@ export class ItemDataService extends DataService { * @param externalSourceEntry * @param collectionId */ - public importExternalSourceEntry(externalSourceEntry: ExternalSourceEntry, collectionId: string): Observable { + public importExternalSourceEntry(externalSourceEntry: ExternalSourceEntry, collectionId: string): Observable> { const options: HttpOptions = Object.create({}); let headers = new HttpHeaders(); headers = headers.append('Content-Type', 'text/uri-list'); @@ -273,7 +273,13 @@ export class ItemDataService extends DataService { return this.requestService.getByUUID(requestId).pipe( find((request: RequestEntry) => request.completed), - map((request: RequestEntry) => request.response) + getResponseFromEntry(), + map((response: any) => { + if (isNotEmpty(response.resourceSelfLinks)) { + return response.resourceSelfLinks[0]; + } + }), + switchMap((selfLink: string) => this.findByHref(selfLink)) ); } diff --git a/src/app/core/data/lookup-relation.service.ts b/src/app/core/data/lookup-relation.service.ts index 5a36474a66..42cf3afdc5 100644 --- a/src/app/core/data/lookup-relation.service.ts +++ b/src/app/core/data/lookup-relation.service.ts @@ -15,6 +15,7 @@ import { getAllSucceededRemoteData, getRemoteDataPayload } from '../shared/opera import { Injectable } from '@angular/core'; import { ExternalSource } from '../shared/external-source.model'; import { ExternalSourceEntry } from '../shared/external-source-entry.model'; +import { RequestService } from './request.service'; /** * A service for retrieving local and external entries information during a relation lookup @@ -35,7 +36,8 @@ export class LookupRelationService { }); constructor(protected externalSourceService: ExternalSourceService, - protected searchService: SearchService) { + protected searchService: SearchService, + protected requestService: RequestService) { } /** @@ -91,4 +93,11 @@ export class LookupRelationService { startWith(0) ); } + + /** + * Remove cached requests from local results + */ + removeLocalResultsCache() { + this.searchService.getEndpoint().subscribe((href) => this.requestService.removeByHrefSubstring(href)); + } } diff --git a/src/app/shared/form/builder/ds-dynamic-form-ui/relation-lookup-modal/dynamic-lookup-relation-modal.component.html b/src/app/shared/form/builder/ds-dynamic-form-ui/relation-lookup-modal/dynamic-lookup-relation-modal.component.html index 06e45ecb92..328cdc6763 100644 --- a/src/app/shared/form/builder/ds-dynamic-form-ui/relation-lookup-modal/dynamic-lookup-relation-modal.component.html +++ b/src/app/shared/form/builder/ds-dynamic-form-ui/relation-lookup-modal/dynamic-lookup-relation-modal.component.html @@ -25,14 +25,14 @@ [title]="'submission.sections.describe.relationship-lookup.search-tab.tab-title.' + source.id | translate : {count: (totalExternal$ | async)[idx]}"> diff --git a/src/app/shared/form/builder/ds-dynamic-form-ui/relation-lookup-modal/dynamic-lookup-relation-modal.component.ts b/src/app/shared/form/builder/ds-dynamic-form-ui/relation-lookup-modal/dynamic-lookup-relation-modal.component.ts index c49a228c01..4845ffb398 100644 --- a/src/app/shared/form/builder/ds-dynamic-form-ui/relation-lookup-modal/dynamic-lookup-relation-modal.component.ts +++ b/src/app/shared/form/builder/ds-dynamic-form-ui/relation-lookup-modal/dynamic-lookup-relation-modal.component.ts @@ -179,6 +179,15 @@ export class DsDynamicLookupRelationModalComponent implements OnInit, OnDestroy ) } + /** + * Called when an external object has been imported, resets the total values and adds the object to the selected list + * @param object + */ + imported(object) { + this.setTotals(); + this.select(object); + } + /** * Calculate and set the total entries available for each tab */ diff --git a/src/app/shared/form/builder/ds-dynamic-form-ui/relation-lookup-modal/external-source-tab/dynamic-lookup-relation-external-source-tab.component.ts b/src/app/shared/form/builder/ds-dynamic-form-ui/relation-lookup-modal/external-source-tab/dynamic-lookup-relation-external-source-tab.component.ts index 65645e0739..ec036e4469 100644 --- a/src/app/shared/form/builder/ds-dynamic-form-ui/relation-lookup-modal/external-source-tab/dynamic-lookup-relation-external-source-tab.component.ts +++ b/src/app/shared/form/builder/ds-dynamic-form-ui/relation-lookup-modal/external-source-tab/dynamic-lookup-relation-external-source-tab.component.ts @@ -22,8 +22,6 @@ import { hasValue } from '../../../../../empty.util'; import { SelectableListService } from '../../../../../object-list/selectable-list/selectable-list.service'; import { Item } from '../../../../../../core/shared/item.model'; import { Collection } from '../../../../../../core/shared/collection.model'; -import { NotificationsService } from '../../../../../notifications/notifications.service'; -import { TranslateService } from '@ngx-translate/core'; @Component({ selector: 'ds-dynamic-lookup-relation-external-source-tab', @@ -45,6 +43,11 @@ import { TranslateService } from '@ngx-translate/core'; * Shows a list of entries matching the current search query with the option to import them into the repository */ export class DsDynamicLookupRelationExternalSourceTabComponent implements OnInit, OnDestroy { + /** + * The label to use for all messages (added to the end of relevant i18n keys) + */ + @Input() label: string; + /** * The ID of the list of selected entries */ @@ -71,14 +74,9 @@ export class DsDynamicLookupRelationExternalSourceTabComponent implements OnInit @Input() context: Context; /** - * Emit an event when an object has been deselected + * Emit an event when an object has been imported (or selected from similar local entries) */ - @Output() deselectObject: EventEmitter = new EventEmitter(); - - /** - * Emit an event when an object has been selected (or imported) - */ - @Output() selectObject: EventEmitter = new EventEmitter(); + @Output() importedObject: EventEmitter = new EventEmitter(); /** * The initial pagination options @@ -101,9 +99,7 @@ export class DsDynamicLookupRelationExternalSourceTabComponent implements OnInit /** * Config to use for the import buttons */ - importConfig = { - buttonLabel: 'submission.sections.describe.relationship-lookup.external-source.import-button-title' - }; + importConfig; /** * The modal for importing the entry @@ -119,9 +115,7 @@ export class DsDynamicLookupRelationExternalSourceTabComponent implements OnInit public searchConfigService: SearchConfigurationService, private externalSourceService: ExternalSourceService, private modalService: NgbModal, - private selectableListService: SelectableListService, - private notificationsService: NotificationsService, - private translateService: TranslateService) { + private selectableListService: SelectableListService) { } /** @@ -131,7 +125,10 @@ export class DsDynamicLookupRelationExternalSourceTabComponent implements OnInit this.entriesRD$ = this.searchConfigService.paginatedSearchOptions.pipe( switchMap((searchOptions: PaginatedSearchOptions) => this.externalSourceService.getExternalSourceEntries(this.externalSource.id, searchOptions).pipe(startWith(undefined))) - ) + ); + this.importConfig = { + buttonLabel: 'submission.sections.describe.relationship-lookup.external-source.import-button-title.' + this.label + }; } /** @@ -148,10 +145,10 @@ export class DsDynamicLookupRelationExternalSourceTabComponent implements OnInit modalComp.item = this.item; modalComp.collection = this.collection; modalComp.relationship = this.relationship; + modalComp.label = this.label; this.importObjectSub = modalComp.importedObject.subscribe((object) => { this.selectableListService.selectSingle(this.listId, object); - this.notificationsService.success(this.translateService.get('submission.sections.describe.relationship-lookup.external-source.added')); - this.selectObject.emit(object); + this.importedObject.emit(object); }); } diff --git a/src/app/shared/form/builder/ds-dynamic-form-ui/relation-lookup-modal/external-source-tab/external-source-entry-import-modal/external-source-entry-import-modal.component.html b/src/app/shared/form/builder/ds-dynamic-form-ui/relation-lookup-modal/external-source-tab/external-source-entry-import-modal/external-source-entry-import-modal.component.html index ffb3aabde8..b88fea8e41 100644 --- a/src/app/shared/form/builder/ds-dynamic-form-ui/relation-lookup-modal/external-source-tab/external-source-entry-import-modal/external-source-entry-import-modal.component.html +++ b/src/app/shared/form/builder/ds-dynamic-form-ui/relation-lookup-modal/external-source-tab/external-source-entry-import-modal/external-source-entry-import-modal.component.html @@ -1,26 +1,26 @@ diff --git a/src/app/shared/form/builder/ds-dynamic-form-ui/relation-lookup-modal/external-source-tab/external-source-entry-import-modal/external-source-entry-import-modal.component.ts b/src/app/shared/form/builder/ds-dynamic-form-ui/relation-lookup-modal/external-source-tab/external-source-entry-import-modal/external-source-entry-import-modal.component.ts index 2107021d40..8ca8305085 100644 --- a/src/app/shared/form/builder/ds-dynamic-form-ui/relation-lookup-modal/external-source-tab/external-source-entry-import-modal/external-source-entry-import-modal.component.ts +++ b/src/app/shared/form/builder/ds-dynamic-form-ui/relation-lookup-modal/external-source-tab/external-source-entry-import-modal/external-source-entry-import-modal.component.ts @@ -18,6 +18,11 @@ import { ListableObject } from '../../../../../../object-collection/shared/lista import { Collection } from '../../../../../../../core/shared/collection.model'; import { ItemDataService } from '../../../../../../../core/data/item-data.service'; import { PaginationComponentOptions } from '../../../../../../pagination/pagination-component-options.model'; +import { getRemoteDataPayload, getSucceededRemoteData } from '../../../../../../../core/shared/operators'; +import { take } from 'rxjs/operators'; +import { ItemSearchResult } from '../../../../../../object-collection/shared/item-search-result.model'; +import { NotificationsService } from '../../../../../../notifications/notifications.service'; +import { TranslateService } from '@ngx-translate/core'; /** * The possible types of import for the external entry @@ -42,6 +47,16 @@ export enum ImportType { * The other option is to import the external entry as a new entity or authority into the repository. */ export class ExternalSourceEntryImportModalComponent implements OnInit { + /** + * The prefix for every i18n key within this modal + */ + labelPrefix = 'submission.sections.describe.relationship-lookup.external-source.import-modal.'; + + /** + * The label to use for all messages (added to the end of relevant i18n keys) + */ + label: string; + /** * The external source entry */ @@ -130,7 +145,9 @@ export class ExternalSourceEntryImportModalComponent implements OnInit { constructor(public modal: NgbActiveModal, public lookupRelationService: LookupRelationService, private selectService: SelectableListService, - private itemService: ItemDataService) { + private itemService: ItemDataService, + private notificationsService: NotificationsService, + private translateService: TranslateService) { } ngOnInit(): void { @@ -180,6 +197,7 @@ export class ExternalSourceEntryImportModalComponent implements OnInit { */ importLocalEntity() { if (this.selectedEntity !== undefined) { + this.notificationsService.success(this.translateService.get(this.labelPrefix + this.label + '.added.local-entity')); this.importedObject.emit(this.selectedEntity); } } @@ -188,8 +206,17 @@ export class ExternalSourceEntryImportModalComponent implements OnInit { * Create and import a new entity from the external entry */ importNewEntity() { - this.itemService.importExternalSourceEntry(this.externalSourceEntry, this.collectionId).subscribe((response) => { - console.log(response); + this.itemService.importExternalSourceEntry(this.externalSourceEntry, this.collectionId).pipe( + getSucceededRemoteData(), + getRemoteDataPayload(), + take(1) + ).subscribe((item: Item) => { + this.lookupRelationService.removeLocalResultsCache(); + const searchResult = Object.assign(new ItemSearchResult(), { + indexableObject: item + }); + this.notificationsService.success(this.translateService.get(this.labelPrefix + this.label + '.added.new-entity')); + this.importedObject.emit(searchResult); }); } From 9246cce7de62a9287de17be1ca64d449e7a9bd8d Mon Sep 17 00:00:00 2001 From: Kristof De Langhe Date: Fri, 6 Dec 2019 17:54:52 +0100 Subject: [PATCH 07/12] 67611: Test cases --- src/app/core/data/item-data.service.spec.ts | 21 ++++++++ .../core/data/lookup-relation.service.spec.ts | 22 ++++++-- ...tion-external-source-tab.component.spec.ts | 54 ++++++++++++++----- 3 files changed, 82 insertions(+), 15 deletions(-) diff --git a/src/app/core/data/item-data.service.spec.ts b/src/app/core/data/item-data.service.spec.ts index 44c5f48cfe..ebe4cbfc0a 100644 --- a/src/app/core/data/item-data.service.spec.ts +++ b/src/app/core/data/item-data.service.spec.ts @@ -23,6 +23,7 @@ import { HttpClient } from '@angular/common/http'; import { RequestEntry } from './request.reducer'; import { of as observableOf } from 'rxjs'; import { getMockRequestService } from '../../shared/mocks/mock-request.service'; +import { ExternalSourceEntry } from '../shared/external-source-entry.model'; describe('ItemDataService', () => { let scheduler: TestScheduler; @@ -202,4 +203,24 @@ describe('ItemDataService', () => { }); }); + describe('importExternalSourceEntry', () => { + let result; + + const externalSourceEntry = Object.assign(new ExternalSourceEntry(), { + display: 'John, Doe', + value: 'John, Doe', + self: 'http://test-rest.com/server/api/integration/externalSources/orcidV2/entryValues/0000-0003-4851-8004' + }); + + beforeEach(() => { + service = initTestService(); + spyOn(requestService, 'configure'); + result = service.importExternalSourceEntry(externalSourceEntry, 'collection-id'); + }); + + it('should configure a POST request', () => { + result.subscribe(() => expect(requestService.configure).toHaveBeenCalledWith(jasmine.any(PostRequest), undefined)); + }); + }); + }); diff --git a/src/app/core/data/lookup-relation.service.spec.ts b/src/app/core/data/lookup-relation.service.spec.ts index 321fd8d218..e12f81f15f 100644 --- a/src/app/core/data/lookup-relation.service.spec.ts +++ b/src/app/core/data/lookup-relation.service.spec.ts @@ -10,11 +10,14 @@ import { SearchResult } from '../../shared/search/search-result.model'; import { Item } from '../shared/item.model'; import { skip, take } from 'rxjs/operators'; import { ExternalSource } from '../shared/external-source.model'; +import { RequestService } from './request.service'; +import { of as observableOf } from 'rxjs'; -describe('LookupRelationService', () => { +fdescribe('LookupRelationService', () => { let service: LookupRelationService; let externalSourceService: ExternalSourceService; let searchService: SearchService; + let requestService: RequestService; const totalExternal = 8; const optionsWithQuery = new PaginatedSearchOptions({ query: 'test-query' }); @@ -35,15 +38,18 @@ describe('LookupRelationService', () => { name: 'orcidV2', hierarchical: false }); + const searchServiceEndpoint = 'http://test-rest.com/server/api/core/search'; function init() { externalSourceService = jasmine.createSpyObj('externalSourceService', { getExternalSourceEntries: createSuccessfulRemoteDataObject$(new PaginatedList(new PageInfo({ elementsPerPage: 1, totalElements: totalExternal, totalPages: totalExternal, currentPage: 1 }), [{}])) }); searchService = jasmine.createSpyObj('searchService', { - search: createSuccessfulRemoteDataObject$(createPaginatedList(localResults)) + search: createSuccessfulRemoteDataObject$(createPaginatedList(localResults)), + getEndpoint: observableOf(searchServiceEndpoint) }); - service = new LookupRelationService(externalSourceService, searchService); + requestService = jasmine.createSpyObj('requestService', ['removeByHrefSubstring']); + service = new LookupRelationService(externalSourceService, searchService, requestService); } beforeEach(() => { @@ -113,4 +119,14 @@ describe('LookupRelationService', () => { }); }); }); + + describe('removeLocalResultsCache', () => { + beforeEach(() => { + service.removeLocalResultsCache(); + }); + + it('should call requestService\'s removeByHrefSubstring with the search endpoint', () => { + expect(requestService.removeByHrefSubstring).toHaveBeenCalledWith(searchServiceEndpoint); + }); + }); }); diff --git a/src/app/shared/form/builder/ds-dynamic-form-ui/relation-lookup-modal/external-source-tab/dynamic-lookup-relation-external-source-tab.component.spec.ts b/src/app/shared/form/builder/ds-dynamic-form-ui/relation-lookup-modal/external-source-tab/dynamic-lookup-relation-external-source-tab.component.spec.ts index 62327e236e..e35b144372 100644 --- a/src/app/shared/form/builder/ds-dynamic-form-ui/relation-lookup-modal/external-source-tab/dynamic-lookup-relation-external-source-tab.component.spec.ts +++ b/src/app/shared/form/builder/ds-dynamic-form-ui/relation-lookup-modal/external-source-tab/dynamic-lookup-relation-external-source-tab.component.spec.ts @@ -3,7 +3,7 @@ import { async, ComponentFixture, TestBed } from '@angular/core/testing'; import { VarDirective } from '../../../../../utils/var.directive'; import { TranslateModule } from '@ngx-translate/core'; import { RouterTestingModule } from '@angular/router/testing'; -import { NO_ERRORS_SCHEMA } from '@angular/core'; +import { EventEmitter, NO_ERRORS_SCHEMA } from '@angular/core'; import { PaginatedSearchOptions } from '../../../../../search/paginated-search-options.model'; import { SearchConfigurationService } from '../../../../../../core/shared/search/search-configuration.service'; import { of as observableOf } from 'rxjs/internal/observable/of'; @@ -18,12 +18,20 @@ import { ExternalSource } from '../../../../../../core/shared/external-source.mo import { BrowserAnimationsModule } from '@angular/platform-browser/animations'; import { By } from '@angular/platform-browser'; import { ExternalSourceEntry } from '../../../../../../core/shared/external-source-entry.model'; +import { NgbModule } from '@ng-bootstrap/ng-bootstrap'; +import { SelectableListService } from '../../../../../object-list/selectable-list/selectable-list.service'; +import { Item } from '../../../../../../core/shared/item.model'; +import { Collection } from '../../../../../../core/shared/collection.model'; +import { RelationshipOptions } from '../../../models/relationship-options.model'; +import { ExternalSourceEntryImportModalComponent } from './external-source-entry-import-modal/external-source-entry-import-modal.component'; -describe('DsDynamicLookupRelationExternalSourceTabComponent', () => { +fdescribe('DsDynamicLookupRelationExternalSourceTabComponent', () => { let component: DsDynamicLookupRelationExternalSourceTabComponent; let fixture: ComponentFixture; let pSearchOptions; let externalSourceService; + let selectableListService; + let modalService; const externalSource = { id: 'orcidV2', @@ -68,6 +76,10 @@ describe('DsDynamicLookupRelationExternalSourceTabComponent', () => { } }) ] as ExternalSourceEntry[]; + const item = Object.assign(new Item(), { id: 'submission-item' }); + const collection = Object.assign(new Collection(), { id: 'submission-collection' }); + const relationship = Object.assign(new RelationshipOptions(), { relationshipType: 'isAuthorOfPublication' }); + const label = 'Author'; function init() { pSearchOptions = new PaginatedSearchOptions({ @@ -76,20 +88,22 @@ describe('DsDynamicLookupRelationExternalSourceTabComponent', () => { externalSourceService = jasmine.createSpyObj('externalSourceService', { getExternalSourceEntries: createSuccessfulRemoteDataObject$(createPaginatedList(externalEntries)) }); + selectableListService = jasmine.createSpyObj('selectableListService', ['selectSingle']); } beforeEach(async(() => { init(); TestBed.configureTestingModule({ declarations: [DsDynamicLookupRelationExternalSourceTabComponent, VarDirective], - imports: [TranslateModule.forRoot(), RouterTestingModule.withRoutes([]), BrowserAnimationsModule], + imports: [TranslateModule.forRoot(), RouterTestingModule.withRoutes([]), NgbModule.forRoot(), BrowserAnimationsModule], providers: [ { provide: SearchConfigurationService, useValue: { paginatedSearchOptions: observableOf(pSearchOptions) } }, - { provide: ExternalSourceService, useValue: externalSourceService } + { provide: ExternalSourceService, useValue: externalSourceService }, + { provide: SelectableListService, useValue: selectableListService } ], schemas: [NO_ERRORS_SCHEMA] }).compileComponents(); @@ -99,13 +113,18 @@ describe('DsDynamicLookupRelationExternalSourceTabComponent', () => { fixture = TestBed.createComponent(DsDynamicLookupRelationExternalSourceTabComponent); component = fixture.componentInstance; component.externalSource = externalSource; + component.item = item; + component.collection = collection; + component.relationship = relationship; + component.label = label; + modalService = (component as any).modalService; fixture.detectChanges(); }); describe('when the external entries finished loading successfully', () => { it('should display a ds-viewable-collection component', () => { - const collection = fixture.debugElement.query(By.css('ds-viewable-collection')); - expect(collection).toBeDefined(); + const viewableCollection = fixture.debugElement.query(By.css('ds-viewable-collection')); + expect(viewableCollection).toBeDefined(); }); }); @@ -116,8 +135,8 @@ describe('DsDynamicLookupRelationExternalSourceTabComponent', () => { }); it('should not display a ds-viewable-collection component', () => { - const collection = fixture.debugElement.query(By.css('ds-viewable-collection')); - expect(collection).toBeNull(); + const viewableCollection = fixture.debugElement.query(By.css('ds-viewable-collection')); + expect(viewableCollection).toBeNull(); }); it('should display a ds-loading component', () => { @@ -133,8 +152,8 @@ describe('DsDynamicLookupRelationExternalSourceTabComponent', () => { }); it('should not display a ds-viewable-collection component', () => { - const collection = fixture.debugElement.query(By.css('ds-viewable-collection')); - expect(collection).toBeNull(); + const viewableCollection = fixture.debugElement.query(By.css('ds-viewable-collection')); + expect(viewableCollection).toBeNull(); }); it('should display a ds-error component', () => { @@ -150,8 +169,8 @@ describe('DsDynamicLookupRelationExternalSourceTabComponent', () => { }); it('should not display a ds-viewable-collection component', () => { - const collection = fixture.debugElement.query(By.css('ds-viewable-collection')); - expect(collection).toBeNull(); + const viewableCollection = fixture.debugElement.query(By.css('ds-viewable-collection')); + expect(viewableCollection).toBeNull(); }); it('should display a message the list is empty', () => { @@ -159,4 +178,15 @@ describe('DsDynamicLookupRelationExternalSourceTabComponent', () => { expect(empty).not.toBeNull(); }); }); + + describe('import', () => { + beforeEach(() => { + spyOn(modalService, 'open').and.returnValue(Object.assign({ componentInstance: Object.assign({ importedObject: new EventEmitter() }) })); + component.import(externalEntries[0]); + }); + + it('should open a new ExternalSourceEntryImportModalComponent', () => { + expect(modalService.open).toHaveBeenCalledWith(ExternalSourceEntryImportModalComponent, jasmine.any(Object)) + }); + }); }); From 6914000e1971502266bd87480bcd0e4be2d98388 Mon Sep 17 00:00:00 2001 From: Kristof De Langhe Date: Mon, 9 Dec 2019 11:59:55 +0100 Subject: [PATCH 08/12] 67611: Remaining test cases --- .../core/data/lookup-relation.service.spec.ts | 2 +- ...tion-external-source-tab.component.spec.ts | 2 +- ...ource-entry-import-modal.component.spec.ts | 194 ++++++++++++++++++ 3 files changed, 196 insertions(+), 2 deletions(-) diff --git a/src/app/core/data/lookup-relation.service.spec.ts b/src/app/core/data/lookup-relation.service.spec.ts index e12f81f15f..c9fc7fc50d 100644 --- a/src/app/core/data/lookup-relation.service.spec.ts +++ b/src/app/core/data/lookup-relation.service.spec.ts @@ -13,7 +13,7 @@ import { ExternalSource } from '../shared/external-source.model'; import { RequestService } from './request.service'; import { of as observableOf } from 'rxjs'; -fdescribe('LookupRelationService', () => { +describe('LookupRelationService', () => { let service: LookupRelationService; let externalSourceService: ExternalSourceService; let searchService: SearchService; diff --git a/src/app/shared/form/builder/ds-dynamic-form-ui/relation-lookup-modal/external-source-tab/dynamic-lookup-relation-external-source-tab.component.spec.ts b/src/app/shared/form/builder/ds-dynamic-form-ui/relation-lookup-modal/external-source-tab/dynamic-lookup-relation-external-source-tab.component.spec.ts index e35b144372..00242ad9ce 100644 --- a/src/app/shared/form/builder/ds-dynamic-form-ui/relation-lookup-modal/external-source-tab/dynamic-lookup-relation-external-source-tab.component.spec.ts +++ b/src/app/shared/form/builder/ds-dynamic-form-ui/relation-lookup-modal/external-source-tab/dynamic-lookup-relation-external-source-tab.component.spec.ts @@ -25,7 +25,7 @@ import { Collection } from '../../../../../../core/shared/collection.model'; import { RelationshipOptions } from '../../../models/relationship-options.model'; import { ExternalSourceEntryImportModalComponent } from './external-source-entry-import-modal/external-source-entry-import-modal.component'; -fdescribe('DsDynamicLookupRelationExternalSourceTabComponent', () => { +describe('DsDynamicLookupRelationExternalSourceTabComponent', () => { let component: DsDynamicLookupRelationExternalSourceTabComponent; let fixture: ComponentFixture; let pSearchOptions; diff --git a/src/app/shared/form/builder/ds-dynamic-form-ui/relation-lookup-modal/external-source-tab/external-source-entry-import-modal/external-source-entry-import-modal.component.spec.ts b/src/app/shared/form/builder/ds-dynamic-form-ui/relation-lookup-modal/external-source-tab/external-source-entry-import-modal/external-source-entry-import-modal.component.spec.ts index e69de29bb2..5248f95573 100644 --- a/src/app/shared/form/builder/ds-dynamic-form-ui/relation-lookup-modal/external-source-tab/external-source-entry-import-modal/external-source-entry-import-modal.component.spec.ts +++ b/src/app/shared/form/builder/ds-dynamic-form-ui/relation-lookup-modal/external-source-tab/external-source-entry-import-modal/external-source-entry-import-modal.component.spec.ts @@ -0,0 +1,194 @@ +import { ExternalSourceEntryImportModalComponent, ImportType } from './external-source-entry-import-modal.component'; +import { async, ComponentFixture, TestBed } from '@angular/core/testing'; +import { TranslateModule } from '@ngx-translate/core'; +import { RouterTestingModule } from '@angular/router/testing'; +import { NO_ERRORS_SCHEMA } from '@angular/core'; +import { NgbActiveModal, NgbModule } from '@ng-bootstrap/ng-bootstrap'; +import { LookupRelationService } from '../../../../../../../core/data/lookup-relation.service'; +import { ExternalSourceEntry } from '../../../../../../../core/shared/external-source-entry.model'; +import { Item } from '../../../../../../../core/shared/item.model'; +import { ItemSearchResult } from '../../../../../../object-collection/shared/item-search-result.model'; +import { createPaginatedList, createSuccessfulRemoteDataObject$ } from '../../../../../../testing/utils'; +import { Collection } from '../../../../../../../core/shared/collection.model'; +import { RelationshipOptions } from '../../../../models/relationship-options.model'; +import { SelectableListService } from '../../../../../../object-list/selectable-list/selectable-list.service'; +import { ItemDataService } from '../../../../../../../core/data/item-data.service'; +import { NotificationsService } from '../../../../../../notifications/notifications.service'; + +describe('DsDynamicLookupRelationExternalSourceTabComponent', () => { + let component: ExternalSourceEntryImportModalComponent; + let fixture: ComponentFixture; + let lookupRelationService: LookupRelationService; + let selectService: SelectableListService; + let itemService: ItemDataService; + let notificationsService: NotificationsService; + let modalStub: NgbActiveModal; + + const uri = 'https://orcid.org/0001-0001-0001-0001'; + const entry = Object.assign(new ExternalSourceEntry(), { + id: '0001-0001-0001-0001', + display: 'John Doe', + value: 'John, Doe', + metadata: { + 'dc.identifier.uri': [ + { + value: uri + } + ] + } + }); + + const label = 'Author'; + const relationship = Object.assign(new RelationshipOptions(), { relationshipType: 'isAuthorOfPublication' }); + const submissionCollection = Object.assign(new Collection(), { uuid: '9398affe-a977-4992-9a1d-6f00908a259f' }); + const submissionItem = Object.assign(new Item(), { uuid: '26224069-5f99-412a-9e9b-7912a7e35cb1' }); + const item1 = Object.assign(new Item(), { uuid: 'e1c51c69-896d-42dc-8221-1d5f2ad5516e' }); + const item2 = Object.assign(new Item(), { uuid: 'c8279647-1acc-41ae-b036-951d5f65649b' }); + const item3 = Object.assign(new Item(), { uuid: 'c3bcbff5-ec0c-4831-8e4c-94b9c933ccac' }); + const searchResult1 = Object.assign(new ItemSearchResult(), { indexableObject: item1 }); + const searchResult2 = Object.assign(new ItemSearchResult(), { indexableObject: item2 }); + const searchResult3 = Object.assign(new ItemSearchResult(), { indexableObject: item3 }); + const importedItem = Object.assign(new Item(), { uuid: '5d0098fc-344a-4067-a57d-457092b72e82' }); + + function init() { + lookupRelationService = jasmine.createSpyObj('lookupRelationService', { + getLocalResults: createSuccessfulRemoteDataObject$(createPaginatedList([searchResult1, searchResult2, searchResult3])), + removeLocalResultsCache: {} + }); + selectService = jasmine.createSpyObj('selectService', ['deselectAll']); + notificationsService = jasmine.createSpyObj('notificationsService', ['success']); + itemService = jasmine.createSpyObj('itemService', { + importExternalSourceEntry: createSuccessfulRemoteDataObject$(importedItem) + }); + modalStub = jasmine.createSpyObj('modal', ['close']); + } + + beforeEach(async(() => { + init(); + TestBed.configureTestingModule({ + declarations: [ExternalSourceEntryImportModalComponent], + imports: [TranslateModule.forRoot(), RouterTestingModule.withRoutes([]), NgbModule.forRoot()], + providers: [ + { provide: LookupRelationService, useValue: lookupRelationService }, + { provide: SelectableListService, useValue: selectService }, + { provide: NotificationsService, useValue: notificationsService }, + { provide: ItemDataService, useValue: itemService }, + { provide: NgbActiveModal, useValue: modalStub } + ], + schemas: [NO_ERRORS_SCHEMA] + }).compileComponents(); + })); + + beforeEach(() => { + fixture = TestBed.createComponent(ExternalSourceEntryImportModalComponent); + component = fixture.componentInstance; + component.externalSourceEntry = entry; + component.label = label; + component.relationship = relationship; + component.collection = submissionCollection; + component.item = submissionItem; + fixture.detectChanges(); + }); + + describe('close', () => { + beforeEach(() => { + component.close(); + }); + + it('should close the modal', () => { + expect(modalStub.close).toHaveBeenCalled(); + }); + }); + + describe('selectEntity', () => { + const entity = Object.assign(new Item(), { uuid: 'd8698de5-5b05-4ea4-9d02-da73803a50f9' }); + + beforeEach(() => { + component.selectEntity(entity); + }); + + it('should set selected entity', () => { + expect(component.selectedEntity).toBe(entity); + }); + + it('should set the import type to local entity', () => { + expect(component.selectedImportType).toEqual(ImportType.LocalEntity); + }); + }); + + describe('deselectEntity', () => { + const entity = Object.assign(new Item(), { uuid: 'd8698de5-5b05-4ea4-9d02-da73803a50f9' }); + + beforeEach(() => { + component.selectedImportType = ImportType.LocalEntity; + component.selectedEntity = entity; + component.deselectEntity(); + }); + + it('should remove the selected entity', () => { + expect(component.selectedEntity).toBeUndefined(); + }); + + it('should set the import type to none', () => { + expect(component.selectedImportType).toEqual(ImportType.None); + }); + }); + + describe('selectNewEntity', () => { + describe('when current import type is set to new entity', () => { + beforeEach(() => { + component.selectedImportType = ImportType.NewEntity; + component.selectNewEntity(); + }); + + it('should set the import type to none', () => { + expect(component.selectedImportType).toEqual(ImportType.None); + }); + }); + + describe('when current import type is not set to new entity', () => { + beforeEach(() => { + component.selectedImportType = ImportType.None; + component.selectNewEntity(); + }); + + it('should set the import type to new entity', () => { + expect(component.selectedImportType).toEqual(ImportType.NewEntity); + }); + + it('should deselect the entity and authority list', () => { + expect(selectService.deselectAll).toHaveBeenCalledWith(component.entityListId); + expect(selectService.deselectAll).toHaveBeenCalledWith(component.authorityListId); + }); + }); + }); + + describe('selectNewAuthority', () => { + describe('when current import type is set to new authority', () => { + beforeEach(() => { + component.selectedImportType = ImportType.NewAuthority; + component.selectNewAuthority(); + }); + + it('should set the import type to none', () => { + expect(component.selectedImportType).toEqual(ImportType.None); + }); + }); + + describe('when current import type is not set to new authority', () => { + beforeEach(() => { + component.selectedImportType = ImportType.None; + component.selectNewAuthority(); + }); + + it('should set the import type to new authority', () => { + expect(component.selectedImportType).toEqual(ImportType.NewAuthority); + }); + + it('should deselect the entity and authority list', () => { + expect(selectService.deselectAll).toHaveBeenCalledWith(component.entityListId); + expect(selectService.deselectAll).toHaveBeenCalledWith(component.authorityListId); + }); + }); + }); +}); From ea05af74bd05a45ebfc794e2b396c32aa09d2b58 Mon Sep 17 00:00:00 2001 From: Kristof De Langhe Date: Thu, 19 Dec 2019 17:34:13 +0100 Subject: [PATCH 09/12] 67611: Import external source entry window layout changes --- ...rnal-source-entry-import-modal.component.html | 16 +++++++++------- ...ternal-source-entry-import-modal.component.ts | 5 +++++ 2 files changed, 14 insertions(+), 7 deletions(-) diff --git a/src/app/shared/form/builder/ds-dynamic-form-ui/relation-lookup-modal/external-source-tab/external-source-entry-import-modal/external-source-entry-import-modal.component.html b/src/app/shared/form/builder/ds-dynamic-form-ui/relation-lookup-modal/external-source-tab/external-source-entry-import-modal/external-source-entry-import-modal.component.html index b88fea8e41..a4fc356ef9 100644 --- a/src/app/shared/form/builder/ds-dynamic-form-ui/relation-lookup-modal/external-source-tab/external-source-entry-import-modal/external-source-entry-import-modal.component.html +++ b/src/app/shared/form/builder/ds-dynamic-form-ui/relation-lookup-modal/external-source-tab/external-source-entry-import-modal/external-source-entry-import-modal.component.html @@ -13,15 +13,17 @@

{{ (labelPrefix + 'select' | translate) }}

-
-
- - -
-
+
{{ (labelPrefix + 'entities' | translate) }}
+
+
+ + +
+
+ {{ (labelPrefix + 'entities.new' | translate) }}
-
+
{{ (labelPrefix + 'authority' | translate) }}
diff --git a/src/app/shared/form/builder/ds-dynamic-form-ui/relation-lookup-modal/external-source-tab/external-source-entry-import-modal/external-source-entry-import-modal.component.ts b/src/app/shared/form/builder/ds-dynamic-form-ui/relation-lookup-modal/external-source-tab/external-source-entry-import-modal/external-source-entry-import-modal.component.ts index 8ca8305085..7e0fe78717 100644 --- a/src/app/shared/form/builder/ds-dynamic-form-ui/relation-lookup-modal/external-source-tab/external-source-entry-import-modal/external-source-entry-import-modal.component.ts +++ b/src/app/shared/form/builder/ds-dynamic-form-ui/relation-lookup-modal/external-source-tab/external-source-entry-import-modal/external-source-entry-import-modal.component.ts @@ -142,6 +142,11 @@ export class ExternalSourceEntryImportModalComponent implements OnInit { */ importedObject: EventEmitter = new EventEmitter(); + /** + * Should it display the ability to import the entry as an authority? + */ + authorityEnabled = false; + constructor(public modal: NgbActiveModal, public lookupRelationService: LookupRelationService, private selectService: SelectableListService, From b1575b3336398c3af8aff282d05388348e084393 Mon Sep 17 00:00:00 2001 From: Kristof De Langhe Date: Mon, 6 Jan 2020 16:08:43 +0100 Subject: [PATCH 10/12] 67611: Remove redundant test --- .../dynamic-lookup-relation-selection-tab.component.spec.ts | 5 ----- 1 file changed, 5 deletions(-) diff --git a/src/app/shared/form/builder/ds-dynamic-form-ui/relation-lookup-modal/selection-tab/dynamic-lookup-relation-selection-tab.component.spec.ts b/src/app/shared/form/builder/ds-dynamic-form-ui/relation-lookup-modal/selection-tab/dynamic-lookup-relation-selection-tab.component.spec.ts index 203a4df0b0..18e5d3c3ab 100644 --- a/src/app/shared/form/builder/ds-dynamic-form-ui/relation-lookup-modal/selection-tab/dynamic-lookup-relation-selection-tab.component.spec.ts +++ b/src/app/shared/form/builder/ds-dynamic-form-ui/relation-lookup-modal/selection-tab/dynamic-lookup-relation-selection-tab.component.spec.ts @@ -73,11 +73,6 @@ describe('DsDynamicLookupRelationSelectionTabComponent', () => { expect(component).toBeTruthy(); }); - it('should call navigate on the router when is called resetRoute', () => { - component.resetRoute(); - expect(router.navigate).toHaveBeenCalled(); - }); - it('should call navigate on the router when is called resetRoute', () => { component.selectionRD$ = createSelection([]); fixture.detectChanges(); From 9d71f0348bbeb70e8e682dbe5ab478c866d8e822 Mon Sep 17 00:00:00 2001 From: Kristof De Langhe Date: Tue, 14 Jan 2020 13:38:01 +0100 Subject: [PATCH 11/12] 67611: fix test --- src/app/core/data/item-data.service.spec.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/app/core/data/item-data.service.spec.ts b/src/app/core/data/item-data.service.spec.ts index efc82de955..8263601e28 100644 --- a/src/app/core/data/item-data.service.spec.ts +++ b/src/app/core/data/item-data.service.spec.ts @@ -211,7 +211,7 @@ describe('ItemDataService', () => { }); it('should configure a POST request', () => { - result.subscribe(() => expect(requestService.configure).toHaveBeenCalledWith(jasmine.any(PostRequest), undefined)); + result.subscribe(() => expect(requestService.configure).toHaveBeenCalledWith(jasmine.any(PostRequest))); }); }); From 3fd4ecbfc46a4ce4a1afda861f576bab51a34070 Mon Sep 17 00:00:00 2001 From: Kristof De Langhe Date: Thu, 16 Jan 2020 14:47:37 +0100 Subject: [PATCH 12/12] 67611: ExpressionChangedAfterItHasBeenCheckedError fix --- src/app/app.component.ts | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/src/app/app.component.ts b/src/app/app.component.ts index 1f3da086c2..2141b06a77 100644 --- a/src/app/app.component.ts +++ b/src/app/app.component.ts @@ -1,4 +1,4 @@ -import { filter, map, take } from 'rxjs/operators'; +import { delay, filter, map, take } from 'rxjs/operators'; import { AfterViewInit, ChangeDetectionStrategy, Component, HostListener, Inject, OnInit, ViewEncapsulation } from '@angular/core'; import { NavigationCancel, NavigationEnd, NavigationStart, Router } from '@angular/router'; @@ -125,8 +125,11 @@ export class AppComponent implements OnInit, AfterViewInit { } ngAfterViewInit() { - this.router.events - .subscribe((event) => { + this.router.events.pipe( + // This fixes an ExpressionChangedAfterItHasBeenCheckedError from being thrown while loading the component + // More information on this bug-fix: https://blog.angular-university.io/angular-debugging/ + delay(0) + ).subscribe((event) => { if (event instanceof NavigationStart) { this.isLoading = true; } else if (