diff --git a/lib/core/form/components/widgets/upload/upload.widget.ts b/lib/core/form/components/widgets/upload/upload.widget.ts index c6a50dee7f..9ddb9e029b 100644 --- a/lib/core/form/components/widgets/upload/upload.widget.ts +++ b/lib/core/form/components/widgets/upload/upload.widget.ts @@ -94,6 +94,7 @@ export class UploadWidgetComponent extends WidgetComponent implements OnInit { return this.processContentService.createTemporaryRawRelatedContent(file) .map((response: any) => { this.logService.info(response); + response.contentBlob = file; return response; }); } diff --git a/lib/core/i18n/en.json b/lib/core/i18n/en.json index 8b5eaa2c49..e94d77b4f2 100644 --- a/lib/core/i18n/en.json +++ b/lib/core/i18n/en.json @@ -9,6 +9,9 @@ "FIELD": { "LOCALSTORAGE" : "Local storage", "SOURCE": "Select source from ", + "SHOW_FILE": "Show", + "DOWNLOAD_FILE": "Download", + "REMOVE_FILE":"Remove", "UPLOAD": "UPLOAD", "REQUIRED": "*Required", "VALIDATOR": { diff --git a/lib/process-services/content-widget/attach-file-widget.component.html b/lib/process-services/content-widget/attach-file-widget.component.html index 561efd3ac3..d7d83ff0d2 100644 --- a/lib/process-services/content-widget/attach-file-widget.component.html +++ b/lib/process-services/content-widget/attach-file-widget.component.html @@ -13,7 +13,7 @@ [multiple]="multipleOption" type="file" [id]="field.id" - (change)="onFileChanged($event)" /> + (change)="onAttachFileChanged($event)" />
@@ -32,7 +32,7 @@ [multiple]="multipleOption" type="file" [id]="field.id" - (change)="onFileChanged($event)" /> + (change)="onAttachFileChanged($event)" /> + + + + +
diff --git a/lib/process-services/content-widget/attach-file-widget.component.ts b/lib/process-services/content-widget/attach-file-widget.component.ts index 9eab0f881f..610f4ca38f 100644 --- a/lib/process-services/content-widget/attach-file-widget.component.ts +++ b/lib/process-services/content-widget/attach-file-widget.component.ts @@ -25,7 +25,9 @@ import { LogService, ThumbnailService, ProcessContentService, - ActivitiContentService + ActivitiContentService, + ContentService, + FormEvent } from '@alfresco/adf-core'; import { ContentNodeDialogService } from '@alfresco/adf-content-services'; import { MinimalNodeEntryEntity } from 'alfresco-js-api'; @@ -41,12 +43,14 @@ import { Observable } from 'rxjs/Observable'; export class AttachFileWidgetComponent extends UploadWidgetComponent implements OnInit { repositoryList = []; + private tempFilesList = []; constructor(public formService: FormService, private logger: LogService, public thumbnails: ThumbnailService, public processContentService: ProcessContentService, private activitiContentService: ActivitiContentService, + private contentService: ContentService, private contentDialog: ContentNodeDialogService) { super(formService, logger, thumbnails, processContentService); } @@ -58,9 +62,16 @@ export class AttachFileWidgetComponent extends UploadWidgetComponent implements this.hasFile = true; } this.getMultipleFileParam(); + this.activitiContentService.getAlfrescoRepositories(null, true).subscribe((repoList) => { this.repositoryList = repoList; }); + + this.formService.taskSaved.subscribe((formSaved: FormEvent) => { + if (formSaved.form.id === this.field.form.id) { + this.tempFilesList = []; + } + }); } isFileSourceConfigured(): boolean { @@ -99,6 +110,10 @@ export class AttachFileWidgetComponent extends UploadWidgetComponent implements !!this.field.params.fileSource.selectedFolder; } + isTemporaryFile(file): boolean { + return this.tempFilesList.indexOf(file) !== -1 ? true : false; + } + openSelectDialogFromFileSource() { let params = this.field.params; if (this.isDefinedSourceFolder()) { @@ -111,6 +126,41 @@ export class AttachFileWidgetComponent extends UploadWidgetComponent implements } } + onAttachFileChanged(event: any) { + this.tempFilesList.push(...Array.from(event.target.files)); + this.onFileChanged(event); + } + + onRemoveAttachFile(file: any) { + if (this.isTemporaryFile(file.contentBlob)) { + this.tempFilesList.splice(this.tempFilesList.indexOf(file.contentBlob), 1); + } + this.removeFile(file); + } + + onAttachFileClicked(file: any) { + if (this.isTemporaryFile(file.contentBlob)) { + this.formService.formContentClicked.next(file); + } else { + this.fileClicked(file); + } + } + + downloadContent(file: any): void { + if (this.isTemporaryFile(file.contentBlob)) { + this.contentService.downloadBlob(file.contentBlob, file.name); + } else { + this.processContentService.getFileRawContent(file.id).subscribe( + (blob: Blob) => { + this.contentService.downloadBlob(blob, file.name); + }, + (err) => { + this.logger.error('Impossible retrieve content for download'); + } + ); + } + } + openSelectDialog(repoId: string, repoName: string) { const accountIdentifier = 'alfresco-' + repoId + repoName; this.contentDialog.openFileBrowseDialogBySite().subscribe( diff --git a/lib/process-services/content-widget/attach-file-widget.components.spec.ts b/lib/process-services/content-widget/attach-file-widget.components.spec.ts index 5f52021e8b..d966cb4686 100644 --- a/lib/process-services/content-widget/attach-file-widget.components.spec.ts +++ b/lib/process-services/content-widget/attach-file-widget.components.spec.ts @@ -29,7 +29,8 @@ import { LogService, ThumbnailService, SitesService, - FormFieldMetadata + FormFieldMetadata, + ContentService } from '@alfresco/adf-core'; import { ContentNodeDialogService, DocumentListService } from '@alfresco/adf-content-services'; import { MaterialModule } from '../material.module'; @@ -99,6 +100,8 @@ describe('AttachFileWidgetComponent', () => { let activitiContentService: ActivitiContentService; let contentNodeDialogService: ContentNodeDialogService; let processContentService: ProcessContentService; + let contentService: ContentService; + let formService: FormService; beforeEach(async(() => { TestBed.configureTestingModule({ @@ -113,7 +116,8 @@ describe('AttachFileWidgetComponent', () => { LogService, SitesService, DocumentListService, - ContentNodeDialogService + ContentNodeDialogService, + ContentService ] }).compileComponents().then(() => { fixture = TestBed.createComponent(AttachFileWidgetComponent); @@ -122,6 +126,8 @@ describe('AttachFileWidgetComponent', () => { activitiContentService = TestBed.get(ActivitiContentService); contentNodeDialogService = TestBed.get(ContentNodeDialogService); processContentService = TestBed.get(ProcessContentService); + contentService = TestBed.get(ContentService); + formService = TestBed.get(FormService); }); })); @@ -133,7 +139,8 @@ describe('AttachFileWidgetComponent', () => { expect(widget).not.toBeNull(); }); - it('should show up as simple upload when is configured for only local files', () => { + it('should show up as simple upload when is configured for only local files', async(() => { + spyOn(activitiContentService, 'getAlfrescoRepositories').and.returnValue(Observable.of(null)); widget.field = new FormFieldModel(new FormModel(), { type: FormFieldTypes.UPLOAD, value: [] @@ -141,103 +148,187 @@ describe('AttachFileWidgetComponent', () => { widget.field.id = 'simple-upload-button'; widget.field.params = onlyLocalParams; fixture.detectChanges(); - expect(element.querySelector('#simple-upload-button')).not.toBeNull(); - }); + fixture.whenStable().then(() => { + expect(element.querySelector('#simple-upload-button')).not.toBeNull(); + }); + })); - it('should show up all the repository option on menu list', () => { + it('should show up all the repository option on menu list', async(() => { widget.field = new FormFieldModel(new FormModel(), { type: FormFieldTypes.UPLOAD, value: [] }); widget.field.id = 'attach-file-attach'; - widget.field.params = allSourceParams; + widget.field.params = allSourceParams; spyOn(activitiContentService, 'getAlfrescoRepositories').and.returnValue(Observable.of(fakeRepositoryListAnswer)); fixture.detectChanges(); + fixture.whenRenderingDone().then(() => { + let attachButton: HTMLButtonElement = element.querySelector('#attach-file-attach'); + expect(attachButton).not.toBeNull(); + attachButton.click(); + fixture.detectChanges(); + fixture.whenStable().then(() => { + expect(fixture.debugElement.queryAll(By.css('#attach-local-file'))).not.toBeNull(); + expect(fixture.debugElement.queryAll(By.css('#attach-local-file'))).not.toBeUndefined(); + expect(fixture.debugElement.queryAll(By.css('#attach-SHAREME'))).not.toBeNull(); + expect(fixture.debugElement.queryAll(By.css('#attach-SHAREME'))).not.toBeUndefined(); + expect(fixture.debugElement.queryAll(By.css('#attach-GOKUSHARE'))).not.toBeNull(); + expect(fixture.debugElement.queryAll(By.css('#attach-GOKUSHARE'))).not.toBeUndefined(); + }); + }); + })); - let attachButton: HTMLButtonElement = element.querySelector('#attach-file-attach'); - expect(attachButton).not.toBeNull(); - attachButton.click(); - fixture.detectChanges(); - - expect(fixture.debugElement.queryAll(By.css('#attach-local-file'))).not.toBeNull(); - expect(fixture.debugElement.queryAll(By.css('#attach-local-file'))).not.toBeUndefined(); - expect(fixture.debugElement.queryAll(By.css('#attach-SHAREME'))).not.toBeNull(); - expect(fixture.debugElement.queryAll(By.css('#attach-SHAREME'))).not.toBeUndefined(); - expect(fixture.debugElement.queryAll(By.css('#attach-GOKUSHARE'))).not.toBeNull(); - expect(fixture.debugElement.queryAll(By.css('#attach-GOKUSHARE'))).not.toBeUndefined(); - }); - - it('should be able to upload files coming from content node selector', () => { + it('should be able to upload files coming from content node selector', async(() => { widget.field = new FormFieldModel(new FormModel(), { type: FormFieldTypes.UPLOAD, value: [] }); widget.field.id = 'attach-file-attach'; - widget.field.params = allSourceParams; + widget.field.params = allSourceParams; spyOn(activitiContentService, 'getAlfrescoRepositories').and.returnValue(Observable.of(fakeRepositoryListAnswer)); spyOn(activitiContentService, 'applyAlfrescoNode').and.returnValue(Observable.of(fakePngAnswer)); spyOn(contentNodeDialogService, 'openFileBrowseDialogBySite').and.returnValue(Observable.of([fakeMinimalNode])); fixture.detectChanges(); + fixture.whenStable().then(() => { + let attachButton: HTMLButtonElement = element.querySelector('#attach-file-attach'); + expect(attachButton).not.toBeNull(); + attachButton.click(); + fixture.detectChanges(); + fixture.debugElement.query(By.css('#attach-SHAREME')).nativeElement.click(); + fixture.detectChanges(); - let attachButton: HTMLButtonElement = element.querySelector('#attach-file-attach'); - expect(attachButton).not.toBeNull(); - attachButton.click(); - fixture.detectChanges(); - fixture.debugElement.query(By.css('#attach-SHAREME')).nativeElement.click(); - fixture.detectChanges(); + expect(element.querySelector('#file-1155-icon')).not.toBeNull(); + }); + })); - expect(element.querySelector('#file-1155-icon')).not.toBeNull(); - }); - - it('should be able to upload files when a defined folder is selected', () => { + it('should be able to upload files when a defined folder is selected', async(() => { widget.field = new FormFieldModel(new FormModel(), { type: FormFieldTypes.UPLOAD, value: [] }); widget.field.id = 'attach-file-attach'; - widget.field.params = definedSourceParams; + widget.field.params = definedSourceParams; spyOn(activitiContentService, 'getAlfrescoRepositories').and.returnValue(Observable.of(fakeRepositoryListAnswer)); spyOn(activitiContentService, 'applyAlfrescoNode').and.returnValue(Observable.of(fakePngAnswer)); spyOn(contentNodeDialogService, 'openFileBrowseDialogByFolderId').and.returnValue(Observable.of([fakeMinimalNode])); fixture.detectChanges(); + fixture.whenStable().then(() => { + let attachButton: HTMLButtonElement = element.querySelector('#attach-file-attach'); + expect(attachButton).not.toBeNull(); + attachButton.click(); + fixture.detectChanges(); + fixture.debugElement.query(By.css('#attach-pippo-baudo')).nativeElement.click(); + fixture.detectChanges(); - let attachButton: HTMLButtonElement = element.querySelector('#attach-file-attach'); - expect(attachButton).not.toBeNull(); - attachButton.click(); - fixture.detectChanges(); - fixture.debugElement.query(By.css('#attach-pippo-baudo')).nativeElement.click(); - fixture.detectChanges(); + expect(element.querySelector('#file-1155-icon')).not.toBeNull(); + }); + })); - expect(element.querySelector('#file-1155-icon')).not.toBeNull(); - }); - - it('should be able to upload files from local source', () => { + it('should be able to upload files from local source', async(() => { + spyOn(activitiContentService, 'getAlfrescoRepositories').and.returnValue(Observable.of(null)); widget.field = new FormFieldModel(new FormModel(), { type: FormFieldTypes.UPLOAD, value: [] }); widget.field.id = 'attach-file-attach'; - widget.field.params = onlyLocalParams; + widget.field.params = onlyLocalParams; spyOn(processContentService, 'createTemporaryRawRelatedContent').and.returnValue(Observable.of(fakePngAnswer)); fixture.detectChanges(); + fixture.whenStable().then(() => { + let inputDebugElement = fixture.debugElement.query(By.css('#attach-file-attach')); + inputDebugElement.triggerEventHandler('change', { target: { files: [fakePngAnswer] } }); + fixture.detectChanges(); - let inputDebugElement = fixture.debugElement.query(By.css('#attach-file-attach')); - inputDebugElement.triggerEventHandler('change', {target: {files: [fakePngAnswer]}}); - fixture.detectChanges(); + expect(element.querySelector('#file-1155-icon')).not.toBeNull(); + }); + })); - expect(element.querySelector('#file-1155-icon')).not.toBeNull(); - }); - - it('should display file list when field has value', () => { + it('should display file list when field has value', async(() => { widget.field = new FormFieldModel(new FormModel(), { type: FormFieldTypes.UPLOAD, value: [fakePngAnswer] }); + spyOn(activitiContentService, 'getAlfrescoRepositories').and.returnValue(Observable.of(null)); widget.field.id = 'attach-file-attach'; - widget.field.params = onlyLocalParams; + widget.field.params = 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 = onlyLocalParams; + spyOn(activitiContentService, 'getAlfrescoRepositories').and.returnValue(Observable.of(null)); + spyOn(processContentService, 'createTemporaryRawRelatedContent').and.returnValue(Observable.of(fakePngAnswer)); + fixture.detectChanges(); + fixture.whenStable().then(() => { + let inputDebugElement = fixture.debugElement.query(By.css('#attach-file-attach')); + inputDebugElement.triggerEventHandler('change', {target: {files: [fakePngAnswer]}}); + fixture.detectChanges(); + expect(element.querySelector('#file-1155-icon')).not.toBeNull(); + }); + })); + + it('should show the action menu', async(() => { + let menuButton: HTMLButtonElement = element.querySelector('#file-1155-option-menu'); + expect(menuButton).not.toBeNull(); + menuButton.click(); + fixture.detectChanges(); + fixture.whenStable().then(() => { + expect(fixture.debugElement.query(By.css('#file-1155-show-file'))).not.toBeNull(); + expect(fixture.debugElement.query(By.css('#file-1155-download-file'))).not.toBeNull(); + expect(fixture.debugElement.query(By.css('#file-1155-remove'))).not.toBeNull(); + }); + })); + + it('should remove file when remove is clicked', async(() => { + let menuButton: HTMLButtonElement = element.querySelector('#file-1155-option-menu'); + expect(menuButton).not.toBeNull(); + menuButton.click(); + fixture.detectChanges(); + const removeOption: HTMLButtonElement = fixture.debugElement.query(By.css('#file-1155-remove')).nativeElement; + removeOption.click(); + fixture.detectChanges(); + fixture.whenStable().then(() => { + expect(element.querySelector('#file-1155')).toBeNull(); + }); + })); + + it('should download file when download is clicked', async(() => { + spyOn(contentService, 'downloadBlob').and.stub(); + let menuButton: HTMLButtonElement = element.querySelector('#file-1155-option-menu'); + expect(menuButton).not.toBeNull(); + menuButton.click(); + fixture.detectChanges(); + const downloadOption: HTMLButtonElement = fixture.debugElement.query(By.css('#file-1155-download-file')).nativeElement; + downloadOption.click(); + fixture.whenStable().then(() => { + expect(contentService.downloadBlob).toHaveBeenCalled(); + }); + })); + + it('should raise formContentClicked event when show file is clicked', async(() => { + spyOn(processContentService, 'getFileRawContent').and.returnValue(Observable.of(fakePngAnswer)); + formService.formContentClicked.subscribe((file) => { + expect(file).not.toBeNull(); + expect(file.id).toBe(1155); + }); + let menuButton: HTMLButtonElement = element.querySelector('#file-1155-option-menu'); + expect(menuButton).not.toBeNull(); + menuButton.click(); + fixture.detectChanges(); + const showOption: HTMLButtonElement = fixture.debugElement.query(By.css('#file-1155-show-file')).nativeElement; + showOption.click(); + })); - expect(element.querySelector('#file-1155-icon')).not.toBeNull(); }); });