Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(resource): upload pdf document (DSP-1776) #481

Merged
merged 7 commits into from Jul 9, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
14 changes: 7 additions & 7 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.5.0",
"@dasch-swiss/dsp-js": "^2.6.0",
"@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 @@ -92,6 +92,7 @@ import { UsersComponent } from './system/users/users.component';
import { UsersListComponent } from './system/users/users-list/users-list.component';
import { VisualizerComponent } from './project/ontology/ontology-visualizer/visualizer/visualizer.component';
import { UploadComponent } from './workspace/resource/representation/upload/upload.component';
import { SplitPipe } from './main/pipes/split.pipe';

// translate: AoT requires an exported function for factories
export function httpLoaderFactory(httpClient: HttpClient) {
Expand Down Expand Up @@ -171,6 +172,7 @@ export function httpLoaderFactory(httpClient: HttpClient) {
UsersListComponent,
VisualizerComponent,
UploadComponent,
SplitPipe,
],
imports: [
AppRoutingModule,
Expand Down
8 changes: 8 additions & 0 deletions src/app/main/pipes/split.pipe.spec.ts
@@ -0,0 +1,8 @@
import { SplitPipe } from './split.pipe';

describe('SplitPipe', () => {
it('create an instance', () => {
const pipe = new SplitPipe();
expect(pipe).toBeTruthy();
});
});
22 changes: 22 additions & 0 deletions src/app/main/pipes/split.pipe.ts
@@ -0,0 +1,22 @@
import { Pipe, PipeTransform } from '@angular/core';

/**
* splits by first argument and returns element from position (second argument)
*
* mystr = application/pdf
* {{ mystr | split: '/':1 }} --> returns 'pdf'
*/
@Pipe({
name: 'split'
})
export class SplitPipe implements PipeTransform {

transform(val: string, separator: string, position: number): string {
return val.split(separator)[position];
}

// transform(value: unknown, ...args: unknown[]): unknown {
// return null;
// }

}
@@ -1,33 +1,27 @@
<div class="form-container">
<form [formGroup]="form">
<div dspDragDrop
*ngIf="isLoading || !file"
(click)="fileInput.click()"
(fileDropped)="addFile($event)"
<div dspDragDrop *ngIf="isLoading || !file" (click)="fileInput.click()" (fileDropped)="addFile($event)"
class="dd-container">
<input hidden
type="file"
(change)="addFile($event)"
#fileInput />
<mat-icon *ngIf="!isLoading"
class="upload-icon">
<input hidden type="file" (change)="addFile($event)" #fileInput />
<mat-icon *ngIf="!isLoading" class="upload-icon">
cloud_upload
</mat-icon>
<dsp-progress-indicator *ngIf="isLoading"></dsp-progress-indicator>
<div class="title">Upload file</div>
<p class="title">Upload file<br>
<span class="mat-body-1">The following file types are supported:<br>
<span *ngFor="let item of allowedFileTypes; let last = last">{{ item | split: '/':1 }}<span
*ngIf="!last">,&nbsp;</span></span>
</span>
</p>
<div class="bottom-line">
Drag and drop or click to upload
</div>
</div>

<ng-container *ngIf="!isLoading && file">
<div class="thumbnail">
<img src="{{ thumbnailUrl }}"
alt="thumbnail" />
<button mat-button
class="delete-file"
title="delete file"
(click)="deleteAttachment()">
<div *ngIf="thumbnailUrl" class="thumbnail">
<img src="{{ thumbnailUrl }}" alt="thumbnail" />
<button mat-button class="delete-file" title="delete file" (click)="deleteAttachment()">
<mat-icon>close</mat-icon>
</button>
</div>
Expand All @@ -48,9 +42,7 @@
<td>{{ convertBytes(file.size) }}</td>
<td>{{ convertDate(file.lastModified) }}</td>
<td>
<button mat-icon-button
class="delete-file"
title="delete file"
<button mat-icon-button class="delete-file" title="delete file"
(click)="deleteAttachment()">
<mat-icon>delete</mat-icon>
</button>
Expand Down
Expand Up @@ -28,7 +28,7 @@
font-size: 48px;
padding: 0;
position: inherit;
top: 35%;
top: 12%;
}
.title {
bottom: 20%;
Expand Down
Expand Up @@ -4,9 +4,10 @@ import { FormBuilder, FormGroup, ReactiveFormsModule } from '@angular/forms';
import { MatIconModule } from '@angular/material/icon';
import { MatInputModule } from '@angular/material/input';
import { MatSnackBarModule } from '@angular/material/snack-bar';
import { Constants, CreateStillImageFileValue } from '@dasch-swiss/dsp-js';
import { CreateStillImageFileValue } from '@dasch-swiss/dsp-js';
import { DspActionModule } from '@dasch-swiss/dsp-ui';
import { of } from 'rxjs';
import { SplitPipe } from 'src/app/main/pipes/split.pipe';
import { UploadFileService } from './upload-file.service';
import { UploadComponent } from './upload.component';

Expand Down Expand Up @@ -49,7 +50,8 @@ describe('UploadComponent', () => {
TestBed.configureTestingModule({
declarations: [
UploadComponent,
TestHostComponent
TestHostComponent,
SplitPipe
],
imports: [
DspActionModule,
Expand Down
@@ -1,13 +1,15 @@
import { Component, EventEmitter, Input, OnInit, Output } from '@angular/core';
import { FormBuilder, FormControl, FormGroup, Validators } from '@angular/forms';
import {
CreateDocumentFileValue,
CreateFileValue,
CreateStillImageFileValue,
UpdateDocumentFileValue,
UpdateFileValue,
UpdateStillImageFileValue
} from '@dasch-swiss/dsp-js';
import { NotificationService } from '@dasch-swiss/dsp-ui';
import { UploadedFile, UploadedFileResponse, UploadFileService } from './upload-file.service';
import { UploadedFileResponse, UploadFileService } from './upload-file.service';

// https://stackoverflow.com/questions/45661010/dynamic-nested-reactive-form-expressionchangedafterithasbeencheckederror
const resolvedPromise = Promise.resolve(null);
Expand All @@ -22,7 +24,8 @@ export class UploadComponent implements OnInit {

@Input() parentForm?: FormGroup;

@Input() representation: string; // only StillImageRepresentation supported so far
@Input() representation: 'stillImage' | 'movingImage' | 'audio' | 'document' | 'text';
// only StillImageRepresentation and DocumentPresentation is supported so far

@Input() formName: string;

Expand All @@ -34,8 +37,10 @@ export class UploadComponent implements OnInit {
isLoading = false;
thumbnailUrl: string;

allowedFileTypes: string[];
// todo: maybe we can use this list to display which file format is allowed to
supportedImageTypes = ['image/jpeg', 'image/jp2', 'image/tiff', 'image/tiff-fx', 'image/png'];
supportedDocumentTypes = ['application/pdf'];

// readonly fromLabels = {
// upload: 'Upload file',
Expand All @@ -49,6 +54,7 @@ export class UploadComponent implements OnInit {

ngOnInit(): void {
this.initializeForm();
this._supportedFileTypes();
}

/**
Expand Down Expand Up @@ -80,14 +86,28 @@ export class UploadComponent implements OnInit {
formData.append(this.file.name, this.file);
this._upload.upload(formData).subscribe(
(res: UploadedFileResponse) => {
const temporaryUrl = res.uploadedFiles[0].temporaryUrl;
const thumbnailUri = '/full/256,/0/default.jpg';
this.thumbnailUrl = `${temporaryUrl}${thumbnailUri}`;

switch (this.representation) {
case 'stillImage':
const temporaryUrl = res.uploadedFiles[0].temporaryUrl;
const thumbnailUri = '/full/256,/0/default.jpg';
this.thumbnailUrl = `${temporaryUrl}${thumbnailUri}`;
break;

case 'document':
// the preview thumbnail is deactivated for the moment;
// --> TODO: it will be activated as soon as we implement a pdf viewer
// this.thumbnailUrl = res.uploadedFiles[0].temporaryUrl;
this.thumbnailUrl = undefined;
break;

default:
this.thumbnailUrl = undefined;
break;
}

this.fileControl.setValue(res.uploadedFiles[0]);
const fileValue = this.getNewValue();
// console.log('here we should emit the values', res)
// console.log(fileValue);

if (fileValue) {
this.fileInfo.emit(fileValue);
Expand Down Expand Up @@ -184,9 +204,22 @@ export class UploadComponent implements OnInit {

const filename = this.fileControl.value.internalFilename;

// --> TODO: handle different file types
let fileValue: CreateStillImageFileValue | CreateDocumentFileValue;

switch (this.representation) {
case 'stillImage':
fileValue = new CreateStillImageFileValue();
break;

case 'document':
fileValue = new CreateDocumentFileValue();
break;

default:
// --> TODO for UPLOAD: expand with other representation file types
break;
}

const fileValue = new CreateStillImageFileValue();
fileValue.filename = filename;

return fileValue;
Expand All @@ -206,9 +239,23 @@ export class UploadComponent implements OnInit {

const filename = this.fileControl.value.internalFilename;

// --> TODO: handle different file types
let fileValue: UpdateStillImageFileValue | UpdateDocumentFileValue;

const fileValue = new UpdateStillImageFileValue();

switch (this.representation) {
case 'stillImage':
fileValue = new UpdateStillImageFileValue();
break;

case 'document':
fileValue = new UpdateDocumentFileValue();
break;
default:
// --> TODO for UPLOAD: expand with other representation file types
break;
}

// const fileValue = new UpdateStillImageFileValue();
fileValue.filename = filename;
fileValue.id = id;

Expand All @@ -228,16 +275,19 @@ export class UploadComponent implements OnInit {
* returns supported file types list for certain resource type
*/
private _supportedFileTypes(): string[] {
let allowedFileTypes: string[];
this.allowedFileTypes = [];
switch (this.representation) {
case 'stillImage':
allowedFileTypes = this.supportedImageTypes;
this.allowedFileTypes = this.supportedImageTypes;
break;
case 'document':
this.allowedFileTypes = this.supportedDocumentTypes;
break;
default:
allowedFileTypes = [];
this.allowedFileTypes = [];
break;
}
return allowedFileTypes;
return this.allowedFileTypes;
}

/**
Expand Down
Expand Up @@ -165,7 +165,14 @@ export class ResourceInstanceFormComponent implements OnInit, OnDestroy {
});

if (this.fileValue) {
this.propertiesObj[Constants.HasStillImageFileValue] = [this.fileValue];
switch (this.hasFileValue) {
case 'stillImage':
this.propertiesObj[Constants.HasStillImageFileValue] = [this.fileValue];
break;
case 'document':
this.propertiesObj[Constants.HasDocumentFileValue] = [this.fileValue];
break;
}
}

createResource.properties = this.propertiesObj;
Expand Down Expand Up @@ -370,11 +377,19 @@ export class ResourceInstanceFormComponent implements OnInit, OnDestroy {

// filter out all props that cannot be edited or are link props but also the hasFileValue props
this.properties = onto.getPropertyDefinitionsByType(ResourcePropertyDefinition).filter(
prop => prop.isEditable && !prop.isLinkProperty && prop.id !== Constants.HasStillImageFileValue);
prop =>
!prop.isLinkProperty &&
prop.isEditable &&
prop.id !== Constants.HasStillImageFileValue &&
prop.id !== Constants.HasDocumentFileValue // --> TODO for UPLOAD: expand with other representation file values
);

if (onto.properties[Constants.HasStillImageFileValue]) {
this.hasFileValue = 'stillImage';
}
if (onto.properties[Constants.HasDocumentFileValue]) {
this.hasFileValue = 'document';
}

// notifies the user that the selected resource does not have any properties defined yet.
if (!this.selectPropertiesComponent && this.properties.length === 0) {
Expand Down