Skip to content

Commit 33b59c7

Browse files
YanaDePauwalexandrevryghem
authored andcommitted
115284: Fix issue with same type relationships
1 parent 227d471 commit 33b59c7

18 files changed

Lines changed: 425 additions & 40 deletions

src/app/item-page/edit-item-page/edit-item-page.module.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,9 @@ import { ResultsBackButtonModule } from '../../shared/results-back-button/result
4646
import {
4747
AccessControlFormModule
4848
} from '../../shared/access-control-form-container/access-control-form.module';
49+
import {
50+
EditRelationshipListWrapperComponent
51+
} from './item-relationships/edit-relationship-list-wrapper/edit-relationship-list-wrapper.component';
4952

5053
/**
5154
* Module that contains all components related to the Edit Item page administrator functionality
@@ -94,6 +97,7 @@ import {
9497
ItemRegisterDoiComponent,
9598
ItemCurateComponent,
9699
ItemAccessControlComponent,
100+
EditRelationshipListWrapperComponent,
97101
],
98102
providers: [
99103
BundleDataService,

src/app/item-page/edit-item-page/item-relationships/edit-item-relationships.service.spec.ts

Lines changed: 89 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -265,6 +265,95 @@ describe('EditItemRelationshipsService', () => {
265265
});
266266
});
267267

268+
describe('isProvidedItemTypeLeftType', () => {
269+
it('should return true if the provided item corresponds to the left type of the relationship', (done) => {
270+
const relationshipType = Object.assign(new RelationshipType(), {
271+
leftType: createSuccessfulRemoteDataObject$({id: 'leftType'}),
272+
rightType: createSuccessfulRemoteDataObject$({id: 'rightType'}),
273+
});
274+
const itemType = Object.assign(new ItemType(), {id: 'leftType'} );
275+
const item = Object.assign(new Item(), {uuid: 'item-uuid'});
276+
277+
const result = service.isProvidedItemTypeLeftType(relationshipType, itemType, item);
278+
result.subscribe((resultValue) => {
279+
expect(resultValue).toBeTrue();
280+
done();
281+
});
282+
});
283+
284+
it('should return false if the provided item corresponds to the right type of the relationship', (done) => {
285+
const relationshipType = Object.assign(new RelationshipType(), {
286+
leftType: createSuccessfulRemoteDataObject$({id: 'leftType'}),
287+
rightType: createSuccessfulRemoteDataObject$({id: 'rightType'}),
288+
});
289+
const itemType = Object.assign(new ItemType(), {id: 'rightType'} );
290+
const item = Object.assign(new Item(), {uuid: 'item-uuid'});
291+
292+
const result = service.isProvidedItemTypeLeftType(relationshipType, itemType, item);
293+
result.subscribe((resultValue) => {
294+
expect(resultValue).toBeFalse();
295+
done();
296+
});
297+
});
298+
299+
it('should return undefined if the provided item corresponds does not match any of the relationship types', (done) => {
300+
const relationshipType = Object.assign(new RelationshipType(), {
301+
leftType: createSuccessfulRemoteDataObject$({id: 'leftType'}),
302+
rightType: createSuccessfulRemoteDataObject$({id: 'rightType'}),
303+
});
304+
const itemType = Object.assign(new ItemType(), {id: 'something-else'} );
305+
const item = Object.assign(new Item(), {uuid: 'item-uuid'});
306+
307+
const result = service.isProvidedItemTypeLeftType(relationshipType, itemType, item);
308+
result.subscribe((resultValue) => {
309+
expect(resultValue).toBeUndefined();
310+
done();
311+
});
312+
});
313+
});
314+
315+
describe('relationshipMatchesBothSameTypes', () => {
316+
it('should return true if both left and right type of the relationship type are the same and match the provided itemtype', (done) => {
317+
const relationshipType = Object.assign(new RelationshipType(), {
318+
leftType: createSuccessfulRemoteDataObject$({id: 'sameType'}),
319+
rightType: createSuccessfulRemoteDataObject$({id:'sameType'}),
320+
});
321+
const itemType = Object.assign(new ItemType(), {id: 'sameType'} );
322+
323+
const result = service.relationshipMatchesBothSameTypes(relationshipType, itemType);
324+
result.subscribe((resultValue) => {
325+
expect(resultValue).toBeTrue();
326+
done();
327+
});
328+
});
329+
it('should return false if both left and right type of the relationship type are the same and do not match the provided itemtype', (done) => {
330+
const relationshipType = Object.assign(new RelationshipType(), {
331+
leftType: createSuccessfulRemoteDataObject$({id: 'sameType'}),
332+
rightType: createSuccessfulRemoteDataObject$({id: 'sameType'}),
333+
});
334+
const itemType = Object.assign(new ItemType(), {id: 'something-else'} );
335+
336+
const result = service.relationshipMatchesBothSameTypes(relationshipType, itemType);
337+
result.subscribe((resultValue) => {
338+
expect(resultValue).toBeFalse();
339+
done();
340+
});
341+
});
342+
it('should return false if both left and right type of the relationship type are different', (done) => {
343+
const relationshipType = Object.assign(new RelationshipType(), {
344+
leftType: createSuccessfulRemoteDataObject$({id: 'leftType'}),
345+
rightType: createSuccessfulRemoteDataObject$({id: 'rightType'}),
346+
});
347+
const itemType = Object.assign(new ItemType(), {id: 'leftType'} );
348+
349+
const result = service.relationshipMatchesBothSameTypes(relationshipType, itemType);
350+
result.subscribe((resultValue) => {
351+
expect(resultValue).toBeFalse();
352+
done();
353+
});
354+
});
355+
});
356+
268357
describe('displayNotifications', () => {
269358
it('should show one success notification when multiple requests succeeded', () => {
270359
service.displayNotifications([

src/app/item-page/edit-item-page/item-relationships/edit-item-relationships.service.ts

Lines changed: 47 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ import {
1010
} from '../../../core/data/object-updates/object-updates.reducer';
1111
import { RemoteData } from '../../../core/data/remote-data';
1212
import { Relationship } from '../../../core/shared/item-relationships/relationship.model';
13-
import { EMPTY, Observable, BehaviorSubject, Subscription } from 'rxjs';
13+
import { EMPTY, Observable, BehaviorSubject, Subscription, combineLatest as observableCombineLatest } from 'rxjs';
1414
import { ObjectUpdatesService } from '../../../core/data/object-updates/object-updates.service';
1515
import { ItemDataService } from '../../../core/data/item-data.service';
1616
import { Item } from '../../../core/shared/item.model';
@@ -20,6 +20,9 @@ import { NgbModal } from '@ng-bootstrap/ng-bootstrap';
2020
import { RelationshipDataService } from '../../../core/data/relationship-data.service';
2121
import { EntityTypeDataService } from '../../../core/data/entity-type-data.service';
2222
import { TranslateService } from '@ngx-translate/core';
23+
import { ItemType } from '../../../core/shared/item-relationships/item-type.model';
24+
import { getFirstSucceededRemoteData, getRemoteDataPayload } from '../../../core/shared/operators';
25+
import { RelationshipType } from '../../../core/shared/item-relationships/relationship-type.model';
2326

2427
@Injectable({
2528
providedIn: 'root'
@@ -169,6 +172,49 @@ export class EditItemRelationshipsService {
169172
}
170173
}
171174

175+
isProvidedItemTypeLeftType(relationshipType: RelationshipType, itemType: ItemType, item: Item): Observable<boolean> {
176+
return this.getRelationshipLeftAndRightType(relationshipType).pipe(
177+
map(([leftType, rightType]: [ItemType, ItemType]) => {
178+
if (leftType.id === itemType.id) {
179+
return true;
180+
}
181+
182+
if (rightType.id === itemType.id) {
183+
return false;
184+
}
185+
186+
// should never happen...
187+
console.warn(`The item ${item.uuid} is not on the right or the left side of relationship type ${relationshipType.uuid}`);
188+
return undefined;
189+
})
190+
);
191+
}
192+
193+
relationshipMatchesBothSameTypes(relationshipType: RelationshipType, itemType: ItemType): Observable<boolean> {
194+
return this.getRelationshipLeftAndRightType(relationshipType).pipe(
195+
map(([leftType, rightType]: [ItemType, ItemType]) => {
196+
return leftType.id === itemType.id && rightType.id === itemType.id;
197+
})
198+
);
199+
}
200+
201+
protected getRelationshipLeftAndRightType(relationshipType: RelationshipType): Observable<[ItemType, ItemType]> {
202+
const leftType$: Observable<ItemType> = relationshipType.leftType.pipe(
203+
getFirstSucceededRemoteData(),
204+
getRemoteDataPayload(),
205+
);
206+
207+
const rightType$: Observable<ItemType> = relationshipType.rightType.pipe(
208+
getFirstSucceededRemoteData(),
209+
getRemoteDataPayload(),
210+
);
211+
212+
return observableCombineLatest([
213+
leftType$,
214+
rightType$,
215+
]);
216+
}
217+
172218

173219

174220
/**
@@ -185,6 +231,5 @@ export class EditItemRelationshipsService {
185231
*/
186232
getNotificationContent(key: string): string {
187233
return this.translateService.instant(this.notificationsPrefix + key + '.content');
188-
189234
}
190235
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
<ng-container *ngIf="bothItemsMatchType$ | async">
2+
<ds-edit-relationship-list
3+
[url]="url"
4+
[item]="item"
5+
[itemType]="itemType"
6+
[relationshipType]="relationshipType"
7+
[hasChanges]="hasChanges"
8+
[currentItemIsLeftItem$]="isLeftItem$"
9+
></ds-edit-relationship-list>
10+
<ds-edit-relationship-list
11+
[url]="url"
12+
[item]="item"
13+
[itemType]="itemType"
14+
[relationshipType]="relationshipType"
15+
[hasChanges]="hasChanges"
16+
[currentItemIsLeftItem$]="isRightItem$"
17+
></ds-edit-relationship-list>
18+
</ng-container>
19+
20+
<ng-container *ngIf="!(bothItemsMatchType$ | async)">
21+
<ds-edit-relationship-list
22+
[url]="url"
23+
[item]="item"
24+
[itemType]="itemType"
25+
[relationshipType]="relationshipType"
26+
[hasChanges]="hasChanges"
27+
[currentItemIsLeftItem$]="currentItemIsLeftItem$"
28+
></ds-edit-relationship-list>
29+
</ng-container>
30+

src/app/item-page/edit-item-page/item-relationships/edit-relationship-list-wrapper/edit-relationship-list-wrapper.component.scss

Whitespace-only changes.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,108 @@
1+
import { ChangeDetectorRef, CUSTOM_ELEMENTS_SCHEMA } from '@angular/core';
2+
import { ComponentFixture, TestBed, waitForAsync } from '@angular/core/testing';
3+
import { of as observableOf } from 'rxjs';
4+
import { EditRelationshipListWrapperComponent } from './edit-relationship-list-wrapper.component';
5+
import { EditItemRelationshipsService } from '../edit-item-relationships.service';
6+
import { By } from '@angular/platform-browser';
7+
import { RelationshipType } from '../../../../core/shared/item-relationships/relationship-type.model';
8+
import { createSuccessfulRemoteDataObject$ } from '../../../../shared/remote-data.utils';
9+
import { ItemType } from '../../../../core/shared/item-relationships/item-type.model';
10+
import { Item } from '../../../../core/shared/item.model';
11+
12+
describe('EditRelationshipListWrapperComponent', () => {
13+
let editItemRelationshipsService: EditItemRelationshipsService;
14+
let comp: EditRelationshipListWrapperComponent;
15+
let fixture: ComponentFixture<EditRelationshipListWrapperComponent>;
16+
17+
const leftType = Object.assign(new ItemType(), {id: 'leftType', label: 'leftTypeString'});
18+
const rightType = Object.assign(new ItemType(), {id: 'rightType', label: 'rightTypeString'});
19+
20+
const relationshipType = Object.assign(new RelationshipType(), {
21+
id: '1',
22+
leftMaxCardinality: null,
23+
leftMinCardinality: 0,
24+
leftType: createSuccessfulRemoteDataObject$(leftType),
25+
leftwardType: 'isOrgUnitOfOrgUnit',
26+
rightMaxCardinality: null,
27+
rightMinCardinality: 0,
28+
rightType: createSuccessfulRemoteDataObject$(rightType),
29+
rightwardType: 'isOrgUnitOfOrgUnit',
30+
uuid: 'relationshiptype-1',
31+
});
32+
33+
const item = Object.assign(new Item(), {uuid: 'item-uuid'});
34+
35+
beforeEach(waitForAsync(() => {
36+
37+
editItemRelationshipsService = jasmine.createSpyObj('editItemRelationshipsService', {
38+
isProvidedItemTypeLeftType: observableOf(true),
39+
relationshipMatchesBothSameTypes: observableOf(false)
40+
});
41+
42+
43+
TestBed.configureTestingModule({
44+
// imports: [NoopAnimationsModule, SharedModule, TranslateModule.forRoot()],
45+
declarations: [EditRelationshipListWrapperComponent],
46+
providers: [
47+
{provide: EditItemRelationshipsService, useValue: editItemRelationshipsService},
48+
ChangeDetectorRef
49+
], schemas: [
50+
CUSTOM_ELEMENTS_SCHEMA
51+
]
52+
}).compileComponents();
53+
54+
}));
55+
56+
beforeEach(() => {
57+
fixture = TestBed.createComponent(EditRelationshipListWrapperComponent);
58+
comp = fixture.componentInstance;
59+
comp.relationshipType = relationshipType;
60+
comp.itemType = leftType;
61+
comp.item = item;
62+
63+
fixture.detectChanges();
64+
});
65+
66+
describe('onInit', () => {
67+
it('should render the component', () => {
68+
expect(comp).toBeTruthy();
69+
});
70+
it('should set currentItemIsLeftItem$ and bothItemsMatchType$ based on the provided relationshipType, itemType and item', () => {
71+
expect(editItemRelationshipsService.isProvidedItemTypeLeftType).toHaveBeenCalledWith(relationshipType, leftType, item);
72+
expect(editItemRelationshipsService.relationshipMatchesBothSameTypes).toHaveBeenCalledWith(relationshipType, leftType);
73+
74+
expect(comp.currentItemIsLeftItem$.getValue()).toEqual(true);
75+
expect(comp.bothItemsMatchType$.getValue()).toEqual(false);
76+
});
77+
});
78+
79+
describe('when the current item is left', () => {
80+
it('should render one relationship list section', () => {
81+
const relationshipLists = fixture.debugElement.queryAll(By.css('ds-edit-relationship-list'));
82+
expect(relationshipLists.length).toEqual(1);
83+
});
84+
});
85+
86+
describe('when the current item is right', () => {
87+
it('should render one relationship list section', () => {
88+
(editItemRelationshipsService.isProvidedItemTypeLeftType as jasmine.Spy).and.returnValue(observableOf(false));
89+
comp.ngOnInit();
90+
fixture.detectChanges();
91+
92+
const relationshipLists = fixture.debugElement.queryAll(By.css('ds-edit-relationship-list'));
93+
expect(relationshipLists.length).toEqual(1);
94+
});
95+
});
96+
97+
describe('when the current item is both left and right', () => {
98+
it('should render two relationship list sections', () => {
99+
(editItemRelationshipsService.relationshipMatchesBothSameTypes as jasmine.Spy).and.returnValue(observableOf(true));
100+
comp.ngOnInit();
101+
fixture.detectChanges();
102+
103+
const relationshipLists = fixture.debugElement.queryAll(By.css('ds-edit-relationship-list'));
104+
expect(relationshipLists.length).toEqual(2);
105+
});
106+
});
107+
108+
});

0 commit comments

Comments
 (0)