From 957a76b1b5c75f0a02335f87895c5da09828e5c1 Mon Sep 17 00:00:00 2001 From: siva kumar Date: Tue, 18 Jun 2019 23:24:33 +0530 Subject: [PATCH] [ADF-4519] Attach an ACS content to a form (#4842) * * Process-storage * * Used jsapiServcie * Be able to upload a file on the content with the createNode api * Refactor * [ADF-4519] Attach an ACS content to a form. * * Created attachfile-cloud-widget component * * Created a component to attach an acs content to a form. * * Added unit tests * * Removed unused methods* FIxed tslint errors. * * Reverted demo shell changes. * * Removed unnecessary methods * * Fixed at able to remove attached file * * After rebase. * * Removed tempFile and currentFile properties.* Refactored attach-file-cloud-widget. * Update upload-cloud.widget.html * fix * Fixed readonly form --- .../attach-file-cloud-widget.component.html | 60 +++++ .../attach-file-cloud-widget.component.scss | 73 ++++++ ...attach-file-cloud-widget.component.spec.ts | 222 ++++++++++++++++++ .../attach-file-cloud-widget.component.ts | 128 ++++++++++ .../form/components/form-cloud.component.ts | 14 +- .../form/components/upload-cloud.widget.html | 10 +- .../form/components/upload-cloud.widget.ts | 59 +++-- .../src/lib/form/form-cloud.module.ts | 14 +- .../src/lib/form/public-api.ts | 2 + .../content-cloud-node-selector.service.ts | 69 ++++++ .../services/process-cloud-content.service.ts | 52 ++++ .../components/task-form-cloud.component.ts | 6 +- 12 files changed, 665 insertions(+), 44 deletions(-) create mode 100644 lib/process-services-cloud/src/lib/form/components/attach-file-cloud-widget/attach-file-cloud-widget.component.html create mode 100644 lib/process-services-cloud/src/lib/form/components/attach-file-cloud-widget/attach-file-cloud-widget.component.scss create mode 100644 lib/process-services-cloud/src/lib/form/components/attach-file-cloud-widget/attach-file-cloud-widget.component.spec.ts create mode 100644 lib/process-services-cloud/src/lib/form/components/attach-file-cloud-widget/attach-file-cloud-widget.component.ts create mode 100644 lib/process-services-cloud/src/lib/form/services/content-cloud-node-selector.service.ts create mode 100644 lib/process-services-cloud/src/lib/form/services/process-cloud-content.service.ts diff --git a/lib/process-services-cloud/src/lib/form/components/attach-file-cloud-widget/attach-file-cloud-widget.component.html b/lib/process-services-cloud/src/lib/form/components/attach-file-cloud-widget/attach-file-cloud-widget.component.html new file mode 100644 index 0000000000..173731ed8d --- /dev/null +++ b/lib/process-services-cloud/src/lib/form/components/attach-file-cloud-widget/attach-file-cloud-widget.component.html @@ -0,0 +1,60 @@ +
+ +
+ +
+ + +
+ +
+
+
+
+
+ +
+ + + + {{file.name}} + + + +
+ + + diff --git a/lib/process-services-cloud/src/lib/form/components/attach-file-cloud-widget/attach-file-cloud-widget.component.scss b/lib/process-services-cloud/src/lib/form/components/attach-file-cloud-widget/attach-file-cloud-widget.component.scss new file mode 100644 index 0000000000..22b0501089 --- /dev/null +++ b/lib/process-services-cloud/src/lib/form/components/attach-file-cloud-widget/attach-file-cloud-widget.component.scss @@ -0,0 +1,73 @@ +.adf { + + &-attach-widget-container { + margin-bottom: 15px; + display: flex; + align-items: center; + + input { + cursor: pointer; + height: 100%; + right: 0; + opacity: 0; + position: absolute; + top: 0; + width: 300px; + z-index: 4; + } + } + + &-attach-widget__menu-upload { + display: flex; + align-items: center; + } + + &-attach-widget__input-type { + width: 0.1px; + height: 0.1px; + opacity: 0; + overflow: hidden; + position: absolute; + z-index: -1; + } + + &-attach-widget__image-logo { + padding-left: 5px; + } + + &-attach-widget-repo-button { + padding-left: 10px; + + .mat-button-wrapper { + display: inline; + } + + .mat-mini-fab.mat-accent { + background-color: inherit; + } + } + + &-attach-widget { + width: 100%; + word-break: break-all; + padding: 0.4375em 0; + border-top: 0.84375em solid transparent; + } + + &-attach-widget__icon { + padding: 6px; + float: left; + cursor: pointer; + } + + &-attach-widget__reset { + margin-top: -2px; + } + + &-attach-files-row { + .mat-line { + margin-bottom: 0; + } + } + +} diff --git a/lib/process-services-cloud/src/lib/form/components/attach-file-cloud-widget/attach-file-cloud-widget.component.spec.ts b/lib/process-services-cloud/src/lib/form/components/attach-file-cloud-widget/attach-file-cloud-widget.component.spec.ts new file mode 100644 index 0000000000..90fb438628 --- /dev/null +++ b/lib/process-services-cloud/src/lib/form/components/attach-file-cloud-widget/attach-file-cloud-widget.component.spec.ts @@ -0,0 +1,222 @@ +/*! + * @license + * Copyright 2019 Alfresco Software, Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +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 { ProcessServiceCloudTestingModule } from '../../../testing/process-service-cloud.testing.module'; +import { CUSTOM_ELEMENTS_SCHEMA } from '@angular/core'; +import { ContentModule } from '@alfresco/adf-content-services'; +import { By } from '@angular/platform-browser'; +import { of } from 'rxjs'; +import { Node } from '@alfresco/js-api'; +import { FormCloudModule } from '../../form-cloud.module'; + +describe('AttachFileCloudWidgetComponent', () => { + let widget: AttachFileCloudWidgetComponent; + let fixture: ComponentFixture; + let element: HTMLInputElement; + let contentCloudNodeSelectorService: ContentCloudNodeSelectorService; + let processCloudContentService: ProcessCloudContentService; + + 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 contentSourceparam = { + fileSource: { + name: 'mock-alf-content', + serviceId: 'alfresco-content' + } + }; + + const fakeMinimalNode: 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' + }; + + 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: [] + }); + widget.field.id = 'simple-upload-button'; + widget.field.params = 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 = 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 = 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 = 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 = 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(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', async(() => { + 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-icon')).toBeNull(); + }); + })); + }); +}); diff --git a/lib/process-services-cloud/src/lib/form/components/attach-file-cloud-widget/attach-file-cloud-widget.component.ts b/lib/process-services-cloud/src/lib/form/components/attach-file-cloud-widget/attach-file-cloud-widget.component.ts new file mode 100644 index 0000000000..c2f73cc8eb --- /dev/null +++ b/lib/process-services-cloud/src/lib/form/components/attach-file-cloud-widget/attach-file-cloud-widget.component.ts @@ -0,0 +1,128 @@ +/*! + * @license + * Copyright 2019 Alfresco Software, Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* tslint:disable:component-selector */ + +import { Component, OnInit, ViewEncapsulation } from '@angular/core'; +import { + FormService, + LogService, + ThumbnailService, + ProcessContentService +} from '@alfresco/adf-core'; +import { 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'; + +@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 +}) +export class AttachFileCloudWidgetComponent extends UploadCloudWidgetComponent implements OnInit { + + 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; + } + this.getMultipleFileParam(); + } + + isFileSourceConfigured(): boolean { + return !!this.field.params && !!this.field.params.fileSource; + } + + isMultipleSourceUpload(): boolean { + return !this.field.readOnly && this.isFileSourceConfigured() && !this.isOnlyLocalSourceSelected(); + } + + isOnlyLocalSourceSelected(): 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(); + } + + isUploadButtonVisible(): boolean { + return (!this.hasFile || this.multipleOption) && !this.field.readOnly; + } + + onAttachFileChanged(event: any) { + this.onFileChanged(event); + } + + onRemoveAttachFile(file: File | RelatedContentRepresentation) { + this.removeFile(file); + } + + uploadFileFromCS() { + this.openSelectDialog(); + } + + 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; + } +} diff --git a/lib/process-services-cloud/src/lib/form/components/form-cloud.component.ts b/lib/process-services-cloud/src/lib/form/components/form-cloud.component.ts index 8f137341a7..883887b3f5 100644 --- a/lib/process-services-cloud/src/lib/form/components/form-cloud.component.ts +++ b/lib/process-services-cloud/src/lib/form/components/form-cloud.component.ts @@ -38,7 +38,7 @@ import { FormCloudService } from '../services/form-cloud.service'; import { FormCloud } from '../models/form-cloud.model'; import { TaskVariableCloud } from '../models/task-variable-cloud.model'; import { DropdownCloudWidgetComponent } from './dropdown-cloud/dropdown-cloud.widget'; -import { UploadCloudWidgetComponent } from './upload-cloud.widget'; +import { AttachFileCloudWidgetComponent } from './attach-file-cloud-widget/attach-file-cloud-widget.component'; @Component({ selector: 'adf-cloud-form', @@ -106,11 +106,11 @@ export class FormCloudComponent extends FormBaseComponent implements OnChanges, super(); this.formService.formContentClicked - .pipe(takeUntil(this.onDestroy$)) - .subscribe((content: any) => { - this.formContentClicked.emit(content); - }); - this.formRenderingService.setComponentTypeResolver('upload', () => UploadCloudWidgetComponent, true); + .pipe(takeUntil(this.onDestroy$)) + .subscribe((content: any) => { + this.formContentClicked.emit(content); + }); + this.formRenderingService.setComponentTypeResolver('upload', () => AttachFileCloudWidgetComponent, true); this.formRenderingService.setComponentTypeResolver('dropdown', () => DropdownCloudWidgetComponent, true); } @@ -236,7 +236,7 @@ export class FormCloudComponent extends FormBaseComponent implements OnChanges, await this.getFormByTaskId(appName, taskId); const hasUploadWidget = ( this.form).hasUpload; - if (hasUploadWidget) { + if (hasUploadWidget && !this.readOnly) { try { const processStorageCloudModel = await this.formCloudService.getProcessStorageFolderTask(appName, taskId, processInstanceId).toPromise(); this.form.nodeId = processStorageCloudModel.nodeId; diff --git a/lib/process-services-cloud/src/lib/form/components/upload-cloud.widget.html b/lib/process-services-cloud/src/lib/form/components/upload-cloud.widget.html index 0141499bdb..6cc4d8c65f 100644 --- a/lib/process-services-cloud/src/lib/form/components/upload-cloud.widget.html +++ b/lib/process-services-cloud/src/lib/form/components/upload-cloud.widget.html @@ -5,18 +5,18 @@
- + - {{file.name}} - @@ -30,7 +30,7 @@
diff --git a/lib/process-services-cloud/src/lib/form/components/upload-cloud.widget.ts b/lib/process-services-cloud/src/lib/form/components/upload-cloud.widget.ts index cc136af1f5..c181a9d660 100644 --- a/lib/process-services-cloud/src/lib/form/components/upload-cloud.widget.ts +++ b/lib/process-services-cloud/src/lib/form/components/upload-cloud.widget.ts @@ -20,8 +20,8 @@ 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, ProcessContentService } from '@alfresco/adf-core'; -import { FormCloudService } from '../services/form-cloud.service'; +import { WidgetComponent, baseHost, LogService, FormService, ThumbnailService } from '@alfresco/adf-core'; +import { ProcessCloudContentService } from '../services/process-cloud-content.service'; @Component({ selector: 'upload-cloud-widget', @@ -37,16 +37,14 @@ export class UploadCloudWidgetComponent extends WidgetComponent implements OnIni multipleOption: string = ''; mimeTypeIcon: string; - currentFiles = []; - @ViewChild('uploadFiles') fileInput: ElementRef; - constructor(public formService: FormService, - private thumbnailService: ThumbnailService, - private formCloudService: FormCloudService, - public processContentService: ProcessContentService, - private logService: LogService) { + constructor( + public formService: FormService, + private thumbnailService: ThumbnailService, + public processCloudContentService: ProcessCloudContentService, + private logService: LogService) { super(formService); } @@ -55,7 +53,6 @@ export class UploadCloudWidgetComponent extends WidgetComponent implements OnIni this.field.value && this.field.value.length > 0) { this.hasFile = true; - this.currentFiles = [...this.field.value]; } this.getMultipleFileParam(); } @@ -68,17 +65,18 @@ export class UploadCloudWidgetComponent extends WidgetComponent implements OnIni onFileChanged(event: any) { const files = event.target.files; + const filesSaved = []; if (files && files.length > 0) { from(files) .pipe(mergeMap((file) => this.uploadRawContent(file))) .subscribe( (res) => { - this.currentFiles.push(res); + filesSaved.push(res); }, - (error) => this.logService.error(`Error uploading file. See console output for more details. ${error}` ), + (error) => this.logService.error(`Error uploading file. See console output for more details. ${error}`), () => { - this.fixIncompatibilityFromPreviousAndNewForm(this.currentFiles); + this.fixIncompatibilityFromPreviousAndNewForm(filesSaved); this.hasFile = true; } ); @@ -86,7 +84,9 @@ export class UploadCloudWidgetComponent extends WidgetComponent implements OnIni } fixIncompatibilityFromPreviousAndNewForm(filesSaved) { + this.field.value = filesSaved; this.field.form.values[this.field.id] = filesSaved; + this.hasFile = true; } getIcon(mimeType) { @@ -94,11 +94,16 @@ export class UploadCloudWidgetComponent extends WidgetComponent implements OnIni } private uploadRawContent(file): Observable { - return this.formCloudService.createTemporaryRawRelatedContent(file, this.field.form.nodeId, this.field.form.contentHost) + 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 }; + return { + nodeId: response.id, + name: response.name, + content: response.content, + createdAt: response.createdAt + }; }), catchError((err) => this.handleError(err)) ); @@ -117,21 +122,23 @@ export class UploadCloudWidgetComponent extends WidgetComponent implements OnIni } private removeElementFromList(file) { - const index = this.currentFiles.indexOf(file); - + const savedValues = this.field.form.values[this.field.id]; + const index = savedValues.indexOf(file); if (index !== -1) { - this.currentFiles.splice(index, 1); - this.fixIncompatibilityFromPreviousAndNewForm(this.currentFiles); + const filteredValues = savedValues.filter((value: any) => value.nodeId !== file.nodeId); + this.resetFormValues(filteredValues); } - - this.hasFile = this.currentFiles.length > 0; - - this.resetFormValueWithNoFiles(); } - private resetFormValueWithNoFiles() { - if (this.currentFiles.length === 0) { - this.currentFiles = []; + private resetFormValues(values) { + if (values && values.length > 0) { + this.field.value = values; + this.field.form.values[this.field.id] = values; + this.hasFile = this.field.form.values[this.field.id].length > 0; + } else { + this.field.value = []; + this.field.form.values[this.field.id] = []; + this.hasFile = false; } } diff --git a/lib/process-services-cloud/src/lib/form/form-cloud.module.ts b/lib/process-services-cloud/src/lib/form/form-cloud.module.ts index a4031eb493..ef29b08e0e 100644 --- a/lib/process-services-cloud/src/lib/form/form-cloud.module.ts +++ b/lib/process-services-cloud/src/lib/form/form-cloud.module.ts @@ -27,6 +27,7 @@ import { FormDefinitionSelectorCloudComponent } from './components/form-definiti import { FormDefinitionSelectorCloudService } from './services/form-definition-selector-cloud.service'; import { FormCustomOutcomesComponent } from './components/form-cloud-custom-outcomes.component'; import { DropdownCloudWidgetComponent } from './components/dropdown-cloud/dropdown-cloud.widget'; +import { AttachFileCloudWidgetComponent } from './components/attach-file-cloud-widget/attach-file-cloud-widget.component'; @NgModule({ imports: [ @@ -40,17 +41,24 @@ import { DropdownCloudWidgetComponent } from './components/dropdown-cloud/dropdo FormBaseModule, CoreModule ], - declarations: [FormCloudComponent, UploadCloudWidgetComponent, FormDefinitionSelectorCloudComponent, FormCustomOutcomesComponent, DropdownCloudWidgetComponent], + declarations: [ + FormCloudComponent, + UploadCloudWidgetComponent, + FormDefinitionSelectorCloudComponent, + FormCustomOutcomesComponent, + DropdownCloudWidgetComponent, + AttachFileCloudWidgetComponent], providers: [ FormDefinitionSelectorCloudService, FormRenderingService ], entryComponents: [ UploadCloudWidgetComponent, - DropdownCloudWidgetComponent + DropdownCloudWidgetComponent, + AttachFileCloudWidgetComponent ], exports: [ - FormCloudComponent, UploadCloudWidgetComponent, FormDefinitionSelectorCloudComponent, FormCustomOutcomesComponent + FormCloudComponent, UploadCloudWidgetComponent, FormDefinitionSelectorCloudComponent, FormCustomOutcomesComponent, AttachFileCloudWidgetComponent ] }) export class FormCloudModule { diff --git a/lib/process-services-cloud/src/lib/form/public-api.ts b/lib/process-services-cloud/src/lib/form/public-api.ts index 68a5593f54..e31067eda3 100644 --- a/lib/process-services-cloud/src/lib/form/public-api.ts +++ b/lib/process-services-cloud/src/lib/form/public-api.ts @@ -22,6 +22,8 @@ export * from './models/form-definition-selector-cloud.model'; export * from './components/form-cloud.component'; export * from './components/upload-cloud.widget'; export * from './components/form-definition-selector-cloud.component'; +export * from './components/attach-file-cloud-widget/attach-file-cloud-widget.component'; export * from './services/form-cloud.service'; export * from './services/form-definition-selector-cloud.service'; +export * from './services/content-cloud-node-selector.service'; diff --git a/lib/process-services-cloud/src/lib/form/services/content-cloud-node-selector.service.ts b/lib/process-services-cloud/src/lib/form/services/content-cloud-node-selector.service.ts new file mode 100644 index 0000000000..ba63796dc5 --- /dev/null +++ b/lib/process-services-cloud/src/lib/form/services/content-cloud-node-selector.service.ts @@ -0,0 +1,69 @@ +/*! + * @license + * Copyright 2019 Alfresco Software, Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { Injectable } from '@angular/core'; +import { AlfrescoApiService } from '@alfresco/adf-core'; +import { MatDialog } from '@angular/material'; +import { ContentNodeSelectorComponent, ContentNodeSelectorComponentData } from '@alfresco/adf-content-services'; +import { Node } from '@alfresco/js-api'; +import { Observable, Subject } from 'rxjs'; + +@Injectable({ + providedIn: 'root' +}) +export class ContentCloudNodeSelectorService { + + constructor( + private apiService: AlfrescoApiService, + private dialog: MatDialog) { + } + + openUploadFileDialog(contentHost: string, title?: string, actionName?: string): Observable { + const changedConfig = this.apiService.lastConfig; + changedConfig.provider = 'ALL'; + changedConfig.hostEcm = contentHost.replace('/alfresco', ''); + this.apiService.getInstance().setConfig(changedConfig); + const select = new Subject(); + select.subscribe({ + complete: this.close.bind(this) + }); + const data = { + title: 'Select a file', + actionName: 'Choose', + currentFolderId: '-my-', + select, + isSelectionValid: this.isNodeFile.bind(this) + }; + + this.openContentNodeDialog(data, 'adf-content-node-selector-dialog', '630px'); + return select; + } + + private openContentNodeDialog(data: ContentNodeSelectorComponentData, currentPanelClass: string, chosenWidth: string) { + this.dialog.open(ContentNodeSelectorComponent, { data, panelClass: currentPanelClass, width: chosenWidth }); + } + + close() { + this.dialog.closeAll(); + } + + private isNodeFile(entry: Node): boolean { + if (entry) { + return entry.isFile; + } + } +} diff --git a/lib/process-services-cloud/src/lib/form/services/process-cloud-content.service.ts b/lib/process-services-cloud/src/lib/form/services/process-cloud-content.service.ts new file mode 100644 index 0000000000..377301074e --- /dev/null +++ b/lib/process-services-cloud/src/lib/form/services/process-cloud-content.service.ts @@ -0,0 +1,52 @@ +/*! + * @license + * Copyright 2019 Alfresco Software, Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { Injectable } from '@angular/core'; +import { throwError, Observable, from } from 'rxjs'; +import { catchError, map } from 'rxjs/operators'; +import { AlfrescoApiService, LogService } from '@alfresco/adf-core'; + +@Injectable({ + providedIn: 'root' +}) +export class ProcessCloudContentService { + + constructor( + private apiService: AlfrescoApiService, + private logService: LogService + ) { } + + createTemporaryRawRelatedContent(file, nodeId, contentHost): Observable { + + 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)) + ); + } + + private handleError(error: any) { + this.logService.error(error); + return throwError(error || 'Server error'); + } +} diff --git a/lib/process-services-cloud/src/lib/task/task-form/components/task-form-cloud.component.ts b/lib/process-services-cloud/src/lib/task/task-form/components/task-form-cloud.component.ts index f9ad3a8914..126cf3bccf 100644 --- a/lib/process-services-cloud/src/lib/task/task-form/components/task-form-cloud.component.ts +++ b/lib/process-services-cloud/src/lib/task/task-form/components/task-form-cloud.component.ts @@ -23,7 +23,7 @@ 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 { UploadCloudWidgetComponent } from '../../../form/components/upload-cloud.widget'; +import { AttachFileCloudWidgetComponent } from '../../../form/components/attach-file-cloud-widget/attach-file-cloud-widget.component'; import { DropdownCloudWidgetComponent } from '../../../form/components/dropdown-cloud/dropdown-cloud.widget'; @Component({ @@ -96,8 +96,8 @@ export class TaskFormCloudComponent implements OnChanges { constructor( private taskCloudService: TaskCloudService, private formRenderingService: FormRenderingService) { - this.formRenderingService.setComponentTypeResolver('upload', () => UploadCloudWidgetComponent, true); - this.formRenderingService.setComponentTypeResolver('dropdown', () => DropdownCloudWidgetComponent, true); + this.formRenderingService.setComponentTypeResolver('upload', () => AttachFileCloudWidgetComponent, true); + this.formRenderingService.setComponentTypeResolver('dropdown', () => DropdownCloudWidgetComponent, true); } ngOnChanges(changes: SimpleChanges) {