From df80c33e4e86d49c603d79d934c5aa19e125c404 Mon Sep 17 00:00:00 2001 From: Alexandre Vryghem Date: Fri, 17 May 2024 14:34:24 +0200 Subject: [PATCH] 115046: Fixed multiple edit relationship bugs - Fixed issue making it impossible to add new relationships until the page is refreshed after deleting an existing one (only when you refreshed the page after creating the initial relationship) - Fixed NPE in DsDynamicLookupRelationModalComponent - Grouped buttons on relationship page in order to assure that they always have the same behaviour --- .../abstract-item-update.component.ts | 11 ++- .../item-bitstreams.component.html | 16 ++-- .../edit-item-relationships.service.spec.ts | 2 - .../item-relationships.component.html | 82 +++++++++---------- .../item-relationships.component.spec.ts | 11 ++- .../item-relationships.component.ts | 13 ++- ...namic-lookup-relation-modal.component.html | 2 +- ...dynamic-lookup-relation-modal.component.ts | 7 +- ...ic-lookup-relation-search-tab.component.ts | 6 +- ...ic-lookup-relation-search-tab.component.ts | 4 +- ...lookup-relation-selection-tab.component.ts | 6 +- src/assets/i18n/en.json5 | 2 + 12 files changed, 86 insertions(+), 76 deletions(-) diff --git a/src/app/item-page/edit-item-page/abstract-item-update/abstract-item-update.component.ts b/src/app/item-page/edit-item-page/abstract-item-update/abstract-item-update.component.ts index 77c3fdaafb..69b234fbaf 100644 --- a/src/app/item-page/edit-item-page/abstract-item-update/abstract-item-update.component.ts +++ b/src/app/item-page/edit-item-page/abstract-item-update/abstract-item-update.component.ts @@ -55,6 +55,10 @@ export class AbstractItemUpdateComponent extends AbstractTrackableComponent impl */ updates$: Observable; + hasChanges$: Observable; + + isReinstatable$: Observable; + /** * Route to the item's page */ @@ -101,10 +105,9 @@ export class AbstractItemUpdateComponent extends AbstractTrackableComponent impl } this.discardTimeOut = environment.item.edit.undoTimeout; - this.url = this.router.url; - if (this.url.indexOf('?') > 0) { - this.url = this.url.substr(0, this.url.indexOf('?')); - } + this.url = this.router.url.split('?')[0]; + this.hasChanges$ = this.hasChanges(); + this.isReinstatable$ = this.isReinstatable(); this.hasChanges().pipe(first()).subscribe((hasChanges) => { if (!hasChanges) { this.initializeOriginalFields(); diff --git a/src/app/item-page/edit-item-page/item-bitstreams/item-bitstreams.component.html b/src/app/item-page/edit-item-page/item-bitstreams/item-bitstreams.component.html index bb0c3e3760..88d984c19f 100644 --- a/src/app/item-page/edit-item-page/item-bitstreams/item-bitstreams.component.html +++ b/src/app/item-page/edit-item-page/item-bitstreams/item-bitstreams.component.html @@ -6,21 +6,21 @@ class="fas fa-upload">  {{"item.edit.bitstreams.upload-button" | translate}} - - - - - - - + +
+
@@ -26,36 +10,46 @@ [item]="item" [itemType]="entityType" [relationshipType]="relationshipType" - [hasChanges]="hasChanges()" + [hasChanges]="hasChanges$" >
- - -
-
- - - +
+
-
+ + + + {{ 'item.edit.relationships.no-entity-type' | translate }} + + + + + + + + +
+ + + +
+
diff --git a/src/app/item-page/edit-item-page/item-relationships/item-relationships.component.spec.ts b/src/app/item-page/edit-item-page/item-relationships/item-relationships.component.spec.ts index 05dade88ba..28380b3f27 100644 --- a/src/app/item-page/edit-item-page/item-relationships/item-relationships.component.spec.ts +++ b/src/app/item-page/edit-item-page/item-relationships/item-relationships.component.spec.ts @@ -13,12 +13,10 @@ import { Router, } from '@angular/router'; import { TranslateModule } from '@ngx-translate/core'; -import { getTestScheduler } from 'jasmine-marbles'; import { combineLatest as observableCombineLatest, of as observableOf, } from 'rxjs'; -import { TestScheduler } from 'rxjs/testing'; import { ObjectCacheService } from '../../../core/cache/object-cache.service'; import { RestResponse } from '../../../core/cache/response.models'; @@ -33,6 +31,7 @@ import { Item } from '../../../core/shared/item.model'; import { ItemType } from '../../../core/shared/item-relationships/item-type.model'; import { Relationship } from '../../../core/shared/item-relationships/relationship.model'; import { RelationshipType } from '../../../core/shared/item-relationships/relationship-type.model'; +import { AlertComponent } from '../../../shared/alert/alert.component'; import { getMockThemeService } from '../../../shared/mocks/theme-service.mock'; import { INotification, @@ -78,7 +77,6 @@ let itemService: ItemDataServiceStub; const url = 'http://test-url.com/test-url'; router.url = url; -let scheduler: TestScheduler; let item; let author1; let author2; @@ -226,7 +224,6 @@ describe('ItemRelationshipsComponent', () => { }, ); - scheduler = getTestScheduler(); TestBed.configureTestingModule({ imports: [TranslateModule.forRoot(), ItemRelationshipsComponent], providers: [ @@ -245,6 +242,12 @@ describe('ItemRelationshipsComponent', () => { ], schemas: [ NO_ERRORS_SCHEMA, ], + }).overrideComponent(ItemRelationshipsComponent, { + remove: { + imports: [ + AlertComponent, + ], + }, }).compileComponents(); })); diff --git a/src/app/item-page/edit-item-page/item-relationships/item-relationships.component.ts b/src/app/item-page/edit-item-page/item-relationships/item-relationships.component.ts index 2539c3a37d..051c4db136 100644 --- a/src/app/item-page/edit-item-page/item-relationships/item-relationships.component.ts +++ b/src/app/item-page/edit-item-page/item-relationships/item-relationships.component.ts @@ -2,6 +2,7 @@ import { AsyncPipe, NgForOf, NgIf, + NgTemplateOutlet, } from '@angular/common'; import { ChangeDetectorRef, @@ -39,6 +40,8 @@ import { getFirstSucceededRemoteData, getRemoteDataPayload, } from '../../../core/shared/operators'; +import { AlertComponent } from '../../../shared/alert/alert.component'; +import { AlertType } from '../../../shared/alert/alert-type'; import { ThemedLoadingComponent } from '../../../shared/loading/themed-loading.component'; import { NotificationsService } from '../../../shared/notifications/notifications.service'; import { followLink } from '../../../shared/utils/follow-link-config.model'; @@ -53,12 +56,14 @@ import { EditRelationshipListComponent } from './edit-relationship-list/edit-rel styleUrls: ['./item-relationships.component.scss'], templateUrl: './item-relationships.component.html', imports: [ - ThemedLoadingComponent, + AlertComponent, AsyncPipe, - TranslateModule, - NgIf, EditRelationshipListComponent, NgForOf, + NgIf, + NgTemplateOutlet, + ThemedLoadingComponent, + TranslateModule, VarDirective, ], standalone: true, @@ -83,6 +88,8 @@ export class ItemRelationshipsComponent extends AbstractItemUpdateComponent { return this.editItemRelationshipsService.isSaving$; } + readonly AlertType = AlertType; + constructor( public itemService: ItemDataService, public objectUpdatesService: ObjectUpdatesService, 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 111e2d9994..112175d806 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 @@ -32,7 +32,7 @@
  • - {{'submission.sections.describe.relationship-lookup.search-tab.tab-title.' + source.id | translate : { count: (totalExternal$ | async)[idx] } }} + {{'submission.sections.describe.relationship-lookup.search-tab.tab-title.' + source.id | translate : { count: (totalExternal$ | async)?.[idx] } }} []) { + select(...selectableObjects: SearchResult[]) { this.zone.runOutsideAngular( () => { const obs: Observable = observableCombineLatest([...selectableObjects.map((sri: SearchResult) => { @@ -326,11 +327,11 @@ export class DsDynamicLookupRelationModalComponent implements OnInit, OnDestroy * Deselect (a list of) objects and remove them from the store * @param selectableObjects */ - deselect(...selectableObjects: SearchResult[]) { + deselect(...selectableObjects: SearchResult[]) { this.zone.runOutsideAngular( () => selectableObjects.forEach((object) => { this.subMap[object.indexableObject.uuid].unsubscribe(); - this.store.dispatch(new RemoveRelationshipAction(this.item, object.indexableObject, this.relationshipOptions.relationshipType, this.submissionId)); + this.store.dispatch(new RemoveRelationshipAction(this.item, object.indexableObject as Item, this.relationshipOptions.relationshipType, this.submissionId)); }), ); } 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 06b4946e12..e2654d079d 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 @@ -132,12 +132,12 @@ export class DsDynamicLookupRelationSearchTabComponent implements OnInit, OnDest /** * Send an event to deselect an object from the list */ - @Output() deselectObject: EventEmitter = new EventEmitter(); + @Output() deselectObject: EventEmitter> = new EventEmitter(); /** * Send an event to select an object from the list */ - @Output() selectObject: EventEmitter = new EventEmitter(); + @Output() selectObject: EventEmitter> = new EventEmitter(); /** * Search results @@ -214,7 +214,7 @@ export class DsDynamicLookupRelationSearchTabComponent implements OnInit, OnDest this.selection$ .pipe(take(1)) .subscribe((selection: SearchResult[]) => { - const filteredPage = page.filter((pageItem) => selection.findIndex((selected) => selected.equals(pageItem)) < 0); + const filteredPage: SearchResult[] = page.filter((pageItem: SearchResult) => selection.findIndex((selected: SearchResult) => selected.equals(pageItem)) < 0); this.selectObject.emit(...filteredPage); }); this.selectableListService.select(this.listId, page); diff --git a/src/app/shared/form/builder/ds-dynamic-form-ui/relation-lookup-modal/search-tab/themed-dynamic-lookup-relation-search-tab.component.ts b/src/app/shared/form/builder/ds-dynamic-form-ui/relation-lookup-modal/search-tab/themed-dynamic-lookup-relation-search-tab.component.ts index 71d55e6494..756fee2017 100644 --- a/src/app/shared/form/builder/ds-dynamic-form-ui/relation-lookup-modal/search-tab/themed-dynamic-lookup-relation-search-tab.component.ts +++ b/src/app/shared/form/builder/ds-dynamic-form-ui/relation-lookup-modal/search-tab/themed-dynamic-lookup-relation-search-tab.component.ts @@ -51,9 +51,9 @@ export class ThemedDynamicLookupRelationSearchTabComponent extends ThemedCompone @Input() isEditRelationship: boolean; - @Output() deselectObject: EventEmitter = new EventEmitter(); + @Output() deselectObject: EventEmitter> = new EventEmitter(); - @Output() selectObject: EventEmitter = new EventEmitter(); + @Output() selectObject: EventEmitter> = new EventEmitter(); @Output() resultFound: EventEmitter> = new EventEmitter(); 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 d1e516513b..01cf844e06 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,6 +24,7 @@ import { import { RemoteData } from '../../../../../../core/data/remote-data'; import { PaginationService } from '../../../../../../core/pagination/pagination.service'; import { Context } from '../../../../../../core/shared/context.model'; +import { DSpaceObject } from '../../../../../../core/shared/dspace-object.model'; import { PageInfo } from '../../../../../../core/shared/page-info.model'; import { SearchConfigurationService } from '../../../../../../core/shared/search/search-configuration.service'; import { SEARCH_CONFIG_SERVICE } from '../../../../../../my-dspace-page/my-dspace-configuration.service'; @@ -33,6 +34,7 @@ import { PageSizeSelectorComponent } from '../../../../../page-size-selector/pag import { PaginationComponentOptions } from '../../../../../pagination/pagination-component-options.model'; import { createSuccessfulRemoteDataObject } from '../../../../../remote-data.utils'; import { PaginatedSearchOptions } from '../../../../../search/models/paginated-search-options.model'; +import { SearchResult } from '../../../../../search/models/search-result.model'; @Component({ selector: 'ds-dynamic-lookup-relation-selection-tab', @@ -91,12 +93,12 @@ export class DsDynamicLookupRelationSelectionTabComponent { /** * Send an event to deselect an object from the list */ - @Output() deselectObject: EventEmitter = new EventEmitter(); + @Output() deselectObject: EventEmitter> = new EventEmitter(); /** * Send an event to select an object from the list */ - @Output() selectObject: EventEmitter = new EventEmitter(); + @Output() selectObject: EventEmitter> = new EventEmitter(); /** * The initial pagination to use diff --git a/src/assets/i18n/en.json5 b/src/assets/i18n/en.json5 index a9529900c2..7a9b87cb4b 100644 --- a/src/assets/i18n/en.json5 +++ b/src/assets/i18n/en.json5 @@ -3664,6 +3664,8 @@ "orgunit.page.ror": "ROR Identifier", + "orgunit.search.results.head": "Organizational Unit Search Results", + "pagination.options.description": "Pagination options", "pagination.results-per-page": "Results Per Page",