Skip to content

Commit fb2154f

Browse files
committed
Merge branch 'dspace-cris-2023_02_x' into ux-plus-2023_02_x
# Conflicts: # package.json # yarn.lock
2 parents 3909cfc + d6da45a commit fb2154f

13 files changed

Lines changed: 247 additions & 71 deletions

File tree

package.json

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -100,7 +100,6 @@
100100
"@nicky-lenaers/ngx-scroll-to": "^14.0.0",
101101
"@swimlane/ngx-charts": "^20.4.1",
102102
"@types/googlemaps": "^3.43.3",
103-
"@types/grecaptcha": "^3.0.4",
104103
"@types/leaflet": "^1.9.12",
105104
"angular-idle-preload": "3.0.0",
106105
"angulartics2": "^12.2.1",

src/app/access-control/epeople-registry/eperson-form/eperson-form.component.spec.ts

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import { Observable, of as observableOf } from 'rxjs';
22
import { CommonModule } from '@angular/common';
33
import { CUSTOM_ELEMENTS_SCHEMA } from '@angular/core';
4-
import { ComponentFixture, TestBed, waitForAsync } from '@angular/core/testing';
4+
import { ComponentFixture, fakeAsync, TestBed, tick, waitForAsync } from '@angular/core/testing';
55
import { UntypedFormControl, UntypedFormGroup, FormsModule, ReactiveFormsModule, Validators } from '@angular/forms';
66
import { BrowserModule, By } from '@angular/platform-browser';
77
import { NgbModule } from '@ng-bootstrap/ng-bootstrap';
@@ -30,7 +30,7 @@ import { PaginationServiceStub } from '../../../shared/testing/pagination-servic
3030
import { FindListOptions } from '../../../core/data/find-list-options.model';
3131
import { ValidateEmailNotTaken } from './validators/email-taken.validator';
3232
import { EpersonRegistrationService } from '../../../core/data/eperson-registration.service';
33-
import { FollowLinkConfig } from '../../../shared/utils/follow-link-config.model';
33+
import { followLink, FollowLinkConfig } from '../../../shared/utils/follow-link-config.model';
3434
import { ActivatedRoute, Router } from '@angular/router';
3535
import { RouterStub } from '../../../shared/testing/router.stub';
3636
import { ActivatedRouteStub } from '../../../shared/testing/active-router.stub';
@@ -46,7 +46,7 @@ describe('EPersonFormComponent', () => {
4646
let ePersonDataServiceStub: any;
4747
let authService: AuthServiceStub;
4848
let authorizationService: AuthorizationDataService;
49-
let groupsDataService: GroupDataService;
49+
let groupsDataService: jasmine.SpyObj<GroupDataService>;
5050
let epersonRegistrationService: EpersonRegistrationService;
5151
let route: ActivatedRouteStub;
5252
let router: RouterStub;
@@ -513,4 +513,15 @@ describe('EPersonFormComponent', () => {
513513
expect(epersonRegistrationService.registerEmail).toHaveBeenCalledWith(ePersonEmail, null, 'forgot');
514514
});
515515
});
516+
517+
describe('findListByHref functionality', () => {
518+
it('retrieves groups and object on page change', fakeAsync(() => {
519+
component.activeEPerson$ = observableOf({_links: { groups: { href: 'groups' } } } as EPerson);
520+
521+
const options = { currentPage: 1, elementsPerPage: 5 };
522+
component.onPageChange(options.currentPage);
523+
tick();
524+
expect(groupsDataService.findListByHref).toHaveBeenCalledWith(jasmine.anything(), options, undefined, undefined, followLink('object'));
525+
}));
526+
});
516527
});

src/app/access-control/epeople-registry/eperson-form/eperson-form.component.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -576,7 +576,7 @@ export class EPersonFormComponent implements OnInit, OnDestroy {
576576
*/
577577
private updateGroups(options) {
578578
this.subs.push(this.activeEPerson$.subscribe((eperson: EPerson) => {
579-
this.groups = this.groupsDataService.findListByHref(eperson._links.groups.href, options);
579+
this.groups = this.groupsDataService.findListByHref(eperson._links.groups.href, options, undefined, undefined, followLink('object'));
580580
}));
581581
}
582582
}

src/app/core/shared/metadata.models.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -96,6 +96,10 @@ export interface MetadataValueFilter {
9696

9797
/** Whether the value constraint should match as a substring. */
9898
substring?: boolean;
99+
/**
100+
* Whether to negate the filter
101+
*/
102+
negate?: boolean;
99103
}
100104

101105
export class MetadatumViewModel {

src/app/core/shared/metadata.utils.spec.ts

Lines changed: 1 addition & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import { isUndefined } from '../../shared/empty.util';
22
import { v4 as uuidv4 } from 'uuid';
33
import { MetadataMap, MetadataValue, MetadataValueFilter, MetadatumViewModel } from './metadata.models';
4-
import { Metadata, PLACEHOLDER_VALUE } from './metadata.utils';
4+
import { Metadata } from './metadata.utils';
55

66
const mdValue = (value: string, language?: string, authority?: string): MetadataValue => {
77
return Object.assign(new MetadataValue(), {
@@ -306,21 +306,4 @@ describe('Metadata', () => {
306306
testAllWithLimit(multiMap, 'dc.title', [dcTitle1], 1);
307307
});
308308
});
309-
310-
describe('Placeholder values', () => {
311-
it('should ignore placeholder values in get methods', () => {
312-
const placeholderMd = mdValue(PLACEHOLDER_VALUE);
313-
const key = 'dc.test.placeholder';
314-
const map = { 'dc.test.placeholder': [placeholderMd] };
315-
316-
expect(Metadata.all(map, key).length).toEqual(0);
317-
expect(Metadata.allValues(map, key).length).toEqual(0);
318-
expect(Metadata.has(map, key)).toBeFalsy();
319-
expect(Metadata.first(map, key)).toBeUndefined();
320-
expect(Metadata.firstValue(map, key)).toBeUndefined();
321-
expect(Metadata.hasValue(placeholderMd)).toBeFalsy();
322-
expect(Metadata.valueMatches(placeholderMd, null)).toBeFalsy();
323-
});
324-
});
325-
326309
});

src/app/core/shared/metadata.utils.ts

Lines changed: 10 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -15,8 +15,6 @@ import { validate as uuidValidate } from 'uuid';
1515
export const AUTHORITY_GENERATE = 'will be generated::';
1616
export const AUTHORITY_REFERENCE = 'will be referenced::';
1717
export const PLACEHOLDER_VALUE = '#PLACEHOLDER_PARENT_METADATA_VALUE#';
18-
19-
2018
/**
2119
* Utility class for working with DSpace object metadata.
2220
*
@@ -31,6 +29,7 @@ export const PLACEHOLDER_VALUE = '#PLACEHOLDER_PARENT_METADATA_VALUE#';
3129
* followed by any other (non-dc) metadata values.
3230
*/
3331
export class Metadata {
32+
3433
/**
3534
* Gets all matching metadata in the map(s).
3635
*
@@ -153,11 +152,11 @@ export class Metadata {
153152
* Returns true if this Metadatum's value is defined
154153
*/
155154
public static hasValue(value: MetadataValue|string): boolean {
156-
if (isEmpty(value) || value === PLACEHOLDER_VALUE) {
155+
if (isEmpty(value)) {
157156
return false;
158157
}
159158
if (isObject(value) && value.hasOwnProperty('value')) {
160-
return isNotEmpty(value.value) && value.value !== PLACEHOLDER_VALUE;
159+
return isNotEmpty(value.value);
161160
}
162161
return true;
163162
}
@@ -170,9 +169,7 @@ export class Metadata {
170169
* @returns {boolean} whether the filter matches, or true if no filter is given.
171170
*/
172171
public static valueMatches(mdValue: MetadataValue, filter: MetadataValueFilter) {
173-
if (mdValue.value === PLACEHOLDER_VALUE) {
174-
return false;
175-
} else if (!filter) {
172+
if (!filter) {
176173
return true;
177174
} else if (filter.language && filter.language !== mdValue.language) {
178175
return false;
@@ -181,15 +178,19 @@ export class Metadata {
181178
} else if (filter.value) {
182179
let fValue = filter.value;
183180
let mValue = mdValue.value;
181+
184182
if (filter.ignoreCase) {
185183
fValue = filter.value.toLowerCase();
186184
mValue = mdValue.value.toLowerCase();
187185
}
186+
let result;
187+
188188
if (filter.substring) {
189-
return mValue.includes(fValue);
189+
result = mValue.includes(fValue);
190190
} else {
191-
return mValue === fValue;
191+
result = mValue === fValue;
192192
}
193+
return filter.negate ? !result : result;
193194
}
194195
return true;
195196
}

src/app/dso-shared/dso-edit-metadata/dso-edit-metadata-form.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -424,6 +424,8 @@ export class DsoEditMetadataForm {
424424
value: value.newValue.value,
425425
language: value.newValue.language,
426426
authority: value.newValue.authority,
427+
confidence: value.newValue.confidence,
428+
securityLevel: value.originalValue.securityLevel,
427429
}));
428430
}
429431
// "replace" the security level value
@@ -433,6 +435,7 @@ export class DsoEditMetadataForm {
433435
value: value.newValue.value,
434436
language: value.newValue.language,
435437
authority: value.newValue.authority,
438+
confidence: value.newValue.confidence,
436439
}));
437440
}
438441
} else if (value.change === DsoEditMetadataChangeType.REMOVE) {

src/app/shared/form/builder/ds-dynamic-form-ui/models/onebox/dynamic-onebox.component.spec.ts

Lines changed: 43 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -175,12 +175,12 @@ describe('DsDynamicOneboxComponent test suite', () => {
175175
providers: [
176176
ChangeDetectorRef,
177177
DsDynamicOneboxComponent,
178-
{ provide: VocabularyService, useValue: vocabularyServiceStub },
179-
{ provide: DynamicFormLayoutService, useValue: mockDynamicFormLayoutService },
180-
{ provide: DynamicFormValidationService, useValue: mockDynamicFormValidationService },
181-
{ provide: NgbModal, useValue: modal },
182-
{ provide: FormBuilderService },
183-
{ provide: SubmissionService, useClass: SubmissionServiceStub }
178+
{provide: VocabularyService, useValue: vocabularyServiceStub},
179+
{provide: DynamicFormLayoutService, useValue: mockDynamicFormLayoutService},
180+
{provide: DynamicFormValidationService, useValue: mockDynamicFormValidationService},
181+
{provide: NgbModal, useValue: modal},
182+
{provide: FormBuilderService},
183+
{provide: SubmissionService, useClass: SubmissionServiceStub}
184184
],
185185
schemas: [CUSTOM_ELEMENTS_SCHEMA]
186186
}).compileComponents();
@@ -348,7 +348,7 @@ describe('DsDynamicOneboxComponent test suite', () => {
348348
}));
349349
spyOn((oneboxComponent as any).vocabularyService, 'getVocabularyEntryByValue').and.returnValue(entry);
350350
spyOn((oneboxComponent as any).vocabularyService, 'getVocabularyEntryByID').and.returnValue(entry);
351-
(oneboxComponent.model as any).value = new FormFieldMetadataValueObject('test', null, null,null, 'testDisplay');
351+
(oneboxComponent.model as any).value = new FormFieldMetadataValueObject('test', null, null, null, 'testDisplay');
352352
oneboxCompFixture.detectChanges();
353353
});
354354

@@ -359,7 +359,7 @@ describe('DsDynamicOneboxComponent test suite', () => {
359359

360360
it('should init component properly', fakeAsync(() => {
361361
tick();
362-
expect(oneboxComponent.currentValue).toEqual(new FormFieldMetadataValueObject('test', null, null,null, 'testDisplay'));
362+
expect(oneboxComponent.currentValue).toEqual(new FormFieldMetadataValueObject('test', null, null, null, 'testDisplay'));
363363
expect((oneboxComponent as any).vocabularyService.getVocabularyEntryByValue).not.toHaveBeenCalled();
364364
}));
365365

@@ -396,7 +396,7 @@ describe('DsDynamicOneboxComponent test suite', () => {
396396

397397
it('should init component properly', fakeAsync(() => {
398398
tick();
399-
expect(oneboxComponent.currentValue).toEqual(new FormFieldMetadataValueObject('test', null, null,validAuthority, 'test'));
399+
expect(oneboxComponent.currentValue).toEqual(new FormFieldMetadataValueObject('test', null, null, validAuthority, 'test'));
400400
expect((oneboxComponent as any).vocabularyService.getVocabularyEntryByID).not.toHaveBeenCalled();
401401
}));
402402

@@ -457,7 +457,7 @@ describe('DsDynamicOneboxComponent test suite', () => {
457457
}));
458458
spyOn((oneboxComponent as any).vocabularyService, 'getVocabularyEntryByValue').and.returnValue(entry);
459459
spyOn((oneboxComponent as any).vocabularyService, 'getVocabularyEntryByID').and.returnValue(entry);
460-
(oneboxComponent.model as any).value = new FormFieldMetadataValueObject('test', null, null, null, 'testDisplay');
460+
(oneboxComponent.model as any).value = new FormFieldMetadataValueObject('test', null, null, null, 'testDisplay');
461461
oneboxCompFixture.detectChanges();
462462
});
463463

@@ -468,7 +468,7 @@ describe('DsDynamicOneboxComponent test suite', () => {
468468

469469
it('should init component properly', fakeAsync(() => {
470470
tick();
471-
expect(oneboxComponent.currentValue).toEqual(new FormFieldMetadataValueObject('test', null, null,null, 'testDisplay'));
471+
expect(oneboxComponent.currentValue).toEqual(new FormFieldMetadataValueObject('test', null, null, null, 'testDisplay'));
472472
expect((oneboxComponent as any).vocabularyService.getVocabularyEntryByValue).toHaveBeenCalled();
473473
}));
474474

@@ -517,6 +517,38 @@ describe('DsDynamicOneboxComponent test suite', () => {
517517
}));
518518
});
519519

520+
describe('selectAlternativeInformation', () => {
521+
beforeEach(() => {
522+
oneboxCompFixture = TestBed.createComponent(DsDynamicOneboxComponent);
523+
debugElement = oneboxCompFixture.debugElement;
524+
oneboxComponent = oneboxCompFixture.componentInstance;
525+
oneboxComponent.currentValue = new FormFieldMetadataValueObject('test', null, null, null, 'testDisplay');
526+
oneboxComponent.model = new DynamicOneboxModel(ONEBOX_TEST_MODEL_CONFIG);
527+
528+
spyOn(oneboxComponent, 'onSelectItem').and.returnValue(undefined);
529+
spyOn(oneboxComponent, 'toggleOtherInfoSelection').and.returnValue(undefined);
530+
});
531+
532+
it('sets authority when unformattedOtherInfoValue contains "::"', () => {
533+
const info = 'testInfo';
534+
const unformattedItem = 'testInfo::authorityValue';
535+
oneboxComponent.otherInfoValuesUnformatted = [unformattedItem];
536+
537+
oneboxComponent.selectAlternativeInfo(info);
538+
539+
expect(oneboxComponent.currentValue.authority).toBe('authorityValue');
540+
});
541+
542+
it('sets authority to undefined when unformattedOtherInfoValue does not contain "::"', () => {
543+
const info = 'testInfo';
544+
const unformattedItem = 'testInfo';
545+
oneboxComponent.otherInfoValuesUnformatted = [unformattedItem];
546+
547+
oneboxComponent.selectAlternativeInfo(info);
548+
549+
expect(oneboxComponent.currentValue.authority).toBeUndefined();
550+
});
551+
});
520552
});
521553
});
522554

src/app/shared/form/builder/ds-dynamic-form-ui/models/onebox/dynamic-onebox.component.ts

Lines changed: 22 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,4 @@
1-
import {
2-
ChangeDetectorRef,
3-
Component,
4-
EventEmitter,
5-
Input,
6-
OnInit,
7-
Output,
8-
ViewChild
9-
} from '@angular/core';
1+
import { ChangeDetectorRef, Component, EventEmitter, Input, OnInit, Output, ViewChild } from '@angular/core';
102
import { UntypedFormGroup } from '@angular/forms';
113

124
import {
@@ -373,6 +365,19 @@ export class DsDynamicOneboxComponent extends DsDynamicVocabularyComponent imple
373365
this.currentValue = null;
374366
this.currentValue = temp;
375367

368+
const unformattedOtherInfoValue = this.otherInfoValuesUnformatted.find((unformattedItem) => {
369+
return unformattedItem.startsWith(info);
370+
});
371+
372+
if (hasValue(unformattedOtherInfoValue)) {
373+
const lastIndexOfSeparator = unformattedOtherInfoValue.lastIndexOf('::');
374+
if (lastIndexOfSeparator !== -1) {
375+
this.currentValue.authority = unformattedOtherInfoValue.substring(lastIndexOfSeparator + 2);
376+
} else {
377+
this.currentValue.authority = undefined;
378+
}
379+
}
380+
376381
const event = {
377382
item: this.currentValue
378383
} as any;
@@ -388,7 +393,14 @@ export class DsDynamicOneboxComponent extends DsDynamicVocabularyComponent imple
388393

389394
this.otherInfoKey = hasAlternativeNames ? this.alternativeNamesKey : keys.find(key => hasValue(item.otherInformation[key]) && item.otherInformation[key].includes('|||'));
390395
this.otherInfoValuesUnformatted = item.otherInformation[this.otherInfoKey] ? item.otherInformation[this.otherInfoKey].split('|||') : [];
391-
this.otherInfoValues = this.otherInfoValuesUnformatted.map(unformattedItem => unformattedItem.substring(0, unformattedItem.lastIndexOf('::')));
396+
397+
this.otherInfoValues = this.otherInfoValuesUnformatted.map(unformattedItem => {
398+
let lastIndexOfSeparator = unformattedItem.lastIndexOf('::');
399+
if (lastIndexOfSeparator === -1) {
400+
lastIndexOfSeparator = undefined;
401+
}
402+
return unformattedItem.substring(0, lastIndexOfSeparator);
403+
});
392404

393405
if (hasAlternativeNames) {
394406
this.otherName = hasValue(this.otherName) ? this.otherName : this.otherInfoValues[0];

src/app/shared/object-list/search-result-list-element/item-search-result/item-types/item/item-search-result-list-element.component.html

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -38,15 +38,15 @@
3838
<span *ngIf="dso.firstMetadataValue('dc.date.issued')" class="item-list-date"
3939
[innerHTML]="firstMetadataValue('dc.date.issued')"></span>)
4040
</ng-container>
41-
<span *ngIf="dso.allMetadataValues(authorMetadata).length > 0" class="item-list-authors">
41+
<span *ngIf="dso.allMetadataValues(authorMetadata, placeholderFilter).length > 0" class="item-list-authors">
4242
<ng-container *ngVar="(isCollapsed() | async) as isCollapsed">
4343
<ng-container *ngIf="isCollapsed">
44-
<span *ngFor="let author of dso.limitedMetadata(authorMetadata, additionalMetadataLimit); let i=index; let last=last;">
44+
<span *ngFor="let author of dso.limitedMetadata(authorMetadata, additionalMetadataLimit, placeholderFilter); let i=index; let last=last;">
4545
<ds-metadata-link-view [item]="dso" [metadata]="author" [metadataName]="authorMetadata"></ds-metadata-link-view><span *ngIf="!last">; </span>
4646
</span>
4747
</ng-container>
4848
<ng-container *ngIf="!isCollapsed">
49-
<span *ngFor="let author of dso.allMetadata(authorMetadata); let i=index; let last=last;">
49+
<span *ngFor="let author of dso.allMetadata(authorMetadata, placeholderFilter); let i=index; let last=last;">
5050
<ds-metadata-link-view [item]="dso" [metadata]="author" [metadataName]="authorMetadata"></ds-metadata-link-view><span *ngIf="!last">; </span>
5151
</span>
5252
</ng-container>

0 commit comments

Comments
 (0)