[AAE-3110] Move upload button inside the node selector dialog (#5901)

* Open select dialog on all types, fetch destination folder from a relative path

* Dialog UI refactor, multiple upload from local

* Fix document list should automatically reload after upload

* Remove not used ViewChild

* Fix imports, read destination folder from form field

* support different alias

* Remove not needed property, reuse selection mode

* Remove unused methods

* Fix unit tests

* * Added unit tests
* Fixed failing unit tests

* * Added unit for upload button
* Skipped failing e2e

* * Removed process-storage related code

* * Removed unncessory model and code
*

* * Removed contentHost from formCloud model

* * Skiped content-services e2e

* Skip failing process e2e related to attachment

Co-authored-by: sivakumar414ram <siva.kumar@muraai.com>
Co-authored-by: maurizio vitale <maurizio.vitale@alfresco.com>
This commit is contained in:
arditdomi
2020-07-31 07:38:58 +02:00
committed by GitHub
parent 1e692252a5
commit d553c71b1e
31 changed files with 338 additions and 432 deletions

View File

@@ -17,7 +17,7 @@
import { Component, DebugElement, SimpleChange, NgModule, Injector, ComponentFactoryResolver, ViewChild } from '@angular/core';
import { By } from '@angular/platform-browser';
import { async, ComponentFixture, fakeAsync, TestBed, tick } from '@angular/core/testing';
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
import { Observable, of, throwError } from 'rxjs';
import {
AppConfigService,
@@ -370,45 +370,6 @@ describe('FormCloudComponent', () => {
expect(formComponent.getFormByTaskId).toHaveBeenCalledWith(appName, taskId, 1);
});
it('should call the process storage to retrieve the folder with only the taskId', fakeAsync(() => {
spyOn(formCloudService, 'getTaskForm').and.returnValue(of(cloudFormMock));
spyOn(formCloudService, 'getTaskVariables').and.returnValue(of([]));
spyOn(formCloudService, 'getProcessStorageFolderTask')
.and.returnValue(of({ nodeId: '123', path: '/a/path/type', type: 'fakeType' }));
const taskId = '<task id>';
const appName = 'test-app';
formComponent.appName = appName;
formComponent.taskId = taskId;
const change = new SimpleChange(null, appName, true);
formComponent.ngOnChanges({ 'appName': change });
tick();
expect(formCloudService.getProcessStorageFolderTask).toHaveBeenCalledWith(appName, taskId, undefined);
expect(formComponent.form.nodeId).toBe('123');
expect(formComponent.form.contentHost).toBe('/a/path/type');
}));
it('should call the process storage to retrieve the folder with taskId and processInstanceId', fakeAsync(() => {
spyOn(formCloudService, 'getTaskForm').and.returnValue(of(cloudFormMock));
spyOn(formCloudService, 'getTaskVariables').and.returnValue(of([]));
spyOn(formCloudService, 'getProcessStorageFolderTask')
.and.returnValue(of({ nodeId: '123', path: '/a/path/type', type: 'fakeType' }));
const taskId = '<task id>';
const processInstanceId = 'i-am-the-process-instance-id';
const appName = 'test-app';
formComponent.appName = appName;
formComponent.taskId = taskId;
formComponent.processInstanceId = processInstanceId;
const change = new SimpleChange(null, 'new-app-name', true);
formComponent.ngOnChanges({ 'appName': change });
tick();
expect(formCloudService.getProcessStorageFolderTask).toHaveBeenCalledWith(appName, taskId, processInstanceId);
expect(formComponent.form.nodeId).toBe('123');
expect(formComponent.form.contentHost).toBe('/a/path/type');
}));
it('should reload form definition by form id on binding changes', () => {
spyOn(formComponent, 'getFormById').and.stub();
const formId = '123';

View File

@@ -28,12 +28,10 @@ import {
FormOutcomeModel,
WidgetVisibilityService,
FormService,
NotificationService,
FORM_FIELD_VALIDATORS,
FormFieldValidator,
FormValues,
FormModel,
AppConfigService,
ContentLinkModel
} from '@alfresco/adf-core';
import { FormCloudService } from '../services/form-cloud.service';
@@ -106,9 +104,7 @@ export class FormCloudComponent extends FormBaseComponent implements OnChanges,
constructor(protected formCloudService: FormCloudService,
protected formService: FormService,
private notificationService: NotificationService,
protected visibilityService: WidgetVisibilityService,
private appConfigService: AppConfigService) {
protected visibilityService: WidgetVisibilityService) {
super();
this.formService.formContentClicked
@@ -123,7 +119,7 @@ export class FormCloudComponent extends FormBaseComponent implements OnChanges,
if (appName && appName.currentValue) {
if (this.taskId) {
this.getFormDefinitionWithFolderTask(this.appName, this.taskId, this.processInstanceId);
this.getFormByTaskId(appName.currentValue, this.taskId, this.appVersion);
} else if (this.formId) {
this.getFormById(appName.currentValue, this.formId, this.appVersion);
}
@@ -200,7 +196,6 @@ export class FormCloudComponent extends FormBaseComponent implements OnChanges,
parsedForm.validateForm();
this.form = parsedForm;
this.form.nodeId = '-my-';
this.form.contentHost = this.appConfigService.get('ecmHost');
this.onFormLoaded(this.form);
resolve(this.form);
},
@@ -230,7 +225,6 @@ export class FormCloudComponent extends FormBaseComponent implements OnChanges,
parsedForm.validateForm();
this.form = parsedForm;
this.form.nodeId = '-my-';
this.form.contentHost = this.appConfigService.get('ecmHost');
this.onFormLoaded(this.form);
},
(error) => {
@@ -239,31 +233,6 @@ export class FormCloudComponent extends FormBaseComponent implements OnChanges,
);
}
getFormDefinitionWithFolderTask(appName: string, taskId: string, processInstanceId: string) {
this.getFormDefinitionWithFolder(appName, taskId, processInstanceId);
}
async getFormDefinitionWithFolder(appName: string, taskId: string, processInstanceId: string) {
try {
await this.getFormByTaskId(appName, taskId, this.appVersion);
const hasUploadWidget = (<any> this.form).hasUpload;
if (hasUploadWidget) {
try {
const processStorageCloudModel = await this.formCloudService.getProcessStorageFolderTask(appName, taskId, processInstanceId).toPromise();
this.form.nodeId = processStorageCloudModel.nodeId;
this.form.contentHost = processStorageCloudModel.path;
} catch (error) {
this.notificationService.openSnackMessage('The content repo is not configured');
}
}
} catch (error) {
this.notificationService.openSnackMessage('Form service an error occour');
}
}
saveTaskForm() {
if (this.form && this.appName && this.taskId) {
this.formCloudService

View File

@@ -5,35 +5,11 @@
<span *ngIf="isRequired()">*</span>
</label>
<div class="adf-attach-widget-container">
<div id="adf-attach-widget-simple-upload" *ngIf="isSimpleUploadButton() && isUploadButtonVisible()">
<a mat-raised-button color="primary">
{{ 'FORM.FIELD.UPLOAD' | translate }}
<mat-icon>file_upload</mat-icon>
<input #uploadFiles
[multiple]="multipleOption"
type="file"
[id]="field.id"
(change)="onAttachFileChanged($event)"/>
</a>
</div>
<div class="adf-attach-widget__menu-upload" *ngIf="isUploadButtonVisible() && isMultipleSourceUpload()">
<button mat-raised-button color="primary" [matMenuTriggerFor]="menu" [id]="field.id">
{{ 'FORM.FIELD.UPLOAD' | translate }}
<mat-icon>attach_file</mat-icon>
<div class="adf-attach-widget__menu-upload" *ngIf="isUploadButtonVisible()">
<button (click)="openSelectDialog()" mat-raised-button color="primary" [id]="field.id">
{{ 'FORM.FIELD.ATTACH' | translate }}
<mat-icon>{{getWidgetIcon()}}</mat-icon>
</button>
<mat-menu #menu="matMenu" class="adf-attach-widget__menu-content">
<div *ngIf="isContentSourceSelected()">
<button mat-menu-item
id="attach-{{field.params?.fileSource?.name}}"
(click)="uploadFileFromCS()">
{{field.params?.fileSource?.name}}
<mat-icon>
<img alt="alfresco" class="adf-attach-widget__image-logo"
src="./assets/images/alfresco-flower.svg">
</mat-icon>
</button>
</div>
</mat-menu>
</div>
</div>
</div>

View File

@@ -27,7 +27,8 @@ import {
FormFieldTypes,
FormFieldMetadata,
FormService,
DownloadService
DownloadService,
NotificationService
} from '@alfresco/adf-core';
import { ProcessServiceCloudTestingModule } from '../../../../testing/process-service-cloud.testing.module';
import { CUSTOM_ELEMENTS_SCHEMA } from '@angular/core';
@@ -44,6 +45,7 @@ describe('AttachFileCloudWidgetComponent', () => {
let element: HTMLInputElement;
let contentCloudNodeSelectorService: ContentCloudNodeSelectorService;
let processCloudContentService: ProcessCloudContentService;
let notificationService: NotificationService;
let formService: FormService;
let downloadService: DownloadService;
@@ -80,6 +82,22 @@ describe('AttachFileCloudWidgetComponent', () => {
}
};
const allSourceParams = {
fileSource: {
name: 'all file sources',
serviceId: 'all-file-sources',
destinationFolderPath: '-root-/myfiles'
}
};
const allSourceParamsWithWrongPath = {
fileSource: {
name: 'all file sources',
serviceId: 'all-file-sources',
destinationFolderPath: 'mock-folder'
}
};
const fakeMinimalNode: Node = <Node> {
id: 'fake',
name: 'fake-name',
@@ -88,25 +106,9 @@ describe('AttachFileCloudWidgetComponent', () => {
}
};
const fakeLocalPngAnswer = {
id: 1155,
nodeId: 1155,
name: 'a_png_file.png',
created: '2017-07-25T17:17:37.099Z',
createdBy: {
id: 1001,
firstName: 'Admin',
lastName: 'admin',
email: 'admin'
},
relatedContent: false,
contentAvailable: true,
link: false,
mimeType: 'image/png',
simpleType: 'image',
previewStatus: 'queued',
thumbnailStatus: 'queued'
};
const mockNodeId = new Promise(function (resolve) {
resolve('mock-node-id');
});
setupTestBed({
imports: [
@@ -128,23 +130,20 @@ describe('AttachFileCloudWidgetComponent', () => {
ContentCloudNodeSelectorService
);
formService = TestBed.inject(FormService);
notificationService = TestBed.inject(NotificationService);
}));
afterEach(() => {
fixture.destroy();
});
it('should be able to create the widget', () => {
expect(widget).not.toBeNull();
});
it('should show up as simple upload when is configured for only local files', async(() => {
widget.field = new FormFieldModel(new FormModel(), {
type: FormFieldTypes.UPLOAD,
value: []
});
widget.field.id = 'simple-upload-button';
widget.field.params = <FormFieldMetadata> onlyLocalParams;
widget.field.params = <FormFieldMetadata> allSourceParams;
fixture.detectChanges();
fixture.whenStable().then(() => {
expect(
@@ -168,7 +167,7 @@ describe('AttachFileCloudWidgetComponent', () => {
});
}));
it('should be able to attach files coming from content selector', async(() => {
it('should be able to attach files coming from content selector', async() => {
spyOn(
contentCloudNodeSelectorService,
'openUploadFileDialog'
@@ -180,47 +179,108 @@ describe('AttachFileCloudWidgetComponent', () => {
widget.field.id = 'attach-file-alfresco';
widget.field.params = <FormFieldMetadata> contentSourceParam;
fixture.detectChanges();
fixture.whenStable().then(() => {
const attachButton: HTMLButtonElement = element.querySelector(
'#attach-file-alfresco'
);
expect(attachButton).not.toBeNull();
attachButton.click();
fixture.whenStable().then(() => {
fixture.detectChanges();
fixture.debugElement
.query(By.css('#attach-mock-alf-content'))
.nativeElement.click();
fixture.detectChanges();
expect(element.querySelector('#file-fake-icon')).not.toBeNull();
});
});
}));
await fixture.whenStable();
const attachButton: HTMLButtonElement = element.querySelector('#attach-file-alfresco');
it('should be able to upload files from local source', async(() => {
expect(attachButton).not.toBeNull();
attachButton.click();
await fixture.whenStable();
fixture.detectChanges();
const attachedFileName = fixture.debugElement.query(By.css('.adf-file'));
const fileIcon = element.querySelector('#file-fake-icon');
expect(attachedFileName.nativeElement.innerText).toEqual('fake-name');
expect(fileIcon).not.toBeNull();
});
it('should be able to attach files coming from all files source', async() => {
spyOn(contentCloudNodeSelectorService, 'fetchNodeIdFromRelativePath').and.returnValue(mockNodeId);
spyOn(
contentCloudNodeSelectorService,
'openUploadFileDialog'
).and.returnValue(of([fakeMinimalNode]));
widget.field = new FormFieldModel(new FormModel(), {
type: FormFieldTypes.UPLOAD,
value: []
});
widget.field.id = 'attach-file-local';
widget.field.params = <FormFieldMetadata> onlyLocalParams;
spyOn(
processCloudContentService,
'createTemporaryRawRelatedContent'
).and.returnValue(of(fakeLocalPngAnswer));
widget.field.id = 'attach-file-alfresco';
widget.field.params = <FormFieldMetadata> allSourceParams;
fixture.detectChanges();
fixture.whenStable().then(() => {
fixture.detectChanges();
const inputDebugElement = fixture.debugElement.query(
By.css('#attach-file-local')
);
inputDebugElement.triggerEventHandler('change', {
target: { files: [fakeLocalPngAnswer] }
});
fixture.detectChanges();
expect(element.querySelector('#file-1155-icon')).not.toBeNull();
await fixture.whenStable();
const attachButton: HTMLButtonElement = element.querySelector('#attach-file-alfresco');
expect(attachButton).not.toBeNull();
attachButton.click();
await fixture.whenStable();
fixture.detectChanges();
const attachedFileName = fixture.debugElement.query(By.css('.adf-file'));
const fileIcon = element.querySelector('#file-fake-icon');
expect(attachedFileName.nativeElement.innerText).toEqual('fake-name');
expect(fileIcon).not.toBeNull();
});
it('should be able to fetch nodeId if destinationFolderPtah defined ', async() => {
const fetchNodeIdFromRelativePathSpy = spyOn(contentCloudNodeSelectorService, 'fetchNodeIdFromRelativePath').and.returnValue(mockNodeId);
spyOn(
contentCloudNodeSelectorService,
'openUploadFileDialog'
).and.returnValue(of([fakeMinimalNode]));
widget.field = new FormFieldModel(new FormModel(), {
type: FormFieldTypes.UPLOAD,
value: []
});
}));
widget.field.id = 'attach-file-alfresco';
widget.field.params = <FormFieldMetadata> allSourceParams;
fixture.detectChanges();
await fixture.whenStable();
const attachButton: HTMLButtonElement = element.querySelector('#attach-file-alfresco');
expect(attachButton).not.toBeNull();
attachButton.click();
await fixture.whenStable();
fixture.detectChanges();
const alias = '-root-';
const opt = { relativePath: '/myfiles' };
expect(fetchNodeIdFromRelativePathSpy).toHaveBeenCalledWith(alias, opt);
expect(widget.field.params.fileSource.destinationFolderPath).toBe('-root-/myfiles');
expect(widget.rootNodeId).toEqual('mock-node-id');
});
it('should be able to show error notification if destinationFolderPtah wrong/undefined', async() => {
const fetchNodeIdFromRelativePathSpy = spyOn(contentCloudNodeSelectorService, 'fetchNodeIdFromRelativePath').and.returnValue(mockNodeId);
spyOn(
contentCloudNodeSelectorService,
'openUploadFileDialog'
).and.returnValue(of([fakeMinimalNode]));
widget.field = new FormFieldModel(new FormModel(), {
type: FormFieldTypes.UPLOAD,
value: []
});
const showErrorSpy = spyOn(notificationService, 'showError').and.callThrough();
widget.field = new FormFieldModel(new FormModel(), {
type: FormFieldTypes.UPLOAD,
value: []
});
widget.field.id = 'attach-file-alfresco';
widget.field.params = <FormFieldMetadata> allSourceParamsWithWrongPath;
fixture.detectChanges();
await fixture.whenStable();
const attachButton: HTMLButtonElement = element.querySelector('#attach-file-alfresco');
expect(attachButton).not.toBeNull();
attachButton.click();
await fixture.whenStable();
fixture.detectChanges();
expect(fetchNodeIdFromRelativePathSpy).not.toHaveBeenCalled();
expect(showErrorSpy).toHaveBeenCalled();
});
it('should display file list when field has value', async(() => {
widget.field = new FormFieldModel(new FormModel(), {
@@ -249,38 +309,6 @@ describe('AttachFileCloudWidgetComponent', () => {
});
});
it('should be able to enable multiple file upload', async(() => {
const files = [fakeLocalPngAnswer, { ...fakeLocalPngAnswer, id: 1166, nodeId: 1166, name: 'second_png_file.png' }];
widget.field = new FormFieldModel(new FormModel(), {
type: FormFieldTypes.UPLOAD,
id: 'attach-file',
name: 'Upload',
value: [],
params: { onlyLocalParams, multiple: true }
});
spyOn(processCloudContentService, 'createTemporaryRawRelatedContent')
.and.returnValues(of(files[0]), of(files[1]));
fixture.detectChanges();
fixture.whenStable().then(() => {
const inputDebugElement = fixture.debugElement.query(By.css('#attach-file'));
expect(inputDebugElement.nativeElement.multiple).toBe(true);
inputDebugElement.triggerEventHandler('change', {
target: { files: [ files[0] ] }
});
fixture.detectChanges();
expect(element.querySelector('#file-1155-icon')).toBeDefined();
let name: HTMLElement = element.querySelector('span[id="file-1155"]');
expect(name.innerText).toEqual('a_png_file.png');
inputDebugElement.triggerEventHandler('change', {
target: { files: [ files[1] ] }
});
fixture.detectChanges();
expect(element.querySelector('#file-1166-icon')).toBeDefined();
name = element.querySelector('span[id="file-1166"]');
expect(name.innerText).toEqual('second_png_file.png');
});
}));
describe('when is readonly', () => {
it('should show empty list message when there are no file', async(() => {
@@ -332,46 +360,44 @@ describe('AttachFileCloudWidgetComponent', () => {
});
describe('when a file is uploaded', () => {
beforeEach(async(() => {
beforeEach(async() => {
spyOn(
contentCloudNodeSelectorService,
'openUploadFileDialog'
).and.returnValue(of([fakeMinimalNode]));
widget.field = new FormFieldModel(new FormModel(), {
type: FormFieldTypes.UPLOAD,
value: []
});
widget.field.id = 'attach-file-attach';
widget.field.params = <FormFieldMetadata> onlyLocalParams;
spyOn(
processCloudContentService,
'createTemporaryRawRelatedContent'
).and.returnValue(of(fakeLocalPngAnswer));
widget.field.id = 'attach-file-alfresco';
widget.field.params = <FormFieldMetadata> contentSourceParam;
fixture.detectChanges();
fixture.whenStable().then(() => {
const inputDebugElement = fixture.debugElement.query(
By.css('#attach-file-attach')
);
inputDebugElement.triggerEventHandler('change', {
target: { files: [fakeLocalPngAnswer] }
});
fixture.detectChanges();
expect(element.querySelector('#file-1155-icon')).not.toBeNull();
});
}));
await fixture.whenStable();
const attachButton: HTMLButtonElement = element.querySelector('#attach-file-alfresco');
expect(attachButton).not.toBeNull();
attachButton.click();
fixture.detectChanges();
await fixture.whenStable();
});
it('should remove file when remove is clicked', (done) => {
fixture.detectChanges();
const menuButton: HTMLButtonElement = <HTMLButtonElement> (
fixture.debugElement.query(By.css('#file-1155-option-menu'))
fixture.debugElement.query(By.css('#file-fake-option-menu'))
.nativeElement
);
menuButton.click();
fixture.detectChanges();
const removeOption: HTMLButtonElement = <HTMLButtonElement> (
fixture.debugElement.query(By.css('#file-1155-remove'))
fixture.debugElement.query(By.css('#file-fake-remove'))
.nativeElement
);
removeOption.click();
fixture.detectChanges();
fixture.whenRenderingDone().then(() => {
expect(element.querySelector('#file-1155-icon')).toBeNull();
expect(element.querySelector('#file-fake-icon')).toBeNull();
done();
});
});
@@ -384,7 +410,7 @@ describe('AttachFileCloudWidgetComponent', () => {
fixture.detectChanges();
const menuButton: HTMLButtonElement = <HTMLButtonElement> (
fixture.debugElement.query(By.css('#file-1155-option-menu'))
fixture.debugElement.query(By.css('#file-fake-option-menu'))
.nativeElement
);
@@ -392,7 +418,7 @@ describe('AttachFileCloudWidgetComponent', () => {
fixture.detectChanges();
const downloadOption: HTMLButtonElement = <HTMLButtonElement> (
fixture.debugElement.query(By.css('#file-1155-download-file'))
fixture.debugElement.query(By.css('#file-fake-download-file'))
.nativeElement
);
@@ -409,7 +435,7 @@ describe('AttachFileCloudWidgetComponent', () => {
spyOn(processCloudContentService, 'getRawContentNode').and.returnValue(of(new Blob()));
formService.formContentClicked.subscribe(
(fileClicked: any) => {
expect(fileClicked.nodeId).toBe(1155);
expect(fileClicked.nodeId).toBe('fake');
done();
}
);
@@ -417,14 +443,14 @@ describe('AttachFileCloudWidgetComponent', () => {
fixture.detectChanges();
const menuButton: HTMLButtonElement = <HTMLButtonElement> (
fixture.debugElement.query(
By.css('#file-1155-option-menu')
By.css('#file-fake-option-menu')
).nativeElement
);
menuButton.click();
fixture.detectChanges();
const showOption: HTMLButtonElement = <HTMLButtonElement> (
fixture.debugElement.query(
By.css('#file-1155-show-file')
By.css('#file-fake-show-file')
).nativeElement
);
showOption.click();

View File

@@ -23,7 +23,8 @@ import {
LogService,
ThumbnailService,
NotificationService,
ContentLinkModel
ContentLinkModel,
TranslationService
} from '@alfresco/adf-core';
import { Node, RelatedContentRepresentation } from '@alfresco/js-api';
import { ContentCloudNodeSelectorService } from '../../../services/content-cloud-node-selector.service';
@@ -49,9 +50,9 @@ import { UploadCloudWidgetComponent } from './upload-cloud.widget';
})
export class AttachFileCloudWidgetComponent extends UploadCloudWidgetComponent
implements OnInit {
static ACS_SERVICE = 'alfresco-content';
typeId = 'AttachFileCloudWidgetComponent';
rootNodeId = '-my-';
constructor(
formService: FormService,
@@ -59,35 +60,18 @@ export class AttachFileCloudWidgetComponent extends UploadCloudWidgetComponent
thumbnails: ThumbnailService,
processCloudContentService: ProcessCloudContentService,
notificationService: NotificationService,
private contentNodeSelectorService: ContentCloudNodeSelectorService
private contentNodeSelectorService: ContentCloudNodeSelectorService,
private translationService: TranslationService
) {
super(formService, thumbnails, processCloudContentService, notificationService, logger);
}
isFileSourceConfigured(): boolean {
return !!this.field.params && !!this.field.params.fileSource;
}
isMultipleSourceUpload(): boolean {
return (
!this.field.readOnly &&
this.isFileSourceConfigured() &&
!this.isOnlyLocalSourceSelected()
);
}
isOnlyLocalSourceSelected(): boolean {
isAlfrescoAndLocal(): boolean {
return (
this.field.params &&
this.field.params.fileSource &&
this.field.params.fileSource.serviceId === 'local-file'
);
}
isSimpleUploadButton(): boolean {
return (
(this.isUploadButtonVisible() && !this.isFileSourceConfigured()) ||
this.isOnlyLocalSourceSelected()
this.field.params.fileSource.serviceId === 'all-file-sources'
|| this.field.params.fileSource.serviceId === 'local-file'
);
}
@@ -95,23 +79,31 @@ export class AttachFileCloudWidgetComponent extends UploadCloudWidgetComponent
return (!this.hasFile || this.multipleOption) && !this.field.readOnly;
}
onAttachFileChanged(event: any) {
this.onFileChanged(event);
}
onRemoveAttachFile(file: File | RelatedContentRepresentation | Node) {
this.removeFile(file);
}
uploadFileFromCS() {
this.openSelectDialog();
}
openSelectDialog() {
async openSelectDialog() {
const selectedMode = this.field.params.multiple ? 'multiple' : 'single';
if (this.isAlfrescoAndLocal()) {
const destinationFolderPath = this.field.params.fileSource.destinationFolderPath;
const alias = this.getAliasFromDestinationFolderPath(destinationFolderPath);
const opts = {
relativePath: this.getRelativePathFromDestinationFolderPath(destinationFolderPath)
};
if (alias && opts && opts.relativePath) {
await this.contentNodeSelectorService.fetchNodeIdFromRelativePath(alias, opts).then((nodeId: string) => {
this.rootNodeId = nodeId;
});
} else {
const errorMessage = this.translationService.instant('ADF_CLOUD_TASK_FORM.ERROR.INVALID_DESTINATION_FOLDER_PATH');
this.notificationService.showError(errorMessage);
}
}
this.contentNodeSelectorService
.openUploadFileDialog(this.field.form.contentHost, '-my-', selectedMode)
.openUploadFileDialog(this.rootNodeId, selectedMode, this.isAlfrescoAndLocal())
.subscribe((selections: Node[]) => {
selections.forEach(node => (node['isExternal'] = true));
const selectionWithoutDuplication = this.removeExistingSelection(selections);
@@ -119,29 +111,31 @@ export class AttachFileCloudWidgetComponent extends UploadCloudWidgetComponent
});
}
getAliasFromDestinationFolderPath(destinationFolderPath: string): string {
const startOfRelativePathIndex = destinationFolderPath.indexOf('/');
return destinationFolderPath.substring(0, startOfRelativePathIndex);
}
getRelativePathFromDestinationFolderPath(destinationFolderPath: string): string {
const startOfRelativePathIndex = destinationFolderPath.indexOf('/');
return destinationFolderPath.substring(startOfRelativePathIndex, destinationFolderPath.length);
}
removeExistingSelection(selections: Node[]) {
const existingNode: Node[] = [...this.field.value || []];
return selections.filter(opt => !existingNode.some( (node) => node.id === opt.id));
}
isContentSourceSelected(): boolean {
return (
this.field.params &&
this.field.params.fileSource &&
this.field.params.fileSource.serviceId ===
AttachFileCloudWidgetComponent.ACS_SERVICE
);
}
downloadContent(file: Node): void {
this.processCloudContentService.downloadFile(
file.id,
this.field.form.contentHost
);
this.processCloudContentService.downloadFile(file.id);
}
onAttachFileClicked(nodeSelector: any) {
nodeSelector.nodeId = nodeSelector.id;
this.fileClicked(new ContentLinkModel(nodeSelector));
}
getWidgetIcon(): string {
return this.isAlfrescoAndLocal() ? 'file_upload' : 'attach_file';
}
}

View File

@@ -124,9 +124,7 @@ export class UploadCloudWidgetComponent extends WidgetComponent implements OnIni
}
private uploadRawContent(file: File): Observable<Node> {
return this.processCloudContentService.createTemporaryRawRelatedContent(
file, this.field.form.nodeId, this.field.form.contentHost
);
return this.processCloudContentService.createTemporaryRawRelatedContent(file, this.field.form.nodeId);
}
getMultipleFileParam() {

View File

@@ -23,16 +23,3 @@ export class TaskVariableCloud {
this.value = obj.value || null;
}
}
export class ProcessStorageCloudModel {
nodeId: string;
path: string;
type: string;
constructor(obj) {
this.nodeId = obj.nodeId || null;
this.path = obj.path || null;
this.type = obj.type || null;
}
}

View File

@@ -32,30 +32,35 @@ export class ContentCloudNodeSelectorService {
private dialog: MatDialog) {
}
openUploadFileDialog(contentHost: string, currentFolderId?: string, selectionMode?: string): Observable<Node[]> {
const changedConfig = this.apiService.lastConfig;
changedConfig.provider = 'ALL';
changedConfig.hostEcm = contentHost.replace('/alfresco', '');
this.apiService.getInstance().setConfig(changedConfig);
openUploadFileDialog(currentFolderId?: string, selectionMode?: string, showLocalUploadButton?: boolean): Observable<Node[]> {
const select = new Subject<Node[]>();
select.subscribe({
complete: this.close.bind(this)
});
const data = <ContentNodeSelectorComponentData> {
title: 'Select a file',
actionName: 'Choose',
actionName: 'Attach',
currentFolderId,
restrictRootToCurrentFolderId: true,
select,
selectionMode,
isSelectionValid: (entry: Node) => entry.isFile,
showFilesInResult: true
};
showFilesInResult: true,
showDropdownSiteList: false,
showLocalUploadButton
};
this.openContentNodeDialog(data, 'adf-content-node-selector-dialog', '630px');
return select;
}
async fetchNodeIdFromRelativePath(alias: string, opts: { relativePath: string }): Promise<string> {
let nodeId = '';
await this.apiService.getInstance().node.getNode(alias, opts).then(node => {
nodeId = node.entry.id;
});
return nodeId;
}
private openContentNodeDialog(data: ContentNodeSelectorComponentData, currentPanelClass: string, chosenWidth: string) {
this.dialog.open(ContentNodeSelectorComponent, { data, panelClass: currentPanelClass, width: chosenWidth });
}

View File

@@ -183,45 +183,6 @@ describe('Form Cloud service', () => {
expect(oauth2Auth.callCustomApi.calls.mostRecent().args[1]).toBe('POST');
done();
});
});
it('should fetch process storage folder with process instance id and task id', (done) => {
oauth2Auth.callCustomApi.and.returnValue(Promise.resolve({
nodeId: 'fake-node-id-really-long',
path: 'path/to/node/id',
type: 'nodeType'
}));
service.getProcessStorageFolderTask(appName, taskId, processInstanceId).subscribe((result) => {
expect(result).toBeDefined();
expect(result).not.toBeNull();
expect(result.nodeId).toBe('fake-node-id-really-long');
expect(result.path).toBe('path/to/node/id');
expect(result.type).toBe('nodeType');
expect(oauth2Auth.callCustomApi.calls.mostRecent().args[0].endsWith(`${appName}/process-storage/v1/folders/${processInstanceId}/${taskId}`)).toBeTruthy();
expect(oauth2Auth.callCustomApi.calls.mostRecent().args[1]).toBe('GET');
done();
});
});
it('should fetch process storage folder with task id only', (done) => {
oauth2Auth.callCustomApi.and.returnValue(Promise.resolve({
nodeId: 'fake-node-id-really-long',
path: 'path/to/node/id',
type: 'nodeType'
}));
service.getProcessStorageFolderTask(appName, taskId, null).subscribe((result) => {
expect(result).toBeDefined();
expect(result).not.toBeNull();
expect(result.nodeId).toBe('fake-node-id-really-long');
expect(result.path).toBe('path/to/node/id');
expect(result.type).toBe('nodeType');
expect(oauth2Auth.callCustomApi.calls.mostRecent().args[0].endsWith(`${appName}/process-storage/v1/folders/${taskId}`)).toBeTruthy();
expect(oauth2Auth.callCustomApi.calls.mostRecent().args[1]).toBe('GET');
done();
});
});
});
});

View File

@@ -27,7 +27,7 @@ import { Observable, from } from 'rxjs';
import { map, switchMap } from 'rxjs/operators';
import { TaskDetailsCloudModel } from '../../task/start-task/models/task-details-cloud.model';
import { CompleteFormRepresentation } from '@alfresco/js-api';
import { TaskVariableCloud, ProcessStorageCloudModel } from '../models/task-variable-cloud.model';
import { TaskVariableCloud } from '../models/task-variable-cloud.model';
import { BaseCloudService } from '../../services/base-cloud.service';
import { FormContent } from '../../services/form-fields.interfaces';
@@ -151,16 +151,6 @@ export class FormCloudService extends BaseCloudService {
);
}
getProcessStorageFolderTask(appName: string, taskId: string, processInstanceId: string): Observable<ProcessStorageCloudModel> {
const apiUrl = this.buildFolderTask(appName, taskId, processInstanceId);
return this.get(apiUrl).pipe(
map((res: any) => {
return new ProcessStorageCloudModel(res);
})
);
}
/**
* Gets the variables of a task.
* @param appName Name of the app
@@ -237,10 +227,4 @@ export class FormCloudService extends BaseCloudService {
}
return null;
}
private buildFolderTask(appName: string, taskId: string, processInstanceId: string): string {
return processInstanceId
? `${this.getBasePath(appName)}/process-storage/v1/folders/${processInstanceId}/${taskId}`
: `${this.getBasePath(appName)}/process-storage/v1/folders/${taskId}`;
}
}

View File

@@ -39,10 +39,8 @@ export class ProcessCloudContentService {
createTemporaryRawRelatedContent(
file: File,
nodeId: string,
contentHost: string
nodeId: string
): Observable<Node> {
this.updateConfig(contentHost);
return from(
this.apiService
@@ -59,8 +57,7 @@ export class ProcessCloudContentService {
);
}
getRawContentNode(nodeId: string, contentHost: string): Observable<Blob> {
this.updateConfig(contentHost);
getRawContentNode(nodeId: string): Observable<Blob> {
return this.contentService.getNodeContent(nodeId);
}
@@ -68,8 +65,7 @@ export class ProcessCloudContentService {
this.contentService.downloadBlob(blob, fileName);
}
async downloadFile(nodeId: string, contentHost: string) {
this.updateConfig(contentHost);
async downloadFile(nodeId: string) {
const ticket = await this.getAuthTicket();
const url = this.contentService.getContentUrl(nodeId, true, ticket);
@@ -88,18 +84,6 @@ export class ProcessCloudContentService {
return '';
}
private updateConfig(contentHost: string) {
const changedConfig = this.apiService.lastConfig;
changedConfig.provider = 'ALL';
if (contentHost) {
changedConfig.hostEcm = contentHost.replace('/alfresco', '');
}
this.apiService.getInstance().setConfig(changedConfig);
}
private handleError(error: any) {
this.logService.error(error);
return throwError(error || 'Server error');

View File

@@ -266,6 +266,9 @@
"CLAIM": "CLAIM",
"UNCLAIM": "RELEASE"
}
},
"ERROR": {
"INVALID_DESTINATION_FOLDER_PATH": "Invalid destination folder path"
}
}