[ADF-4823] added download and show preview for attach cloud widget (#4996)

* [ADF-4823] fixed download and start fixing show preview

* [ADF-4823] fixed preview files

* [ADF-4823] - added unit test

* [ADF-4823] - fixed lint problem

* [ADF-4823] - rebased and fixed lint problem

* added a new method in BrowserActions to check that the action menu is visible, and using that in the tests.

* linting fixes
This commit is contained in:
Vito
2019-09-03 11:10:40 +01:00
committed by Eugenio Romano
parent c142371222
commit 19a17ca6e6
14 changed files with 478 additions and 281 deletions

View File

@@ -10,6 +10,7 @@
(taskCompleted)="onTaskCompleted()"
(taskClaimed)="onTaskClaimed()"
(taskUnclaimed)="onTaskUnclaimed()"
(formContentClicked)="onFormContentClicked($event)"
(formSaved)="onFormSaved()">
</adf-cloud-task-form>
</div>

View File

@@ -19,6 +19,7 @@ import { Component, ViewChild } from '@angular/core';
import { ActivatedRoute, Router } from '@angular/router';
import { NotificationService } from '@alfresco/adf-core';
import { TaskHeaderCloudComponent } from '@alfresco/adf-process-services-cloud';
import { PreviewService } from 'app/services/preview.service';
@Component({
templateUrl: './task-details-cloud-demo.component.html',
@@ -35,7 +36,8 @@ export class TaskDetailsCloudDemoComponent {
constructor(
private route: ActivatedRoute,
private router: Router,
private notificationService: NotificationService
private notificationService: NotificationService,
private previewService: PreviewService
) {
this.route.params.subscribe((params) => {
this.taskId = params.taskId;
@@ -66,8 +68,8 @@ export class TaskDetailsCloudDemoComponent {
this.taskHeader.ngOnInit();
}
onFormContentClicked(resourceId) {
this.router.navigate([`/cloud/${this.appName}/task-details/${this.taskId}/files/${resourceId.nodeId}/view`]);
onFormContentClicked(resourceClicked: any) {
this.previewService.showResource(resourceClicked.nodeId);
}
onFormSaved() {

View File

@@ -25,6 +25,7 @@
created: Date;
createdBy: any;
id: number;
nodeId: string;
link: boolean;
mimeType: string;
name: string;
@@ -48,6 +49,7 @@
this.relatedContent = obj && obj.relatedContent;
this.simpleType = obj && obj.simpleType;
this.thumbnailStatus = obj && obj.thumbnailStatus;
this.nodeId = obj && obj.nodeId;
}
hasPreviewStatus(): boolean {

View File

@@ -48,10 +48,28 @@
tabindex="0"/>
<span matLine id="{{'file-'+file?.nodeId}}"
role="button" tabindex="0" class="adf-file">{{file.name}}</span>
<button *ngIf="!field.readOnly" mat-icon-button [id]="'file-'+file?.nodeId+'-remove'"
(click)="onRemoveAttachFile(file);" (keyup.enter)="onRemoveAttachFile(file);">
<mat-icon class="mat-24">highlight_off</mat-icon>
<button id="{{'file-'+file?.nodeId+'-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"
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'}}"
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'"
(click)="onRemoveAttachFile(file);" (keyup.enter)="onRemoveAttachFile(file);">
<mat-icon class="mat-24">highlight_off</mat-icon>
<span>{{ 'FORM.FIELD.REMOVE_FILE' | translate }}</span>
</button>
</mat-menu>
</mat-list-item>
</mat-list>
</div>

View File

@@ -20,7 +20,14 @@ import { async, ComponentFixture, TestBed } from '@angular/core/testing';
import { ContentCloudNodeSelectorService } from '../../services/content-cloud-node-selector.service';
import { ProcessCloudContentService } from '../../services/process-cloud-content.service';
import { AttachFileCloudWidgetComponent } from './attach-file-cloud-widget.component';
import { setupTestBed, FormFieldModel, FormModel, FormFieldTypes, FormFieldMetadata } from '@alfresco/adf-core';
import {
setupTestBed,
FormFieldModel,
FormModel,
FormFieldTypes,
FormFieldMetadata,
FormService
} from '@alfresco/adf-core';
import { ProcessServiceCloudTestingModule } from '../../../testing/process-service-cloud.testing.module';
import { CUSTOM_ELEMENTS_SCHEMA } from '@angular/core';
import { ContentModule } from '@alfresco/adf-content-services';
@@ -30,193 +37,288 @@ import { Node } from '@alfresco/js-api';
import { FormCloudModule } from '../../form-cloud.module';
describe('AttachFileCloudWidgetComponent', () => {
let widget: AttachFileCloudWidgetComponent;
let fixture: ComponentFixture<AttachFileCloudWidgetComponent>;
let element: HTMLInputElement;
let contentCloudNodeSelectorService: ContentCloudNodeSelectorService;
let processCloudContentService: ProcessCloudContentService;
let widget: AttachFileCloudWidgetComponent;
let fixture: ComponentFixture<AttachFileCloudWidgetComponent>;
let element: HTMLInputElement;
let contentCloudNodeSelectorService: ContentCloudNodeSelectorService;
let processCloudContentService: ProcessCloudContentService;
let formService: FormService;
const fakePngAnswer = {
'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 fakePngAnswer = {
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 onlyLocalParams = {
fileSource: {
serviceId: 'local-file'
}
};
const onlyLocalParams = {
fileSource: {
serviceId: 'local-file'
}
};
const contentSourceParam = {
fileSource: {
name: 'mock-alf-content',
serviceId: 'alfresco-content'
}
};
const contentSourceParam = {
fileSource: {
name: 'mock-alf-content',
serviceId: 'alfresco-content'
}
};
const fakeMinimalNode: Node = <Node> {
id: 'fake',
name: 'fake-name',
content: {
mimeType: 'application/pdf'
}
};
const fakeMinimalNode: Node = <Node> {
id: 'fake',
name: 'fake-name',
content: {
mimeType: 'application/pdf'
}
};
const fakeLocalPngAnswer = {
'id': 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 fakeLocalPngAnswer = {
id: 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'
};
setupTestBed({
imports: [
ProcessServiceCloudTestingModule,
FormCloudModule,
ContentModule.forRoot()
],
providers: [],
schemas: [CUSTOM_ELEMENTS_SCHEMA]
});
beforeEach(async(() => {
fixture = TestBed.createComponent(AttachFileCloudWidgetComponent);
widget = fixture.componentInstance;
element = fixture.nativeElement;
processCloudContentService = TestBed.get(ProcessCloudContentService);
contentCloudNodeSelectorService = TestBed.get(ContentCloudNodeSelectorService);
}));
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: []
setupTestBed({
imports: [
ProcessServiceCloudTestingModule,
FormCloudModule,
ContentModule.forRoot()
],
providers: [],
schemas: [CUSTOM_ELEMENTS_SCHEMA]
});
widget.field.id = 'simple-upload-button';
widget.field.params = <FormFieldMetadata> onlyLocalParams;
fixture.detectChanges();
fixture.whenStable().then(() => {
expect(element.querySelector('#simple-upload-button')).not.toBeNull();
});
}));
it('should show up as content upload when is configured with content', async(() => {
widget.field = new FormFieldModel(new FormModel(), {
type: FormFieldTypes.UPLOAD,
value: []
});
widget.field.id = 'attach-file-alfresco';
widget.field.params = <FormFieldMetadata> contentSourceParam;
fixture.detectChanges();
fixture.whenStable().then(() => {
expect(element.querySelector('.adf-attach-widget__menu-upload')).not.toBeNull();
});
}));
it('should be able to attach files coming from content selector', async(() => {
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> 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();
});
});
}));
it('should be able to upload files from local source', async(() => {
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));
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();
});
}));
it('should display file list when field has value', async(() => {
widget.field = new FormFieldModel(new FormModel(), {
type: FormFieldTypes.UPLOAD,
value: [fakePngAnswer]
});
widget.field.id = 'attach-file-attach';
widget.field.params = <FormFieldMetadata> onlyLocalParams;
fixture.detectChanges();
fixture.whenStable().then(() => {
expect(element.querySelector('#file-1155-icon')).not.toBeNull();
});
}));
describe('when a file is uploaded', () => {
beforeEach(async(() => {
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));
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();
});
fixture = TestBed.createComponent(AttachFileCloudWidgetComponent);
widget = fixture.componentInstance;
element = fixture.nativeElement;
processCloudContentService = TestBed.get(ProcessCloudContentService);
contentCloudNodeSelectorService = TestBed.get(
ContentCloudNodeSelectorService
);
formService = TestBed.get(FormService);
}));
it('should remove file when remove is clicked', async(() => {
fixture.detectChanges();
const removeOption: HTMLButtonElement = <HTMLButtonElement> fixture.debugElement.query(By.css('#file-1155-remove')).nativeElement;
removeOption.click();
fixture.detectChanges();
fixture.whenStable().then(() => {
expect(element.querySelector('#file-1155-icon')).toBeNull();
});
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;
fixture.detectChanges();
fixture.whenStable().then(() => {
expect(
element.querySelector('#simple-upload-button')
).not.toBeNull();
});
}));
});
it('should show up as content upload when is configured with content', async(() => {
widget.field = new FormFieldModel(new FormModel(), {
type: FormFieldTypes.UPLOAD,
value: []
});
widget.field.id = 'attach-file-alfresco';
widget.field.params = <FormFieldMetadata> contentSourceParam;
fixture.detectChanges();
fixture.whenStable().then(() => {
expect(
element.querySelector('.adf-attach-widget__menu-upload')
).not.toBeNull();
});
}));
it('should be able to attach files coming from content selector', async(() => {
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> 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();
});
});
}));
it('should be able to upload files from local source', async(() => {
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));
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();
});
}));
it('should display file list when field has value', async(() => {
widget.field = new FormFieldModel(new FormModel(), {
type: FormFieldTypes.UPLOAD,
value: [fakePngAnswer]
});
widget.field.id = 'attach-file-attach';
widget.field.params = <FormFieldMetadata> onlyLocalParams;
fixture.detectChanges();
fixture.whenStable().then(() => {
expect(element.querySelector('#file-1155-icon')).not.toBeNull();
});
}));
describe('when a file is uploaded', () => {
beforeEach(async(() => {
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));
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();
});
}));
it('should remove file when remove is clicked', (done) => {
fixture.detectChanges();
const menuButton: HTMLButtonElement = <HTMLButtonElement> (
fixture.debugElement.query(By.css('#file-1155-option-menu'))
.nativeElement
);
menuButton.click();
fixture.detectChanges();
const removeOption: HTMLButtonElement = <HTMLButtonElement> (
fixture.debugElement.query(By.css('#file-1155-remove'))
.nativeElement
);
removeOption.click();
fixture.detectChanges();
fixture.whenRenderingDone().then(() => {
expect(element.querySelector('#file-1155-icon')).toBeNull();
done();
});
});
it('should download file when download is clicked', (done) => {
spyOn(processCloudContentService, 'getRawContentNode').and.returnValue(of(new Blob()));
spyOn(processCloudContentService, 'downloadNodeContent').and.stub();
fixture.detectChanges();
const menuButton: HTMLButtonElement = <HTMLButtonElement> (
fixture.debugElement.query(By.css('#file-1155-option-menu'))
.nativeElement
);
menuButton.click();
fixture.detectChanges();
const downloadOption: HTMLButtonElement = <HTMLButtonElement> (
fixture.debugElement.query(By.css('#file-1155-download-file'))
.nativeElement
);
downloadOption.click();
fixture.detectChanges();
fixture.whenStable().then(() => {
expect(processCloudContentService.downloadNodeContent).toHaveBeenCalled();
done();
});
});
it('should preview file when show is clicked', (done) => {
spyOn(processCloudContentService, 'getRawContentNode').and.returnValue(of(new Blob()));
formService.formContentClicked.subscribe(
(fileClicked: any) => {
expect(fileClicked.nodeId).toBe(1155);
done();
}
);
fixture.detectChanges();
const menuButton: HTMLButtonElement = <HTMLButtonElement> (
fixture.debugElement.query(
By.css('#file-1155-option-menu')
).nativeElement
);
menuButton.click();
fixture.detectChanges();
const showOption: HTMLButtonElement = <HTMLButtonElement> (
fixture.debugElement.query(
By.css('#file-1155-show-file')
).nativeElement
);
showOption.click();
});
});
});

View File

@@ -22,7 +22,7 @@ import {
FormService,
LogService,
ThumbnailService,
ProcessContentService
ContentLinkModel
} from '@alfresco/adf-core';
import { RelatedContentRepresentation } from '@alfresco/js-api';
import { ContentCloudNodeSelectorService } from '../../services/content-cloud-node-selector.service';
@@ -30,99 +30,137 @@ import { ProcessCloudContentService } from '../../services/process-cloud-content
import { UploadCloudWidgetComponent } from '../upload-cloud.widget';
@Component({
selector: 'adf-cloud-attach-file-cloud-widget',
templateUrl: './attach-file-cloud-widget.component.html',
styleUrls: ['./attach-file-cloud-widget.component.scss'],
host: {
'(click)': 'event($event)',
'(blur)': 'event($event)',
'(change)': 'event($event)',
'(focus)': 'event($event)',
'(focusin)': 'event($event)',
'(focusout)': 'event($event)',
'(input)': 'event($event)',
'(invalid)': 'event($event)',
'(select)': 'event($event)'
},
encapsulation: ViewEncapsulation.None
selector: 'adf-cloud-attach-file-cloud-widget',
templateUrl: './attach-file-cloud-widget.component.html',
styleUrls: ['./attach-file-cloud-widget.component.scss'],
host: {
'(click)': 'event($event)',
'(blur)': 'event($event)',
'(change)': 'event($event)',
'(focus)': 'event($event)',
'(focusin)': 'event($event)',
'(focusout)': 'event($event)',
'(input)': 'event($event)',
'(invalid)': 'event($event)',
'(select)': 'event($event)'
},
encapsulation: ViewEncapsulation.None
})
export class AttachFileCloudWidgetComponent extends UploadCloudWidgetComponent implements OnInit {
export class AttachFileCloudWidgetComponent extends UploadCloudWidgetComponent
implements OnInit {
static ACS_SERVICE = 'alfresco-content';
static ACS_SERVICE = 'alfresco-content';
constructor(
public formService: FormService,
public logger: LogService,
public processContentService: ProcessContentService,
public thumbnails: ThumbnailService,
public processCloudContentService: ProcessCloudContentService,
public contentNodeSelectorService: ContentCloudNodeSelectorService) {
super(formService, thumbnails, processCloudContentService, logger);
}
ngOnInit() {
if (this.field &&
this.field.value &&
this.field.value.length > 0) {
this.hasFile = true;
constructor(
public formService: FormService,
public logger: LogService,
public thumbnails: ThumbnailService,
public processCloudContentService: ProcessCloudContentService,
public contentNodeSelectorService: ContentCloudNodeSelectorService
) {
super(formService, thumbnails, processCloudContentService, logger);
}
this.getMultipleFileParam();
}
isFileSourceConfigured(): boolean {
return !!this.field.params && !!this.field.params.fileSource;
}
ngOnInit() {
if (this.field && this.field.value && this.field.value.length > 0) {
this.hasFile = true;
}
this.getMultipleFileParam();
}
isMultipleSourceUpload(): boolean {
return !this.field.readOnly && this.isFileSourceConfigured() && !this.isOnlyLocalSourceSelected();
}
isFileSourceConfigured(): boolean {
return !!this.field.params && !!this.field.params.fileSource;
}
isOnlyLocalSourceSelected(): boolean {
return this.field.params &&
this.field.params.fileSource &&
this.field.params.fileSource.serviceId === 'local-file';
}
isMultipleSourceUpload(): boolean {
return (
!this.field.readOnly &&
this.isFileSourceConfigured() &&
!this.isOnlyLocalSourceSelected()
);
}
isSimpleUploadButton(): boolean {
return this.isUploadButtonVisible() &&
!this.isFileSourceConfigured() ||
this.isOnlyLocalSourceSelected();
}
isOnlyLocalSourceSelected(): boolean {
return (
this.field.params &&
this.field.params.fileSource &&
this.field.params.fileSource.serviceId === 'local-file'
);
}
isUploadButtonVisible(): boolean {
return (!this.hasFile || this.multipleOption) && !this.field.readOnly;
}
isSimpleUploadButton(): boolean {
return (
(this.isUploadButtonVisible() && !this.isFileSourceConfigured()) ||
this.isOnlyLocalSourceSelected()
);
}
onAttachFileChanged(event: any) {
this.onFileChanged(event);
}
isUploadButtonVisible(): boolean {
return (!this.hasFile || this.multipleOption) && !this.field.readOnly;
}
onRemoveAttachFile(file: File | RelatedContentRepresentation) {
this.removeFile(file);
}
onAttachFileChanged(event: any) {
this.onFileChanged(event);
}
uploadFileFromCS() {
this.openSelectDialog();
}
onRemoveAttachFile(file: File | RelatedContentRepresentation) {
this.removeFile(file);
}
openSelectDialog() {
const filesSaved = [];
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);
this.fixIncompatibilityFromPreviousAndNewForm(filesSaved);
});
}
uploadFileFromCS() {
this.openSelectDialog();
}
isContentSourceSelected(): boolean {
return this.field.params &&
this.field.params.fileSource &&
this.field.params.fileSource.serviceId === AttachFileCloudWidgetComponent.ACS_SERVICE;
}
openSelectDialog() {
const filesSaved = [];
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);
this.fixIncompatibilityFromPreviousAndNewForm(filesSaved);
});
}
isContentSourceSelected(): boolean {
return (
this.field.params &&
this.field.params.fileSource &&
this.field.params.fileSource.serviceId ===
AttachFileCloudWidgetComponent.ACS_SERVICE
);
}
downloadContent(file: any): void {
this.processCloudContentService
.getRawContentNode(file.nodeId, this.field.form.contentHost)
.subscribe(
(blob: Blob) => {
this.processCloudContentService.downloadNodeContent(
blob,
file.name
);
},
() => {
this.logger.error(
'Impossible retrieve content for download'
);
}
);
}
onAttachFileClicked(file: ContentLinkModel) {
this.processCloudContentService
.getRawContentNode(file.nodeId, this.field.form.contentHost)
.subscribe(
(blob: Blob) => {
file.contentBlob = blob;
this.fileClicked(file);
});
}
}

View File

@@ -236,7 +236,7 @@ export class FormCloudComponent extends FormBaseComponent implements OnChanges,
await this.getFormByTaskId(appName, taskId);
const hasUploadWidget = (<any> this.form).hasUpload;
if (hasUploadWidget && !this.readOnly) {
if (hasUploadWidget) {
try {
const processStorageCloudModel = await this.formCloudService.getProcessStorageFolderTask(appName, taskId, processInstanceId).toPromise();
this.form.nodeId = processStorageCloudModel.nodeId;

View File

@@ -20,7 +20,7 @@
import { Component, ElementRef, OnInit, ViewChild, ViewEncapsulation } from '@angular/core';
import { Observable, from } from 'rxjs';
import { mergeMap, map, catchError } from 'rxjs/operators';
import { WidgetComponent, baseHost, LogService, FormService, ThumbnailService } from '@alfresco/adf-core';
import { WidgetComponent, baseHost, LogService, FormService, ThumbnailService, ContentLinkModel } from '@alfresco/adf-core';
import { ProcessCloudContentService } from '../services/process-cloud-content.service';
@Component({
@@ -122,7 +122,8 @@ export class UploadCloudWidgetComponent extends WidgetComponent implements OnIni
}
private removeElementFromList(file) {
const savedValues = this.field.form.values[this.field.id];
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);
@@ -142,7 +143,7 @@ export class UploadCloudWidgetComponent extends WidgetComponent implements OnIni
}
}
fileClicked(nodeId: any): void {
this.formService.formContentClicked.next(nodeId);
fileClicked(file: ContentLinkModel): void {
this.formService.formContentClicked.next(file);
}
}

View File

@@ -18,7 +18,7 @@
import { Injectable } from '@angular/core';
import { throwError, Observable, from } from 'rxjs';
import { catchError, map } from 'rxjs/operators';
import { AlfrescoApiService, LogService } from '@alfresco/adf-core';
import { AlfrescoApiService, LogService, ContentService } from '@alfresco/adf-core';
@Injectable({
providedIn: 'root'
@@ -27,11 +27,11 @@ export class ProcessCloudContentService {
constructor(
private apiService: AlfrescoApiService,
private logService: LogService
private logService: LogService,
public contentService: ContentService
) { }
createTemporaryRawRelatedContent(file, nodeId, contentHost): Observable<any> {
const changedConfig = this.apiService.lastConfig;
changedConfig.provider = 'ALL';
changedConfig.hostEcm = contentHost.replace('/alfresco', '');
@@ -45,6 +45,18 @@ export class ProcessCloudContentService {
);
}
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');

View File

@@ -10,7 +10,8 @@
[showSaveButton]="canCompleteTask()"
(formSaved)="onFormSaved($event)"
(formCompleted)="onFormCompleted($event)"
(formError)="onError($event)">
(formError)="onError($event)"
(formContentClicked)="onFormContentClicked($event)">
<adf-cloud-form-custom-outcomes>
<ng-template [ngTemplateOutlet]="taskFormCloudButtons">
</ng-template>

View File

@@ -22,7 +22,7 @@ import {
import { FormCloud } from '../../../form/models/form-cloud.model';
import { TaskDetailsCloudModel } from '../../start-task/models/task-details-cloud.model';
import { TaskCloudService } from '../../services/task-cloud.service';
import { FormRenderingService } from '@alfresco/adf-core';
import { FormRenderingService, ContentLinkModel } from '@alfresco/adf-core';
import { AttachFileCloudWidgetComponent } from '../../../form/components/attach-file-cloud-widget/attach-file-cloud-widget.component';
import { DropdownCloudWidgetComponent } from '../../../form/components/dropdown-cloud/dropdown-cloud.widget';
import { DateCloudWidgetComponent } from '../../../form/components/date-cloud/date-cloud.widget';
@@ -90,6 +90,9 @@ export class TaskFormCloudComponent implements OnChanges {
@Output()
error: EventEmitter<any> = new EventEmitter<any>();
@Output()
formContentClicked: EventEmitter<ContentLinkModel> = new EventEmitter();
taskDetails: TaskDetailsCloudModel;
loading: boolean = false;
@@ -180,4 +183,8 @@ export class TaskFormCloudComponent implements OnChanges {
onError(data: any) {
this.error.emit(data);
}
onFormContentClicked(content: ContentLinkModel) {
this.formContentClicked.emit(content);
}
}

View File

@@ -23,7 +23,6 @@ import { BrowserActions } from '../../core/utils/browser-actions';
export class DocumentListPage {
rootElement: ElementFinder;
actionMenu: ElementFinder = element(by.css('div[role="menu"]'));
optionButton: Locator = by.css('button[data-automation-id*="action_menu_"]');
tableBody: ElementFinder;
dataTable: DataTableComponentPage;
@@ -66,12 +65,12 @@ export class DocumentListPage {
await BrowserActions.closeMenuAndDialogs();
const row: ElementFinder = this.dataTable.getRow('Display name', content);
await BrowserActions.click(row.element(this.optionButton));
await BrowserVisibility.waitUntilElementIsVisible(this.actionMenu);
await BrowserActions.waitUntilActionMenuIsVisible();
await browser.sleep(500);
}
async checkActionMenuIsNotDisplayed(): Promise<void> {
await BrowserVisibility.waitUntilElementIsNotVisible(this.actionMenu);
await BrowserActions.waitUntilActionMenuIsNotVisible();
}
dataTablePage(): DataTableComponentPage {

View File

@@ -76,8 +76,12 @@ export class AttachFileWidgetCloud {
async removeFile(fileName: string): Promise<void> {
const fileId = await this.getFileId(fileName);
const deleteButton = this.widget.element(by.css(`button[id='${fileId}-remove']`));
const optionMenu = this.widget.element(by.css(`button[id='${fileId}-option-menu']`));
await BrowserActions.click(optionMenu);
await BrowserActions.waitUntilActionMenuIsVisible();
const deleteButton = element(by.css(`button#${fileId}-remove`));
await BrowserActions.click(deleteButton);
await BrowserVisibility.waitUntilElementIsNotVisible(deleteButton);
}
async viewFile(name): Promise<void> {

View File

@@ -26,6 +26,16 @@ export class BrowserActions {
await elementFinder.click();
}
static async waitUntilActionMenuIsVisible(): Promise<void> {
const actionMenu = element(by.css('div[role="menu"]'));
await BrowserVisibility.waitUntilElementIsVisible(actionMenu);
}
static async waitUntilActionMenuIsNotVisible(): Promise<void> {
const actionMenu = element(by.css('div[role="menu"]'));
await BrowserVisibility.waitUntilElementIsNotVisible(actionMenu);
}
static async getUrl(url: string): Promise<any> {
return browser.get(url);
}