From 36008c6f8d5883e92492bd39e7e85564310fae36 Mon Sep 17 00:00:00 2001 From: mdelez <60604010+mdelez@users.noreply.github.com> Date: Wed, 7 Sep 2022 10:57:47 +0200 Subject: [PATCH] feat(document): document viewer for non-pdf documents (DEV-1303) (#812) * feat(document): add default document viewer if document is not a pdf * fix(document): call correct function for downloading document file * chore(document): remove console log --- .../document/document.component.html | 123 +++++++++----- .../document/document.component.scss | 32 +++- .../document/document.component.spec.ts | 159 +++++++++++++++--- .../document/document.component.ts | 19 ++- .../resource/resource.component.html | 3 +- src/assets/style/_elements.scss | 8 +- 6 files changed, 269 insertions(+), 75 deletions(-) diff --git a/src/app/workspace/resource/representation/document/document.component.html b/src/app/workspace/resource/representation/document/document.component.html index e92732262a..8ced3a1288 100644 --- a/src/app/workspace/resource/representation/document/document.component.html +++ b/src/app/workspace/resource/representation/document/document.component.html @@ -1,4 +1,4 @@ -
+
@@ -6,58 +6,95 @@ + +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
-
-
- - + +
+
+
+
+
+ + text_snippet + +
+
+

{{originalFilename}}

+
+
+
+
+
+ +
+ - - - - - - - - - - - - - - - - - - - - - - - - +
\ No newline at end of file diff --git a/src/app/workspace/resource/representation/document/document.component.scss b/src/app/workspace/resource/representation/document/document.component.scss index c88a0f03fd..892b3466a5 100644 --- a/src/app/workspace/resource/representation/document/document.component.scss +++ b/src/app/workspace/resource/representation/document/document.component.scss @@ -13,7 +13,7 @@ $osd-height: 460px; } .mat-button-disabled { - color: $grey !important; + color: $grey !important; } app-status { @@ -50,10 +50,36 @@ $osd-height: 460px; } +.file-representation { + width: 100%; + + .container { + background: #292929; + border-radius: 8px 8px 0px 0px; + display: flex; + justify-content: center; + align-items: center; + padding: 15.5% 0%; + + .contents { + color: #FFFFFF; + + .icon { + mat-icon { + height: 90px; + width: 90px; + font-size: 90px; + line-height: 90px; + } + } + } + } +} + ::ng-deep .mat-menu-custom-black { background: #292929; + .menu-content { color: #FFFFFF; } -} - +} \ No newline at end of file diff --git a/src/app/workspace/resource/representation/document/document.component.spec.ts b/src/app/workspace/resource/representation/document/document.component.spec.ts index 28749ed9c0..3d7b10998a 100644 --- a/src/app/workspace/resource/representation/document/document.component.spec.ts +++ b/src/app/workspace/resource/representation/document/document.component.spec.ts @@ -1,13 +1,21 @@ -import { Component, OnInit, ViewChild } from '@angular/core'; +import { HttpClientTestingModule } from '@angular/common/http/testing'; +import { Component, DebugElement, Input, OnInit, ViewChild } from '@angular/core'; import { ComponentFixture, TestBed } from '@angular/core/testing'; import { MatButtonModule } from '@angular/material/button'; +import { MatDialogModule } from '@angular/material/dialog'; import { MatIconModule } from '@angular/material/icon'; +import { MatMenuModule } from '@angular/material/menu'; +import { MatSnackBarModule } from '@angular/material/snack-bar'; +import { By } from '@angular/platform-browser'; +import { KnoraApiConnection } from '@dasch-swiss/dsp-js'; import { PdfViewerModule } from 'ng2-pdf-viewer'; +import { AppInitService } from 'src/app/app-init.service'; +import { DspApiConfigToken, DspApiConnectionToken } from 'src/app/main/declarations/dsp-api-tokens'; +import { TestConfig } from 'test.config'; import { FileRepresentation } from '../file-representation'; import { DocumentComponent } from './document.component'; -// --> TODO: get test data from dsp-js or from dsp-api test data -const documentFileValue = { +const documentPdfFileValue = { 'type': 'http://api.knora.org/ontology/knora-api/v2#DocumentFileValue', 'id': 'http://rdfh.ch/1111/ay_F18DrTHeJ4zKuTt8Qzw/values/uY_qTEqVSBOW3c2vyeGXQg', 'attachedToUser': 'http://rdfh.ch/users/Iscj52QaSk-LNurRU6z3Hw', @@ -28,55 +36,158 @@ const documentFileValue = { 'propertyComment': 'Connects a Representation to a document' }; +const documentPptFileValue = { + 'type': 'http://api.knora.org/ontology/knora-api/v2#DocumentFileValue', + 'id': 'http://rdfh.ch/1111/ay_F18DrTHeJ4zKuTt8Qzw/values/uY_qTEqVSBOW3c2vyeGXQg', + 'attachedToUser': 'http://rdfh.ch/users/Iscj52QaSk-LNurRU6z3Hw', + 'arkUrl': 'http://0.0.0.0:3336/ark:/72163/1/1111/ay_F18DrTHeJ4zKuTt8Qzws/lRExhaYnQZuWVspAnbrjAQO', + 'versionArkUrl': 'http://0.0.0.0:3336/ark:/72163/1/1111/ay_F18DrTHeJ4zKuTt8Qzws/lRExhaYnQZuWVspAnbrjAQO.20210716T062258456728Z', + 'valueCreationDate': '2021-07-16T06:22:58.456728Z', + 'hasPermissions': 'CR knora-admin:ProjectAdmin|D knora-admin:ProjectAdmin|M knora-admin:ProjectAdmin|V knora-admin:ProjectAdmin|RV knora-admin:ProjectAdmin', + 'userHasPermission': 'CR', + 'uuid': 'lRExhaYnQZuWVspAnbrjAQ', + 'filename': 'Bf9iaid15df-EOrcDcZEtfk.ppt', + 'fileUrl': 'http://0.0.0.0:1024/1111/Bf9iaid15df-EOrcDcZEtfk.ppt/file', + 'strval': 'http://0.0.0.0:1024/1111/Bf9iaid15df-EOrcDcZEtfk.ppt/file', + 'property': 'http://api.knora.org/ontology/knora-api/v2#hasDocumentFileValue', + 'propertyLabel': 'hat Dokument', + 'propertyComment': 'Connects a Representation to a document' +}; + +/** + * test host component with a pdf document + */ @Component({ template: ` - + ` }) -class TestHostComponent implements OnInit { - - @ViewChild(DocumentComponent) pdfViewerComp: DocumentComponent; +class TestPdfDocumentHostComponent implements OnInit { - documnetFileRepresentation: FileRepresentation; - caption = 'test image'; - inputActivateRegion: string; + @ViewChild(DocumentComponent) documentComp: DocumentComponent; - activeRegion: string; + documentFileRepresentation: FileRepresentation; ngOnInit() { - - this.documnetFileRepresentation = new FileRepresentation(documentFileValue); + this.documentFileRepresentation = new FileRepresentation(documentPdfFileValue); } +} + +/** + * test host component with a ppt document + */ +@Component({ + template: ` + + ` +}) +class TestPptDocumentHostComponent implements OnInit { + + @ViewChild(DocumentComponent) documentComp: DocumentComponent; - regHovered(regIri: string) { - this.activeRegion = regIri; + documentFileRepresentation: FileRepresentation; + + ngOnInit() { + this.documentFileRepresentation = new FileRepresentation(documentPptFileValue); } } +@Component({ selector: 'app-status', template: '' }) +class MockStatusComponent { + @Input() status: number; + + @Input() comment?: string; + @Input() url?: string; + @Input() representation?: 'archive' | 'audio' | 'document' | 'still-image' | 'video' | 'text'; + + constructor() { } +} + describe('DocumentComponent', () => { - let testHostComponent: TestHostComponent; - let testHostFixture: ComponentFixture; beforeEach(async () => { await TestBed.configureTestingModule({ - declarations: [DocumentComponent], + declarations: [ + DocumentComponent, + TestPdfDocumentHostComponent, + TestPptDocumentHostComponent, + MockStatusComponent + ], imports: [ + HttpClientTestingModule, MatButtonModule, + MatDialogModule, MatIconModule, + MatMenuModule, + MatSnackBarModule, PdfViewerModule + ], + providers: [ + AppInitService, + { + provide: DspApiConfigToken, + useValue: TestConfig.ApiConfig + }, + { + provide: DspApiConnectionToken, + useValue: new KnoraApiConnection(TestConfig.ApiConfig) + } ] }) .compileComponents(); }); - beforeEach(() => { - testHostFixture = TestBed.createComponent(TestHostComponent); - testHostComponent = testHostFixture.componentInstance; - testHostFixture.detectChanges(); + describe('pdf viewer', () => { + let testHostComponent: TestPdfDocumentHostComponent; + let testHostFixture: ComponentFixture; + let documentComponentDe: DebugElement; + + beforeEach(() => { + testHostFixture = TestBed.createComponent(TestPdfDocumentHostComponent); + testHostComponent = testHostFixture.componentInstance; + testHostFixture.detectChanges(); + + const hostCompDe = testHostFixture.debugElement; + documentComponentDe = hostCompDe.query(By.directive(DocumentComponent)); + + expect(testHostComponent).toBeTruthy(); + }); + + it('should show the pdf viewer if the document is a pdf', () => { + const pdfDebugElement = documentComponentDe.query(By.css('.pdf-viewer')); + expect(pdfDebugElement).toBeTruthy(); + + // should not show the default document viewer if the pdf viewer is shown + const fileRepresentationDebugElement = documentComponentDe.query(By.css('.file-representation')); + expect(fileRepresentationDebugElement).toBeFalsy(); + }); }); - it('should create', () => { - expect(testHostComponent).toBeTruthy(); + describe('default document viewer', () => { + let testHostComponent: TestPptDocumentHostComponent; + let testHostFixture: ComponentFixture; + let documentComponentDe: DebugElement; + + beforeEach(() => { + testHostFixture = TestBed.createComponent(TestPptDocumentHostComponent); + testHostComponent = testHostFixture.componentInstance; + testHostFixture.detectChanges(); + + const hostCompDe = testHostFixture.debugElement; + documentComponentDe = hostCompDe.query(By.directive(DocumentComponent)); + + expect(testHostComponent).toBeTruthy(); + }); + + it('should show the default document viewer if the document is not a pdf', () => { + const fileRepresentationDebugElement = documentComponentDe.query(By.css('.file-representation')); + expect(fileRepresentationDebugElement).toBeTruthy(); + + // should not show the pdf viewer if the default document viewer is shown + const pdfDebugElement = documentComponentDe.query(By.css('.pdf-viewer')); + expect(pdfDebugElement).toBeFalsy(); + }); }); + }); diff --git a/src/app/workspace/resource/representation/document/document.component.ts b/src/app/workspace/resource/representation/document/document.component.ts index 8205684574..94faf6e7bc 100644 --- a/src/app/workspace/resource/representation/document/document.component.ts +++ b/src/app/workspace/resource/representation/document/document.component.ts @@ -47,6 +47,8 @@ export class DocumentComponent implements OnInit, AfterViewInit { elem: any; + fileType: string; + constructor( @Inject(DOCUMENT) private document: any, @Inject(DspApiConnectionToken) private _dspApiConnection: KnoraApiConnection, @@ -58,7 +60,10 @@ export class DocumentComponent implements OnInit, AfterViewInit { ) { } ngOnInit(): void { - this.elem = document.getElementsByClassName('pdf-viewer')[0]; + this.fileType = this._getFileType(this.src.fileValue.filename); + if (this.fileType === 'pdf') { + this.elem = document.getElementsByClassName('pdf-viewer')[0]; + } this._getOriginalFilename(); this.failedToLoad = !this._rs.doesFileExist(this.src.fileValue.fileUrl); } @@ -108,7 +113,7 @@ export class DocumentComponent implements OnInit, AfterViewInit { document.body.removeChild(e); } - openReplaceFileDialog(){ + openReplaceFileDialog() { const propId = this.parentResource.properties[Constants.HasDocumentFileValue][0].id; const dialogConfig: MatDialogConfig = { @@ -117,7 +122,7 @@ export class DocumentComponent implements OnInit, AfterViewInit { position: { top: '112px' }, - data: { mode: 'replaceFile', title: 'Document', subtitle: 'Update the document file of this resource' , representation: 'document', id: propId }, + data: { mode: 'replaceFile', title: 'Document', subtitle: 'Update the document file of this resource', representation: 'document', id: propId }, disableClose: true }; const dialogRef = this._dialog.open( @@ -147,6 +152,10 @@ export class DocumentComponent implements OnInit, AfterViewInit { } } + private _getFileType(filename: string): string { + return filename.split('.').pop(); + } + private _getOriginalFilename() { const requestOptions = { headers: new HttpHeaders({ 'Content-Type': 'application/json' }), @@ -179,6 +188,10 @@ export class DocumentComponent implements OnInit, AfterViewInit { this.src.fileValue.strval = (res2.properties[Constants.HasDocumentFileValue][0] as ReadDocumentFileValue).strval; this.src.fileValue.valueCreationDate = (res2.properties[Constants.HasDocumentFileValue][0] as ReadDocumentFileValue).valueCreationDate; + this.fileType = this._getFileType(this.src.fileValue.filename); + if (this.fileType === 'pdf') { + this.elem = document.getElementsByClassName('pdf-viewer')[0]; + } this._getOriginalFilename(); this.zoomFactor = 1.0; diff --git a/src/app/workspace/resource/resource.component.html b/src/app/workspace/resource/resource.component.html index 8d088c954d..a117f106a3 100644 --- a/src/app/workspace/resource/resource.component.html +++ b/src/app/workspace/resource/resource.component.html @@ -21,7 +21,8 @@ (regionAdded)="updateRegions($event)"> - diff --git a/src/assets/style/_elements.scss b/src/assets/style/_elements.scss index 82d3e12080..7086ed515b 100644 --- a/src/assets/style/_elements.scss +++ b/src/assets/style/_elements.scss @@ -301,9 +301,15 @@ a, &.video, &.audio, &.archive, - &.text { + &.text, + &.document { height: auto; + + &.pdf { + height: 70vh; + } } + .caption { padding: 10px 16px; white-space: nowrap;