Skip to content

Commit e7729fb

Browse files
atarix83FrancescoMolinaro
authored andcommitted
Merged in task/main-cris/DSC-2052 (pull request DSpace#2578)
[DSC-2052] Refactoring bitstream-attachment.component in order to fix rendering issue with functions called inside the template Approved-by: Francesco Molinaro
2 parents fa5e1c9 + 2dbe9f9 commit e7729fb

5 files changed

Lines changed: 122 additions & 77 deletions

File tree

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

Lines changed: 15 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,7 @@
11
import {
22
Component,
3-
ComponentFactory,
4-
ComponentFactoryResolver,
53
ComponentRef,
4+
inject,
65
Injector,
76
Input,
87
OnInit,
@@ -53,12 +52,7 @@ export class AttachmentRenderComponent implements OnInit {
5352
read: ViewContainerRef,
5453
}) attachmentValueViewRef: ViewContainerRef;
5554

56-
constructor(
57-
protected componentFactoryResolver: ComponentFactoryResolver,
58-
private injector: Injector,
59-
) {
60-
61-
}
55+
private injector: Injector = inject(Injector);
6256

6357
ngOnInit(): void {
6458
this.attachmentValueViewRef.clear();
@@ -68,26 +62,28 @@ export class AttachmentRenderComponent implements OnInit {
6862
/**
6963
* Generate ComponentFactory for attachment rendering
7064
*/
71-
computeComponentFactory(): ComponentFactory<any> {
65+
computeComponentFactory(): GenericConstructor<Component> {
7266
const rendering = this.computeRendering();
7367
const attachmentTypeRenderOptions = getAttachmentTypeRendering(rendering);
74-
const constructor: GenericConstructor<Component> = attachmentTypeRenderOptions?.componentRef;
75-
return constructor ? this.componentFactoryResolver.resolveComponentFactory(constructor) : null;
68+
return attachmentTypeRenderOptions?.componentRef || null;
7669
}
7770

7871
/**
7972
* Generate ComponentRef for attachment rendering
8073
*/
8174
generateComponentRef(): ComponentRef<any> {
82-
let attachentComponentRef: ComponentRef<Component>;
83-
const factory: ComponentFactory<any> = this.computeComponentFactory();
84-
if (factory) {
85-
attachentComponentRef = this.attachmentValueViewRef.createComponent(factory, 0, this.getComponentInjector());
86-
(attachentComponentRef.instance as any).item = this.item;
87-
(attachentComponentRef.instance as any).bitstream = this.bitstream;
88-
(attachentComponentRef.instance as any).tabName = this.tabName;
75+
let attachmentComponentRef: ComponentRef<Component>;
76+
const component: GenericConstructor<Component> = this.computeComponentFactory();
77+
if (component) {
78+
attachmentComponentRef = this.attachmentValueViewRef.createComponent(component, {
79+
index: 0,
80+
injector: this.getComponentInjector(),
81+
});
82+
(attachmentComponentRef.instance as any).item = this.item;
83+
(attachmentComponentRef.instance as any).bitstream = this.bitstream;
84+
(attachmentComponentRef.instance as any).tabName = this.tabName;
8985
}
90-
return attachentComponentRef;
86+
return attachmentComponentRef;
9187
}
9288

9389
/**
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
<ng-container *ngIf="attachment">
1+
@if (attachment) {
22
<div class="d-flex flex-row flex-wrap flex-lg-nowrap card-container mt-1 mb-3 gap-3" data-test="attachment-info">
33

44
<div class="order-lg-1 thumbnail-wrapper">
@@ -7,11 +7,11 @@
77

88
<div class="order-lg-3 ml-auto">
99
<div class="d-flex flex-column align-items-end gap-3">
10-
<ng-container *ngFor="let renderingType of allAttachmentProviders">
10+
@for (renderingType of allAttachmentProviders; track $index) {
1111
<div class="text-nowrap">
1212
<ds-attachment-render [renderingType]="renderingType" [bitstream]="attachment" [item]="item" [tabName]="tabName"></ds-attachment-render>
1313
</div>
14-
</ng-container>
14+
}
1515
<!-- Default download button -->
1616
<div class="text-nowrap">
1717
<ds-attachment-render [renderingType]="AttachmentRenderingType.DOWNLOAD" [bitstream]="attachment" [item]="item" [tabName]="tabName"></ds-attachment-render>
@@ -20,56 +20,64 @@
2020
</div>
2121

2222
<div class="order-lg-2 w-100 mb-3">
23-
<ng-container *ngFor="let attachmentConf of envMetadata">
23+
@for (attachmentConf of envMetadata; track $index) {
24+
@if (attachment.firstMetadataValue(attachmentConf.name) || attachmentConf.type === AdvancedAttachmentElementType.Attribute) {
25+
<div class="content" [attr.data-test]="attachmentConf.name">
26+
<strong>{{ 'cris-layout.advanced-attachment.' + attachmentConf.name | translate }}</strong>
2427

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

31-
<ng-container *ngIf="attachmentConf.type === AdvancedAttachmentElementType.Metadata">
30+
@if(!attachmentConf.truncatable && attachmentConf.name === attachmentTypeMetadata) {
31+
<p class="text-break m-0">
32+
{{attachment.firstMetadataValue(attachmentConf.name) | titlecase}}
33+
</p>
34+
}
3235

33-
<p class="text-break m-0" *ngIf="!attachmentConf.truncatable && attachmentConf.name === attachmentTypeMetadata">
34-
{{attachment.firstMetadataValue(attachmentConf.name) | titlecase}}
35-
</p>
36+
@if(!attachmentConf.truncatable && attachmentConf.name !== attachmentTypeMetadata) {
37+
<p class="text-break m-0">
38+
{{attachment.firstMetadataValue(attachmentConf.name)}}
39+
</p>
40+
}
3641

37-
<p class="text-break m-0" *ngIf="!attachmentConf.truncatable && attachmentConf.name !== attachmentTypeMetadata">
38-
{{attachment.firstMetadataValue(attachmentConf.name)}}
39-
</p>
42+
@if (attachmentConf.truncatable) {
43+
<ds-truncatable [id]=" attachment.id">
44+
<ds-truncatable-part [id]="attachment.id" [minLines]="1">
45+
{{attachment.firstMetadataValue(attachmentConf.name)}}
46+
</ds-truncatable-part>
47+
</ds-truncatable>
48+
}
49+
}
50+
@if (attachmentConf.type === AdvancedAttachmentElementType.Attribute) {
51+
@if (attachmentConf.name === 'format') {
52+
@if ((bitstreamFormat$ | async) === null || (bitstreamFormat$ | async) === undefined) {
53+
<p class="text-muted">
54+
{{'cris-layout.advanced-attachment.label.not-present' | translate}}
55+
</p>
56+
} @else {
57+
<p class="word-break m-0">{{(bitstreamFormat$ | async)}}</p>
58+
}
59+
}
4060

41-
<ds-truncatable *ngIf="attachmentConf.truncatable" [id]=" attachment.id">
42-
<ds-truncatable-part [id]="attachment.id" [minLines]="1">
43-
{{attachment.firstMetadataValue(attachmentConf.name)}}
44-
</ds-truncatable-part>
45-
</ds-truncatable>
61+
@if (attachmentConf.name === 'size' && bitstreamSize) {
62+
<p class="word-break m-0">{{bitstreamSize | dsFileSize}}</p>
63+
}
4664

47-
</ng-container>
65+
@if (attachmentConf.name === 'checksum') {
66+
@if (checksumInfo?.value === null || checksumInfo?.value === undefined) {
67+
<p class="text-muted">
68+
{{'cris-layout.advanced-attachment.label.not-present' | translate}}
69+
</p>
70+
} @else {
71+
<p class="word-break m-0">({{checksumInfo.checkSumAlgorithm}}):{{ checksumInfo.value }}</p>
72+
}
73+
}
74+
}
4875

49-
<ng-container *ngIf="attachmentConf.type === AdvancedAttachmentElementType.Attribute">
50-
<ng-container *ngIf="attachmentConf.name === 'format'">
51-
<p *ngIf="(getFormat(attachment) | async) === null || (getFormat(attachment) | async) === undefined" class="text-muted">
52-
{{'cris-layout.advanced-attachment.label.not-present' | translate}}
53-
</p>
54-
<p class="word-break m-0">{{getFormat(attachment) | async}}</p>
55-
</ng-container>
56-
57-
<ng-container *ngIf="attachmentConf.name === 'size'">
58-
<p class="word-break m-0">{{getSize(attachment) | dsFileSize}}</p>
59-
</ng-container>
60-
61-
<ng-container *ngIf="attachmentConf.name === 'checksum'">
62-
<p *ngIf="(getChecksum(attachment)?.value) !== true"class="text-muted">
63-
{{'cris-layout.advanced-attachment.label.not-present' | translate}}
64-
</p>
65-
<p class="word-break m-0">({{getChecksum(attachment).checkSumAlgorithm}}):{{ getChecksum(attachment).value }}</p>
66-
</ng-container>
67-
</ng-container>
68-
69-
</div>
70-
</ng-container>
76+
</div>
77+
}
78+
}
7179

7280
</div>
7381

7482
</div>
75-
</ng-container>
83+
}

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

Lines changed: 20 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3,13 +3,19 @@ import {
33
ComponentFixture,
44
TestBed,
55
} from '@angular/core/testing';
6-
import { RouterTestingModule } from '@angular/router/testing';
7-
import { TranslateService } from '@ngx-translate/core';
6+
import { provideRouter } from '@angular/router';
7+
import {
8+
TranslateLoader,
9+
TranslateModule,
10+
} from '@ngx-translate/core';
811

912
import { BitstreamDataService } from '../../../../../../../../core/data/bitstream-data.service';
13+
import { MockBitstream1 } from '../../../../../../../../shared/mocks/item.mock';
14+
import { TranslateLoaderMock } from '../../../../../../../../shared/mocks/translate-loader.mock';
1015
import { TruncatableComponent } from '../../../../../../../../shared/truncatable/truncatable.component';
1116
import { TruncatablePartComponent } from '../../../../../../../../shared/truncatable/truncatable-part/truncatable-part.component';
1217
import { ThemedThumbnailComponent } from '../../../../../../../../thumbnail/themed-thumbnail.component';
18+
import { BitstreamRenderingModelComponent } from '../../bitstream-rendering-model';
1319
import { AttachmentRenderComponent } from './attachment-render/attachment-render.component';
1420
import { BitstreamAttachmentComponent } from './bitstream-attachment.component';
1521

@@ -19,14 +25,23 @@ describe('BitstreamAttachmentComponent', () => {
1925

2026
beforeEach(async () => {
2127
await TestBed.configureTestingModule({
22-
imports: [RouterTestingModule.withRoutes([]), BitstreamAttachmentComponent],
28+
imports: [
29+
BitstreamAttachmentComponent,
30+
BitstreamRenderingModelComponent,
31+
TranslateModule.forRoot({
32+
loader: {
33+
provide: TranslateLoader,
34+
useClass: TranslateLoaderMock,
35+
},
36+
}),
37+
],
2338
providers: [
39+
provideRouter([]),
2440
{ provide: 'fieldProvider', useValue: {} },
2541
{ provide: 'itemProvider', useValue: {} },
2642
{ provide: 'renderingSubTypeProvider', useValue: '' },
2743
{ provide: 'tabNameProvider', useValue: '' },
2844
{ provide: BitstreamDataService, useValue: {} },
29-
{ provide: TranslateService, useValue: {} },
3045
],
3146
schemas: [NO_ERRORS_SCHEMA],
3247
})
@@ -36,6 +51,7 @@ describe('BitstreamAttachmentComponent', () => {
3651
beforeEach(() => {
3752
fixture = TestBed.createComponent(BitstreamAttachmentComponent);
3853
component = fixture.componentInstance;
54+
component.attachment = MockBitstream1;
3955
fixture.detectChanges();
4056
});
4157

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: 29 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,5 @@
11
import {
22
AsyncPipe,
3-
NgFor,
4-
NgIf,
53
TitleCasePipe,
64
} from '@angular/common';
75
import {
@@ -18,12 +16,16 @@ import {
1816
TranslateModule,
1917
TranslateService,
2018
} from '@ngx-translate/core';
19+
import { Observable } from 'rxjs';
2120

2221
import { AdvancedAttachmentElementType } from '../../../../../../../../../config/advanced-attachment-rendering.config';
2322
import { environment } from '../../../../../../../../../environments/environment';
2423
import { BitstreamDataService } from '../../../../../../../../core/data/bitstream-data.service';
2524
import { LayoutField } from '../../../../../../../../core/layout/models/box.model';
26-
import { Bitstream } from '../../../../../../../../core/shared/bitstream.model';
25+
import {
26+
Bitstream,
27+
ChecksumInfo,
28+
} from '../../../../../../../../core/shared/bitstream.model';
2729
import { Item } from '../../../../../../../../core/shared/item.model';
2830
import { TruncatableComponent } from '../../../../../../../../shared/truncatable/truncatable.component';
2931
import { TruncatablePartComponent } from '../../../../../../../../shared/truncatable/truncatable-part/truncatable-part.component';
@@ -39,9 +41,7 @@ import { AttachmentRenderingType } from './attachment-type.decorator';
3941
styleUrls: ['./bitstream-attachment.component.scss'],
4042
standalone: true,
4143
imports: [
42-
NgIf,
4344
ThemedThumbnailComponent,
44-
NgFor,
4545
AttachmentRenderComponent,
4646
TruncatableComponent,
4747
TruncatablePartComponent,
@@ -63,6 +63,9 @@ export class BitstreamAttachmentComponent extends BitstreamRenderingModelCompone
6363
*/
6464
AdvancedAttachmentElementType = AdvancedAttachmentElementType;
6565

66+
/**
67+
* Configuration type enum
68+
*/
6669
AttachmentRenderingType = AttachmentRenderingType;
6770

6871
/**
@@ -73,11 +76,26 @@ export class BitstreamAttachmentComponent extends BitstreamRenderingModelCompone
7376
/**
7477
* Attachment metadata to be displayed in title case
7578
*/
76-
7779
attachmentTypeMetadata = 'dc.type';
7880

79-
@Input()
80-
attachment: Bitstream;
81+
/**
82+
* Attachment to be displayed
83+
*/
84+
@Input() attachment: Bitstream;
85+
86+
/**
87+
* Format of the bitstream
88+
*/
89+
bitstreamFormat$: Observable<string>;
90+
91+
/**
92+
* Size of the bitstream
93+
*/
94+
bitstreamSize: number;
95+
/**
96+
* Checksum info of the bitstream
97+
*/
98+
checksumInfo: ChecksumInfo;
8199

82100
constructor(
83101
@Inject('fieldProvider') public fieldProvider: LayoutField,
@@ -94,5 +112,8 @@ export class BitstreamAttachmentComponent extends BitstreamRenderingModelCompone
94112

95113
ngOnInit() {
96114
this.allAttachmentProviders = this.attachment?.allMetadataValues('bitstream.viewer.provider');
115+
this.bitstreamFormat$ = this.getFormat(this.attachment);
116+
this.bitstreamSize = this.getSize(this.attachment);
117+
this.checksumInfo = this.getChecksum(this.attachment);
97118
}
98119
}

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

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,10 @@ import {
44
} from '@angular/core';
55
import { TranslateService } from '@ngx-translate/core';
66
import { Observable } from 'rxjs';
7-
import { map } from 'rxjs/operators';
7+
import {
8+
map,
9+
take,
10+
} from 'rxjs/operators';
811

912
import {
1013
BitstreamDataService,
@@ -123,6 +126,7 @@ export abstract class BitstreamRenderingModelComponent extends RenderingTypeStru
123126
map((rd: RemoteData<BitstreamFormat>) => {
124127
return rd.payload?.shortDescription;
125128
}),
129+
take(1),
126130
);
127131
}
128132

0 commit comments

Comments
 (0)