mirror of
https://github.com/Alfresco/alfresco-ng2-components.git
synced 2025-05-26 17:24:56 +00:00
[ADF-4921] upload widget fixes (#5109)
* upload widget fixes * fix mocks
This commit is contained in:
parent
7ebd287728
commit
178740bbde
@ -33,7 +33,8 @@
|
||||
"NOT_LESS_THAN": "Can't be less than {{ minValue }}",
|
||||
"AT_LEAST_LONG": "Enter at least {{ minLength }} characters",
|
||||
"NO_LONGER_THAN": "Enter no more than {{ maxLength }} characters"
|
||||
}
|
||||
},
|
||||
"FILE_ALREADY_UPLOADED": "A file with the same name is already uploaded."
|
||||
},
|
||||
"FORM_RENDERER": {
|
||||
"NAMELESS_TASK": "Nameless task"
|
||||
|
@ -39,32 +39,32 @@
|
||||
|
||||
<div id="adf-attach-widget-readonly-list">
|
||||
<mat-list *ngIf="hasFile">
|
||||
<mat-list-item class="adf-attach-files-row" *ngFor="let file of field.value">
|
||||
<mat-list-item class="adf-attach-files-row" *ngFor="let file of uploadedFiles">
|
||||
<img mat-list-icon class="adf-attach-widget__icon"
|
||||
[id]="'file-'+file?.nodeId+'-icon'"
|
||||
[id]="'file-'+file?.id+'-icon'"
|
||||
[src]="file.content ? getIcon(file.content.mimeType) : getIcon(file.mimeType)"
|
||||
[alt]="mimeTypeIcon"
|
||||
role="button"
|
||||
tabindex="0"/>
|
||||
<span matLine id="{{'file-'+file?.nodeId}}"
|
||||
<span matLine id="{{'file-'+file?.id}}"
|
||||
role="button" tabindex="0" class="adf-file">{{file.name}}</span>
|
||||
<button id="{{'file-'+file?.nodeId+'-option-menu'}}" mat-icon-button [matMenuTriggerFor]="fileActionMenu">
|
||||
<button id="{{'file-'+file?.id+'-option-menu'}}" mat-icon-button [matMenuTriggerFor]="fileActionMenu">
|
||||
<mat-icon>more_vert</mat-icon>
|
||||
</button>
|
||||
<mat-menu #fileActionMenu="matMenu" xPosition="before">
|
||||
<button id="{{'file-'+file?.nodeId+'-show-file'}}"
|
||||
[disabled]="file.isExternal"
|
||||
<button id="{{'file-'+file?.id+'-show-file'}}"
|
||||
[disabled]="file['isExternal']"
|
||||
mat-menu-item (click)="onAttachFileClicked(file)">
|
||||
<mat-icon>image</mat-icon>
|
||||
<span>{{ 'FORM.FIELD.SHOW_FILE' | translate }}</span>
|
||||
</button>
|
||||
<button id="{{'file-'+file?.nodeId+'-download-file'}}"
|
||||
<button id="{{'file-'+file?.id+'-download-file'}}"
|
||||
mat-menu-item (click)="downloadContent(file)">
|
||||
<mat-icon>file_download</mat-icon>
|
||||
<span>{{ 'FORM.FIELD.DOWNLOAD_FILE' | translate }}</span>
|
||||
</button>
|
||||
<button *ngIf="!field.readOnly" id="{{'file-'+file?.nodeId+'-remove-file'}}"
|
||||
mat-menu-item [id]="'file-'+file?.nodeId+'-remove'"
|
||||
<button *ngIf="!field.readOnly" id="{{'file-'+file?.id+'-remove-file'}}"
|
||||
mat-menu-item [id]="'file-'+file?.id+'-remove'"
|
||||
(click)="onRemoveAttachFile(file);" (keyup.enter)="onRemoveAttachFile(file);">
|
||||
<mat-icon class="mat-24">highlight_off</mat-icon>
|
||||
<span>{{ 'FORM.FIELD.REMOVE_FILE' | translate }}</span>
|
||||
|
@ -45,6 +45,7 @@ describe('AttachFileCloudWidgetComponent', () => {
|
||||
let formService: FormService;
|
||||
|
||||
const fakePngAnswer = {
|
||||
id: 1155,
|
||||
nodeId: 1155,
|
||||
name: 'a_png_file.png',
|
||||
created: '2017-07-25T17:17:37.099Z',
|
||||
@ -86,6 +87,7 @@ describe('AttachFileCloudWidgetComponent', () => {
|
||||
|
||||
const fakeLocalPngAnswer = {
|
||||
id: 1155,
|
||||
nodeId: 1155,
|
||||
name: 'a_png_file.png',
|
||||
created: '2017-07-25T17:17:37.099Z',
|
||||
createdBy: {
|
||||
|
@ -22,9 +22,10 @@ import {
|
||||
FormService,
|
||||
LogService,
|
||||
ThumbnailService,
|
||||
ContentLinkModel
|
||||
ContentLinkModel,
|
||||
NotificationService
|
||||
} from '@alfresco/adf-core';
|
||||
import { RelatedContentRepresentation } from '@alfresco/js-api';
|
||||
import { Node, RelatedContentRepresentation } from '@alfresco/js-api';
|
||||
import { ContentCloudNodeSelectorService } from '../../services/content-cloud-node-selector.service';
|
||||
import { ProcessCloudContentService } from '../../services/process-cloud-content.service';
|
||||
import { UploadCloudWidgetComponent } from '../upload-cloud.widget';
|
||||
@ -55,16 +56,10 @@ export class AttachFileCloudWidgetComponent extends UploadCloudWidgetComponent
|
||||
public logger: LogService,
|
||||
public thumbnails: ThumbnailService,
|
||||
public processCloudContentService: ProcessCloudContentService,
|
||||
public contentNodeSelectorService: ContentCloudNodeSelectorService
|
||||
public contentNodeSelectorService: ContentCloudNodeSelectorService,
|
||||
notificationService: NotificationService
|
||||
) {
|
||||
super(formService, thumbnails, processCloudContentService, logger);
|
||||
}
|
||||
|
||||
ngOnInit() {
|
||||
if (this.field && this.field.value && this.field.value.length > 0) {
|
||||
this.hasFile = true;
|
||||
}
|
||||
this.getMultipleFileParam();
|
||||
super(formService, thumbnails, processCloudContentService, notificationService, logger);
|
||||
}
|
||||
|
||||
isFileSourceConfigured(): boolean {
|
||||
@ -111,18 +106,13 @@ export class AttachFileCloudWidgetComponent extends UploadCloudWidgetComponent
|
||||
}
|
||||
|
||||
openSelectDialog() {
|
||||
const filesSaved = [];
|
||||
const filesSaved: Node[] = [];
|
||||
|
||||
this.contentNodeSelectorService
|
||||
.openUploadFileDialog(this.field.form.contentHost)
|
||||
.subscribe((selections: any[]) => {
|
||||
selections.forEach(node => (node.isExternal = true));
|
||||
const result = {
|
||||
nodeId: selections[0].id,
|
||||
name: selections[0].name,
|
||||
content: selections[0].content,
|
||||
createdAt: selections[0].createdAt
|
||||
};
|
||||
filesSaved.push(result);
|
||||
.subscribe((selections: Node[]) => {
|
||||
selections.forEach(node => (node['isExternal'] = true));
|
||||
filesSaved.push(selections[0]);
|
||||
this.fixIncompatibilityFromPreviousAndNewForm(filesSaved);
|
||||
});
|
||||
}
|
||||
@ -136,9 +126,9 @@ export class AttachFileCloudWidgetComponent extends UploadCloudWidgetComponent
|
||||
);
|
||||
}
|
||||
|
||||
downloadContent(file: any): void {
|
||||
downloadContent(file: Node): void {
|
||||
this.processCloudContentService
|
||||
.getRawContentNode(file.nodeId, this.field.form.contentHost)
|
||||
.getRawContentNode(file.id, this.field.form.contentHost)
|
||||
.subscribe(
|
||||
(blob: Blob) => {
|
||||
this.processCloudContentService.downloadNodeContent(
|
||||
|
@ -5,18 +5,18 @@
|
||||
<div class="adf-cloud-upload-widget-container">
|
||||
<div>
|
||||
<mat-list *ngIf="hasFile">
|
||||
<mat-list-item class="adf-upload-files-row" *ngFor="let file of field.value">
|
||||
<mat-list-item class="adf-upload-files-row" *ngFor="let file of uploadedFiles">
|
||||
<img mat-list-icon class="adf-upload-widget__icon"
|
||||
[id]="'file-'+file.nodeId+'-icon'"
|
||||
[id]="'file-'+file.id+'-icon'"
|
||||
[src]="getIcon(file.content.mimeType)"
|
||||
[alt]="mimeTypeIcon"
|
||||
(click)="fileClicked(file)"
|
||||
(keyup.enter)="fileClicked(file)"
|
||||
role="button"
|
||||
tabindex="0"/>
|
||||
<span matLine id="{{'file-'+file.nodeId}}" (click)="fileClicked(file)" (keyup.enter)="fileClicked(file)"
|
||||
<span matLine id="{{'file-'+file.id}}" (click)="fileClicked(file)" (keyup.enter)="fileClicked(file)"
|
||||
role="button" tabindex="0" class="adf-file">{{file.name}}</span>
|
||||
<button *ngIf="!field.readOnly" mat-icon-button [id]="'file-'+file.nodeId+'-remove'"
|
||||
<button *ngIf="!field.readOnly" mat-icon-button [id]="'file-'+file.id+'-remove'"
|
||||
(click)="removeFile(file);" (keyup.enter)="removeFile(file);">
|
||||
<mat-icon class="mat-24">highlight_off</mat-icon>
|
||||
</button>
|
||||
|
@ -18,9 +18,10 @@
|
||||
/* tslint:disable:component-selector */
|
||||
|
||||
import { Component, ElementRef, OnInit, ViewChild, ViewEncapsulation } from '@angular/core';
|
||||
import { Node } from '@alfresco/js-api';
|
||||
import { Observable, from } from 'rxjs';
|
||||
import { mergeMap, map, catchError } from 'rxjs/operators';
|
||||
import { WidgetComponent, baseHost, LogService, FormService, ThumbnailService, ContentLinkModel } from '@alfresco/adf-core';
|
||||
import { mergeMap } from 'rxjs/operators';
|
||||
import { WidgetComponent, baseHost, LogService, FormService, ThumbnailService, ContentLinkModel, NotificationService } from '@alfresco/adf-core';
|
||||
import { ProcessCloudContentService } from '../services/process-cloud-content.service';
|
||||
|
||||
@Component({
|
||||
@ -44,6 +45,7 @@ export class UploadCloudWidgetComponent extends WidgetComponent implements OnIni
|
||||
public formService: FormService,
|
||||
private thumbnailService: ThumbnailService,
|
||||
public processCloudContentService: ProcessCloudContentService,
|
||||
private notificationService: NotificationService,
|
||||
private logService: LogService) {
|
||||
super(formService);
|
||||
}
|
||||
@ -53,6 +55,7 @@ export class UploadCloudWidgetComponent extends WidgetComponent implements OnIni
|
||||
this.field.value &&
|
||||
this.field.value.length > 0) {
|
||||
this.hasFile = true;
|
||||
this.fixIncompatibilityFromPreviousAndNewForm([]);
|
||||
}
|
||||
this.getMultipleFileParam();
|
||||
}
|
||||
@ -64,8 +67,16 @@ export class UploadCloudWidgetComponent extends WidgetComponent implements OnIni
|
||||
}
|
||||
|
||||
onFileChanged(event: any) {
|
||||
const files = event.target.files;
|
||||
const filesSaved = [];
|
||||
const files: File[] = [];
|
||||
const filesSaved: Node[] = [];
|
||||
|
||||
for (const file of Array.from<File>(event.target.files)) {
|
||||
if (!this.isUploaded(file)) {
|
||||
files.push(file);
|
||||
} else {
|
||||
this.notificationService.showWarning('FORM.FIELD.FILE_ALREADY_UPLOADED');
|
||||
}
|
||||
}
|
||||
|
||||
if (files && files.length > 0) {
|
||||
from(files)
|
||||
@ -83,34 +94,29 @@ export class UploadCloudWidgetComponent extends WidgetComponent implements OnIni
|
||||
}
|
||||
}
|
||||
|
||||
fixIncompatibilityFromPreviousAndNewForm(filesSaved) {
|
||||
this.field.value = filesSaved;
|
||||
this.field.form.values[this.field.id] = filesSaved;
|
||||
this.hasFile = true;
|
||||
private isUploaded(file: File): boolean {
|
||||
const current: Node[] = this.field.value || [];
|
||||
return current.some(entry => entry.name === file.name);
|
||||
}
|
||||
|
||||
getIcon(mimeType) {
|
||||
protected fixIncompatibilityFromPreviousAndNewForm(filesSaved: Node[]) {
|
||||
const value: Node[] = [...this.field.value || []];
|
||||
value.push(...filesSaved || []);
|
||||
|
||||
this.field.value = value;
|
||||
this.field.form.values[this.field.id] = value;
|
||||
|
||||
this.hasFile = value.length > 0;
|
||||
}
|
||||
|
||||
getIcon(mimeType: string): string {
|
||||
return this.thumbnailService.getMimeTypeIcon(mimeType);
|
||||
}
|
||||
|
||||
private uploadRawContent(file): Observable<any> {
|
||||
return this.processCloudContentService.createTemporaryRawRelatedContent(file, this.field.form.nodeId, this.field.form.contentHost)
|
||||
.pipe(
|
||||
map((response: any) => {
|
||||
this.logService.info(response);
|
||||
return {
|
||||
nodeId: response.id,
|
||||
name: response.name,
|
||||
content: response.content,
|
||||
createdAt: response.createdAt
|
||||
};
|
||||
}),
|
||||
catchError((err) => this.handleError(err))
|
||||
);
|
||||
}
|
||||
|
||||
private handleError(error: any): any {
|
||||
return this.logService.error(error || 'Server error');
|
||||
private uploadRawContent(file: File): Observable<Node> {
|
||||
return this.processCloudContentService.createTemporaryRawRelatedContent(
|
||||
file, this.field.form.nodeId, this.field.form.contentHost
|
||||
);
|
||||
}
|
||||
|
||||
getMultipleFileParam() {
|
||||
@ -121,17 +127,17 @@ export class UploadCloudWidgetComponent extends WidgetComponent implements OnIni
|
||||
}
|
||||
}
|
||||
|
||||
private removeElementFromList(file) {
|
||||
const savedValues = this.field.form.values[this.field.id]
|
||||
? this.field.form.values[this.field.id] : this.field.value;
|
||||
const index = savedValues.indexOf(file);
|
||||
if (index !== -1) {
|
||||
const filteredValues = savedValues.filter((value: any) => value.nodeId !== file.nodeId);
|
||||
this.resetFormValues(filteredValues);
|
||||
}
|
||||
get uploadedFiles(): Node[] {
|
||||
const result = this.field.value || this.field.form.values[this.field.id];
|
||||
return result || [];
|
||||
}
|
||||
|
||||
private resetFormValues(values) {
|
||||
private removeElementFromList(file: Node) {
|
||||
const filteredValues = this.uploadedFiles.filter(value => value.id !== file.id);
|
||||
this.resetFormValues(filteredValues);
|
||||
}
|
||||
|
||||
private resetFormValues(values: Node[]) {
|
||||
if (values && values.length > 0) {
|
||||
this.field.value = values;
|
||||
this.field.form.values[this.field.id] = values;
|
||||
|
@ -18,47 +18,64 @@
|
||||
import { Injectable } from '@angular/core';
|
||||
import { throwError, Observable, from } from 'rxjs';
|
||||
import { catchError, map } from 'rxjs/operators';
|
||||
import { AlfrescoApiService, LogService, ContentService } from '@alfresco/adf-core';
|
||||
import {
|
||||
AlfrescoApiService,
|
||||
LogService,
|
||||
ContentService
|
||||
} from '@alfresco/adf-core';
|
||||
import { Node } from '@alfresco/js-api';
|
||||
|
||||
@Injectable({
|
||||
providedIn: 'root'
|
||||
providedIn: 'root'
|
||||
})
|
||||
export class ProcessCloudContentService {
|
||||
constructor(
|
||||
private apiService: AlfrescoApiService,
|
||||
private logService: LogService,
|
||||
public contentService: ContentService
|
||||
) {}
|
||||
|
||||
constructor(
|
||||
private apiService: AlfrescoApiService,
|
||||
private logService: LogService,
|
||||
public contentService: ContentService
|
||||
) { }
|
||||
createTemporaryRawRelatedContent(
|
||||
file: File,
|
||||
nodeId: string,
|
||||
contentHost: string
|
||||
): Observable<Node> {
|
||||
const changedConfig = this.apiService.lastConfig;
|
||||
|
||||
createTemporaryRawRelatedContent(file, nodeId, contentHost): Observable<any> {
|
||||
const changedConfig = this.apiService.lastConfig;
|
||||
changedConfig.provider = 'ALL';
|
||||
changedConfig.hostEcm = contentHost.replace('/alfresco', '');
|
||||
this.apiService.getInstance().setConfig(changedConfig);
|
||||
return from(this.apiService.getInstance().upload.uploadFile(
|
||||
file, '', nodeId, '', { overwrite: true })).pipe(
|
||||
map((res: any) => {
|
||||
return (res.entry);
|
||||
}),
|
||||
catchError((err) => this.handleError(err))
|
||||
);
|
||||
}
|
||||
changedConfig.provider = 'ALL';
|
||||
changedConfig.hostEcm = contentHost.replace('/alfresco', '');
|
||||
|
||||
getRawContentNode(nodeId: string, contentHost: string): Observable<any> {
|
||||
const changedConfig = this.apiService.lastConfig;
|
||||
changedConfig.provider = 'ALL';
|
||||
changedConfig.hostEcm = contentHost.replace('/alfresco', '');
|
||||
this.apiService.getInstance().setConfig(changedConfig);
|
||||
return this.contentService.getNodeContent(nodeId);
|
||||
}
|
||||
this.apiService.getInstance().setConfig(changedConfig);
|
||||
|
||||
downloadNodeContent(blob: Blob, fileName: string): void {
|
||||
this.contentService.downloadBlob(blob, fileName);
|
||||
}
|
||||
return from(
|
||||
this.apiService
|
||||
.getInstance()
|
||||
.upload.uploadFile(file, '', nodeId, '', { overwrite: true })
|
||||
).pipe(
|
||||
map((res: any) => {
|
||||
return {
|
||||
...res.entry,
|
||||
nodeId: res.entry.id
|
||||
};
|
||||
}),
|
||||
catchError(err => this.handleError(err))
|
||||
);
|
||||
}
|
||||
|
||||
private handleError(error: any) {
|
||||
this.logService.error(error);
|
||||
return throwError(error || 'Server error');
|
||||
}
|
||||
getRawContentNode(nodeId: string, contentHost: string): Observable<any> {
|
||||
const changedConfig = this.apiService.lastConfig;
|
||||
changedConfig.provider = 'ALL';
|
||||
changedConfig.hostEcm = contentHost.replace('/alfresco', '');
|
||||
this.apiService.getInstance().setConfig(changedConfig);
|
||||
return this.contentService.getNodeContent(nodeId);
|
||||
}
|
||||
|
||||
downloadNodeContent(blob: Blob, fileName: string): void {
|
||||
this.contentService.downloadBlob(blob, fileName);
|
||||
}
|
||||
|
||||
private handleError(error: any) {
|
||||
this.logService.error(error);
|
||||
return throwError(error || 'Server error');
|
||||
}
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user