Skip to content

Commit

Permalink
feat(resource): audio player (DSP-1805) (#487)
Browse files Browse the repository at this point in the history
* feat(resource): new component for audio player

* chore(deps): bump dsp-js to latest version
  • Loading branch information
kilchenmann committed Jul 22, 2021
1 parent ec881ef commit bf372dc
Show file tree
Hide file tree
Showing 13 changed files with 117 additions and 26 deletions.
22 changes: 5 additions & 17 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion package.json
Expand Up @@ -34,7 +34,7 @@
"@angular/platform-browser-dynamic": "^11.2.9",
"@angular/router": "^11.2.9",
"@ckeditor/ckeditor5-angular": "^1.2.3",
"@dasch-swiss/dsp-js": "^2.6.1",
"@dasch-swiss/dsp-js": "^2.6.2",
"@dasch-swiss/dsp-ui": "^1.6.0",
"@ngx-translate/core": "^12.1.2",
"@ngx-translate/http-loader": "5.0.0",
Expand Down
2 changes: 2 additions & 0 deletions src/app/app.module.ts
Expand Up @@ -95,6 +95,7 @@ import { SwitchPropertiesComponent } from './workspace/resource/resource-instanc
import { SelectResourceClassComponent } from './workspace/resource/resource-instance-form/select-resource-class/select-resource-class.component';
import { ResourceComponent } from './workspace/resource/resource.component';
import { ResultsComponent } from './workspace/results/results.component';
import { AudioComponent } from './workspace/resource/representation/audio/audio.component';

// translate: AoT requires an exported function for factories
export function httpLoaderFactory(httpClient: HttpClient) {
Expand Down Expand Up @@ -176,6 +177,7 @@ export function httpLoaderFactory(httpClient: HttpClient) {
UsersComponent,
UsersListComponent,
VisualizerComponent,
AudioComponent,
],
imports: [
AppRoutingModule,
Expand Down
@@ -0,0 +1,4 @@
<audio controls >
<source [src]="src.fileValue.fileUrl" type="audio/mpeg">
Your browser does not support the audio element.
</audio>
@@ -0,0 +1,3 @@
audio {
width: 100%;
}
@@ -0,0 +1,64 @@
import { Component, OnInit, ViewChild } from '@angular/core';
import { ComponentFixture, TestBed } from '@angular/core/testing';
import { FileRepresentation } from '../file-representation';
import { AudioComponent } from './audio.component';

// --> TODO: get test data from dsp-js or from dsp-api test data
const audioFileValue = {
'type': 'http://api.knora.org/ontology/knora-api/v2#AudioFileValue',
'id': 'http://rdfh.ch/1111/hgWTQVPRRTSI87PnlRmUxg/values/VKiMFffXQ9SzWeeCVrk8gw',
'attachedToUser': 'http://rdfh.ch/users/Iscj52QaSk-LNurRU6z3Hw',
'arkUrl': 'http://0.0.0.0:3336/ark:/72163/1/1111/hgWTQVPRRTSI87PnlRmUxgI/RVy0rG=vTe=vU=QW6zDToAY',
'versionArkUrl': 'http://0.0.0.0:3336/ark:/72163/1/1111/hgWTQVPRRTSI87PnlRmUxgI/RVy0rG=vTe=vU=QW6zDToAY.20210719T074023813773Z',
'valueCreationDate': '2021-07-19T07:40:23.813773Z',
'hasPermissions': 'CR knora-admin:ProjectAdmin|D knora-admin:ProjectAdmin|M knora-admin:ProjectAdmin|V knora-admin:ProjectAdmin|RV knora-admin:ProjectAdmin',
'userHasPermission': 'CR',
'uuid': 'RVy0rG-vTe-vU-QW6zDToA',
'filename': '7vpVORXYoFV-FkzJ5Fg4bkU.mp3',
'fileUrl': 'http://0.0.0.0:1024/1111/7vpVORXYoFV-FkzJ5Fg4bkU.mp3/file',
'duration': 0,
'strval': 'http://0.0.0.0:1024/1111/7vpVORXYoFV-FkzJ5Fg4bkU.mp3/file',
'property': 'http://api.knora.org/ontology/knora-api/v2#hasAudioFileValue',
'propertyLabel': 'hat Audiodatei',
'propertyComment': 'Connects a Representation to an audio file'
};

@Component({
template: `
<app-audio [src]="audioFileRepresentation">
</app-audio>`
})
class TestHostComponent implements OnInit {

@ViewChild(AudioComponent) audioPlayerComp: AudioComponent;

audioFileRepresentation: FileRepresentation;

ngOnInit() {

this.audioFileRepresentation = new FileRepresentation(audioFileValue);
}
}

describe('AudioComponent', () => {
let testHostComponent: TestHostComponent;
let testHostFixture: ComponentFixture<TestHostComponent>;


beforeEach(async () => {
await TestBed.configureTestingModule({
declarations: [AudioComponent]
})
.compileComponents();
});

beforeEach(() => {
testHostFixture = TestBed.createComponent(TestHostComponent);
testHostComponent = testHostFixture.componentInstance;
testHostFixture.detectChanges();
});

it('should create', () => {
expect(testHostComponent).toBeTruthy();
});
});
20 changes: 20 additions & 0 deletions src/app/workspace/resource/representation/audio/audio.component.ts
@@ -0,0 +1,20 @@
import { Component, Input, OnInit } from '@angular/core';
import { FileRepresentation } from '../file-representation';

@Component({
selector: 'app-audio',
templateUrl: './audio.component.html',
styleUrls: ['./audio.component.scss']
})
export class AudioComponent implements OnInit {

@Input() src: FileRepresentation;


constructor() { }

ngOnInit(): void {

}

}
Expand Up @@ -27,13 +27,13 @@
<button mat-icon-button id="DSP_PDF_ZOOM_IN" matTooltip="Zoom in" (click)="zoomFactor = zoomFactor + 0.2">
<mat-icon>add_circle_outline</mat-icon>
</button>
<a [href]="document.fileValue.fileUrl" download mat-icon-button id="DSP_PDF_DOWNLOAD" matTooltip="Open pdf in new tab">
<a [href]="src.fileValue.fileUrl" download mat-icon-button id="DSP_PDF_DOWNLOAD" matTooltip="Open pdf in new tab">
<mat-icon>launch</mat-icon>
</a>
</span>
</div>

<pdf-viewer [src]="document.fileValue.fileUrl" [original-size]="false" [autoresize]="true" [show-all]="true"
<pdf-viewer [src]="src.fileValue.fileUrl" [original-size]="false" [autoresize]="true" [show-all]="true"
[show-borders]="true" [zoom]="zoomFactor" [zoom-scale]="'page-width'">
</pdf-viewer>
</div>
Expand Up @@ -6,7 +6,6 @@ import { PdfViewerModule } from 'ng2-pdf-viewer';
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 = {
'type': 'http://api.knora.org/ontology/knora-api/v2#DocumentFileValue',
Expand All @@ -31,7 +30,7 @@ const documentFileValue = {

@Component({
template: `
<app-document [document]="documnetFileRepresentation">
<app-document [src]="documnetFileRepresentation">
</app-document>`
})
class TestHostComponent implements OnInit {
Expand Down
Expand Up @@ -9,7 +9,7 @@ import { FileRepresentation } from '../file-representation';
})
export class DocumentComponent implements OnInit {

@Input() document: FileRepresentation;
@Input() src: FileRepresentation;

@ViewChild(PdfViewerComponent) private _pdfComponent: PdfViewerComponent;

Expand Down
5 changes: 3 additions & 2 deletions src/app/workspace/resource/resource.component.html
Expand Up @@ -11,10 +11,11 @@
(regionClicked)="openRegion($event)">
</app-still-image>

<app-document class="dsp-representation" *ngSwitchCase="representationConstants.document" [document]="representationsToDisplay[0]">

<app-document class="dsp-representation" *ngSwitchCase="representationConstants.document" [src]="representationsToDisplay[0]">
</app-document>

<app-audio class="dsp-representation audio" *ngSwitchCase="representationConstants.audio" [src]="representationsToDisplay[0]"></app-audio>

<span *ngSwitchDefault>
The file representation type "{{representationsToDisplay[0].fileValue.type}}" is not yet implemented
</span>
Expand Down
8 changes: 7 additions & 1 deletion src/app/workspace/resource/resource.component.ts
Expand Up @@ -14,6 +14,7 @@ import {
CountQueryResponse,
IHasPropertyWithPropertyDefinition,
KnoraApiConnection,
ReadAudioFileValue,
ReadDocumentFileValue, ReadResource,
ReadResourceSequence,
ReadStillImageFileValue, SystemPropertyDefinition
Expand Down Expand Up @@ -354,6 +355,11 @@ export class ResourceComponent implements OnInit, OnChanges, OnDestroy {
representations.push(document);
}

} else if (resource.res.properties[Constants.HasAudioFileValue]) {

const fileValue: ReadAudioFileValue = resource.res.properties[Constants.HasAudioFileValue][0] as ReadAudioFileValue;
const audio = new FileRepresentation(fileValue);
representations.push(audio);
}
this.representationsToDisplay = representations;

Expand Down Expand Up @@ -408,7 +414,7 @@ export class ResourceComponent implements OnInit, OnChanges, OnDestroy {
}

// request incoming regions --> TODO: add case to get incoming sequences in case of video and audio
if (resource.res.properties[Constants.HasStillImageFileValue] || resource.res.properties[Constants.HasDocumentFileValue]) {
if (resource.res.properties[Constants.HasStillImageFileValue] || resource.res.properties[Constants.HasDocumentFileValue] || resource.res.properties[Constants.HasAudioFileValue]) {
// --> TODO: check if resources is a StillImageRepresentation using the ontology responder (support for subclass relations required)
// the resource is a StillImageRepresentation, check if there are regions pointing to it

Expand Down
4 changes: 4 additions & 0 deletions src/assets/style/_elements.scss
Expand Up @@ -290,6 +290,10 @@ a,
display: block;
position: relative;
padding: 0;

&.audio {
height: auto;
}
.caption {
padding: 10px 16px;
white-space: nowrap;
Expand Down

0 comments on commit bf372dc

Please sign in to comment.