diff --git a/demo-shell-ng2/app/components/setting/setting.component.ts b/demo-shell-ng2/app/components/setting/setting.component.ts
index b0d7d17a53b..733007344c1 100644
--- a/demo-shell-ng2/app/components/setting/setting.component.ts
+++ b/demo-shell-ng2/app/components/setting/setting.component.ts
@@ -15,15 +15,17 @@
* limitations under the License.
*/
-import { Component } from '@angular/core';
+import { Component, AfterViewChecked } from '@angular/core';
import { AlfrescoSettingsService, StorageService, LogService } from 'ng2-alfresco-core';
+declare var componentHandler: any;
+
@Component({
selector: 'alfresco-setting-demo',
templateUrl: './setting.component.html',
styleUrls: ['./setting.component.css']
})
-export class SettingComponent {
+export class SettingComponent implements AfterViewChecked {
ecmHost: string;
bpmHost: string;
@@ -35,24 +37,39 @@ export class SettingComponent {
this.bpmHost = this.settingsService.bpmHost;
}
+ ngAfterViewChecked() {
+ // workaround for MDL issues with dynamic components
+ if (componentHandler) {
+ componentHandler.upgradeAllRegistered();
+ }
+ }
+
public onChangeECMHost(event: KeyboardEvent): void {
let value = (event.target).value.trim();
- if (value) {
+ if (value && this.isValidUrl(value)) {
this.logService.info(`ECM host: ${value}`);
this.ecmHost = value;
this.settingsService.ecmHost = value;
this.storage.setItem(`ecmHost`, value);
+ } else {
+ console.error('Ecm address does not match the pattern');
}
}
public onChangeBPMHost(event: KeyboardEvent): void {
let value = (event.target).value.trim();
- if (value) {
+ if (value && this.isValidUrl(value)) {
this.logService.info(`BPM host: ${value}`);
this.bpmHost = value;
this.settingsService.bpmHost = value;
this.storage.setItem(`bpmHost`, value);
+ } else {
+ console.error('Bpm address does not match the pattern');
}
}
+ isValidUrl(url: string) {
+ return /^(http|https):\/\/.*/.test(url);
+ }
+
}
diff --git a/demo-shell-ng2/app/components/social/social.component.ts b/demo-shell-ng2/app/components/social/social.component.ts
new file mode 100644
index 00000000000..af40a06f6c7
--- /dev/null
+++ b/demo-shell-ng2/app/components/social/social.component.ts
@@ -0,0 +1,39 @@
+/*!
+ * @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 } from '@angular/core';
+
+@Component({
+ selector: 'alfresco-social-demo',
+ template: `
+
+
+
+
+ Like component
+
+
+ Rating component
+
+
+
+ `
+})
+export class SocialComponent {
+
+ nodeId: string = '74cd8a96-8a21-47e5-9b3b-a1b3e296787d';
+}
diff --git a/demo-shell-ng2/app/vendor.ts b/demo-shell-ng2/app/vendor.ts
index 55f232dee51..91d7764380b 100644
--- a/demo-shell-ng2/app/vendor.ts
+++ b/demo-shell-ng2/app/vendor.ts
@@ -25,6 +25,7 @@ import 'ng2-alfresco-documentlist';
import 'ng2-alfresco-login';
import 'ng2-alfresco-search';
import 'ng2-alfresco-tag';
+import 'ng2-alfresco-social';
import 'ng2-alfresco-upload';
import 'ng2-alfresco-viewer';
import 'ng2-alfresco-webscript';
diff --git a/demo-shell-ng2/package.json b/demo-shell-ng2/package.json
index 1dcccc870c3..e86868a891e 100644
--- a/demo-shell-ng2/package.json
+++ b/demo-shell-ng2/package.json
@@ -1,11 +1,11 @@
{
"name": "Alfresco-Angular2-Demo",
"description": "Demo shell for Alfresco Angular2 components",
- "version": "1.3.0",
+ "version": "1.4.0",
"author": "Alfresco Software, Ltd.",
"scripts": {
"clean": "npm install rimraf && npm run clean-build && rimraf dist node_modules typings dist",
- "start": "npm run server-versions && webpack-dev-server --progress --max_old_space_size=4096 --max_new_space_size=4096",
+ "start": "npm run tslint && npm run server-versions && webpack-dev-server --progress --max_old_space_size=4096 --max_new_space_size=4096",
"start:dist": "wsrv -s dist/ -p 3000 -a 0.0.0.0",
"clean-build": "rimraf 'app/{,**/}**.js' 'app/{,**/}**.js.map' 'app/{,**/}**.d.ts'",
"test": "karma start",
@@ -63,7 +63,7 @@
"@angular/platform-browser-dynamic": "2.2.2",
"@angular/router": "3.2.2",
"@angular/upgrade": "2.2.2",
- "alfresco-js-api": "~1.3.0",
+ "alfresco-js-api": "~1.4.0",
"chart.js": "2.5.0",
"core-js": "2.4.1",
"dialog-polyfill": "0.4.7",
@@ -75,20 +75,21 @@
"md-date-time-picker": "2.2.0",
"moment": "2.15.1",
"ng2-3d-editor": "0.0.15",
- "ng2-activiti-analytics": "1.3.0",
- "ng2-activiti-form": "1.3.0",
- "ng2-activiti-processlist": "1.3.0",
- "ng2-activiti-tasklist": "1.3.0",
- "ng2-alfresco-core": "1.3.0",
- "ng2-alfresco-datatable": "1.3.0",
- "ng2-alfresco-documentlist": "1.3.0",
- "ng2-alfresco-login": "1.3.0",
- "ng2-alfresco-search": "1.3.0",
- "ng2-alfresco-tag": "1.3.0",
- "ng2-alfresco-upload": "1.3.0",
- "ng2-alfresco-userinfo": "1.3.0",
- "ng2-alfresco-viewer": "1.3.0",
- "ng2-alfresco-webscript": "1.3.0",
+ "ng2-activiti-analytics": "1.4.0",
+ "ng2-activiti-form": "1.4.0",
+ "ng2-activiti-processlist": "1.4.0",
+ "ng2-activiti-tasklist": "1.4.0",
+ "ng2-alfresco-core": "1.4.0",
+ "ng2-alfresco-datatable": "1.4.0",
+ "ng2-alfresco-documentlist": "1.4.0",
+ "ng2-alfresco-login": "1.4.0",
+ "ng2-alfresco-search": "1.4.0",
+ "ng2-alfresco-tag": "1.4.0",
+ "ng2-alfresco-social": "1.3.0",
+ "ng2-alfresco-upload": "1.4.0",
+ "ng2-alfresco-userinfo": "1.4.0",
+ "ng2-alfresco-viewer": "1.4.0",
+ "ng2-alfresco-webscript": "1.4.0",
"ng2-charts": "1.5.0",
"ng2-translate": "2.5.0",
"pdfjs-dist": "1.5.404",
diff --git a/fabric8.yml b/fabric8.yml
deleted file mode 100644
index a4c33210d17..00000000000
--- a/fabric8.yml
+++ /dev/null
@@ -1,11 +0,0 @@
----
-buildName: "adf2"
-links:
- Git: "https://github.com/Alfresco/alfresco-ng2-components.git"
- Job: "http://192.168.64.3:31752/job/adf2"
- Production: "http://10.0.0.114:80/kubernetes/pods?namespace=default-production"
- Staging: "http://10.0.0.114:80/kubernetes/pods?namespace=default-staging"
-environments:
- Staging: "default-staging"
- Production: "default-production"
-useLocalFlow: true
diff --git a/ng2-components/ng2-activiti-analytics/demo/package.json b/ng2-components/ng2-activiti-analytics/demo/package.json
index 97163946ceb..5a39e014845 100644
--- a/ng2-components/ng2-activiti-analytics/demo/package.json
+++ b/ng2-components/ng2-activiti-analytics/demo/package.json
@@ -59,10 +59,10 @@
"moment": "2.15.1",
"raphael": "^2.2.6",
"ng2-translate": "2.5.0",
- "alfresco-js-api": "~1.3.0",
- "ng2-alfresco-core": "1.3.0",
- "ng2-activiti-diagrams": "1.3.0",
- "ng2-activiti-analytics": "1.3.0"
+ "alfresco-js-api": "~1.4.0",
+ "ng2-alfresco-core": "1.4.0",
+ "ng2-activiti-diagrams": "1.4.0",
+ "ng2-activiti-analytics": "1.4.0"
},
"devDependencies": {
"@types/jasmine": "^2.2.33",
diff --git a/ng2-components/ng2-activiti-analytics/package.json b/ng2-components/ng2-activiti-analytics/package.json
index 7c320334209..06f04794ed2 100644
--- a/ng2-components/ng2-activiti-analytics/package.json
+++ b/ng2-components/ng2-activiti-analytics/package.json
@@ -1,7 +1,7 @@
{
"name": "ng2-activiti-analytics",
"description": "Activiti Angular2 Analytics Component",
- "version": "1.3.0",
+ "version": "1.4.0",
"author": "Alfresco Software, Ltd.",
"scripts": {
"clean": "npm install rimraf && npm run clean-build && rimraf dist node_modules typings",
@@ -52,14 +52,14 @@
"@angular/platform-browser": "2.2.2",
"@angular/platform-browser-dynamic": "2.2.2",
"@angular/router": "3.2.2",
- "alfresco-js-api": "~1.3.0",
+ "alfresco-js-api": "~1.4.0",
"chart.js": "2.5.0",
"core-js": "2.4.1",
"hammerjs": "2.0.8",
"md-date-time-picker": "2.2.0",
"moment": "2.15.1",
- "ng2-activiti-diagrams": "1.3.0",
- "ng2-alfresco-core": "1.3.0",
+ "ng2-activiti-diagrams": "1.4.0",
+ "ng2-alfresco-core": "1.4.0",
"ng2-charts": "1.5.0",
"ng2-translate": "2.5.0",
"raphael": "2.2.7",
diff --git a/ng2-components/ng2-activiti-analytics/src/components/analytics-report-parameters.component.spec.ts b/ng2-components/ng2-activiti-analytics/src/components/analytics-report-parameters.component.spec.ts
index 89a292a9cc2..50f34e6b997 100644
--- a/ng2-components/ng2-activiti-analytics/src/components/analytics-report-parameters.component.spec.ts
+++ b/ng2-components/ng2-activiti-analytics/src/components/analytics-report-parameters.component.spec.ts
@@ -428,6 +428,7 @@ describe('AnalyticsReportParametersComponent', () => {
});
describe('When the form is rendered correctly', () => {
+ let validForm: boolean = true;
let values: any = {
dateRange: {
startDate: '2016-09-01', endDate: '2016-10-05'
@@ -468,11 +469,17 @@ describe('AnalyticsReportParametersComponent', () => {
fixture.whenStable().then(() => {
component.toggleParameters();
component.reportId = '1';
- spyOn(component, 'isFormValid').and.returnValue(true);
+ spyOn(component, 'isFormValid').and.callFake(() => {
+ return validForm;
+ });
fixture.detectChanges();
});
}));
+ afterEach(() => {
+ validForm = true;
+ });
+
it('Should be able to change the report title', async(() => {
let title: HTMLElement = element.querySelector('h4');
title.click();
@@ -567,6 +574,52 @@ describe('AnalyticsReportParametersComponent', () => {
contentType: 'json'
});
}));
+
+ it('Should hide export button if the form is not valid', async(() => {
+ let exportButton: HTMLButtonElement = element.querySelector('#export-button');
+ expect(exportButton).toBeDefined();
+ expect(exportButton).not.toBeNull();
+ validForm = false;
+ fixture.detectChanges();
+ fixture.whenStable().then(() => {
+ fixture.detectChanges();
+ exportButton = element.querySelector('#export-button');
+ expect(exportButton).toBeNull();
+ });
+ }));
+
+ it('Should hide save button if the form is not valid', async(() => {
+ let saveButton: HTMLButtonElement = element.querySelector('#save-button');
+ expect(saveButton).toBeDefined();
+ expect(saveButton).not.toBeNull();
+ validForm = false;
+ fixture.detectChanges();
+ fixture.whenStable().then(() => {
+ fixture.detectChanges();
+ saveButton = element.querySelector('#save-button');
+ expect(saveButton).toBeNull();
+ });
+ }));
+
+ it('Should show export and save button when the form became valid', async(() => {
+ validForm = false;
+ fixture.detectChanges();
+ let saveButton: HTMLButtonElement = element.querySelector('#save-button');
+ let exportButton: HTMLButtonElement = element.querySelector('#export-button');
+ expect(saveButton).toBeNull();
+ expect(exportButton).toBeNull();
+ validForm = true;
+ fixture.whenStable().then(() => {
+ fixture.detectChanges();
+ saveButton = element.querySelector('#save-button');
+ exportButton = element.querySelector('#export-button');
+ expect(saveButton).not.toBeNull();
+ expect(saveButton).toBeDefined();
+ expect(exportButton).not.toBeNull();
+ expect(exportButton).toBeDefined();
+ });
+ }));
});
+
});
});
diff --git a/ng2-components/ng2-activiti-analytics/src/components/analytics-report-parameters.component.ts b/ng2-components/ng2-activiti-analytics/src/components/analytics-report-parameters.component.ts
index cc1905f2b1f..bac24f8cdcd 100644
--- a/ng2-components/ng2-activiti-analytics/src/components/analytics-report-parameters.component.ts
+++ b/ng2-components/ng2-activiti-analytics/src/components/analytics-report-parameters.component.ts
@@ -25,9 +25,10 @@ import {
SimpleChanges,
OnDestroy,
AfterViewChecked,
+ AfterContentChecked,
ViewChild
} from '@angular/core';
-import { FormGroup, FormBuilder, FormControl } from '@angular/forms';
+import { FormGroup, FormBuilder, FormControl, Validators } from '@angular/forms';
import * as moment from 'moment';
import { AlfrescoTranslationService, LogService, ContentService } from 'ng2-alfresco-core';
import { AnalyticsService } from '../services/analytics.service';
@@ -47,7 +48,7 @@ declare let dialogPolyfill: any;
templateUrl: './analytics-report-parameters.component.html',
styleUrls: ['./analytics-report-parameters.component.css']
})
-export class AnalyticsReportParametersComponent implements OnInit, OnChanges, OnDestroy, AfterViewChecked {
+export class AnalyticsReportParametersComponent implements OnInit, OnChanges, OnDestroy, AfterViewChecked, AfterContentChecked {
public static FORMAT_DATE_ACTIVITI: string = 'YYYY-MM-DD';
@@ -102,6 +103,7 @@ export class AnalyticsReportParametersComponent implements OnInit, OnChanges, On
private reportParamQuery: ReportQuery;
private reportName: string;
private hideParameters: boolean = true;
+ private formValidState: boolean = false;
constructor(private translateService: AlfrescoTranslationService,
private analyticsService: AnalyticsService,
@@ -131,6 +133,9 @@ export class AnalyticsReportParametersComponent implements OnInit, OnChanges, On
ngOnChanges(changes: SimpleChanges) {
this.isEditable = false;
+ if (this.reportForm) {
+ this.reportForm.reset();
+ }
let reportId = changes['reportId'];
if (reportId && reportId.currentValue) {
this.getReportParams(reportId.currentValue);
@@ -147,42 +152,42 @@ export class AnalyticsReportParametersComponent implements OnInit, OnChanges, On
parameters.forEach((param: ReportParameterDetailsModel) => {
switch (param.type) {
case 'dateRange' :
- formBuilderGroup.dateRange = new FormGroup({});
+ formBuilderGroup.dateRange = new FormGroup({}, Validators.required);
break;
case 'processDefinition':
formBuilderGroup.processDefGroup = new FormGroup({
- processDefinitionId: new FormControl()
- });
+ processDefinitionId: new FormControl(null, Validators.required, null)
+ }, Validators.required);
break;
case 'duration':
formBuilderGroup.durationGroup = new FormGroup({
- duration: new FormControl()
- });
+ duration: new FormControl(null, Validators.required, null)
+ }, Validators.required);
break;
case 'dateInterval':
formBuilderGroup.dateIntervalGroup = new FormGroup({
- dateRangeInterval: new FormControl()
- });
+ dateRangeInterval: new FormControl(null, Validators.required, null)
+ }, Validators.required);
break;
case 'boolean':
formBuilderGroup.typeFilteringGroup = new FormGroup({
- typeFiltering: new FormControl()
- });
+ typeFiltering: new FormControl(null, Validators.required, null)
+ }, Validators.required);
break;
case 'task':
formBuilderGroup.taskGroup = new FormGroup({
- taskName: new FormControl()
- });
+ taskName: new FormControl(null, Validators.required, null)
+ }, Validators.required);
break;
case 'integer':
formBuilderGroup.processInstanceGroup = new FormGroup({
- slowProcessInstanceInteger: new FormControl()
- });
+ slowProcessInstanceInteger: new FormControl(null, Validators.required, null)
+ }, Validators.required);
break;
case 'status':
formBuilderGroup.statusGroup = new FormGroup({
- status: new FormControl()
- });
+ status: new FormControl(null, Validators.required, null)
+ }, Validators.required);
break;
default:
return;
@@ -190,6 +195,7 @@ export class AnalyticsReportParametersComponent implements OnInit, OnChanges, On
});
this.reportForm = this.formBuilder.group(formBuilderGroup);
this.reportForm.valueChanges.subscribe(data => this.onValueChanged(data));
+ this.reportForm.statusChanges.subscribe(data => this.onStatusChanged(data));
}
public getReportParams(reportId: string) {
@@ -243,6 +249,12 @@ export class AnalyticsReportParametersComponent implements OnInit, OnChanges, On
}
}
+ onStatusChanged(status: any) {
+ if (this.reportForm && !this.reportForm.pending && this.reportForm.dirty) {
+ this.formValidState = this.reportForm.valid;
+ }
+ }
+
public convertMomentDate(date: string) {
return moment(date, AnalyticsReportParametersComponent.FORMAT_DATE_ACTIVITI, true)
.format(AnalyticsReportParametersComponent.FORMAT_DATE_ACTIVITI) + 'T00:00:00.000Z';
@@ -346,14 +358,14 @@ export class AnalyticsReportParametersComponent implements OnInit, OnChanges, On
this.reportName = '';
}
- isFormValid() {
- return this.reportForm && this.reportForm.valid && this.reportForm.dirty;
- }
-
isSaveAction() {
return this.action === 'Save';
}
+ isFormValid() {
+ return this.reportForm && this.reportForm.dirty && this.reportForm.valid;
+ }
+
doExport(paramQuery: ReportQuery) {
this.analyticsService.exportReportToCsv(this.reportId, paramQuery).subscribe(
(data: any) => {
@@ -375,12 +387,17 @@ export class AnalyticsReportParametersComponent implements OnInit, OnChanges, On
}
ngAfterViewChecked() {
- // workaround for MDL issues with dynamic components
if (componentHandler) {
componentHandler.upgradeAllRegistered();
}
}
+ ngAfterContentChecked() {
+ if (this.reportForm && this.reportForm.valid) {
+ this.reportForm.markAsDirty();
+ }
+ }
+
toggleParameters() {
this.hideParameters = !this.hideParameters;
}
diff --git a/ng2-components/ng2-activiti-diagrams/demo/package.json b/ng2-components/ng2-activiti-diagrams/demo/package.json
index 1f56dcf3ca2..5d5e770acdb 100644
--- a/ng2-components/ng2-activiti-diagrams/demo/package.json
+++ b/ng2-components/ng2-activiti-diagrams/demo/package.json
@@ -43,15 +43,15 @@
"@angular/material": "2.0.0-beta.1",
"@angular/router": "3.2.2",
"@angular/upgrade": "2.2.2",
- "alfresco-js-api": "~1.3.0",
+ "alfresco-js-api": "~1.4.0",
"core-js": "2.4.1",
"dialog-polyfill": "0.4.7",
"element.scrollintoviewifneeded-polyfill": "1.0.1",
"intl": "1.2.4",
"material-design-icons": "2.2.3",
"material-design-lite": "1.2.1",
- "ng2-activiti-diagrams": "1.3.0",
- "ng2-alfresco-core": "1.3.0",
+ "ng2-activiti-diagrams": "1.4.0",
+ "ng2-alfresco-core": "1.4.0",
"ng2-translate": "2.5.0",
"raphael": "^2.2.6",
"reflect-metadata": "0.1.10",
diff --git a/ng2-components/ng2-activiti-diagrams/package.json b/ng2-components/ng2-activiti-diagrams/package.json
index 1032411f615..562e8139f78 100644
--- a/ng2-components/ng2-activiti-diagrams/package.json
+++ b/ng2-components/ng2-activiti-diagrams/package.json
@@ -1,7 +1,7 @@
{
"name": "ng2-activiti-diagrams",
"description": "Activiti Angular2 Diagrams Component",
- "version": "1.3.0",
+ "version": "1.4.0",
"author": "Alfresco Software, Ltd.",
"scripts": {
"clean": "npm install rimraf && npm run clean-build && rimraf dist node_modules typings",
@@ -48,10 +48,10 @@
"@angular/platform-browser": "2.2.2",
"@angular/platform-browser-dynamic": "2.2.2",
"@angular/router": "3.2.2",
- "alfresco-js-api": "~1.3.0",
+ "alfresco-js-api": "~1.4.0",
"core-js": "2.4.1",
"hammerjs": "2.0.8",
- "ng2-alfresco-core": "1.3.0",
+ "ng2-alfresco-core": "1.4.0",
"ng2-translate": "2.5.0",
"raphael": "^2.2.6",
"reflect-metadata": "0.1.10",
diff --git a/ng2-components/ng2-activiti-form/README.md b/ng2-components/ng2-activiti-form/README.md
index 4a377ee56f8..e4017047527 100644
--- a/ng2-components/ng2-activiti-form/README.md
+++ b/ng2-components/ng2-activiti-form/README.md
@@ -438,10 +438,33 @@ class MyComponent {
| getRestFieldValuesByProcessId | (processDefinitionId: string, field: string) | Observable\ | |
| getRestFieldValuesColumnByProcessId | (processDefinitionId: string, field: string, column?: string) | Observable\ | |
| getRestFieldValuesColumn | (taskId: string, field: string, column?: string) | Observable\ | |
-| getWorkflowGroups\* | (filter: string, groupId?: string) | Observable\ | |
-| getWorkflowUsers\* | (filter: string, groupId?: string) | Observable\ | |
+| getWorkflowGroups\ | (filter: string, groupId?: string) | Observable\ | |
+| getWorkflowUsers\ | (filter: string, groupId?: string) | Observable\ | |
-\* _Uses private Activiti WebApp api_
+## Common scenarios
+
+### Changing field value based on another field
+
+Create a simple Form with a dropdown widget (id: `type`), and a multiline text (id: `description`).
+
+```ts
+formService.formFieldValueChanged.subscribe((e: FormFieldEvent) => {
+ if (e.field.id === 'type') {
+ const fields: FormFieldModel[] = e.form.getFormFields();
+ const description = fields.find(f => f.id === 'description');
+ if (description != null) {
+ console.log(description);
+ description.value = 'Type set to ' + e.field.value;
+ }
+ }
+});
+```
+
+You subscribe to the `formFieldValueChanged` event and check whether event is raised for the `type` widget, then you search for a `description` widget and assign its value to some simple text.
+
+The result should be as following:
+
+
## See also
diff --git a/ng2-components/ng2-activiti-form/demo/package.json b/ng2-components/ng2-activiti-form/demo/package.json
index ea982f06d17..b5aa8bf9de0 100644
--- a/ng2-components/ng2-activiti-form/demo/package.json
+++ b/ng2-components/ng2-activiti-form/demo/package.json
@@ -56,9 +56,9 @@
"moment": "2.15.1",
"md-date-time-picker": "2.2.0",
"ng2-translate": "2.5.0",
- "alfresco-js-api": "~1.3.0",
- "ng2-alfresco-core": "1.3.0",
- "ng2-activiti-form": "1.3.0"
+ "alfresco-js-api": "~1.4.0",
+ "ng2-alfresco-core": "1.4.0",
+ "ng2-activiti-form": "1.4.0"
},
"devDependencies": {
"@types/jasmine": "^2.2.33",
diff --git a/ng2-components/ng2-activiti-form/docs/assets/form-service-sample-01.png b/ng2-components/ng2-activiti-form/docs/assets/form-service-sample-01.png
new file mode 100644
index 00000000000..479144ac25a
Binary files /dev/null and b/ng2-components/ng2-activiti-form/docs/assets/form-service-sample-01.png differ
diff --git a/ng2-components/ng2-activiti-form/package.json b/ng2-components/ng2-activiti-form/package.json
index bfa63188fd8..23f7672e9d8 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": "1.3.0",
+ "version": "1.4.0",
"author": "Alfresco Software, Ltd.",
"scripts": {
"clean": "npm install rimraf && npm run clean-build && rimraf dist node_modules typings",
@@ -55,12 +55,12 @@
"@angular/platform-browser": "2.2.2",
"@angular/platform-browser-dynamic": "2.2.2",
"@angular/router": "3.2.2",
- "alfresco-js-api": "~1.3.0",
+ "alfresco-js-api": "~1.4.0",
"core-js": "2.4.1",
"hammerjs": "2.0.8",
"md-date-time-picker": "2.2.0",
"moment": "2.15.1",
- "ng2-alfresco-core": "1.3.0",
+ "ng2-alfresco-core": "1.4.0",
"ng2-translate": "2.5.0",
"reflect-metadata": "0.1.10",
"rxjs": "5.0.0-beta.12",
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 e3ea619a737..0fa09bf4fd5 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,7 +26,6 @@ import { FormEvent, FormErrorEvent } from './../events/index';
import { WidgetVisibilityService } from './../services/widget-visibility.service';
-declare let dialogPolyfill: any;
declare var componentHandler: any;
/**
@@ -118,7 +117,7 @@ export class ActivitiForm implements OnInit, AfterViewChecked, OnChanges {
showSaveButton: boolean = true;
@Input()
- showDebugButton: boolean = true;
+ showDebugButton: boolean = false;
@Input()
readOnly: boolean = false;
diff --git a/ng2-components/ng2-activiti-form/src/components/widgets/core/form-field.model.spec.ts b/ng2-components/ng2-activiti-form/src/components/widgets/core/form-field.model.spec.ts
index 1ae3a0c1193..45b47162a5a 100644
--- a/ng2-components/ng2-activiti-form/src/components/widgets/core/form-field.model.spec.ts
+++ b/ng2-components/ng2-activiti-form/src/components/widgets/core/form-field.model.spec.ts
@@ -121,6 +121,109 @@ describe('FormFieldModel', () => {
expect(field.value).toBe('deferred');
});
+ it('should parse the date with the default format (D-M-YYYY) if the display format is missing', () => {
+ let form = new FormModel();
+ let field = new FormFieldModel(form, {
+ fieldType: 'FormFieldRepresentation',
+ id: 'mmddyyyy',
+ name: 'MM-DD-YYYY',
+ type: 'date',
+ value: '2017-04-28T00:00:00.000+0000',
+ required: false,
+ readOnly: false,
+ params: {
+ field: {
+ id: 'mmddyyyy',
+ name: 'MM-DD-YYYY',
+ type: 'date',
+ value: null,
+ required: false,
+ readOnly: false
+ }
+ }
+ });
+ expect(field.value).toBe('28-4-2017');
+ expect(form.values['mmddyyyy']).toEqual('2017-04-28T00:00:00.000Z');
+ });
+
+ it('should parse the date with the format MM-DD-YYYY', () => {
+ let form = new FormModel();
+ let field = new FormFieldModel(form, {
+ fieldType: 'FormFieldRepresentation',
+ id: 'mmddyyyy',
+ name: 'MM-DD-YYYY',
+ type: 'date',
+ value: '2017-04-28T00:00:00.000+0000',
+ required: false,
+ readOnly: false,
+ params: {
+ field: {
+ id: 'mmddyyyy',
+ name: 'MM-DD-YYYY',
+ type: 'date',
+ value: null,
+ required: false,
+ readOnly: false
+ }
+ },
+ dateDisplayFormat: 'MM-DD-YYYY'
+ });
+ expect(field.value).toBe('04-28-2017');
+ expect(form.values['mmddyyyy']).toEqual('2017-04-28T00:00:00.000Z');
+ });
+
+ it('should parse the date with the format MM-YY-DD', () => {
+ let form = new FormModel();
+ let field = new FormFieldModel(form, {
+ fieldType: 'FormFieldRepresentation',
+ id: 'mmyydd',
+ name: 'MM-YY-DD',
+ type: 'date',
+ value: '2017-04-28T00:00:00.000+0000',
+ required: false,
+ readOnly: false,
+ params: {
+ field: {
+ id: 'mmyydd',
+ name: 'MM-YY-DD',
+ type: 'date',
+ value: null,
+ required: false,
+ readOnly: false
+ }
+ },
+ dateDisplayFormat: 'MM-YY-DD'
+ });
+ expect(field.value).toBe('04-17-28');
+ expect(form.values['mmyydd']).toEqual('2017-04-28T00:00:00.000Z');
+ });
+
+ it('should parse the date with the format DD-MM-YYYY', () => {
+ let form = new FormModel();
+ let field = new FormFieldModel(form, {
+ fieldType: 'FormFieldRepresentation',
+ id: 'ddmmyyy',
+ name: 'DD-MM-YYYY',
+ type: 'date',
+ value: '2017-04-28T00:00:00.000+0000',
+ required: false,
+ readOnly: false,
+ params: {
+ field: {
+ id: 'ddmmyyy',
+ name: 'DD-MM-YYYY',
+ type: 'date',
+ value: null,
+ required: false,
+ readOnly: false
+ }
+ },
+ dateDisplayFormat: 'DD-MM-YYYY'
+ });
+ expect(field.value).toBe('28-04-2017');
+ expect(form.values['ddmmyyy']).toEqual('2017-04-28T00:00:00.000Z');
+ });
+
it('should return the label of selected dropdown value ', () => {
let field = new FormFieldModel(new FormModel(), {
type: FormFieldTypes.DROPDOWN,
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 cba2e957280..6a20425aeee 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
@@ -76,7 +76,7 @@ export class FormFieldModel extends FormWidgetModel {
visibilityCondition: WidgetVisibilityModel = null;
enableFractions: boolean = false;
currency: string = null;
- dateDisplayFormat: string = this.defaultDateFormat;
+ dateDisplayFormat: string = this.dateDisplayFormat || this.defaultDateFormat;
// container model members
numberOfColumns: number = 1;
@@ -249,9 +249,14 @@ export class FormFieldModel extends FormWidgetModel {
*/
if (json.type === FormFieldTypes.DATE) {
if (value) {
- let d = moment(value.split('T')[0], 'YYYY-M-D');
- if (d.isValid()) {
- value = d.format(this.dateDisplayFormat);
+ let dateValue;
+ if (NumberFieldValidator.isNumber(value)) {
+ dateValue = moment(value);
+ } else {
+ dateValue = moment(value.split('T')[0], 'YYYY-M-D');
+ }
+ if (dateValue && dateValue.isValid()) {
+ value = dateValue.format(this.dateDisplayFormat);
}
}
}
@@ -307,9 +312,14 @@ export class FormFieldModel extends FormWidgetModel {
}
break;
case FormFieldTypes.DATE:
- let d = moment(this.value, this.dateDisplayFormat);
- if (d.isValid()) {
- this.form.values[this.id] = `${d.format('YYYY-MM-DD')}T00:00:00.000Z`;
+ let dateValue;
+ if (NumberFieldValidator.isNumber(this.value)) {
+ dateValue = moment(this.value);
+ } else {
+ dateValue = moment(this.value, this.dateDisplayFormat);
+ }
+ if (dateValue && dateValue.isValid()) {
+ this.form.values[this.id] = `${dateValue.format('YYYY-MM-DD')}T00:00:00.000Z`;
} else {
this.form.values[this.id] = null;
}
diff --git a/ng2-components/ng2-activiti-form/src/components/widgets/display-value/display-value.widget.html b/ng2-components/ng2-activiti-form/src/components/widgets/display-value/display-value.widget.html
index 375c3a884b4..cc370722a9e 100644
--- a/ng2-components/ng2-activiti-form/src/components/widgets/display-value/display-value.widget.html
+++ b/ng2-components/ng2-activiti-form/src/components/widgets/display-value/display-value.widget.html
@@ -42,30 +42,7 @@
-
-
-
{{field.name}}
-
-
-
-
-
- {{column.name}}
-
-
-
-
-
-
- {{ getCellValue(row, column) }}
-
-
-
-
-
-
+
diff --git a/ng2-components/ng2-activiti-form/src/components/widgets/display-value/display-value.widget.spec.ts b/ng2-components/ng2-activiti-form/src/components/widgets/display-value/display-value.widget.spec.ts
index 207e51f4a11..2cb5bee5b9a 100644
--- a/ng2-components/ng2-activiti-form/src/components/widgets/display-value/display-value.widget.spec.ts
+++ b/ng2-components/ng2-activiti-form/src/components/widgets/display-value/display-value.widget.spec.ts
@@ -15,6 +15,7 @@
* limitations under the License.
*/
+import { CUSTOM_ELEMENTS_SCHEMA } from '@angular/core';
import { ComponentFixture, TestBed, async } from '@angular/core/testing';
import { CoreModule, LogServiceMock } from 'ng2-alfresco-core';
import { Observable } from 'rxjs/Rx';
@@ -25,7 +26,6 @@ import { EcmModelService } from '../../../services/ecm-model.service';
import { FormFieldModel } from './../core/form-field.model';
import { FormFieldTypes } from '../core/form-field-types';
import { FormModel } from '../core/form.model';
-import { DynamicTableColumn, DynamicTableRow } from './../dynamic-table/dynamic-table.widget.model';
import { WidgetVisibilityService } from '../../../services/widget-visibility.service';
describe('DisplayValueWidget', () => {
@@ -441,6 +441,65 @@ describe('DisplayValueWidget', () => {
expect(widget.value).toBe('');
});
+ it('should show the [DATE] field with the default format (D-M-YYYY) if the display format is missing', () => {
+ widget.field = new FormFieldModel(null, {
+ type: FormFieldTypes.DISPLAY_VALUE,
+ value: '1982-03-13T00:00:00.000Z',
+ params: {
+ field: {
+ type: FormFieldTypes.DATE
+ }
+ }
+ });
+ widget.ngOnInit();
+ expect(widget.value).toBe('13-3-1982');
+ });
+
+ it('should show the [DATE] field with the custom display format (MM-DD-YYYY)', () => {
+ widget.field = new FormFieldModel(null, {
+ type: FormFieldTypes.DISPLAY_VALUE,
+ value: '1982-03-13T00:00:00.000Z',
+ dateDisplayFormat: 'MM-DD-YYYY',
+ params: {
+ field: {
+ type: FormFieldTypes.DATE
+ }
+ }
+ });
+ widget.ngOnInit();
+ expect(widget.value).toBe('03-13-1982');
+ });
+
+ it('should show the [DATE] field with the custom display format (MM-YY-DD)', () => {
+ widget.field = new FormFieldModel(null, {
+ type: FormFieldTypes.DISPLAY_VALUE,
+ value: '1982-03-13T00:00:00.000Z',
+ dateDisplayFormat: 'MM-YY-DD',
+ params: {
+ field: {
+ type: FormFieldTypes.DATE
+ }
+ }
+ });
+ widget.ngOnInit();
+ expect(widget.value).toBe('03-82-13');
+ });
+
+ it('should show the [DATE] field with the custom display format (DD-MM-YYYY)', () => {
+ widget.field = new FormFieldModel(null, {
+ type: FormFieldTypes.DISPLAY_VALUE,
+ value: '1982-03-13T00:00:00.000Z',
+ dateDisplayFormat: 'DD-MM-YYYY',
+ params: {
+ field: {
+ type: FormFieldTypes.DATE
+ }
+ }
+ });
+ widget.ngOnInit();
+ expect(widget.value).toBe('13-03-1982');
+ });
+
it('should not setup [DATE] field when missing value', () => {
widget.field = new FormFieldModel(null, {
type: FormFieldTypes.DISPLAY_VALUE,
@@ -549,135 +608,6 @@ describe('DisplayValueWidget', () => {
expect(widget.value).toBe(value);
});
- it('should setup [DYNAMIC_TABLE] field', () => {
- let columns = [{id: '1', visible: false}, {id: '2', visible: true}];
- let rows = [{}, {}];
-
- widget.field = new FormFieldModel(null, {
- type: FormFieldTypes.DISPLAY_VALUE,
- params: {
- field: {
- type: FormFieldTypes.DYNAMIC_TABLE
- }
- },
- columnDefinitions: columns,
- value: rows
- });
- widget.ngOnInit();
-
- expect(widget.columns.length).toBe(2);
- expect(widget.columns[0].id).toBe(columns[0].id);
- expect(widget.columns[1].id).toBe(columns[1].id);
-
- expect(widget.visibleColumns.length).toBe(1);
- expect(widget.visibleColumns[0].id).toBe(columns[1].id);
-
- expect(widget.rows.length).toBe(2);
- });
-
- it('should setup [DYNAMIC_TABLE] field with empty schema', () => {
- widget.field = new FormFieldModel(null, {
- type: FormFieldTypes.DISPLAY_VALUE,
- params: {
- field: {
- type: FormFieldTypes.DYNAMIC_TABLE
- }
- },
- columnDefinitions: null,
- value: null
- });
- widget.ngOnInit();
-
- expect(widget.value).toBeNull();
- expect(widget.columns).toEqual([]);
- expect(widget.rows).toEqual([]);
- });
-
- it('should retrieve default cell value', () => {
- const value = '';
- let row = {value: {key: value}};
- let column = {id: 'key'};
-
- expect(widget.getCellValue(row, column)).toBe(value);
- });
-
- it('should retrieve dropdown cell value', () => {
- const value = {id: '1', name: 'one'};
- let row = {value: {key: value}};
- let column = {id: 'key', type: 'Dropdown'};
-
- expect(widget.getCellValue(row, column)).toBe(value.name);
- });
-
- it('should fallback to empty cell value for dropdown', () => {
- let row = {value: {}};
- let column = {id: 'key', type: 'Dropdown'};
-
- expect(widget.getCellValue(row, column)).toBe('');
- });
-
- it('should retrieve boolean cell value', () => {
- let row1 = {value: {key: true}};
- let row2 = {value: {key: 'positive'}};
- let row3 = {value: {key: null}};
- let column = {id: 'key', type: 'Boolean'};
-
- expect(widget.getCellValue(row1, column)).toBe(true);
- expect(widget.getCellValue(row2, column)).toBe(true);
- expect(widget.getCellValue(row3, column)).toBe(false);
- });
-
- it('should retrieve date cell value', () => {
- const value = '2016-10-04T00:00:00.000Z';
- let row = {value: {key: value}};
- let column = {id: 'key', type: 'Date'};
-
- expect(widget.getCellValue(row, column)).toBe('4-10-2016');
- });
-
- it('should fallback to empty cell value for date', () => {
- let row = {value: {}};
- let column = {id: 'key', type: 'Date'};
-
- expect(widget.getCellValue(row, column)).toBe('');
- });
-
- it('should retrieve empty text cell value', () => {
- let row = {value: {}};
- let column = {id: 'key'};
-
- expect(widget.getCellValue(row, column)).toBe('');
- });
-
- it('should prepend default amount currency', () => {
- const value = '10';
- let row = {value: {key: value}};
- let column = {id: 'key', type: 'Amount'};
-
- const expected = `$ ${value}`;
- expect(widget.getCellValue(row, column)).toBe(expected);
- });
-
- it('should prepend custom amount currency', () => {
- const value = '10';
- const currency = 'GBP';
- let row = {value: {key: value}};
- let column = {id: 'key', type: 'Amount', amountCurrency: currency};
-
- const expected = `${currency} ${value}`;
- expect(widget.getCellValue(row, column)).toBe(expected);
- });
-
- it('should use zero for missing amount', () => {
- const value = null;
- const currency = 'GBP';
- let row = {value: {key: value}};
- let column = {id: 'key', type: 'Amount', amountCurrency: currency};
-
- const expected = `${currency} 0`;
- expect(widget.getCellValue(row, column)).toBe(expected);
- });
-
describe('UI check', () => {
let widgetUI: DisplayValueWidget;
let fixture: ComponentFixture;
@@ -689,12 +619,16 @@ describe('DisplayValueWidget', () => {
window['componentHandler'] = componentHandler;
TestBed.configureTestingModule({
imports: [CoreModule],
- declarations: [DisplayValueWidget, ActivitiContent],
+ declarations: [
+ DisplayValueWidget,
+ ActivitiContent
+ ],
providers: [
EcmModelService,
FormService,
WidgetVisibilityService
- ]
+ ],
+ schemas: [ CUSTOM_ELEMENTS_SCHEMA ]
}).compileComponents().then(() => {
fixture = TestBed.createComponent(DisplayValueWidget);
widgetUI = fixture.componentInstance;
diff --git a/ng2-components/ng2-activiti-form/src/components/widgets/display-value/display-value.widget.ts b/ng2-components/ng2-activiti-form/src/components/widgets/display-value/display-value.widget.ts
index 12fcd4f0406..c1f16decf6b 100644
--- a/ng2-components/ng2-activiti-form/src/components/widgets/display-value/display-value.widget.ts
+++ b/ng2-components/ng2-activiti-form/src/components/widgets/display-value/display-value.widget.ts
@@ -22,8 +22,8 @@ import { WidgetComponent } from './../widget.component';
import { FormFieldTypes } from '../core/form-field-types';
import { FormService } from '../../../services/form.service';
import { FormFieldOption } from './../core/form-field-option';
-import { DynamicTableColumn, DynamicTableRow } from './../dynamic-table/dynamic-table.widget.model';
import { WidgetVisibilityService } from '../../../services/widget-visibility.service';
+import { NumberFieldValidator } from '../core/form-field-validator';
@Component({
moduleId: module.id,
@@ -42,9 +42,7 @@ export class DisplayValueWidget extends WidgetComponent implements OnInit {
linkText: string;
// dynamic table
- rows: DynamicTableRow[] = [];
- columns: DynamicTableColumn[] = [];
- visibleColumns: DynamicTableColumn[] = [];
+ tableEditable = false;
// upload/attach
hasFile: boolean = false;
@@ -64,6 +62,10 @@ export class DisplayValueWidget extends WidgetComponent implements OnInit {
if (this.field.params['showDocumentContent'] !== undefined) {
this.showDocumentContent = !!this.field.params['showDocumentContent'];
}
+ if (this.field.params['tableEditable'] !== undefined) {
+ this.tableEditable = !!this.field.params['tableEditable'];
+ }
+
let originalField = this.field.params['field'];
if (originalField && originalField.type) {
this.fieldType = originalField.type;
@@ -115,10 +117,15 @@ export class DisplayValueWidget extends WidgetComponent implements OnInit {
break;
case FormFieldTypes.DATE:
if (this.value) {
- let d = moment(this.value.split('T')[0], 'YYYY-M-D');
- if (d.isValid()) {
- const displayFormat = originalField['dateDisplayFormat'] || this.field.defaultDateFormat;
- this.value = d.format(displayFormat);
+ let dateValue;
+ if (NumberFieldValidator.isNumber(this.value)) {
+ dateValue = moment(this.value);
+ } else {
+ dateValue = moment(this.value.split('T')[0], 'YYYY-M-D');
+ }
+ if (dateValue && dateValue.isValid()) {
+ const displayFormat = this.field.dateDisplayFormat || this.field.defaultDateFormat;
+ this.value = dateValue.format(displayFormat);
}
}
break;
@@ -132,16 +139,6 @@ export class DisplayValueWidget extends WidgetComponent implements OnInit {
this.linkUrl = this.getHyperlinkUrl(this.field);
this.linkText = this.getHyperlinkText(this.field);
break;
- case FormFieldTypes.DYNAMIC_TABLE:
- let json = this.field.json;
- if (json.columnDefinitions) {
- this.columns = json.columnDefinitions.map(obj => obj);
- this.visibleColumns = this.columns.filter(col => col.visible);
- }
- if (json.value) {
- this.rows = json.value.map(obj => {selected: false, value: obj});
- }
- break;
default:
this.value = this.field.value;
break;
@@ -216,31 +213,4 @@ export class DisplayValueWidget extends WidgetComponent implements OnInit {
}
);
}
-
- getCellValue(row: DynamicTableRow, column: DynamicTableColumn): any {
-
- let result = row.value[column.id];
-
- if (column.type === 'Dropdown') {
- if (result) {
- return result.name;
- }
- }
-
- if (column.type === 'Boolean') {
- return result ? true : false;
- }
-
- if (column.type === 'Date') {
- if (result) {
- return moment(result.split('T')[0], 'YYYY-MM-DD').format('D-M-YYYY');
- }
- }
-
- if (column.type === 'Amount') {
- return (column.amountCurrency || '$') + ' ' + (result || 0);
- }
-
- return result || '';
- }
}
diff --git a/ng2-components/ng2-activiti-form/src/components/widgets/dynamic-table/dynamic-table.widget.html b/ng2-components/ng2-activiti-form/src/components/widgets/dynamic-table/dynamic-table.widget.html
index cb78fcb0e80..7c5270ba6ac 100644
--- a/ng2-components/ng2-activiti-form/src/components/widgets/dynamic-table/dynamic-table.widget.html
+++ b/ng2-components/ng2-activiti-form/src/components/widgets/dynamic-table/dynamic-table.widget.html
@@ -1,9 +1,9 @@