Skip to content

Commit d8501ae

Browse files
Merged dspace-cris-2023_02_x into DSC-1111-latest-version-maintenance
2 parents 304a49e + a77762a commit d8501ae

24 files changed

Lines changed: 282 additions & 103 deletions

File tree

cypress/e2e/search-navbar.cy.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ const page = {
1515
}
1616
};
1717

18-
xdescribe('Search from Navigation Bar', () => {
18+
describe('Search from Navigation Bar', () => {
1919
// NOTE: these tests currently assume this query will return results!
2020
const query = TEST_SEARCH_TERM;
2121

src/app/admin/admin-edit-user-agreement/admin-edit-user-agreement.component.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -72,7 +72,7 @@ export class AdminEditUserAgreementComponent implements OnInit, OnDestroy {
7272
this.subs.push(this.siteService.patch(this.site, operations).pipe(
7373
getFirstCompletedRemoteData(),
7474
).subscribe((restResponse) => {
75-
if (restResponse.isSuccess) {
75+
if (restResponse.hasSucceeded) {
7676
this.notificationsService.success(this.translateService.get('admin.edit-user-agreement.success'));
7777
if ( result === 'edit-with-reset' ) {
7878
this.deleteAllUserAgreementMetadataValues();

src/app/core/browse/search-manager.ts

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ import { map, switchMap } from 'rxjs/operators';
44
import { PaginatedList } from '../data/paginated-list.model';
55
import { RemoteData } from '../data/remote-data';
66
import { Item } from '../shared/item.model';
7-
import { getFirstSucceededRemoteData } from '../shared/operators';
7+
import { getFirstCompletedRemoteData } from '../shared/operators';
88
import { BrowseEntrySearchOptions } from './browse-entry-search-options.model';
99
import { FollowLinkConfig } from '../../shared/utils/follow-link-config.model';
1010
import { ItemDataService } from '../data/item-data.service';
@@ -107,8 +107,16 @@ export class SearchManager {
107107
.filter((item) => hasValue(item));
108108

109109
const uuidList = this.extractUUID(items, environment.followAuthorityMetadata);
110-
111-
return uuidList.length > 0 ? this.itemService.findAllById(uuidList).pipe(getFirstSucceededRemoteData()) : of(null);
110+
return uuidList.length > 0 ? this.itemService.findAllById(uuidList).pipe(
111+
getFirstCompletedRemoteData(),
112+
map(data => {
113+
if (data.hasSucceeded) {
114+
return of(data);
115+
} else {
116+
of(null);
117+
}
118+
})
119+
) : of(null);
112120
}
113121

114122
protected extractUUID(items: Item[], metadataToFollow: FollowAuthorityMetadata[]): string[] {

src/app/cris-layout/cris-layout-matrix/cris-layout-box-container/boxes/metadata/rendering-types/advanced-attachment/bitstream-attachment/bitstream-attachment.component.html

Lines changed: 11 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -22,13 +22,19 @@
2222
<div class="order-lg-2 w-100 mb-3">
2323
<ng-container *ngFor="let attachmentConf of envMetadata">
2424

25-
<div class="content" [attr.data-test]="attachmentConf.name"
26-
*ngIf="attachment.firstMetadataValue(attachmentConf.name) || attachmentConf.type == AdvancedAttachmentElementType.Attribute">
25+
<div class="content"
26+
[attr.data-test]="attachmentConf.name"
27+
*ngIf="attachment.firstMetadataValue(attachmentConf.name) || attachmentConf.type == AdvancedAttachmentElementType.Attribute"
28+
>
2729
<strong>{{ 'cris-layout.advanced-attachment.'+attachmentConf.name | translate }}</strong>
2830

2931
<ng-container *ngIf="attachmentConf.type == AdvancedAttachmentElementType.Metadata">
3032

31-
<p class="text-break m-0" *ngIf="!attachmentConf.truncatable">
33+
<p class="text-break m-0" *ngIf="!attachmentConf.truncatable && attachmentConf.name === attachmentTypeMetadata">
34+
{{attachment.firstMetadataValue(attachmentConf.name) | titlecase}}
35+
</p>
36+
37+
<p class="text-break m-0" *ngIf="!attachmentConf.truncatable && attachmentConf.name !== attachmentTypeMetadata">
3238
{{attachment.firstMetadataValue(attachmentConf.name)}}
3339
</p>
3440

@@ -42,7 +48,7 @@
4248

4349
<ng-container *ngIf="attachmentConf.type == AdvancedAttachmentElementType.Attribute">
4450
<ng-container *ngIf="attachmentConf.name == 'format'">
45-
<p *ngIf="!(getFormat(attachment) | async) "class="text-muted">
51+
<p *ngIf="!(getFormat(attachment) | async) " class="text-muted">
4652
{{'cris-layout.advanced-attachment.label.not-present' | translate}}
4753
</p>
4854
<p class="word-break m-0">{{getFormat(attachment) | async}}</p>
@@ -53,7 +59,7 @@
5359
</ng-container>
5460

5561
<ng-container *ngIf="attachmentConf.name == 'checksum'">
56-
<p *ngIf="!(getChecksum(attachment)?.value) "class="text-muted">
62+
<p *ngIf="!(getChecksum(attachment)?.value) " class="text-muted">
5763
{{'cris-layout.advanced-attachment.label.not-present' | translate}}
5864
</p>
5965
<p class="word-break m-0">({{getChecksum(attachment).checkSumAlgorithm}}):{{ getChecksum(attachment).value }}</p>

src/app/cris-layout/cris-layout-matrix/cris-layout-box-container/boxes/metadata/rendering-types/advanced-attachment/bitstream-attachment/bitstream-attachment.component.ts

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,12 @@ export class BitstreamAttachmentComponent extends BitstreamRenderingModelCompone
3434
*/
3535
allAttachmentProviders: string[] = [];
3636

37+
/**
38+
* Attachment metadata to be displayed in title case
39+
*/
40+
41+
attachmentTypeMetadata = 'dc.type';
42+
3743
@Input()
3844
attachment: Bitstream;
3945

src/app/cris-layout/cris-layout-matrix/cris-layout-box-container/boxes/metadata/rendering-types/attachment/attachment.component.html

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
<div *ngFor="let attachment of (bitstreams$ | async)" class="mb-2">
33
<ds-truncatable [id]="attachment.id">
44
<ds-file-download-link [bitstream]="attachment" [enableRequestACopy]="true" [item]="item" [showIcon]="true">
5-
<span data-test="title" *ngIf="fileName(attachment)"><span data-test="type" *ngIf="getType(attachment)" class="font-weight-bold">{{getType(attachment)}}: </span>{{fileName(attachment)}} ({{getSize(attachment) | dsFileSize}})</span>
5+
<span data-test="title" *ngIf="fileName(attachment)"><span data-test="type" *ngIf="getType(attachment)" class="font-weight-bold">{{getType(attachment) | titlecase}}: </span>{{fileName(attachment)}} ({{getSize(attachment) | dsFileSize}})</span>
66
</ds-file-download-link>
77
<ds-truncatable-part [id]="attachment.id" [minLines]="1">
88
<span *ngIf="getDescription(attachment)" data-test="description">{{getDescription(attachment)}}</span>
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,3 @@
11
<h2 class="mb-3">{{ 'info.end-user-agreement.head' | translate }}</h2>
22

3-
<ds-markdown-viewer [value]="userAgreementText$ | async"></ds-markdown-viewer>
3+
<ds-markdown-viewer [value]="(userAgreementText$ | async)"></ds-markdown-viewer>

src/app/item-page/edit-item-page/edit-item-page.component.html

Lines changed: 16 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -4,20 +4,22 @@
44
<h2 class="border-bottom">{{'item.edit.head' | translate}}</h2>
55
<div class="pt-2">
66
<ul class="nav nav-tabs justify-content-start" role="tablist">
7-
<li *ngFor="let page of pages" class="nav-item" [attr.aria-selected]="page.page === currentPage" role="tab">
8-
<a *ngIf="(page.enabled | async)"
9-
class="nav-link"
10-
[ngClass]="{'active' : page.page === currentPage}"
11-
[routerLink]="['./' + page.page]">
12-
{{'item.edit.tabs.' + page.page + '.head' | translate}}
13-
</a>
14-
<span [ngbTooltip]="'item.edit.tabs.disabled.tooltip' | translate">
15-
<button *ngIf="!(page.enabled | async)"
16-
class="nav-link disabled">
17-
{{'item.edit.tabs.' + page.page + '.head' | translate}}
18-
</button>
19-
</span>
20-
</li>
7+
<ng-container *ngFor="let page of pages">
8+
<li *ngIf="page.page != 'relationships'" [attr.aria-selected]="page.page === currentPage" role="tab" class="nav-item">
9+
<a *ngIf="(page.enabled | async)"
10+
class="nav-link"
11+
[ngClass]="{'active' : page.page === currentPage}"
12+
[routerLink]="['./' + page.page]">
13+
{{'item.edit.tabs.' + page.page + '.head' | translate}}
14+
</a>
15+
<span [ngbTooltip]="'item.edit.tabs.disabled.tooltip' | translate">
16+
<button *ngIf="!(page.enabled | async)"
17+
class="nav-link disabled">
18+
{{'item.edit.tabs.' + page.page + '.head' | translate}}
19+
</button>
20+
</span>
21+
</li>
22+
</ng-container>
2123
</ul>
2224
<div class="tab-pane active">
2325
<div class="mb-4">
Lines changed: 35 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -1,43 +1,44 @@
11
<div [formGroup]="group" class="input-group">
22

3-
<input ngbDatepicker class="form-control date-input" #datepicker="ngbDatepicker"
4-
[attr.aria-labelledby]="'label_' + model.id"
5-
[class.is-invalid]="showErrorMessages"
6-
[displayMonths]="model.getAdditional('displayMonths', config['displayMonths'])"
7-
[id]="id"
8-
[firstDayOfWeek]="model.getAdditional('firstDayOfWeek', config['firstDayOfWeek'])"
9-
[formControlName]="model.id"
10-
[maxDate]="model.max"
11-
[minDate]="model.min"
12-
[name]="model.name"
13-
[navigation]="model.getAdditional('navigation', config['navigation'])"
14-
[ngClass]="getClass('element', 'control')"
15-
[outsideDays]="model.getAdditional('outsideDays', config['outsideDays'])"
16-
[placeholder]="model.placeholder"
17-
[placement]="model.getAdditional('placement', 'bottom-left')"
18-
[weekdays]="model.getAdditional('showWeekdays', config['showWeekdays'])"
19-
[showWeekNumbers]="model.getAdditional('showWeekNumbers', config['showWeekNumbers'])"
20-
[startDate]="model.focusedDate"
21-
[value]="getInitDate()"
22-
(blur)="onBlur($event)"
23-
(dateSelect)="onChange($event)"
24-
(change)="onChange($event)"
25-
(focus)="onFocus($event)">
3+
<input ngbDatepicker class="form-control date-input" #datepicker="ngbDatepicker"
4+
[attr.aria-labelledby]="'label_' + model.id"
5+
[class.is-invalid]="showErrorMessages"
6+
[displayMonths]="model.getAdditional('displayMonths', config['displayMonths'])"
7+
[id]="id"
8+
[firstDayOfWeek]="model.getAdditional('firstDayOfWeek', config['firstDayOfWeek'])"
9+
[formControlName]="model.id"
10+
[maxDate]="model.max"
11+
[minDate]="model.min"
12+
[name]="model.name"
13+
[navigation]="model.getAdditional('navigation', config['navigation'])"
14+
[ngClass]="getClass('element', 'control')"
15+
[outsideDays]="model.getAdditional('outsideDays', config['outsideDays'])"
16+
[placeholder]="model.placeholder"
17+
[placement]="model.getAdditional('placement', 'bottom-left')"
18+
[weekdays]="model.getAdditional('showWeekdays', config['showWeekdays'])"
19+
[showWeekNumbers]="model.getAdditional('showWeekNumbers', config['showWeekNumbers'])"
20+
[startDate]="model.focusedDate"
21+
[value]="formattedDate"
22+
(blur)="onBlur($event)"
23+
(dateSelect)="onChange($event)"
24+
(change)="onChange($event)"
25+
(focus)="onFocus($event)"
26+
>
2627

27-
<div class="input-group-append">
28+
<div class="input-group-append">
2829

29-
<button class="btn btn-outline-secondary"
30-
type="button"
31-
[attr.aria-labelledby]="'label_' + model.id"
32-
[class.disabled]="model.disabled"
33-
[disabled]="model.disabled"
34-
(click)="datepicker.toggle()">
30+
<button class="btn btn-outline-secondary"
31+
type="button"
32+
[attr.aria-labelledby]="'label_' + model.id"
33+
[class.disabled]="model.disabled"
34+
[disabled]="model.disabled"
35+
(click)="datepicker.toggle()">
3536

36-
<i *ngIf="model.toggleIcon" class="{{model.toggleIcon}}" aria-hidden="true"></i>
37-
<span *ngIf="model.toggleLabel">{{ model.toggleLabel }}</span>
37+
<i *ngIf="model.toggleIcon" class="{{model.toggleIcon}}" aria-hidden="true"></i>
38+
<span *ngIf="model.toggleLabel">{{ model.toggleLabel }}</span>
3839

39-
</button>
40+
</button>
4041

41-
</div>
42+
</div>
4243

4344
</div>

src/app/shared/form/builder/ds-dynamic-form-ui/models/date-picker-inline/dynamic-date-picker-inline.component.ts

Lines changed: 40 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { Component, EventEmitter, Input, Output, ViewChild } from '@angular/core';
1+
import { Component, EventEmitter, Input, OnDestroy, OnInit, Output, ViewChild } from '@angular/core';
22
import { UntypedFormGroup } from '@angular/forms';
33
import { NgbDateParserFormatter, NgbDatepicker, NgbDatepickerConfig, NgbDateStruct } from '@ng-bootstrap/ng-bootstrap';
44
import {
@@ -8,13 +8,16 @@ import {
88
DynamicFormLayoutService,
99
DynamicFormValidationService
1010
} from '@ng-dynamic-forms/core';
11+
import { FormFieldMetadataValueObject } from '../../../models/form-field-metadata-value.model';
12+
import { hasValue } from '../../../../../empty.util';
13+
import { Subscription } from 'rxjs';
1114

1215
@Component({
1316
selector: 'ds-dynamic-date-picker-inline',
1417
styleUrls: ['./dynamic-date-picker-inline.component.scss'],
1518
templateUrl: './dynamic-date-picker-inline.component.html'
1619
})
17-
export class DsDatePickerInlineComponent extends DynamicFormControlComponent {
20+
export class DsDatePickerInlineComponent extends DynamicFormControlComponent implements OnInit, OnDestroy{
1821

1922
@Input() bindId = true;
2023
@Input() group: UntypedFormGroup;
@@ -26,6 +29,9 @@ export class DsDatePickerInlineComponent extends DynamicFormControlComponent {
2629
@Output() focus: EventEmitter<any> = new EventEmitter();
2730

2831
@ViewChild(NgbDatepicker) ngbDatePicker: NgbDatepicker;
32+
formattedDate: string;
33+
private isOnFocus: boolean;
34+
private modelChangeSub: Subscription;
2935

3036
constructor(protected layoutService: DynamicFormLayoutService,
3137
protected validationService: DynamicFormValidationService,
@@ -35,7 +41,38 @@ export class DsDatePickerInlineComponent extends DynamicFormControlComponent {
3541
super(layoutService, validationService);
3642
}
3743

44+
ngOnInit() {
45+
this.formattedDate = this.getInitDate();
46+
this.modelChangeSub = this.model.valueChanges.subscribe(() => {
47+
const newDate = this.getInitDate();
48+
if (hasValue(newDate) && newDate !== this.formattedDate && !this.isOnFocus) {
49+
this.formattedDate = newDate;
50+
}
51+
});
52+
}
53+
54+
ngOnDestroy() {
55+
if (hasValue(this.modelChangeSub)) {
56+
this.modelChangeSub.unsubscribe();
57+
}
58+
}
59+
3860
getInitDate(): string {
39-
return this.formatter.format(this.model.value as NgbDateStruct);
61+
return this.model.value instanceof FormFieldMetadataValueObject ? this.model.value.value : this.formatter.format(this.model.value as NgbDateStruct);
4062
}
63+
64+
onBlur(event) {
65+
this.isOnFocus = false;
66+
const newDate = this.getInitDate();
67+
if (!hasValue(this.model.value) || newDate !== this.formattedDate) {
68+
this.formattedDate = newDate;
69+
this.blur.emit(event);
70+
}
71+
}
72+
73+
onFocus($event: any) {
74+
super.onFocus($event);
75+
this.isOnFocus = true;
76+
}
77+
4178
}

0 commit comments

Comments
 (0)