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..e8e3c695c3 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 @@ -4,6 +4,9 @@ import { ExternalSourceEntry } from '../../shared/external-source-entry.model'; import { mapsTo } from '../builders/build-decorators'; import { MetadataMap, MetadataMapSerializer } from '../../shared/metadata.models'; +/** + * Normalized model class for an external source entry + */ @mapsTo(ExternalSourceEntry) @inheritSerialization(NormalizedObject) export class NormalizedExternalSourceEntry extends NormalizedObject { diff --git a/src/app/core/cache/models/normalized-external-source.model.ts b/src/app/core/cache/models/normalized-external-source.model.ts index dbcaeaf0de..fd9a42fb72 100644 --- a/src/app/core/cache/models/normalized-external-source.model.ts +++ b/src/app/core/cache/models/normalized-external-source.model.ts @@ -3,6 +3,9 @@ import { NormalizedObject } from './normalized-object.model'; import { ExternalSource } from '../../shared/external-source.model'; import { mapsTo } from '../builders/build-decorators'; +/** + * Normalized model class for an external source + */ @mapsTo(ExternalSource) @inheritSerialization(NormalizedObject) export class NormalizedExternalSource extends NormalizedObject { diff --git a/src/app/core/data/external-source.service.ts b/src/app/core/data/external-source.service.ts index 2ef1fa3d0e..c32c13a20f 100644 --- a/src/app/core/data/external-source.service.ts +++ b/src/app/core/data/external-source.service.ts @@ -21,6 +21,9 @@ import { PaginatedList } from './paginated-list'; import { ExternalSourceEntry } from '../shared/external-source-entry.model'; import { DefaultChangeAnalyzer } from './default-change-analyzer.service'; +/** + * A service handling all external source requests + */ @Injectable() export class ExternalSourceService extends DataService { protected linkPath = 'externalsources'; @@ -38,6 +41,11 @@ export class ExternalSourceService extends DataService { super(); } + /** + * Get the endpoint to browse external sources + * @param options + * @param linkPath + */ getBrowseEndpoint(options: FindListOptions = {}, linkPath: string = this.linkPath): Observable { return this.halService.getEndpoint(linkPath); } diff --git a/src/app/core/data/relationship.service.ts b/src/app/core/data/relationship.service.ts index 978eb3aa5f..4dfae732f4 100644 --- a/src/app/core/data/relationship.service.ts +++ b/src/app/core/data/relationship.service.ts @@ -288,24 +288,51 @@ export class RelationshipService extends DataService { ); } + /** + * Set a name variant for item with ID "itemID" part of list with ID "listID" + * @param listID ID of the list the item is a part of + * @param itemID ID of the item + * @param nameVariant A name variant for the item + */ public setNameVariant(listID: string, itemID: string, nameVariant: string) { this.appStore.dispatch(new SetNameVariantAction(listID, itemID, nameVariant)); } + /** + * Get the name variant for item with ID "itemID" part of list with ID "listID" + * @param listID ID of the list the item is a part of + * @param itemID ID of the item + */ public getNameVariant(listID: string, itemID: string): Observable { return this.appStore.pipe( select(relationshipStateSelector(listID, itemID)) ); } + /** + * Remove the name variant for item with ID "itemID" part of list with ID "listID" + * @param listID ID of the list the item is a part of + * @param itemID ID of the item + */ public removeNameVariant(listID: string, itemID: string) { this.appStore.dispatch(new RemoveNameVariantAction(listID, itemID)); } + /** + * Get the name variants of all items part of list with ID "listID" + * @param listID ID of the list the items are a part of + */ public getNameVariantsByListID(listID: string) { return this.appStore.pipe(select(relationshipListStateSelector(listID))); } + /** + * Get the relationship between two items with a name variant for the item on the opposite side of the relationship-label + * @param item1 Related item + * @param item2 Other related item + * @param relationshipLabel The label describing the relationship between the two items + * @param nameVariant The name variant to give the item on the opposite side of the relationship-label + */ public updateNameVariant(item1: Item, item2: Item, relationshipLabel: string, nameVariant: string): Observable> { return this.getRelationshipByItemsAndLabel(item1, item2, relationshipLabel) .pipe( diff --git a/src/app/core/services/route.service.ts b/src/app/core/services/route.service.ts index 8bca76f7d2..762d546705 100644 --- a/src/app/core/services/route.service.ts +++ b/src/app/core/services/route.service.ts @@ -187,14 +187,27 @@ export class RouteService { ); } + /** + * Add a parameter to the current route + * @param key The parameter name + * @param value The parameter value + */ public addParameter(key, value) { this.store.dispatch(new AddParameterAction(key, value)); } + /** + * Set a parameter in the current route (overriding the previous value) + * @param key The parameter name + * @param value The parameter value + */ public setParameter(key, value) { this.store.dispatch(new SetParameterAction(key, value)); } + /** + * Get the current query and route parameters and add them + */ public setCurrentRouteInfo() { combineLatest(this.getRouteParams(), this.route.queryParams) .pipe(take(1)) diff --git a/src/app/core/utilities/equatable.ts b/src/app/core/utilities/equatable.ts index 1029a295ba..ce327c5cc3 100644 --- a/src/app/core/utilities/equatable.ts +++ b/src/app/core/utilities/equatable.ts @@ -1,6 +1,12 @@ import { getExcludedFromEqualsFor, getFieldsForEquals } from './equals.decorators'; import { hasNoValue, hasValue } from '../../shared/empty.util'; +/** + * Compare two objects by comparing a given list of their properties + * @param object1 The first object + * @param object2 The second object + * @param fieldList A list of fields to compare the two objects by + */ function equalsByFields(object1, object2, fieldList): boolean { const unequalProperty = fieldList.find((key) => { if (object1[key] === object2[key]) { @@ -27,6 +33,9 @@ function equalsByFields(object1, object2, fieldList): boolean { return hasNoValue(unequalProperty); } +/** + * An object with a defined equals method + */ export abstract class EquatableObject { equals(other: T): boolean { if (hasNoValue(other)) { 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..c0512b4995 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 @@ -13,6 +13,9 @@ import { MetadataValue } from '../../../../../core/shared/metadata.models'; styleUrls: ['./external-source-entry-list-submission-element.component.scss'], templateUrl: './external-source-entry-list-submission-element.component.html' }) +/** + * The component for displaying a list element of an external source entry + */ export class ExternalSourceEntryListSubmissionElementComponent extends AbstractListableElementComponent implements OnInit { /** * The metadata value for the object's uri diff --git a/src/app/entity-groups/research-entities/submission/name-variant-modal/name-variant-modal.component.ts b/src/app/entity-groups/research-entities/submission/name-variant-modal/name-variant-modal.component.ts index 34eab47b47..3b5d8077cc 100644 --- a/src/app/entity-groups/research-entities/submission/name-variant-modal/name-variant-modal.component.ts +++ b/src/app/entity-groups/research-entities/submission/name-variant-modal/name-variant-modal.component.ts @@ -6,7 +6,13 @@ import { NgbActiveModal } from '@ng-bootstrap/ng-bootstrap'; templateUrl: './name-variant-modal.component.html', styleUrls: ['./name-variant-modal.component.scss'] }) +/** + * The component for the modal to add a name variant to an item + */ export class NameVariantModalComponent { + /** + * The name variant + */ @Input() value: string; constructor(public modal: NgbActiveModal) { diff --git a/src/app/shared/form/builder/ds-dynamic-form-ui/models/disabled/dynamic-disabled.component.ts b/src/app/shared/form/builder/ds-dynamic-form-ui/models/disabled/dynamic-disabled.component.ts index 173509acf9..cb4db189e1 100644 --- a/src/app/shared/form/builder/ds-dynamic-form-ui/models/disabled/dynamic-disabled.component.ts +++ b/src/app/shared/form/builder/ds-dynamic-form-ui/models/disabled/dynamic-disabled.component.ts @@ -9,6 +9,9 @@ import { RelationshipTypeService } from '../../../../../../core/data/relationshi selector: 'ds-dynamic-disabled', templateUrl: './dynamic-disabled.component.html' }) +/** + * Component for displaying a form input with a disabled property + */ export class DsDynamicDisabledComponent extends DynamicFormControlComponent { @Input() formId: string; 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 39f3e12bb9..c03d025530 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 @@ -41,16 +41,53 @@ import { ExternalSourceService } from '../../../../../core/data/external-source. } ] }) - +/** + * Modal component for looking up relations + */ export class DsDynamicLookupRelationModalComponent implements OnInit, OnDestroy { + /** + * The label to use to display i18n messages (describing the type of relationship) + */ label: string; + + /** + * Options for searching related items + */ relationshipOptions: RelationshipOptions; + + /** + * The ID of the list to add/remove selected items to/from + */ listId: string; + + /** + * The item we're adding relationships to + */ item; + + /** + * Is the selection repeatable? + */ repeatable: boolean; + + /** + * The list of selected items + */ selection$: Observable; + + /** + * The context to display lists + */ context: Context; + + /** + * The metadata-fields describing these relationships + */ metadataFields: string; + + /** + * A map of subscriptions within this component + */ subMap: { [uuid: string]: Subscription } = {}; @@ -104,6 +141,10 @@ export class DsDynamicLookupRelationModalComponent implements OnInit, OnDestroy this.modal.close(); } + /** + * Select (a list of) objects and add them to the store + * @param selectableObjects + */ select(...selectableObjects: Array>) { this.zone.runOutsideAngular( () => { @@ -131,6 +172,10 @@ export class DsDynamicLookupRelationModalComponent implements OnInit, OnDestroy }); } + /** + * Add a subscription updating relationships with name variants + * @param sri The search result to track name variants for + */ private addNameVariantSubscription(sri: SearchResult) { const nameVariant$ = this.relationshipService.getNameVariant(this.listId, sri.indexableObject.uuid); this.subMap[sri.indexableObject.uuid] = nameVariant$.pipe( @@ -138,6 +183,10 @@ export class DsDynamicLookupRelationModalComponent implements OnInit, OnDestroy ).subscribe((nameVariant: string) => this.store.dispatch(new UpdateRelationshipAction(this.item, sri.indexableObject, this.relationshipOptions.relationshipType, nameVariant))) } + /** + * Deselect (a list of) objects and remove them from the store + * @param selectableObjects + */ deselect(...selectableObjects: Array>) { this.zone.runOutsideAngular( () => selectableObjects.forEach((object) => { @@ -147,6 +196,9 @@ export class DsDynamicLookupRelationModalComponent implements OnInit, OnDestroy ); } + /** + * Set existing name variants for items by the item's virtual metadata + */ private setExistingNameVariants() { const virtualMDs: MetadataValue[] = this.item.allMetadata(this.metadataFields).filter((mdValue) => mdValue.isVirtual); 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 a8332dd3a1..d1fa538de3 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 @@ -30,15 +30,43 @@ import { PaginationComponentOptions } from '../../../../../pagination/pagination fadeInOut ] }) - +/** + * The tab displaying a list of importable entries for an external source + */ export class DsDynamicLookupRelationExternalSourceTabComponent implements OnInit { + /** + * The label to use to display i18n messages (describing the type of relationship) + */ @Input() label: string; + + /** + * The ID of the list to add/remove selected items to/from + */ @Input() listId: string; + + /** + * Is the selection repeatable? + */ @Input() repeatable: boolean; + + /** + * The context to display lists + */ @Input() context: Context; + + /** + * Send an event to deselect an object from the list + */ @Output() deselectObject: EventEmitter = new EventEmitter(); + + /** + * Send an event to select an object from the list + */ @Output() selectObject: EventEmitter = new EventEmitter(); + /** + * The initial pagination to start with + */ initialPagination = Object.assign(new PaginationComponentOptions(), { id: 'submission-external-source-relation-list', pageSize: 5 diff --git a/src/app/shared/form/builder/ds-dynamic-form-ui/relation-lookup-modal/search-tab/dynamic-lookup-relation-search-tab.component.ts b/src/app/shared/form/builder/ds-dynamic-form-ui/relation-lookup-modal/search-tab/dynamic-lookup-relation-search-tab.component.ts index fb2884cb37..1c4a8793b1 100644 --- a/src/app/shared/form/builder/ds-dynamic-form-ui/relation-lookup-modal/search-tab/dynamic-lookup-relation-search-tab.component.ts +++ b/src/app/shared/form/builder/ds-dynamic-form-ui/relation-lookup-modal/search-tab/dynamic-lookup-relation-search-tab.component.ts @@ -33,25 +33,81 @@ import { LookupRelationService } from '../../../../../../core/data/lookup-relati } ] }) - +/** + * Tab for browsing local entities to add to the selection + */ export class DsDynamicLookupRelationSearchTabComponent implements OnInit, OnDestroy { + /** + * Options for searching related items + */ @Input() relationship: RelationshipOptions; + + /** + * The ID of the list to add/remove selected items to/from + */ @Input() listId: string; + + /** + * Is the selection repeatable? + */ @Input() repeatable: boolean; + + /** + * The list of selected items + */ @Input() selection$: Observable; + + /** + * The context to display lists + */ @Input() context: Context; + /** + * Send an event to deselect an object from the list + */ @Output() deselectObject: EventEmitter = new EventEmitter(); + + /** + * Send an event to select an object from the list + */ @Output() selectObject: EventEmitter = new EventEmitter(); + + /** + * Search results + */ resultsRD$: Observable>>>; + + /** + * Are all results selected? + */ allSelected: boolean; + + /** + * Are some results selected? + */ someSelected$: Observable; + + /** + * Is it currently loading to select all results? + */ selectAllLoading: boolean; + + /** + * Subscription to unsubscribe from + */ subscription; + + /** + * The initial pagination to use + */ initialPagination = Object.assign(new PaginationComponentOptions(), { id: 'submission-relation-list', pageSize: 5 }); + + /** + * The type of links to display + */ linkTypes = CollectionElementLinkType; constructor( @@ -76,12 +132,19 @@ export class DsDynamicLookupRelationSearchTabComponent implements OnInit, OnDest ); } + /** + * Reset the route parameters + */ resetRoute() { this.router.navigate([], { queryParams: Object.assign({}, { pageSize: this.initialPagination.pageSize }, this.route.snapshot.queryParams, { page: 1 }) }); } + /** + * Select all results within the page provided + * @param page + */ selectPage(page: Array>) { this.selection$ .pipe(take(1)) @@ -92,6 +155,10 @@ export class DsDynamicLookupRelationSearchTabComponent implements OnInit, OnDest this.selectableListService.select(this.listId, page); } + /** + * Deselect all results within the page provided + * @param page + */ deselectPage(page: Array>) { this.allSelected = false; this.selection$ @@ -103,6 +170,9 @@ export class DsDynamicLookupRelationSearchTabComponent implements OnInit, OnDest this.selectableListService.deselect(this.listId, page); } + /** + * Select all results + */ selectAll() { this.allSelected = true; this.selectAllLoading = true; @@ -128,6 +198,9 @@ export class DsDynamicLookupRelationSearchTabComponent implements OnInit, OnDest ); } + /** + * Deselect all + */ deselectAll() { this.allSelected = false; this.selection$ diff --git a/src/app/shared/form/builder/ds-dynamic-form-ui/relation-lookup-modal/selection-tab/dynamic-lookup-relation-selection-tab.component.ts b/src/app/shared/form/builder/ds-dynamic-form-ui/relation-lookup-modal/selection-tab/dynamic-lookup-relation-selection-tab.component.ts index 3dcde9ea8e..076887b01e 100644 --- a/src/app/shared/form/builder/ds-dynamic-form-ui/relation-lookup-modal/selection-tab/dynamic-lookup-relation-selection-tab.component.ts +++ b/src/app/shared/form/builder/ds-dynamic-form-ui/relation-lookup-modal/selection-tab/dynamic-lookup-relation-selection-tab.component.ts @@ -24,15 +24,48 @@ import { Context } from '../../../../../../core/shared/context.model'; } ] }) - +/** + * Tab displaying the currently selected relations to add + */ export class DsDynamicLookupRelationSelectionTabComponent { + /** + * The label to use to display i18n messages (describing the type of relationship) + */ @Input() label: string; + + /** + * The ID of the list to add/remove selected items to/from + */ @Input() listId: string; + + /** + * Is the selection repeatable? + */ @Input() repeatable: boolean; + + /** + * The list of selected items + */ @Input() selection$: Observable; + + /** + * The paginated list of selected items + */ @Input() selectionRD$: Observable>>; + + /** + * The context to display lists + */ @Input() context: Context; + + /** + * Send an event to deselect an object from the list + */ @Output() deselectObject: EventEmitter = new EventEmitter(); + + /** + * Send an event to select an object from the list + */ @Output() selectObject: EventEmitter = new EventEmitter(); constructor(private router: Router, diff --git a/src/app/shared/form/builder/models/relationship-options.model.ts b/src/app/shared/form/builder/models/relationship-options.model.ts index 7d9542794b..57c6cbca2c 100644 --- a/src/app/shared/form/builder/models/relationship-options.model.ts +++ b/src/app/shared/form/builder/models/relationship-options.model.ts @@ -1,5 +1,8 @@ const RELATION_METADATA_PREFIX = 'relation.' +/** + * Extra options for displaying search results of relationships + */ export class RelationshipOptions { relationshipType: string; filter: string;