From 0220246ff21e1fa5b1748b8a7e53860c4db31e4f Mon Sep 17 00:00:00 2001 From: Jesiel Viana Date: Wed, 3 Dec 2025 17:36:46 -0300 Subject: [PATCH 01/12] feat: add PDF viewer to simple item page --- .../media-viewer-pdf.component.html | 24 +++++++ .../media-viewer-pdf.component.scss | 3 + .../media-viewer-pdf.component.ts | 45 ++++++++++++ .../themed-media-viewer-pdf.component.ts | 34 +++++++++ .../media-viewer/media-viewer.component.html | 72 +++++++++---------- .../media-viewer/media-viewer.component.ts | 13 +++- .../untyped-item/untyped-item.component.html | 10 +-- src/config/default-app-config.ts | 1 + src/config/media-viewer-config.interface.ts | 1 + .../media-viewer/media-viewer.component.ts | 2 + 10 files changed, 162 insertions(+), 43 deletions(-) create mode 100644 src/app/item-page/media-viewer/media-viewer-pdf/media-viewer-pdf.component.html create mode 100644 src/app/item-page/media-viewer/media-viewer-pdf/media-viewer-pdf.component.scss create mode 100644 src/app/item-page/media-viewer/media-viewer-pdf/media-viewer-pdf.component.ts create mode 100644 src/app/item-page/media-viewer/media-viewer-pdf/themed-media-viewer-pdf.component.ts diff --git a/src/app/item-page/media-viewer/media-viewer-pdf/media-viewer-pdf.component.html b/src/app/item-page/media-viewer/media-viewer-pdf/media-viewer-pdf.component.html new file mode 100644 index 00000000000..051b6493724 --- /dev/null +++ b/src/app/item-page/media-viewer/media-viewer-pdf/media-viewer-pdf.component.html @@ -0,0 +1,24 @@ +@if (pdfs?.length > 1) { +
+
+ + +
+ @for (item of pdfs; track $index) { + + } +
+
+
+} +

{{ dsoNameService.getName(pdfs[currentIndex].bitstream) }}

+
+ +

Your browser does not support PDFs. Download the + PDF.

+
+
diff --git a/src/app/item-page/media-viewer/media-viewer-pdf/media-viewer-pdf.component.scss b/src/app/item-page/media-viewer/media-viewer-pdf/media-viewer-pdf.component.scss new file mode 100644 index 00000000000..a4bc4f3dddb --- /dev/null +++ b/src/app/item-page/media-viewer/media-viewer-pdf/media-viewer-pdf.component.scss @@ -0,0 +1,3 @@ +.pdf { + height: 30em; +} \ No newline at end of file diff --git a/src/app/item-page/media-viewer/media-viewer-pdf/media-viewer-pdf.component.ts b/src/app/item-page/media-viewer/media-viewer-pdf/media-viewer-pdf.component.ts new file mode 100644 index 00000000000..f57df84bb32 --- /dev/null +++ b/src/app/item-page/media-viewer/media-viewer-pdf/media-viewer-pdf.component.ts @@ -0,0 +1,45 @@ +import { ChangeDetectorRef, Component, Input, ViewChild } from '@angular/core'; +import { MediaViewerItem } from '../../../core/shared/media-viewer-item.model'; +import { DSONameService } from '../../../core/breadcrumbs/dso-name.service'; +import { TranslateModule } from '@ngx-translate/core'; +import { DomSanitizer, SafeResourceUrl } from '@angular/platform-browser'; +import { HttpClient } from '@angular/common/http'; + +@Component({ + selector: 'ds-media-viewer-pdf', + templateUrl: './media-viewer-pdf.component.html', + styleUrls: ['./media-viewer-pdf.component.scss'], + imports: [TranslateModule], +}) +export class MediaViewerPdfComponent { + @Input() pdfs: MediaViewerItem[]; + @ViewChild('pdfViewer') pdfViewer; + blobUrl: SafeResourceUrl = this.sanitizer.bypassSecurityTrustResourceUrl(""); + currentIndex = 0; + + constructor(private http: HttpClient, private sanitizer: DomSanitizer, public dsoNameService: DSONameService, private cdr: ChangeDetectorRef,) { } + + ngOnInit() { + console.log('initiiiiii') + this.loadPdf(this.currentIndex); + } + + selectedMedia(index: number) { + this.currentIndex = index; + this.loadPdf(index); + } + + private loadPdf(index: number) { + const url = this.pdfs[index].bitstream._links.content.href; + this.http.get(url, { responseType: 'blob' }).subscribe({ + next: (blob) => { + const blobUrl = URL.createObjectURL(blob); + this.blobUrl = this.sanitizer.bypassSecurityTrustResourceUrl(blobUrl); + this.cdr.detectChanges(); + }, + error: (err) => { + console.error('Error loading PDF:', err); + }, + }); + } +} diff --git a/src/app/item-page/media-viewer/media-viewer-pdf/themed-media-viewer-pdf.component.ts b/src/app/item-page/media-viewer/media-viewer-pdf/themed-media-viewer-pdf.component.ts new file mode 100644 index 00000000000..42c79097130 --- /dev/null +++ b/src/app/item-page/media-viewer/media-viewer-pdf/themed-media-viewer-pdf.component.ts @@ -0,0 +1,34 @@ +import { Component, Input } from '@angular/core'; +import { ThemedComponent } from '../../../shared/theme-support/themed.component'; +import { MediaViewerItem } from '../../../core/shared/media-viewer-item.model'; +import { MediaViewerPdfComponent } from './media-viewer-pdf.component'; + +/** + * Themed wrapper for {@link MediaViewerPdfComponent}. + */ +@Component({ + selector: 'ds-themed-media-viewer-pdf', + styleUrls: [], + templateUrl: '../../../shared/theme-support/themed.component.html', +}) +export class ThemedMediaViewerPdfComponent extends ThemedComponent { + + @Input() pdfs: MediaViewerItem[]; + + protected inAndOutputNames: (keyof MediaViewerPdfComponent & keyof this)[] = [ + 'pdfs', + ]; + + protected getComponentName(): string { + return 'MediaViewerPdfComponent'; + } + + protected importThemedComponent(themeName: string): Promise { + return import(`../../../../themes/${themeName}/app/item-page/media-viewer/media-viewer-pdf/media-viewer-pdf.component`); + } + + protected importUnthemedComponent(): Promise { + return import('./media-viewer-pdf.component'); + } + +} diff --git a/src/app/item-page/media-viewer/media-viewer.component.html b/src/app/item-page/media-viewer/media-viewer.component.html index 0629ded8ca3..265d9c5536c 100644 --- a/src/app/item-page/media-viewer/media-viewer.component.html +++ b/src/app/item-page/media-viewer/media-viewer.component.html @@ -1,42 +1,42 @@ @if (isLoading) { - + } @else { -
- @if (mediaList.length > 0) { - - - @if (showVideo) { - - } - @if (showImage) { - - } - @if (showImage || showVideo) { - } @else { - @if (mediaOptions.image && mediaOptions.video) { - - } - @if (!(mediaOptions.image && mediaOptions.video)) { - - - } - } - +
+ @if (mediaList.length > 0) { + + + + @if (showPdf) { + + } + + @if (showVideo) { + + } + @if (showImage) { + + } + @if (showImage || showVideo || showPdf) { + } @else { + @if (mediaOptions.image && mediaOptions.video) { + + } + @if (!(mediaOptions.image && mediaOptions.video)) { + + + } + } - } @else { - - - } -
+
+ + } @else { + + + } +
} -
+ \ No newline at end of file diff --git a/src/app/item-page/media-viewer/media-viewer.component.ts b/src/app/item-page/media-viewer/media-viewer.component.ts index 11b1e6793bc..5d312f358bd 100644 --- a/src/app/item-page/media-viewer/media-viewer.component.ts +++ b/src/app/item-page/media-viewer/media-viewer.component.ts @@ -1,4 +1,4 @@ -import { AsyncPipe } from '@angular/common'; +import { AsyncPipe, CommonModule } from '@angular/common'; import { ChangeDetectorRef, Component, @@ -36,6 +36,7 @@ import { VarDirective } from '../../shared/utils/var.directive'; import { ThemedThumbnailComponent } from '../../thumbnail/themed-thumbnail.component'; import { ThemedMediaViewerImageComponent } from './media-viewer-image/themed-media-viewer-image.component'; import { ThemedMediaViewerVideoComponent } from './media-viewer-video/themed-media-viewer-video.component'; +import { MediaViewerPdfComponent } from "./media-viewer-pdf/media-viewer-pdf.component"; /** * This component renders the media viewers @@ -52,6 +53,7 @@ import { ThemedMediaViewerVideoComponent } from './media-viewer-video/themed-med ThemedThumbnailComponent, TranslateModule, VarDirective, + MediaViewerPdfComponent ], }) export class MediaViewerComponent implements OnDestroy, OnInit { @@ -88,10 +90,12 @@ export class MediaViewerComponent implements OnDestroy, OnInit { * This method loads all the Bitstreams and Thumbnails and converts it to {@link MediaViewerItem}s */ ngOnInit(): void { + console.log('MediaViewerComponent init', this.mediaList$) this.itemRequest = this.route.snapshot.data.itemRequest; const types: string[] = [ ...(this.mediaOptions.image ? ['image'] : []), ...(this.mediaOptions.video ? ['audio', 'video'] : []), + ...(this.mediaOptions.pdf ? ['application/pdf'] : []), ]; this.thumbnailsRD$ = this.loadRemoteData('THUMBNAIL'); this.subs.push(this.loadRemoteData('ORIGINAL').subscribe((bitstreamsRD: RemoteData>) => { @@ -113,7 +117,7 @@ export class MediaViewerComponent implements OnDestroy, OnInit { format, thumbnailsRD.payload && thumbnailsRD.payload.page[index], ); - if (types.includes(mediaItem.format)) { + if (types.includes(mediaItem.mimetype)) { this.mediaList$.next([...this.mediaList$.getValue(), mediaItem]); } else if (format.mimetype === 'text/vtt') { this.captions$.next([...this.captions$.getValue(), bitstreamsRD.payload.page[index]]); @@ -180,4 +184,9 @@ export class MediaViewerComponent implements OnDestroy, OnInit { return null; } + filterPdf(mediaList: MediaViewerItem[]) { + const pdfs = mediaList.filter(item => item.mimetype === 'application/pdf'); + return pdfs; + } + } diff --git a/src/app/item-page/simple/item-types/untyped-item/untyped-item.component.html b/src/app/item-page/simple/item-types/untyped-item/untyped-item.component.html index 52ae5556dce..596ed7cb835 100644 --- a/src/app/item-page/simple/item-types/untyped-item/untyped-item.component.html +++ b/src/app/item-page/simple/item-types/untyped-item/untyped-item.component.html @@ -25,11 +25,6 @@ } - @if (mediaViewer.image || mediaViewer.video) { -
- -
- } + @if (mediaViewer.image || mediaViewer.video || mediaViewer.pdf) { +
+ +
+ } @if (geospatialItemPageFieldsEnabled) { Date: Thu, 4 Dec 2025 10:48:13 -0300 Subject: [PATCH 02/12] improve the layout of pdf viewer --- .../media-viewer-pdf.component.html | 41 +++++++++---------- .../media-viewer-pdf.component.scss | 8 +++- .../media-viewer-pdf.component.ts | 6 +-- src/assets/i18n/en.json5 | 2 + src/assets/i18n/es.json5 | 2 + src/assets/i18n/pt-BR.json5 | 2 + 6 files changed, 34 insertions(+), 27 deletions(-) diff --git a/src/app/item-page/media-viewer/media-viewer-pdf/media-viewer-pdf.component.html b/src/app/item-page/media-viewer/media-viewer-pdf/media-viewer-pdf.component.html index 051b6493724..589f9b721d1 100644 --- a/src/app/item-page/media-viewer/media-viewer-pdf/media-viewer-pdf.component.html +++ b/src/app/item-page/media-viewer/media-viewer-pdf/media-viewer-pdf.component.html @@ -1,24 +1,21 @@ -@if (pdfs?.length > 1) { -
-
- +
+

{{ 'media-viewer.pdflist' | translate }}

+ -
- @for (item of pdfs; track $index) { - - } -
+ +
+ +

+ Your browser does not support PDF viewer. + Download the PDF. +

+
-
-} -

{{ dsoNameService.getName(pdfs[currentIndex].bitstream) }}

-
- -

Your browser does not support PDFs. Download the - PDF.

-
-
+
\ No newline at end of file diff --git a/src/app/item-page/media-viewer/media-viewer-pdf/media-viewer-pdf.component.scss b/src/app/item-page/media-viewer/media-viewer-pdf/media-viewer-pdf.component.scss index a4bc4f3dddb..b58e7cea5fe 100644 --- a/src/app/item-page/media-viewer/media-viewer-pdf/media-viewer-pdf.component.scss +++ b/src/app/item-page/media-viewer/media-viewer-pdf/media-viewer-pdf.component.scss @@ -1,3 +1,7 @@ -.pdf { - height: 30em; +.simple-view-element-header { + font-size: 1.25rem; +} + +.pdf-viewer { + height: 50vh; } \ No newline at end of file diff --git a/src/app/item-page/media-viewer/media-viewer-pdf/media-viewer-pdf.component.ts b/src/app/item-page/media-viewer/media-viewer-pdf/media-viewer-pdf.component.ts index f57df84bb32..4272714c976 100644 --- a/src/app/item-page/media-viewer/media-viewer-pdf/media-viewer-pdf.component.ts +++ b/src/app/item-page/media-viewer/media-viewer-pdf/media-viewer-pdf.component.ts @@ -4,12 +4,13 @@ import { DSONameService } from '../../../core/breadcrumbs/dso-name.service'; import { TranslateModule } from '@ngx-translate/core'; import { DomSanitizer, SafeResourceUrl } from '@angular/platform-browser'; import { HttpClient } from '@angular/common/http'; +import { FormsModule } from '@angular/forms'; @Component({ selector: 'ds-media-viewer-pdf', templateUrl: './media-viewer-pdf.component.html', styleUrls: ['./media-viewer-pdf.component.scss'], - imports: [TranslateModule], + imports: [TranslateModule, FormsModule], }) export class MediaViewerPdfComponent { @Input() pdfs: MediaViewerItem[]; @@ -17,10 +18,9 @@ export class MediaViewerPdfComponent { blobUrl: SafeResourceUrl = this.sanitizer.bypassSecurityTrustResourceUrl(""); currentIndex = 0; - constructor(private http: HttpClient, private sanitizer: DomSanitizer, public dsoNameService: DSONameService, private cdr: ChangeDetectorRef,) { } + constructor(private http: HttpClient, private sanitizer: DomSanitizer, public dsoNameService: DSONameService, private cdr: ChangeDetectorRef) { } ngOnInit() { - console.log('initiiiiii') this.loadPdf(this.currentIndex); } diff --git a/src/assets/i18n/en.json5 b/src/assets/i18n/en.json5 index c0b620d24d7..b75ff1215ee 100644 --- a/src/assets/i18n/en.json5 +++ b/src/assets/i18n/en.json5 @@ -7213,4 +7213,6 @@ "item.preview.organization.address.addressLocality": "City", "item.preview.organization.alternateName": "Alternative name", + + "media-viewer.pdflist": "Files", } diff --git a/src/assets/i18n/es.json5 b/src/assets/i18n/es.json5 index 7f1b2f4d6f6..aaa4cbb2a75 100644 --- a/src/assets/i18n/es.json5 +++ b/src/assets/i18n/es.json5 @@ -10975,5 +10975,7 @@ // TODO New key - Add a translation "file-download-link.request-copy": "Request a copy of ", + "media-viewer.pdflist": "Archivos", + } diff --git a/src/assets/i18n/pt-BR.json5 b/src/assets/i18n/pt-BR.json5 index 7d35b5ccfe8..101958da2aa 100644 --- a/src/assets/i18n/pt-BR.json5 +++ b/src/assets/i18n/pt-BR.json5 @@ -11144,4 +11144,6 @@ "item.preview.organization.address.addressLocality": "Cidade", "item.preview.organization.alternateName": "Nome alternativo", + + "media-viewer.pdflist": "Arquivos", } From 624f9c180b1cef5f63001cae204f733dc8cafa59 Mon Sep 17 00:00:00 2001 From: Jesiel Viana Date: Thu, 4 Dec 2025 11:54:11 -0300 Subject: [PATCH 03/12] add translation keys --- .../media-viewer-pdf/media-viewer-pdf.component.html | 6 +++--- src/assets/i18n/en.json5 | 6 +++++- src/assets/i18n/es.json5 | 5 ++++- src/assets/i18n/pt-BR.json5 | 7 ++++++- 4 files changed, 18 insertions(+), 6 deletions(-) diff --git a/src/app/item-page/media-viewer/media-viewer-pdf/media-viewer-pdf.component.html b/src/app/item-page/media-viewer/media-viewer-pdf/media-viewer-pdf.component.html index 589f9b721d1..07a5c8c8370 100644 --- a/src/app/item-page/media-viewer/media-viewer-pdf/media-viewer-pdf.component.html +++ b/src/app/item-page/media-viewer/media-viewer-pdf/media-viewer-pdf.component.html @@ -1,5 +1,5 @@
-

{{ 'media-viewer.pdflist' | translate }}

+

{{ 'media-viewer.pdf.files' | translate }}

-
+

{{ 'media-viewer.pdf.browser-not-support' | translate }} diff --git a/src/app/item-page/media-viewer/media-viewer-pdf/media-viewer-pdf.component.scss b/src/app/item-page/media-viewer/media-viewer-pdf/media-viewer-pdf.component.scss index b58e7cea5fe..03781cbb339 100644 --- a/src/app/item-page/media-viewer/media-viewer-pdf/media-viewer-pdf.component.scss +++ b/src/app/item-page/media-viewer/media-viewer-pdf/media-viewer-pdf.component.scss @@ -1,7 +1,12 @@ +.pdf-viewer-container { + margin-bottom: 2rem; +} + .simple-view-element-header { font-size: 1.25rem; } .pdf-viewer { height: 50vh; + padding-bottom: 1px; } \ No newline at end of file diff --git a/src/app/item-page/simple/item-types/publication/publication.component.html b/src/app/item-page/simple/item-types/publication/publication.component.html index a294cc025bc..83989b4a85b 100644 --- a/src/app/item-page/simple/item-types/publication/publication.component.html +++ b/src/app/item-page/simple/item-types/publication/publication.component.html @@ -24,11 +24,6 @@ } - @if (mediaViewer.image || mediaViewer.video) { -

- -
- } + @if (mediaViewer.image || mediaViewer.video || mediaViewer.pdf) { +
+ +
+ } @if (geospatialItemPageFieldsEnabled) { Date: Fri, 5 Dec 2025 10:36:44 +0100 Subject: [PATCH 06/12] added a loading for the pdf viewer and a badge for the number of files --- .../media-viewer-pdf.component.html | 38 ++++++++++++++----- .../media-viewer-pdf.component.scss | 12 ++++++ .../media-viewer-pdf.component.ts | 12 +++++- 3 files changed, 52 insertions(+), 10 deletions(-) diff --git a/src/app/item-page/media-viewer/media-viewer-pdf/media-viewer-pdf.component.html b/src/app/item-page/media-viewer/media-viewer-pdf/media-viewer-pdf.component.html index 2f80cdc1411..6dc687f2fc9 100644 --- a/src/app/item-page/media-viewer/media-viewer-pdf/media-viewer-pdf.component.html +++ b/src/app/item-page/media-viewer/media-viewer-pdf/media-viewer-pdf.component.html @@ -1,6 +1,14 @@
-

{{ 'media-viewer.pdf.files' | translate }}

- @for (item of pdfs; track $index) {