diff --git a/ng2-components/ng2-activiti-form/README.md b/ng2-components/ng2-activiti-form/README.md index a8cb1de03b..8da8cbf5df 100644 --- a/ng2-components/ng2-activiti-form/README.md +++ b/ng2-components/ng2-activiti-form/README.md @@ -244,10 +244,17 @@ will also be executed after your custom code.** - Header * [x] Plain header * [x] Collapsible header -- [ ] Attach +- [x] Attach file ** - [x] Display value - [x] Display text +** Files may be uploaded from a user's device if the file source selected is +'Local file' or 'All sources' and 'link to files' is not selected. Alternatively +you can link to files in a configured Alfresco repository by selecting this source +explicitly from the list and making sure that 'link to files' is selected. Copying +files from Alfresco into Activiti via the control (no linking) is not currently +supported, nor is allowing the user to choose between more than one source. + ## Build from sources Alternatively you can build component from sources with the following commands: diff --git a/ng2-components/ng2-activiti-form/src/components/activiti-form.component.ts b/ng2-components/ng2-activiti-form/src/components/activiti-form.component.ts index e2ae2ff507..d8d4c61755 100644 --- a/ng2-components/ng2-activiti-form/src/components/activiti-form.component.ts +++ b/ng2-components/ng2-activiti-form/src/components/activiti-form.component.ts @@ -26,6 +26,7 @@ import { import { MATERIAL_DESIGN_DIRECTIVES } from 'ng2-alfresco-core'; import { EcmModelService } from './../services/ecm-model.service'; import { FormService } from './../services/form.service'; +import { ActivitiAlfrescoContentService } from './../services/activiti-alfresco.service'; import { NodeService } from './../services/node.service'; import { FormModel, FormOutcomeModel, FormValues, FormFieldModel, FormOutcomeEvent } from './widgets/core/index'; @@ -85,7 +86,7 @@ import { WidgetVisibilityService } from './../services/widget-visibility.servic templateUrl: './activiti-form.component.html', styleUrls: ['./activiti-form.component.css'], directives: [MATERIAL_DESIGN_DIRECTIVES, ContainerWidget, TabsWidget], - providers: [EcmModelService, FormService, WidgetVisibilityService, NodeService] + providers: [EcmModelService, FormService, ActivitiAlfrescoContentService, WidgetVisibilityService, NodeService] }) export class ActivitiForm implements OnInit, AfterViewChecked, OnChanges { diff --git a/ng2-components/ng2-activiti-form/src/components/widgets/attach/attach.widget.css b/ng2-components/ng2-activiti-form/src/components/widgets/attach/attach.widget.css new file mode 100644 index 0000000000..8bb37584c6 --- /dev/null +++ b/ng2-components/ng2-activiti-form/src/components/widgets/attach/attach.widget.css @@ -0,0 +1,15 @@ +.attach-widget { + width:100% +} + +.attach-widget__icon { + float: left; +} + +.attach-widget__file { + margin-top: 4px; +} + +.attach-widget__reset { + margin-top: 4px; +} diff --git a/ng2-components/ng2-activiti-form/src/components/widgets/attach/attach.widget.html b/ng2-components/ng2-activiti-form/src/components/widgets/attach/attach.widget.html new file mode 100644 index 0000000000..e79e98dbc7 --- /dev/null +++ b/ng2-components/ng2-activiti-form/src/components/widgets/attach/attach.widget.html @@ -0,0 +1,33 @@ +
+ + +
+ {{getLinkedFileName()}} + + +
+
+ + +

Select content

+
+ +
+
+ +
+
diff --git a/ng2-components/ng2-activiti-form/src/components/widgets/attach/attach.widget.ts b/ng2-components/ng2-activiti-form/src/components/widgets/attach/attach.widget.ts new file mode 100644 index 0000000000..fbb2293625 --- /dev/null +++ b/ng2-components/ng2-activiti-form/src/components/widgets/attach/attach.widget.ts @@ -0,0 +1,146 @@ +/*! + * @license + * Copyright 2016 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 { Component, OnInit, Input, Output, EventEmitter, ViewChild } from '@angular/core'; +import { WidgetComponent } from './../widget.component'; +import { ActivitiAlfrescoContentService } from '../../../services/activiti-alfresco.service'; +import { ExternalContent } from '../core/external-content'; +import { ExternalContentLink } from '../core/external-content-link'; +import { FormFieldModel } from '../core/form-field.model'; + +declare let __moduleName: string; +declare var componentHandler; + +@Component({ + moduleId: __moduleName, + selector: 'attach-widget', + templateUrl: './attach.widget.html', + styleUrls: ['./attach.widget.css'] +}) +export class AttachWidget extends WidgetComponent implements OnInit { + + selectedFolderPathId: string; + selectedFolderSiteId: string; + selectedFolderSiteName: string; + selectedFolderAccountId: string; + fileName: string; + hasFile: boolean; + selectedFolderNodes: [ExternalContent]; + selectedFile: ExternalContent; + + @Input() + field: FormFieldModel; + + @Output() + fieldChanged: EventEmitter = new EventEmitter(); + + @ViewChild('dialog') + dialog: any; + + constructor(private contentService: ActivitiAlfrescoContentService) { + super(); + } + + ngOnInit() { + if (this.field && + this.field.value) { + this.hasFile = true; + } + if (this.field && + this.field.params && + this.field.params.fileSource && + this.field.params.fileSource.selectedFolder) { + this.selectedFolderSiteId = this.field.params.fileSource.selectedFolder.siteId; + this.selectedFolderSiteName = this.field.params.fileSource.selectedFolder.site; + this.setupFileBrowser(); + this.getExternalContentNodes(); + } + } + + private setupFileBrowser() { + this.selectedFolderPathId = this.field.params.fileSource.selectedFolder.pathId; + this.selectedFolderAccountId = this.field.params.fileSource.selectedFolder.accountId; + } + + getLinkedFileName(): string { + let result = this.fileName; + + if (this.selectedFile && + this.selectedFile.title) { + result = this.selectedFile.title; + } + if (this.field.value && + this.field.value.length > 0 && + this.field.value[0].name) { + result = this.field.value[0].name; + } + + return result; + } + + private getExternalContentNodes() { + + this.contentService.getAlfrescoNodes(this.selectedFolderAccountId, this.selectedFolderPathId) + .subscribe( + (nodes) => { + this.selectedFolderNodes = nodes; + }, + error => console.error(error)); + } + + selectFile(node: ExternalContent, $event: any) { + this.contentService.linkAlfrescoNode(this.selectedFolderAccountId, node, this.selectedFolderSiteId).subscribe( + (link: ExternalContentLink) => { + this.selectedFile = node; + this.field.value = [link]; + this.field.json.value = [link]; + this.closeDialog(); + this.fieldChanged.emit(this.field); + } + ); + } + + selectFolder(node: ExternalContent, $event: any) { + this.selectedFolderPathId = node.id; + this.getExternalContentNodes(); + } + + public showDialog() { + this.setupFileBrowser(); + this.getExternalContentNodes(); + if (this.dialog) { + this.dialog.nativeElement.showModal(); + } + } + + private closeDialog() { + if (this.dialog) { + this.dialog.nativeElement.close(); + } + } + + public cancel() { + this.closeDialog(); + } + + reset() { + this.field.value = null; + this.field.json.value = null; + this.hasFile = false; + } + +} diff --git a/ng2-components/ng2-activiti-form/src/components/widgets/container/container.widget.html b/ng2-components/ng2-activiti-form/src/components/widgets/container/container.widget.html index 5b136d1bf1..bc22014766 100644 --- a/ng2-components/ng2-activiti-form/src/components/widgets/container/container.widget.html +++ b/ng2-components/ng2-activiti-form/src/components/widgets/container/container.widget.html @@ -44,7 +44,8 @@
- + +
diff --git a/ng2-components/ng2-activiti-form/src/components/widgets/core/external-content-link.ts b/ng2-components/ng2-activiti-form/src/components/widgets/core/external-content-link.ts new file mode 100644 index 0000000000..2fc6f8ad09 --- /dev/null +++ b/ng2-components/ng2-activiti-form/src/components/widgets/core/external-content-link.ts @@ -0,0 +1,32 @@ +/*! + * @license + * Copyright 2016 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. + */ + +export interface ExternalContentLink { + contentAvailable: boolean; + created: string; + createdBy: any; + id: number; + link: boolean; + mimeType: string; + name: string; + previewStatus: string; + relatedContent: boolean; + simpleType: string; + source: string; + sourceId: string; + thumbnailStatus: string; +} diff --git a/ng2-components/ng2-activiti-form/src/components/widgets/core/external-content.ts b/ng2-components/ng2-activiti-form/src/components/widgets/core/external-content.ts new file mode 100644 index 0000000000..88bc0dece1 --- /dev/null +++ b/ng2-components/ng2-activiti-form/src/components/widgets/core/external-content.ts @@ -0,0 +1,23 @@ +/*! + * @license + * Copyright 2016 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. + */ + +export interface ExternalContent { + folder: boolean; + id: string; + simpleType: string; + title: string; +} diff --git a/ng2-components/ng2-activiti-form/src/components/widgets/core/form-field-file-source.ts b/ng2-components/ng2-activiti-form/src/components/widgets/core/form-field-file-source.ts new file mode 100644 index 0000000000..6b86dcb5d1 --- /dev/null +++ b/ng2-components/ng2-activiti-form/src/components/widgets/core/form-field-file-source.ts @@ -0,0 +1,25 @@ +/*! + * @license + * Copyright 2016 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 {FormFieldSelectedFolder} from './form-field-selected-folder'; + +export interface FormFieldFileSource { + metadataAllowed: boolean; + name: string; + selectedFolder: FormFieldSelectedFolder; + serviceId: string; +} diff --git a/ng2-components/ng2-activiti-form/src/components/widgets/core/form-field-metadata.ts b/ng2-components/ng2-activiti-form/src/components/widgets/core/form-field-metadata.ts index 02378e3b41..102695019c 100644 --- a/ng2-components/ng2-activiti-form/src/components/widgets/core/form-field-metadata.ts +++ b/ng2-components/ng2-activiti-form/src/components/widgets/core/form-field-metadata.ts @@ -15,6 +15,10 @@ * limitations under the License. */ +import {FormFieldFileSource} from './form-field-file-source'; + export interface FormFieldMetadata { [key: string]: any; + fileSource?: FormFieldFileSource; + link?: boolean; } diff --git a/ng2-components/ng2-activiti-form/src/components/widgets/core/form-field-selected-folder.ts b/ng2-components/ng2-activiti-form/src/components/widgets/core/form-field-selected-folder.ts new file mode 100644 index 0000000000..abd472f109 --- /dev/null +++ b/ng2-components/ng2-activiti-form/src/components/widgets/core/form-field-selected-folder.ts @@ -0,0 +1,25 @@ +/*! + * @license + * Copyright 2016 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. + */ + +export interface FormFieldSelectedFolder { + accountId: string; + folderTree: [any]; + path: string; + pathId: string; + site: string; + siteId: string; +} diff --git a/ng2-components/ng2-activiti-form/src/components/widgets/index.ts b/ng2-components/ng2-activiti-form/src/components/widgets/index.ts index 47846bc631..c5a65c051e 100644 --- a/ng2-components/ng2-activiti-form/src/components/widgets/index.ts +++ b/ng2-components/ng2-activiti-form/src/components/widgets/index.ts @@ -28,6 +28,7 @@ import { RadioButtonsWidget } from './radio-buttons/radio-buttons.widget'; import { DisplayValueWidget } from './display-value/display-value.widget'; import { DisplayTextWidget } from './display-text/display-text.widget'; import { UploadWidget } from './upload/upload.widget'; +import { AttachWidget } from './attach/attach.widget'; import { TypeaheadWidget } from './typeahead/typeahead.widget'; import { FunctionalGroupWidget } from './functional-group/functional-group.widget'; import { PeopleWidget } from './people/people.widget'; @@ -51,6 +52,7 @@ export * from './radio-buttons/radio-buttons.widget'; export * from './display-value/display-value.widget'; export * from './display-text/display-text.widget'; export * from './upload/upload.widget'; +export * from './attach/attach.widget'; export * from './typeahead/typeahead.widget'; export * from './functional-group/functional-group.widget'; export * from './people/people.widget'; @@ -71,6 +73,7 @@ export const PRIMITIVE_WIDGET_DIRECTIVES: [any] = [ DisplayValueWidget, DisplayTextWidget, UploadWidget, + AttachWidget, TypeaheadWidget, FunctionalGroupWidget, PeopleWidget diff --git a/ng2-components/ng2-activiti-form/src/services/activiti-alfresco.service.ts b/ng2-components/ng2-activiti-form/src/services/activiti-alfresco.service.ts new file mode 100644 index 0000000000..dec92c19e3 --- /dev/null +++ b/ng2-components/ng2-activiti-form/src/services/activiti-alfresco.service.ts @@ -0,0 +1,90 @@ +/*! + * @license + * Copyright 2016 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 { Observable } from 'rxjs/Rx'; +import { AlfrescoAuthenticationService } from 'ng2-alfresco-core'; +import { ExternalContent } from '../components/widgets/core/external-content'; +import { ExternalContentLink } from '../components/widgets/core/external-content-link'; + +@Injectable() +export class ActivitiAlfrescoContentService { + + static UNKNOWN_ERROR_MESSAGE: string = 'Unknown error'; + static GENERIC_ERROR_MESSAGE: string = 'Server error'; + + constructor(private authService: AlfrescoAuthenticationService) { + } + + /** + * Returns a list of child nodes below the specified folder + * + * @param accountId + * @param folderId + * @returns {null} + */ + getAlfrescoNodes(accountId: string, folderId: string): Observable<[ExternalContent]> { + let apiService: any = this.authService.getAlfrescoApi(); + let accountShortId = accountId.replace('alfresco-', ''); + return Observable.fromPromise(apiService.activiti.alfrescoApi.getContentInFolder(accountShortId, folderId)) + .map(this.toJsonArray) + .catch(this.handleError); + } + + /** + * Returns a list of child nodes below the specified folder + * + * @param accountId + * @param node + * @param siteId + * @returns {null} + */ + linkAlfrescoNode(accountId: string, node: ExternalContent, siteId: string): Observable { + let apiService: any = this.authService.getAlfrescoApi(); + return Observable.fromPromise(apiService.activiti.contentApi.createTemporaryRelatedContent({ + link: true, + name: node.title, + simpleType: node.simpleType, + source: accountId, + sourceId: node.id + '@' + siteId + })).map(this.toJson).catch(this.handleError); + } + + toJson(res: any) { + if (res) { + return res || {}; + } + return {}; + } + + toJsonArray(res: any) { + if (res) { + return res.data || []; + } + return []; + } + + handleError(error: any): Observable { + let errMsg = ActivitiAlfrescoContentService.UNKNOWN_ERROR_MESSAGE; + if (error) { + errMsg = (error.message) ? error.message : + error.status ? `${error.status} - ${error.statusText}` : ActivitiAlfrescoContentService.GENERIC_ERROR_MESSAGE; + } + console.error(errMsg); + return Observable.throw(errMsg); + } +} diff --git a/ng2-components/ng2-activiti-form/src/services/form.service.ts b/ng2-components/ng2-activiti-form/src/services/form.service.ts index 95ab51d0cc..d9b90bb419 100644 --- a/ng2-components/ng2-activiti-form/src/services/form.service.ts +++ b/ng2-components/ng2-activiti-form/src/services/form.service.ts @@ -273,7 +273,6 @@ export class FormService { }); } - getFormId(res: any) { let result = null;