Merge pull request #629 from Alfresco/dev-mromano-591

ECM node to BPM form & BPM form to ECM node #628
This commit is contained in:
Denys Vuika
2016-08-26 10:55:34 +01:00
committed by GitHub
14 changed files with 755 additions and 36 deletions
@@ -1,3 +1,11 @@
<div class="activiti-form-viewer" *ngIf="taskId">
<activiti-form [taskId]="taskId"></activiti-form>
<!--<activiti-form [formName]="'activitiForms:patientFolder'"
[saveMetadata]="true"
[path]="'/Sites/swsdp/documentLibrary'"
[nameNode]="'test'"></activiti-form>-->
<!--<activiti-form [nodeId]="'e280be3a-6584-45a1-8bb5-89bfe070262e'"-->
<!--[saveMetadata]="true"-->
<!--[path]="'/Sites/swsdp/documentLibrary'">-->
<!--</activiti-form>-->
</div>
@@ -17,7 +17,7 @@
import { Component, OnInit, OnDestroy, AfterViewChecked } from '@angular/core';
import { ActivatedRoute, Router } from '@angular/router';
import { ActivitiForm, FormService } from 'ng2-activiti-form';
import { ActivitiForm, FormService, EcmModelService, NodeService } from 'ng2-activiti-form';
import { Subscription } from 'rxjs/Rx';
declare let __moduleName: string;
@@ -29,7 +29,7 @@ declare var componentHandler;
templateUrl: './form-viewer.component.html',
styleUrls: ['./form-viewer.component.css'],
directives: [ActivitiForm],
providers: [FormService]
providers: [FormService, EcmModelService, NodeService]
})
export class FormViewer implements OnInit, OnDestroy, AfterViewChecked {
@@ -78,6 +78,38 @@ Only form definition will be fetched
</activiti-form>
```
### Display form definition by ECM nodeId, in this case the metadata of the node are showed in an activiti Form. If there are no form
definied in activiti for the type of the node, a new form will be automaticaly created in activiti.
```html
<activiti-form
[nodeId]="'e280be3a-6584-45a1-8bb5-89bfe070262e'">
</activiti-form>
```
### Display form definition by form name, and store the form field as metadata. The param nameNode is optional.
```html
<activiti-form
[formName]="'activitiForms:patientFolder'"
[saveMetadata]="true"
[path]="'/Sites/swsdp/documentLibrary'"
[nameNode]="'test'">
</activiti-form>
```
### Display form definition by ECM nodeId, in this case the metadata of the node are showed in an activiti Form, and store the form field
as metadata. The param nameNode is optional.
```html
<activiti-form
[nodeId]="'e280be3a-6584-45a1-8bb5-89bfe070262e'"
[saveMetadata]="true"
[path]="'/Sites/swsdp/documentLibrary'"
[nameNode]="'test'">
</activiti-form>
```
## Configuration
### Properties
@@ -95,7 +127,15 @@ The recommended set of properties can be found in the following table:
| showSaveButton | boolean | true | Toggle rendering of the `Save` outcome button. |
| readOnly | boolean | false | Toggle readonly state of the form. Enforces all form widgets render readonly if enabled. |
| showRefreshButton | boolean | true | Toggle rendering of the `Refresh` button. |
| saveMetadata | boolean | false | Store the value of the form as metadata. |
| path | string | | Path of the folder where to store the metadata. |
| nameNode (optional) | string | true | Name to assign to the new node where the metadata are stored. |
*
* {path} string - path of the folder where the to store the metadata
*
* {nameNode} string (optional) - name of the node stored, if not defined the node will be sotred with an uuid as name
#### Advanced properties
The following properties are for complex customisation purposes:
@@ -18,3 +18,5 @@
export * from './src/components/activiti-form.component';
export * from './src/services/form.service';
export * from './src/components/widgets/index';
export * from './src/services/ecm-model.service';
export * from './src/services/node.service';
@@ -1,6 +1,6 @@
<div>
<div *ngIf="!hasForm()">
<h3 style="text-align: center">Please select a Visit</h3>
<h3 style="text-align: center">Please select a Task</h3>
</div>
<div *ngIf="hasForm()">
<div class="mdl-card mdl-shadow--2dp activiti-form-container">
@@ -32,7 +32,7 @@ describe('ActivitiForm', () => {
let visibilityService: WidgetVisibilityService;
beforeEach(() => {
componentHandler = jasmine.createSpyObj('componentHandler', [
componentHandler = jasmine.createSpyObj('componentHandler', [
'upgradeAllRegistered'
]);
visibilityService = jasmine.createSpyObj('WidgetVisibilityService', [
@@ -40,8 +40,8 @@ describe('ActivitiForm', () => {
]);
window['componentHandler'] = componentHandler;
formService = new FormService(null);
formComponent = new ActivitiForm(formService, visibilityService);
formService = new FormService(null, null);
formComponent = new ActivitiForm(formService, visibilityService, null, null, null);
});
it('should upgrade MDL content on view checked', () => {
@@ -23,9 +23,10 @@ import {
Output,
EventEmitter
} from '@angular/core';
import { MATERIAL_DESIGN_DIRECTIVES } from 'ng2-alfresco-core';
import { MATERIAL_DESIGN_DIRECTIVES, AlfrescoAuthenticationService } from 'ng2-alfresco-core';
import { EcmModelService } from './../services/ecm-model.service';
import { FormService } from './../services/form.service';
import { NodeService } from './../services/node.service';
import { FormModel, FormOutcomeModel, FormValues, FormFieldModel, FormOutcomeEvent } from './widgets/core/index';
import { TabsWidget } from './widgets/tabs/tabs.widget';
@@ -38,19 +39,23 @@ import { WidgetVisibilityService } from './../services/widget-visibility.servic
/**
* @Input
* ActivitiForm can show 3 forms searching by 3 type of params:
* ActivitiForm can show 4 types of forms searching by 4 type of params:
* 1) Form attached to a task passing the {taskId}.
*
* 2) Form that are only defined with the {formId} (in this case you receive only the form definition and the form will not be
* attached to any process, useful in case you want to use ActivitiForm as form designer), in this case you can pass also other 2
* parameters:
* - {saveOption} as parameter to tell what is the function to call on the save action.
* - {data} to fill the form field with some data, the id of the form must to match the name of the field of the provided data object.
*
* 3) Form that are only defined with the {formName} (in this case you receive only the form definition and the form will not be
* attached to any process, useful in case you want to use ActivitiForm as form designer),
* in this case you can pass also other 2 parameters:
* - {saveOption} as parameter to tell what is the function to call on the save action.
* - {data} to fill the form field with some data, the id of the form must to match the name of the field of the provided data object.
*
* 4) Form that show the metadata of a {nodeId}
*
* {showTitle} boolean - to hide the title of the form pass false, default true;
*
* {showRefreshButton} boolean - to hide the refresh button of the form pass false, default true;
@@ -59,6 +64,12 @@ import { WidgetVisibilityService } from './../services/widget-visibility.servic
*
* {showSaveButton} boolean - to hide the save button of the form pass false, default true;
*
* {saveMetadata} boolean - store the value of the form as metadata, default false;
*
* {path} string - path of the folder where to store the metadata;
*
* {nameNode} string (optional) - Name to assign to the new node where the metadata are stored;
*
* @Output
* {formLoaded} EventEmitter - This event is fired when the form is loaded, it pass all the value in the form.
* {formSaved} EventEmitter - This event is fired when the form is saved, it pass all the value in the form.
@@ -72,7 +83,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: [FormService, WidgetVisibilityService]
providers: [EcmModelService, FormService, WidgetVisibilityService, NodeService]
})
export class ActivitiForm implements OnInit, AfterViewChecked, OnChanges {
@@ -83,15 +94,27 @@ export class ActivitiForm implements OnInit, AfterViewChecked, OnChanges {
@Input()
taskId: string;
@Input()
nodeId: string;
@Input()
formId: string;
@Input()
formName: string;
@Input()
saveMetadata: boolean = false;
@Input()
data: FormValues;
@Input()
path: string;
@Input()
nameNode: string;
@Input()
showTitle: boolean = true;
@@ -124,7 +147,10 @@ export class ActivitiForm implements OnInit, AfterViewChecked, OnChanges {
debugMode: boolean = false;
constructor(private formService: FormService,
private visibilityService: WidgetVisibilityService) {
private visibilityService: WidgetVisibilityService,
private authService: AlfrescoAuthenticationService,
private ecmModelService: EcmModelService,
private nodeService: NodeService) {
}
hasForm(): boolean {
@@ -154,7 +180,11 @@ export class ActivitiForm implements OnInit, AfterViewChecked, OnChanges {
}
ngOnInit() {
this.loadForm();
if (this.nodeId) {
this.loadActivitiFormForEcmNode();
} else {
this.loadForm();
}
}
ngAfterViewChecked() {
@@ -208,6 +238,7 @@ export class ActivitiForm implements OnInit, AfterViewChecked, OnChanges {
if (outcome.id === ActivitiForm.CUSTOM_OUTCOME_ID) {
this.formSaved.emit(this.form);
this.storeFormAsMetadata();
return true;
}
} else {
@@ -275,7 +306,7 @@ export class ActivitiForm implements OnInit, AfterViewChecked, OnChanges {
.getFormDefinitionById(formId)
.subscribe(
form => {
// console.log('Get Form By definition Id', form);
this.formName = form.name;
this.form = this.parseForm(form);
this.formLoaded.emit(this.form);
},
@@ -306,7 +337,10 @@ export class ActivitiForm implements OnInit, AfterViewChecked, OnChanges {
this.formService
.saveTaskForm(this.form.taskId, this.form.values)
.subscribe(
() => this.formSaved.emit(this.form),
() => {
this.formSaved.emit(this.form);
this.storeFormAsMetadata();
},
this.handleError
);
}
@@ -317,13 +351,16 @@ export class ActivitiForm implements OnInit, AfterViewChecked, OnChanges {
this.formService
.completeTaskForm(this.form.taskId, this.form.values, outcome)
.subscribe(
() => this.formCompleted.emit(this.form),
() => {
this.formCompleted.emit(this.form);
this.storeFormAsMetadata();
},
this.handleError
);
}
}
handleError(err: any) {
handleError(err: any): any {
console.log(err);
}
@@ -345,7 +382,7 @@ export class ActivitiForm implements OnInit, AfterViewChecked, OnChanges {
*/
getFormDefinitionOutcomes(form: FormModel): FormOutcomeModel[] {
return [
new FormOutcomeModel(form, { id: '$custom', name: FormOutcomeModel.SAVE_ACTION, isSystem: true })
new FormOutcomeModel(form, {id: '$custom', name: FormOutcomeModel.SAVE_ACTION, isSystem: true})
];
}
@@ -354,4 +391,41 @@ export class ActivitiForm implements OnInit, AfterViewChecked, OnChanges {
this.visibilityService.updateVisibilityForForm(field.form);
}
}
private loadActivitiFormForEcmNode(): void {
this.nodeService.getNodeMetadata(this.nodeId).subscribe(data => {
this.data = data.metadata;
this.loadFormFromActiviti(data.nodeType);
},
this.handleError);
}
public loadFormFromActiviti(nodeType: string): any {
this.formService.searchFrom(nodeType).subscribe(
form => {
if (!form) {
this.formService.createFormFromNodeType(nodeType).subscribe(formMetadata => {
this.loadFormFromFormId(formMetadata.id);
});
} else {
this.loadFormFromFormId(form.id);
}
},
this.handleError
);
}
private loadFormFromFormId(formId: string) {
this.formId = formId;
this.loadForm();
}
private storeFormAsMetadata() {
if (this.saveMetadata) {
this.ecmModelService.createEcmTypeForActivitiForm(this.formName, this.form).subscribe(type => {
this.nodeService.createNodeMetadata(type.nodeType || type.entry.prefixedName, EcmModelService.MODEL_NAMESPACE, this.form.values, this.path, this.nameNode);
}, this.handleError
);
}
}
}
@@ -0,0 +1,95 @@
/*!
* @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 class FormDefinitionModel {
reusable: boolean = false;
newVersion: boolean = false;
formRepresentation: any;
formImageBase64: string = '';
constructor(id: string, name: any, lastUpdatedByFullName: string, lastUpdated: string, metadata: any) {
this.formRepresentation = {
id: id,
name: name,
description: '',
version: 1,
lastUpdatedBy: 1,
lastUpdatedByFullName: lastUpdatedByFullName,
lastUpdated: lastUpdated,
stencilSetId: 0,
referenceId: null,
formDefinition: {
fields: [{
name: 'Label',
type: 'container',
fieldType: 'ContainerRepresentation',
numberOfColumns: 2,
required: false,
readOnly: false,
sizeX: 2,
sizeY: 1,
row: -1,
col: -1,
fields: {'1': this.metadataToFields(metadata)}
}],
gridsterForm: false,
javascriptEvents: [],
metadata: {},
outcomes: [],
className: '',
style: '',
tabs: [],
variables: []
}
};
}
private metadataToFields(metadata: any): any[] {
let fields = [];
if (metadata) {
metadata.forEach(function(property) {
if (property) {
let field = {
type: 'text',
id: property.name,
name: property.name,
required: false,
readOnly: false,
sizeX: 1,
sizeY: 1,
row: -1,
col: -1,
colspan: 1,
params: {
existingColspan: 1,
maxColspan: 2
},
layout: {
colspan: 1,
row: -1,
column: -1
}
};
fields.push(field);
}
});
}
return fields;
}
}
@@ -0,0 +1,26 @@
/*!
* @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 class NodeMetadata {
metadata: any;
nodeType: string;
constructor(metadata: any, nodeType: string) {
this.metadata = metadata;
this.nodeType = nodeType;
}
}
@@ -0,0 +1,262 @@
/*!
* @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 { AlfrescoAuthenticationService, AlfrescoSettingsService } from 'ng2-alfresco-core';
import { Observable } from 'rxjs/Rx';
import { Response, Http, Headers, RequestOptions } from '@angular/http';
import { FormModel } from '../components/widgets/core/form.model';
import { NodeService } from './node.service';
@Injectable()
export class EcmModelService {
public static MODEL_NAMESPACE: string = 'activitiForms';
public static MODEL_NAME: string = 'activitiFormsModel';
public static TYPE_MODEL: string = 'cm:folder';
constructor(private authService: AlfrescoAuthenticationService,
private http: Http,
public alfrescoSettingsService: AlfrescoSettingsService,
private nodeService: NodeService) {
}
public createEcmTypeForActivitiForm(formName: string, form: FormModel): Observable<any> {
return Observable.create(observer => {
this.seachActivitiEcmModel().subscribe(
model => {
if (!model) {
this.createActivitiEcmModel(formName, form).subscribe(typeForm => {
observer.next(typeForm);
observer.complete();
});
} else {
this.createFomType(formName, form).subscribe(typeForm => {
observer.next(typeForm);
observer.complete();
});
}
},
this.handleError
);
});
}
private seachActivitiEcmModel() {
return this.getEcmModels().map(function (ecmModels: any) {
return ecmModels.list.entries.find(model => model.entry.name === EcmModelService.MODEL_NAME);
});
}
private createActivitiEcmModel(formName: string, form: FormModel): Observable<any> {
return Observable.create(observer => {
this.createEcmModel(EcmModelService.MODEL_NAME, EcmModelService.MODEL_NAMESPACE).subscribe(
model => {
console.log('model created', model);
this.activeEcmModel(EcmModelService.MODEL_NAME).subscribe(
modelActive => {
console.log('model active', modelActive);
this.createEcmTypeWithProperties(formName, form).subscribe(typeCreated => {
observer.next(typeCreated);
observer.complete();
});
},
this.handleError
);
},
this.handleError
);
});
}
private createFomType(formName: string, form: FormModel): Observable<any> {
return Observable.create(observer => {
this.searchFormType(formName).subscribe(
ecmType => {
console.log('custom types', ecmType);
if (!ecmType) {
this.createEcmTypeWithProperties(formName, form).subscribe(typeCreated => {
observer.next(typeCreated);
observer.complete();
});
} else {
observer.next(ecmType);
observer.complete();
}
},
this.handleError
);
});
}
public createEcmTypeWithProperties(formName: string, form: FormModel): Observable<any> {
return Observable.create(observer => {
this.createEcmType(formName, EcmModelService.MODEL_NAME, EcmModelService.TYPE_MODEL).subscribe(
typeCreated => {
console.log('type Created', typeCreated);
this.addPropertyToAType(EcmModelService.MODEL_NAME, formName, form).subscribe(
properyAdded => {
console.log('property Added', properyAdded);
observer.next(typeCreated);
observer.complete();
},
this.handleError);
},
this.handleError);
});
}
public searchFormType(formName: string): Observable<any> {
return this.getEcmType(EcmModelService.MODEL_NAME).map(function (customTypes: any) {
return customTypes.list.entries.find(type => type.entry.prefixedName === formName);
});
}
public activeEcmModel(modelName: string): Observable<any> {
let url = `${this.alfrescoSettingsService.ecmHost}/alfresco/api/-default-/private/alfresco/versions/1/cmm/${modelName}?select=status`;
let options = this.getRequestOptions();
let body = {status: 'ACTIVE'};
return this.http
.put(url, body, options)
.map(this.toJson)
.catch(this.handleError);
}
public createEcmModel(modelName: string, nameSpace: string): Observable<any> {
let url = `${this.alfrescoSettingsService.ecmHost}/alfresco/api/-default-/private/alfresco/versions/1/cmm`;
let options = this.getRequestOptions();
let body = {
status: 'DRAFT', namespaceUri: modelName, namespacePrefix: nameSpace, name: modelName, description: '', author: ''
};
return this.http
.post(url, body, options)
.map(this.toJson)
.catch(this.handleError);
}
public getEcmModels(): Observable<any> {
let url = `${this.alfrescoSettingsService.ecmHost}/alfresco/api/-default-/private/alfresco/versions/1/cmm`;
let options = this.getRequestOptions();
return this.http
.get(url, options)
.map(this.toJson)
.catch(this.handleError);
}
public getEcmType(modelName: string): Observable<any> {
let url = `${this.alfrescoSettingsService.ecmHost}/alfresco/api/-default-/private/alfresco/versions/1/cmm/${modelName}/types`;
let options = this.getRequestOptions();
return this.http
.get(url, options)
.map(this.toJson)
.catch(this.handleError);
}
public createEcmType(typeName: string, modelName: string, parentType: string): Observable<any> {
let name = this.cleanNameType(typeName);
let url = `${this.alfrescoSettingsService.ecmHost}/alfresco/api/-default-/private/alfresco/versions/1/cmm/${modelName}/types`;
let options = this.getRequestOptions();
let body = {
name: name,
parentName: parentType,
title: typeName,
description: ''
};
return this.http
.post(url, body, options)
.map(this.toJson)
.catch(this.handleError);
}
public addPropertyToAType(modelName: string, typeName: string, formFields: any) {
let name = this.cleanNameType(typeName);
let url = `${this.alfrescoSettingsService.ecmHost}/alfresco/api/-default-/private/alfresco/versions/1/cmm/${modelName}/types/${name}?select=props`;
let options = this.getRequestOptions();
let properties = [];
if (formFields && formFields.values) {
for (let key in formFields.values) {
if (key) {
properties.push({
name: key,
title: key,
description: key,
dataType: 'd:text',
multiValued: false,
mandatory: false,
mandatoryEnforced: false
});
}
}
}
let body = {
name: name,
properties: properties
};
return this.http
.put(url, body, options)
.map(this.toJson)
.catch(this.handleError);
}
public cleanNameType(name: string): string {
let cleanName = name;
if (name.indexOf(':') !== -1) {
cleanName = name.split(':')[1];
}
return cleanName.replace(/[^a-zA-Z ]/g, '');
}
public getHeaders(): Headers {
return new Headers({
'Accept': 'application/json',
'Content-Type': 'application/json',
'Authorization': this.authService.getTicketEcmBase64()
});
}
public getRequestOptions(): RequestOptions {
let headers = this.getHeaders();
return new RequestOptions({headers: headers});
}
toJson(res: Response) {
if (res) {
let body = res.json();
return body || {};
}
return {};
}
handleError(err: any): any {
console.log(err);
}
}
@@ -17,8 +17,10 @@
import { it, inject, describe, expect, beforeEach, beforeEachProviders, afterEach } from '@angular/core/testing';
import { AlfrescoAuthenticationService, AlfrescoSettingsService } from 'ng2-alfresco-core';
import { Response, ResponseOptions } from '@angular/http';
import { HTTP_PROVIDERS, Response, ResponseOptions } from '@angular/http';
import { FormService } from './form.service';
import { EcmModelService } from './ecm-model.service';
import { NodeService } from './node.service';
declare let jasmine: any;
@@ -30,7 +32,10 @@ describe('FormService', () => {
return [
FormService,
AlfrescoSettingsService,
AlfrescoAuthenticationService
AlfrescoAuthenticationService,
EcmModelService,
HTTP_PROVIDERS,
NodeService
];
});
@@ -15,10 +15,12 @@
* limitations under the License.
*/
import {Injectable} from '@angular/core';
import {Observable} from 'rxjs/Rx';
import {AlfrescoAuthenticationService} from 'ng2-alfresco-core';
import {FormValues} from './../components/widgets/core/index';
import { Injectable } from '@angular/core';
import { Observable } from 'rxjs/Rx';
import { AlfrescoAuthenticationService } from 'ng2-alfresco-core';
import { FormValues } from './../components/widgets/core/index';
import { FormDefinitionModel } from '../models/form-definition.model';
import { EcmModelService } from './ecm-model.service';
@Injectable()
export class FormService {
@@ -26,28 +28,127 @@ export class FormService {
static UNKNOWN_ERROR_MESSAGE: string = 'Unknown error';
static GENERIC_ERROR_MESSAGE: string = 'Server error';
constructor(private authService: AlfrescoAuthenticationService) {
constructor(private authService: AlfrescoAuthenticationService,
private ecmModelService: EcmModelService) {
}
getProcessDefinitions(): Observable<any> {
/**
* Create a Form with a fields for each metadata properties
* @returns {Observable<any>}
*/
public createFormFromNodeType(formName: string): Observable<any> {
return Observable.create(observer => {
this.createForm(formName).subscribe(
form => {
this.ecmModelService.searchFormType(formName).subscribe(
customType => {
let formDefinitionModel = new FormDefinitionModel(form.id, form.name, form.lastUpdatedByFullName, form.lastUpdated, customType.entry.properties);
this.addFieldsNodeTypePropertiesToTheForm(form.id, formDefinitionModel).subscribe(formData => {
observer.next(formData);
observer.complete();
}, this.handleError);
},
this.handleError);
}, this.handleError);
});
}
/**
* Create a Form
* @returns {Observable<any>}
*/
public createForm(formName: string): Observable<any> {
let dataModel = {
name: formName,
description: '',
modelType: 2,
stencilSet: 0
};
return Observable.fromPromise(this.authService.getAlfrescoApi().activiti.modelsApi.createModel(dataModel));
}
/**
* Add Fields to A form from a metadata properties
* @returns {Observable<any>}
*/
public addFieldsNodeTypePropertiesToTheForm(formId: string, formDefinitionModel: FormDefinitionModel): Observable<any> {
return this.addFieldsToAForm(formId, formDefinitionModel);
}
/**
* Add Fileds to A form
* @returns {Observable<any>}
*/
public addFieldsToAForm(formId: string, formModel: FormDefinitionModel): Observable<any> {
return Observable.fromPromise(this.authService.getAlfrescoApi().activiti.editorApi.saveForm(formId, formModel));
}
/**
* Search For A Form by name
* @returns {Observable<any>}
*/
public searchFrom(name: string): Observable<any> {
let opts = {
'modelType': 2
};
return Observable.fromPromise(this.authService.getAlfrescoApi().activiti.modelsApi.getModels(opts)).map(function (forms: any) {
return forms.data.find(formdata => formdata.name === name);
}).catch(this.handleError);
}
/**
* Get All the forms
* @returns {Observable<any>}
*/
public getForms(): Observable<any> {
let opts = {
'modelType': 2
};
return Observable.fromPromise(this.authService.getAlfrescoApi().activiti.modelsApi.getModels(opts));
}
/**
* Get Process Definition
* @returns {Observable<any>}
*/
public getProcessDefinitions(): Observable<any> {
return Observable.fromPromise(this.authService.getAlfrescoApi().activiti.processApi.getProcessDefinitions({}))
.map(this.toJsonArray)
.catch(this.handleError);
}
getTasks(): Observable<any> {
/**
* Get All the Tasks
* @param taskId Task Id
* @returns {Observable<any>}
*/
public getTasks(): Observable<any> {
return Observable.fromPromise(this.authService.getAlfrescoApi().activiti.taskApi.listTasks({}))
.map(this.toJsonArray)
.catch(this.handleError);
}
getTask(taskId: string): Observable<any> {
/**
* Get Task
* @param taskId Task Id
* @returns {Observable<any>}
*/
public getTask(taskId: string): Observable<any> {
return Observable.fromPromise(this.authService.getAlfrescoApi().activiti.taskApi.getTask(taskId))
.map(this.toJson)
.catch(this.handleError);
}
saveTaskForm(taskId: string, formValues: FormValues): Observable<any> {
/**
* Save Task Form
* @param taskId Task Id
* @param formValues Form Values
* @returns {Observable<any>}
*/
public saveTaskForm(taskId: string, formValues: FormValues): Observable<any> {
let body = JSON.stringify({values: formValues});
return Observable.fromPromise(this.authService.getAlfrescoApi().activiti.taskApi.saveTaskForm(taskId, body))
@@ -59,9 +160,9 @@ export class FormService {
* @param taskId Task Id
* @param formValues Form Values
* @param outcome Form Outcome
* @returns {any}
* @returns {Observable<any>}
*/
completeTaskForm(taskId: string, formValues: FormValues, outcome?: string): Observable<any> {
public completeTaskForm(taskId: string, formValues: FormValues, outcome?: string): Observable<any> {
let data: any = {values: formValues};
if (outcome) {
data.outcome = outcome;
@@ -72,13 +173,23 @@ export class FormService {
.catch(this.handleError);
}
getTaskForm(taskId: string): Observable<any> {
/**
* Get Form related to a taskId
* @param taskId Task Id
* @returns {Observable<any>}
*/
public getTaskForm(taskId: string): Observable<any> {
return Observable.fromPromise(this.authService.getAlfrescoApi().activiti.taskApi.getTaskForm(taskId))
.map(this.toJson)
.catch(this.handleError);
}
getFormDefinitionById(formId: string): Observable<any> {
/**
* Get Form Definition
* @param formId Form Id
* @returns {Observable<any>}
*/
public getFormDefinitionById(formId: string): Observable<any> {
return Observable.fromPromise(this.authService.getAlfrescoApi().activiti.editorApi.getForm(formId))
.map(this.toJson)
.catch(this.handleError);
@@ -89,7 +200,7 @@ export class FormService {
* @param name
* @returns {Promise<T>|Promise<ErrorObservable>}
*/
getFormDefinitionByName(name: string): Observable<any> {
public getFormDefinitionByName(name: string): Observable<any> {
let opts = {
'filter': 'myReusableForms',
'filterText': name,
@@ -0,0 +1,96 @@
/*!
* @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 { AlfrescoAuthenticationService } from 'ng2-alfresco-core';
import { Observable } from 'rxjs/Rx';
import { NodeMetadata } from '../models/node-metadata.model';
@Injectable()
export class NodeService {
constructor(private authService: AlfrescoAuthenticationService) {
}
/**
* Get All the metadata and the nodeType for a nodeId cleaned by the prefix
* @param nodeId Node Id
* @returns NodeMetadata
*/
public getNodeMetadata(nodeId: string): Observable<NodeMetadata> {
return Observable.fromPromise(this.authService.getAlfrescoApi().nodes.getNodeInfo(nodeId)).map(this.cleanMetadataFromSemicolon);
}
/**
* Create a new Node from form metadata
* @param path path
* @param nodeType node type
* @param nameSpace namespace node
* @param data data to store
* @returns NodeMetadata
*/
public createNodeMetadata(nodeType: string, nameSpace: any, data: any, path: string, name?: string): Observable<any> {
let properties = {};
for (let key in data) {
if (data[key]) {
properties[nameSpace + ':' + key] = data[key];
}
}
return this.createNode(name || this.generateUuid(), nodeType, properties, path);
}
/**
* Create a new Node from form metadata
* @param name path
* @param nodeType node type
* @param properties namespace node
* @param path path
* @returns NodeMetadata
*/
public createNode(name: string, nodeType: string, properties: any, path: string): Observable<any> {
let body = {
name: name,
nodeType: nodeType,
properties: properties,
relativePath: path
};
return Observable.fromPromise(this.authService.getAlfrescoApi().nodes.addNode('-root-', body, {}));
}
private generateUuid() {
return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function (c) {
let r = Math.random() * 16 | 0, v = c === 'x' ? r : (r & 0x3 | 0x8);
return v.toString(16);
});
}
private cleanMetadataFromSemicolon(data: any): NodeMetadata {
let metadata = {};
if (data && data.properties) {
for (let key in data.properties) {
if (key) {
metadata [key.split(':')[1]] = data.properties[key];
}
}
}
return new NodeMetadata(metadata, data.nodeType);
}
}
@@ -33,9 +33,9 @@ export class AlfrescoSettingsService {
private providers: string = 'ALL'; // ECM, BPM , ALL
bpmHostSubject: Subject<string> = new Subject<string>();
ecmHostSubject: Subject<string> = new Subject<string>();
providerSubject: Subject<string> = new Subject<string>();
public bpmHostSubject: Subject<string> = new Subject<string>();
public ecmHostSubject: Subject<string> = new Subject<string>();
public providerSubject: Subject<string> = new Subject<string>();
public get ecmHost(): string {
return this._ecmHost;