-
+
diff --git a/demo-shell-ng2/app/components/search/search.component.ts b/demo-shell-ng2/app/components/search/search.component.ts
index bf836b7783..2d14f09e4b 100644
--- a/demo-shell-ng2/app/components/search/search.component.ts
+++ b/demo-shell-ng2/app/components/search/search.component.ts
@@ -52,10 +52,7 @@ declare let __moduleName: string;
})
export class SearchComponent {
- previewContentUrl: string;
- previewName: string;
- previewMimeType: string;
- previewActive: boolean = false;
+ fileShowed: boolean = false;
fileNodeId: string;
constructor(public contentService: AlfrescoContentService) {
@@ -64,7 +61,7 @@ export class SearchComponent {
onFileClicked(event) {
if (event.value.entry.isFile) {
this.fileNodeId = event.value.entry.id;
- this.previewActive = true;
+ this.fileShowed = true;
}
}
}
diff --git a/demo-shell-ng2/app/main.ts b/demo-shell-ng2/app/main.ts
index 1ae1a4152d..d7ae6ebc81 100644
--- a/demo-shell-ng2/app/main.ts
+++ b/demo-shell-ng2/app/main.ts
@@ -19,9 +19,9 @@ import { bootstrap } from '@angular/platform-browser-dynamic';
import { HTTP_PROVIDERS } from '@angular/http';
import { ALFRESCO_SEARCH_PROVIDERS } from 'ng2-alfresco-search';
import { ALFRESCO_CORE_PROVIDERS } from 'ng2-alfresco-core';
+import { ATIVITI_FORM_PROVIDERS } from 'ng2-activiti-form';
import { UploadService } from 'ng2-alfresco-upload';
import { AppComponent } from './app.component';
-
import { appRouterProviders } from './app.routes';
bootstrap(AppComponent, [
@@ -29,5 +29,6 @@ bootstrap(AppComponent, [
HTTP_PROVIDERS,
ALFRESCO_CORE_PROVIDERS,
ALFRESCO_SEARCH_PROVIDERS,
- UploadService
+ UploadService,
+ ATIVITI_FORM_PROVIDERS
]).catch(err => console.error(err));
diff --git a/demo-shell-ng2/i18n/en.json b/demo-shell-ng2/i18n/en.json
index 6f006a8158..1a35a1e670 100644
--- a/demo-shell-ng2/i18n/en.json
+++ b/demo-shell-ng2/i18n/en.json
@@ -4,7 +4,7 @@
"DOCUMENT_LIST": {
"COLUMNS": {
"DISPLAY_NAME": "Display name",
- "CREATED_BY": "mario",
+ "CREATED_BY": "Created by",
"CREATED_ON": "Created on"
},
"ACTIONS": {
diff --git a/demo-shell-ng2/index.html b/demo-shell-ng2/index.html
index 3fbdbbf291..bb2bb3260f 100644
--- a/demo-shell-ng2/index.html
+++ b/demo-shell-ng2/index.html
@@ -16,6 +16,10 @@
+
+
+
+
diff --git a/demo-shell-ng2/package.json b/demo-shell-ng2/package.json
index 00c0a6bd02..b211986a22 100644
--- a/demo-shell-ng2/package.json
+++ b/demo-shell-ng2/package.json
@@ -1,7 +1,7 @@
{
"name": "Alfresco-Angular2-Demo",
"description": "Demo shell for Alfresco Angular2 components",
- "version": "0.2.0",
+ "version": "0.3.0",
"author": "Alfresco Software, Ltd.",
"scripts": {
"postinstall": "typings install",
@@ -73,18 +73,20 @@
"material-design-icons": "2.2.3",
"material-design-lite": "1.1.3",
"ng2-translate": "2.2.0",
- "pdfjs-dist": "1.5.258",
+ "pdfjs-dist": "1.5.404",
"flag-icon-css": "2.3.0",
- "ng2-alfresco-core": "0.2.0",
- "ng2-alfresco-datatable": "0.2.0",
- "ng2-alfresco-documentlist": "0.2.0",
- "ng2-alfresco-login": "0.2.0",
- "ng2-alfresco-search": "0.2.0",
- "ng2-alfresco-upload": "0.2.0",
- "ng2-alfresco-viewer": "0.2.0",
- "ng2-activiti-form": "0.2.0",
- "ng2-activiti-tasklist": "0.2.0",
- "ng2-alfresco-webscript": "0.2.0"
+ "intl": "1.2.4",
+ "ng2-alfresco-core": "0.3.0",
+ "ng2-alfresco-datatable": "0.3.0",
+ "ng2-alfresco-documentlist": "0.3.0",
+ "ng2-alfresco-login": "0.3.0",
+ "ng2-alfresco-search": "0.3.0",
+ "ng2-alfresco-upload": "0.3.0",
+ "ng2-alfresco-viewer": "0.3.0",
+ "ng2-activiti-form": "0.3.0",
+ "ng2-activiti-tasklist": "0.3.0",
+ "ng2-activiti-processlist": "0.3.0",
+ "ng2-alfresco-webscript": "0.3.0"
},
"devDependencies": {
"concurrently": "2.0.0",
diff --git a/demo-shell-ng2/systemjs.config.js b/demo-shell-ng2/systemjs.config.js
index 726992d104..2b0b1daf97 100644
--- a/demo-shell-ng2/systemjs.config.js
+++ b/demo-shell-ng2/systemjs.config.js
@@ -22,6 +22,7 @@
'ng2-alfresco-webscript': 'node_modules/ng2-alfresco-webscript/dist',
'ng2-activiti-tasklist': 'node_modules/ng2-activiti-tasklist/dist',
'alfresco-js-api': 'node_modules/alfresco-js-api/dist'
+ 'ng2-activiti-processlist': 'node_modules/ng2-activiti-processlist/dist'
};
// packages tells the System loader how to load when no filename and/or no extension
var packages = {
@@ -39,6 +40,7 @@
'ng2-alfresco-upload': { main: 'index.js', defaultExtension: 'js'},
'ng2-alfresco-viewer': { main: 'index.js', defaultExtension: 'js'},
'ng2-activiti-form': { main: 'index.js', defaultExtension: 'js'},
+ 'ng2-activiti-processlist': { main: 'index.js', defaultExtension: 'js'},
'ng2-activiti-tasklist': { main: 'index.js', defaultExtension: 'js'},
'ng2-alfresco-webscript': { main: 'index.js', defaultExtension: 'js'},
'alfresco-js-api': { main: 'alfresco-js-api.js', defaultExtension: 'js'}
diff --git a/ng2-components/ng2-activiti-form/README.md b/ng2-components/ng2-activiti-form/README.md
index cd66c1e8f6..e0ddb5af56 100644
--- a/ng2-components/ng2-activiti-form/README.md
+++ b/ng2-components/ng2-activiti-form/README.md
@@ -78,6 +78,38 @@ Only form definition will be fetched
```
+### 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
+
+
+```
+
+### Display form definition by form name, and store the form field as metadata. The param nameNode is optional.
+
+```html
+
+
+```
+
+### 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
+
+
+```
+
## Configuration
### Properties
@@ -95,7 +127,14 @@ 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:
@@ -120,7 +159,7 @@ All `form*` events receive an instance of the `FormModel` as event argument for
```html
+ (formSaved)="onFormSaved($event)">
```
diff --git a/ng2-components/ng2-activiti-form/index.ts b/ng2-components/ng2-activiti-form/index.ts
index f57a867f26..093ae1f90c 100644
--- a/ng2-components/ng2-activiti-form/index.ts
+++ b/ng2-components/ng2-activiti-form/index.ts
@@ -15,6 +15,19 @@
* limitations under the License.
*/
+import { FormService } from './src/services/form.service';
+import { EcmModelService } from './src/services/ecm-model.service';
+import { NodeService } from './src/services/node.service';
+
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';
+
+
+export const ATIVITI_FORM_PROVIDERS: [any] = [
+ FormService,
+ EcmModelService,
+ NodeService
+];
diff --git a/ng2-components/ng2-activiti-form/package.json b/ng2-components/ng2-activiti-form/package.json
index d656f1422c..d0594e8c52 100644
--- a/ng2-components/ng2-activiti-form/package.json
+++ b/ng2-components/ng2-activiti-form/package.json
@@ -1,7 +1,7 @@
{
"name": "ng2-activiti-form",
"description": "Alfresco Activiti Form Component for Angular 2",
- "version": "0.2.0",
+ "version": "0.3.0",
"author": "Alfresco Software, Ltd.",
"scripts": {
"postinstall": "typings install",
@@ -65,7 +65,7 @@
"rxjs": "5.0.0-beta.6",
"zone.js": "0.6.12",
"ng2-translate": "2.2.2",
- "ng2-alfresco-core": "0.2.0"
+ "ng2-alfresco-core": "0.3.0"
},
"peerDependencies": {
"material-design-icons": "^2.2.3",
diff --git a/ng2-components/ng2-activiti-form/src/components/activiti-form.component.html b/ng2-components/ng2-activiti-form/src/components/activiti-form.component.html
index b0a1858552..7bb2551e8a 100644
--- a/ng2-components/ng2-activiti-form/src/components/activiti-form.component.html
+++ b/ng2-components/ng2-activiti-form/src/components/activiti-form.component.html
@@ -1,6 +1,6 @@
-
Please select a Visit
+
Please select a Task
diff --git a/ng2-components/ng2-activiti-form/src/components/activiti-form.component.spec.ts b/ng2-components/ng2-activiti-form/src/components/activiti-form.component.spec.ts
index 4571c1a6a4..133206d5b6 100644
--- a/ng2-components/ng2-activiti-form/src/components/activiti-form.component.spec.ts
+++ b/ng2-components/ng2-activiti-form/src/components/activiti-form.component.spec.ts
@@ -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', () => {
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 69865b8a1c..d763eb0128 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
@@ -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
+ );
+ }
+ }
}
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 bd2732ddc4..6cffc9730c 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
@@ -43,6 +43,9 @@
+
+
+
UNKNOWN WIDGET TYPE: {{field.type}}
diff --git a/ng2-components/ng2-activiti-form/src/components/widgets/core/form-field-types.ts b/ng2-components/ng2-activiti-form/src/components/widgets/core/form-field-types.ts
index e01b261033..627bcfe5d2 100644
--- a/ng2-components/ng2-activiti-form/src/components/widgets/core/form-field-types.ts
+++ b/ng2-components/ng2-activiti-form/src/components/widgets/core/form-field-types.ts
@@ -23,6 +23,7 @@ export class FormFieldTypes {
static RADIO_BUTTONS: string = 'radio-buttons';
static DISPLAY_VALUE: string = 'readonly';
static READONLY_TEXT: string = 'readonly-text';
+ static UPLOAD: string = 'upload';
static READONLY_TYPES: string[] = [
FormFieldTypes.HYPERLINK,
diff --git a/ng2-components/ng2-activiti-form/src/components/widgets/core/form-field.model.ts b/ng2-components/ng2-activiti-form/src/components/widgets/core/form-field.model.ts
index 916c8714df..22bd3822ae 100644
--- a/ng2-components/ng2-activiti-form/src/components/widgets/core/form-field.model.ts
+++ b/ng2-components/ng2-activiti-form/src/components/widgets/core/form-field.model.ts
@@ -129,34 +129,45 @@ export class FormFieldModel extends FormWidgetModel {
}
updateForm() {
- if (this.type === FormFieldTypes.DROPDOWN) {
- /*
- This is needed due to Activiti reading dropdown values as string
- but saving back as object: { id: , name: }
- */
- if (this.value === 'empty' || this.value === '') {
- this.form.values[this.id] = {};
- } else {
+
+ switch (this.type) {
+ case FormFieldTypes.DROPDOWN:
+ /*
+ This is needed due to Activiti reading dropdown values as string
+ but saving back as object: { id: , name: }
+ */
+ if (this.value === 'empty' || this.value === '') {
+ this.form.values[this.id] = {};
+ } else {
+ let entry: FormFieldOption[] = this.options.filter(opt => opt.id === this.value);
+ if (entry.length > 0) {
+ this.form.values[this.id] = entry[0];
+ }
+ }
+ break;
+ case FormFieldTypes.RADIO_BUTTONS:
+ /*
+ This is needed due to Activiti issue related to reading radio button values as value string
+ but saving back as object: { id: , name: }
+ */
let entry: FormFieldOption[] = this.options.filter(opt => opt.id === this.value);
if (entry.length > 0) {
this.form.values[this.id] = entry[0];
+ } else if (this.options.length > 0) {
+ this.form.values[this.id] = this.options[0];
+ }
+ break;
+ case FormFieldTypes.UPLOAD:
+ if (this.value && this.value.length > 0) {
+ this.form.values[this.id] = `${this.value[0].id}`;
+ } else {
+ this.form.values[this.id] = null;
+ }
+ break;
+ default:
+ if (!FormFieldTypes.isReadOnlyType(this.type)) {
+ this.form.values[this.id] = this.value;
}
- }
- } else if (this.type === FormFieldTypes.RADIO_BUTTONS) {
- /*
- This is needed due to Activiti issue related to reading radio button values as value string
- but saving back as object: { id: , name: }
- */
- let entry: FormFieldOption[] = this.options.filter(opt => opt.id === this.value);
- if (entry.length > 0) {
- this.form.values[this.id] = entry[0];
- } else if (this.options.length > 0) {
- this.form.values[this.id] = this.options[0];
- }
- } else {
- if (!FormFieldTypes.isReadOnlyType(this.type)) {
- this.form.values[this.id] = this.value;
- }
}
}
}
diff --git a/ng2-components/ng2-activiti-form/src/components/widgets/dropdown/dropdown.widget.html b/ng2-components/ng2-activiti-form/src/components/widgets/dropdown/dropdown.widget.html
index 3da33231b0..a6c3d50a94 100644
--- a/ng2-components/ng2-activiti-form/src/components/widgets/dropdown/dropdown.widget.html
+++ b/ng2-components/ng2-activiti-form/src/components/widgets/dropdown/dropdown.widget.html
@@ -1,4 +1,5 @@
- Authentication failed to ip {{ host }} with user: admin, admin, you can still try to add a valid token to perform
+ Authentication failed to ip {{ ecmHost }} with user: admin, admin, you can still try to add a valid ticket to perform
operations.