From 4970920643c80ec7644bb3a7f3317b16f4797ac0 Mon Sep 17 00:00:00 2001 From: Denys Vuika Date: Fri, 11 Nov 2016 15:14:44 +0000 Subject: [PATCH 001/103] #828 remove conflicting and obsolete i18n blocks --- demo-shell-ng2/i18n/en.json | 43 ------------------------------------- demo-shell-ng2/i18n/it.json | 20 +---------------- 2 files changed, 1 insertion(+), 62 deletions(-) diff --git a/demo-shell-ng2/i18n/en.json b/demo-shell-ng2/i18n/en.json index 1993786440..b35c62c63a 100644 --- a/demo-shell-ng2/i18n/en.json +++ b/demo-shell-ng2/i18n/en.json @@ -20,48 +20,5 @@ "CUSTOM": "Custom action" } } - }, - - "DATATABLE": { - "COLUMNS": { - "DISPLAY_NAME": "Display name", - "CREATED_BY": "Created by", - "CREATED_ON": "Created on" - }, - "ACTIONS": { - "FOLDER": { - "SYSTEM_1": "System folder action 1", - "CUSTOM": "Custom folder action" - }, - "DOCUMENT": { - "DOWNLOAD": "Download", - "SYSTEM_2": "System document action 2", - "CUSTOM": "Custom action" - } - } - }, - - "LOGIN": { - "LOGO": "Alfresco", - "LABEL": { - "LOGIN": "Login", - "USERNAME": "Username", - "PASSWORD": "Password", - "REMEMBER": "Remember" - }, - "MESSAGES": { - "USERNAME-REQUIRED": "Required", - "USERNAME-MIN": "Your username needs to be at least 4 characters.", - "PASSWORD-REQUIRED": "Enter your password to sign in", - "LOGIN-ERROR": "You have entered an invalid username or password", - "LOGIN-SUCCESS": "Login successful" - }, - "BUTTON": { - "LOGIN": "Login" - }, - "ACTION": { - "HELP": "NEED HELP?", - "REGISTER": "REGISTER" - } } } diff --git a/demo-shell-ng2/i18n/it.json b/demo-shell-ng2/i18n/it.json index 5e6b750063..a1a8da6877 100644 --- a/demo-shell-ng2/i18n/it.json +++ b/demo-shell-ng2/i18n/it.json @@ -18,24 +18,6 @@ "CUSTOM": "Custom action" } } - }, - - "DATATABLE": { - "COLUMNS": { - "DISPLAY_NAME": "Display name", - "CREATED_BY": "Created by", - "CREATED_ON": "Created on" - }, - "ACTIONS": { - "FOLDER": { - "SYSTEM_1": "System folder action 1", - "CUSTOM": "Custom folder action" - }, - "DOCUMENT": { - "DOWNLOAD": "Download", - "SYSTEM_2": "System document action 2", - "CUSTOM": "Custom action" - } - } } + } From 55d73b80069a80f012db2b8c1d100e4352d7a5e8 Mon Sep 17 00:00:00 2001 From: Vito Albano Date: Thu, 10 Nov 2016 14:15:28 +0000 Subject: [PATCH 002/103] Start fix for default option on dropdown --- .../widgets/dropdown/dropdown.widget.html | 4 +- .../widgets/dropdown/dropdown.widget.spec.ts | 49 +++++++++++++++++++ .../widgets/dropdown/dropdown.widget.ts | 10 ++++ 3 files changed, 61 insertions(+), 2 deletions(-) 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 5b8f73f170..5ca84824b9 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,11 +1,11 @@ diff --git a/ng2-components/ng2-activiti-form/src/components/widgets/dropdown/dropdown.widget.spec.ts b/ng2-components/ng2-activiti-form/src/components/widgets/dropdown/dropdown.widget.spec.ts index 7fb176b8c1..4da33f8b69 100644 --- a/ng2-components/ng2-activiti-form/src/components/widgets/dropdown/dropdown.widget.spec.ts +++ b/ng2-components/ng2-activiti-form/src/components/widgets/dropdown/dropdown.widget.spec.ts @@ -98,4 +98,53 @@ describe('DropdownWidget', () => { expect(widget.field.options[0]).toBe(emptyOption); expect(widget.field.options[1]).toBe(restFieldValue); }); + + describe('when template is ready', () => { + let dropDownWidget: DropdownWidget; + let fixture: ComponentFixture; + let element: HTMLElement; + let componentHandler; + + beforeEach(async(() => { + componentHandler = jasmine.createSpyObj('componentHandler', ['upgradeAllRegistered', 'upgradeElement']); + window['componentHandler'] = componentHandler; + TestBed.configureTestingModule({ + imports: [CoreModule], + declarations: [DropdownWidget] + }).compileComponents().then(() => { + fixture = TestBed.createComponent(DropdownWidget); + dateWidget = fixture.componentInstance; + element = fixture.nativeElement; + }); + })); + + beforeEach(() => { + spyOn(dateWidget, 'setupMaterialTextField').and.stub(); + dateWidget.field = new FormFieldModel(new FormModel(), { + id: 'date-field-id', + name: 'date-name', + value: '9-9-9999', + type: 'date', + readOnly: 'false' + }); + dateWidget.field.isVisible = true; + fixture.detectChanges(); + }); + + afterEach(() => { + fixture.destroy(); + TestBed.resetTestingModule(); + }); + + it('should show visible date widget', async(() => { + fixture.whenStable() + .then(() => { + expect(element.querySelector('#date-field-id')).toBeDefined(); + expect(element.querySelector('#date-field-id')).not.toBeNull(); + let dateElement: any = element.querySelector('#date-field-id'); + expect(dateElement.value).toEqual('9-9-9999'); + }); + })); + + }); }); diff --git a/ng2-components/ng2-activiti-form/src/components/widgets/dropdown/dropdown.widget.ts b/ng2-components/ng2-activiti-form/src/components/widgets/dropdown/dropdown.widget.ts index 721bccf4da..f20345f8a5 100644 --- a/ng2-components/ng2-activiti-form/src/components/widgets/dropdown/dropdown.widget.ts +++ b/ng2-components/ng2-activiti-form/src/components/widgets/dropdown/dropdown.widget.ts @@ -80,6 +80,16 @@ export class DropdownWidget extends WidgetComponent implements OnInit { ); } + getOptionValue(option: FormFieldOption): string { + let optionValue: string = ''; + if (option.id === 'empty') { + optionValue = option.id; + } else { + optionValue = option.name; + } + return optionValue; + } + handleError(error: any) { console.error(error); } From 2cb5987420f46f4dd309d850eb3e4e1d953eec6b Mon Sep 17 00:00:00 2001 From: mauriziovitale84 Date: Mon, 14 Nov 2016 12:07:04 +0000 Subject: [PATCH 003/103] #1020 define a default value for layoutType --- .../src/components/activiti-apps.component.spec.ts | 6 ++++++ .../src/components/activiti-apps.component.ts | 9 ++++++++- 2 files changed, 14 insertions(+), 1 deletion(-) diff --git a/ng2-components/ng2-activiti-tasklist/src/components/activiti-apps.component.spec.ts b/ng2-components/ng2-activiti-tasklist/src/components/activiti-apps.component.spec.ts index a7649b665a..250b9b7421 100644 --- a/ng2-components/ng2-activiti-tasklist/src/components/activiti-apps.component.spec.ts +++ b/ng2-components/ng2-activiti-tasklist/src/components/activiti-apps.component.spec.ts @@ -67,6 +67,12 @@ describe('ActivitiApps', () => { window['componentHandler'] = componentHandler; }); + it('should define layoutType with the default value', () => { + component.layoutType = ''; + fixture.detectChanges(); + expect(component.isGrid()).toBe(true); + }); + it('should load apps on init', () => { fixture.detectChanges(); expect(getAppsSpy).toHaveBeenCalled(); diff --git a/ng2-components/ng2-activiti-tasklist/src/components/activiti-apps.component.ts b/ng2-components/ng2-activiti-tasklist/src/components/activiti-apps.component.ts index a0db97ca53..5d5e54cf81 100644 --- a/ng2-components/ng2-activiti-tasklist/src/components/activiti-apps.component.ts +++ b/ng2-components/ng2-activiti-tasklist/src/components/activiti-apps.component.ts @@ -77,7 +77,7 @@ export class ActivitiApps implements OnInit { ngOnInit() { if (!this.isValidType()) { - throw( new Error(`LayoutType property allowed values: ${ActivitiApps.LAYOUT_LIST} - ${ActivitiApps.LAYOUT_GRID}`)); + this.setDefaultLayoutType(); } this.apps$.subscribe((app: any) => { @@ -136,6 +136,13 @@ export class ActivitiApps implements OnInit { return false; } + /** + * Assign the default value to LayoutType + */ + setDefaultLayoutType(): void { + this.layoutType = ActivitiApps.LAYOUT_GRID; + } + /** * Return true if the layout type is LIST * @returns {boolean} From a6eace8e5b47610ebe1f86682e47cf9f87818949 Mon Sep 17 00:00:00 2001 From: Mario Romano Date: Mon, 14 Nov 2016 12:12:26 +0000 Subject: [PATCH 004/103] improve builds --- .travis.yml | 31 ++++++++++++++----------------- 1 file changed, 14 insertions(+), 17 deletions(-) diff --git a/.travis.yml b/.travis.yml index a3786026b6..e863e3999b 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,22 +1,17 @@ language: node_js dist: trusty -sudo: required +sudo: false node_js: - "5" addons: - apt: - sources: - - google-chrome - packages: - - google-chrome-stable before_install: - - export CHROME_BIN=/usr/bin/google-chrome - - export DISPLAY=:99.0 - - sh -e /etc/init.d/xvfb start + - "export DISPLAY=:99.0" + - "sh -e /etc/init.d/xvfb start" + env: matrix: - MODULE=ng2-alfresco-core @@ -37,31 +32,33 @@ env: before_script: - if ([ "$MODULE" != "ng2-alfresco-core" ]); then - (cd ng2-components/ng2-alfresco-core; npm install; npm link); + (cd ng2-components/ng2-alfresco-core; if [ ! -d "dist" ]; then npm install; fi; npm link); fi - if ([ "$MODULE" == "ng2-alfresco-documentlist" ] || [ "$MODULE" == "ng2-alfresco-webscript" ] || [ "$MODULE" == "ng2-activiti-processlist" ] || [ "$MODULE" == "ng2-activiti-tasklist" ]); then - (cd ng2-components/ng2-alfresco-datatable; npm link ng2-alfresco-core; npm install; npm link); + (cd ng2-components/ng2-alfresco-datatable; npm link ng2-alfresco-core; if [ ! -d "dist" ]; then npm install; fi; npm link); fi - if ([ "$MODULE" == "ng2-activiti-tasklist" ] || [ "$MODULE" == "ng2-activiti-processlist" ]); then - (cd ng2-components/ng2-activiti-form; npm link ng2-alfresco-core; npm install; npm link); + (cd ng2-components/ng2-activiti-form; npm link ng2-alfresco-core; if [ ! -d "dist" ]; then npm install; fi; npm link); fi - if ([ "$MODULE" == "ng2-activiti-processlist" ]); then - (cd ng2-components/ng2-activiti-tasklist; npm link ng2-alfresco-core; npm link ng2-alfresco-datatable; npm link ng2-activiti-form; npm install; npm link); + (cd ng2-components/ng2-activiti-tasklist; npm link ng2-alfresco-core; npm link ng2-alfresco-datatable; npm link ng2-activiti-form; if [ ! -d "dist" ]; then npm install; fi; npm link); fi - if ([ "$MODULE" == "ng2-activiti-analytics" ]); then - (cd ng2-components/ng2-activiti-diagrams; npm link ng2-alfresco-core; npm install; npm link); + (cd ng2-components/ng2-activiti-diagrams; npm link ng2-alfresco-core; if [ ! -d "dist" ]; then npm install; fi; npm link); fi - cd ng2-components/$MODULE; - - npm run travis - npm install; - - ls -ltrh ./node_modules/ script: npm run test # Send coverage data to Coveralls after_success: - - bash <(curl -s https://codecov.io/bash) + - if ([ "$TRAVIS_BRANCH" == "development" ] || [ "$TRAVIS_BRANCH" == "master" ]); then + bash <(curl -s https://codecov.io/bash) + fi cache: directories: + - ./node_modules/material-design-lite + - ./node_modules/material-design-icons - demo-shell-ng2/node_modules - ng2-components/ng2-activiti-form/node_modules - ng2-components/ng2-activiti-processlist/node_modules From c9e3723613fc1ffcb113b1bc3d613761cc9b59fd Mon Sep 17 00:00:00 2001 From: Mario Romano Date: Mon, 14 Nov 2016 12:24:40 +0000 Subject: [PATCH 005/103] remove polyfill and material from components, leave it in the core and demo --- ng2-components/ng2-activiti-analytics/package.json | 6 ------ ng2-components/ng2-activiti-diagrams/package.json | 6 ------ ng2-components/ng2-activiti-form/package.json | 6 ------ ng2-components/ng2-activiti-processlist/package.json | 6 ------ ng2-components/ng2-activiti-tasklist/package.json | 6 ------ ng2-components/ng2-alfresco-datatable/package.json | 6 ------ ng2-components/ng2-alfresco-documentlist/demo/package.json | 6 ------ ng2-components/ng2-alfresco-documentlist/package.json | 6 ------ ng2-components/ng2-alfresco-login/package.json | 6 ------ ng2-components/ng2-alfresco-search/package.json | 6 ------ ng2-components/ng2-alfresco-tag/package.json | 6 ------ ng2-components/ng2-alfresco-upload/package.json | 6 ------ ng2-components/ng2-alfresco-userinfo/package.json | 6 ------ ng2-components/ng2-alfresco-viewer/package.json | 6 ------ ng2-components/ng2-alfresco-webscript/package.json | 6 ------ 15 files changed, 90 deletions(-) diff --git a/ng2-components/ng2-activiti-analytics/package.json b/ng2-components/ng2-activiti-analytics/package.json index 47b104b9df..8d0791c095 100644 --- a/ng2-components/ng2-activiti-analytics/package.json +++ b/ng2-components/ng2-activiti-analytics/package.json @@ -54,12 +54,6 @@ "systemjs": "0.19.27", "zone.js": "^0.6.23", - "intl": "1.2.4", - "dialog-polyfill": "^0.4.3", - "element.scrollintoviewifneeded-polyfill": "^1.0.1", - "material-design-icons": "2.2.3", - "material-design-lite": "1.2.1", - "chart.js": "^2.1.4", "md-date-time-picker": "^2.2.0", "ng2-charts": "1.1.0", diff --git a/ng2-components/ng2-activiti-diagrams/package.json b/ng2-components/ng2-activiti-diagrams/package.json index 28bbbdfa74..ef8a910001 100644 --- a/ng2-components/ng2-activiti-diagrams/package.json +++ b/ng2-components/ng2-activiti-diagrams/package.json @@ -50,12 +50,6 @@ "systemjs": "0.19.27", "zone.js": "^0.6.23", - "intl": "1.2.4", - "dialog-polyfill": "^0.4.3", - "element.scrollintoviewifneeded-polyfill": "^1.0.1", - "material-design-icons": "2.2.3", - "material-design-lite": "1.2.1", - "raphael": "^2.2.6", "ng2-translate": "2.5.0", diff --git a/ng2-components/ng2-activiti-form/package.json b/ng2-components/ng2-activiti-form/package.json index f764072bce..9091398409 100644 --- a/ng2-components/ng2-activiti-form/package.json +++ b/ng2-components/ng2-activiti-form/package.json @@ -58,12 +58,6 @@ "systemjs": "0.19.27", "zone.js": "^0.6.23", - "intl": "1.2.4", - "dialog-polyfill": "^0.4.3", - "element.scrollintoviewifneeded-polyfill": "^1.0.1", - "material-design-icons": "2.2.3", - "material-design-lite": "1.2.1", - "moment": "2.15.1", "md-date-time-picker": "^2.2.0", diff --git a/ng2-components/ng2-activiti-processlist/package.json b/ng2-components/ng2-activiti-processlist/package.json index cd19bc7a4e..18d7ecf22f 100644 --- a/ng2-components/ng2-activiti-processlist/package.json +++ b/ng2-components/ng2-activiti-processlist/package.json @@ -57,12 +57,6 @@ "systemjs": "0.19.27", "zone.js": "^0.6.23", - "intl": "1.2.4", - "dialog-polyfill": "^0.4.3", - "element.scrollintoviewifneeded-polyfill": "^1.0.1", - "material-design-icons": "2.2.3", - "material-design-lite": "1.2.1", - "moment": "2.15.1", "md-date-time-picker": "^2.2.0", diff --git a/ng2-components/ng2-activiti-tasklist/package.json b/ng2-components/ng2-activiti-tasklist/package.json index c4c91c9113..beeafa9be3 100644 --- a/ng2-components/ng2-activiti-tasklist/package.json +++ b/ng2-components/ng2-activiti-tasklist/package.json @@ -61,12 +61,6 @@ "systemjs": "0.19.27", "zone.js": "^0.6.23", - "intl": "1.2.4", - "dialog-polyfill": "^0.4.3", - "element.scrollintoviewifneeded-polyfill": "^1.0.1", - "material-design-icons": "2.2.3", - "material-design-lite": "1.2.1", - "moment": "2.15.1", "md-date-time-picker": "^2.2.0", diff --git a/ng2-components/ng2-alfresco-datatable/package.json b/ng2-components/ng2-alfresco-datatable/package.json index 1269fed714..78641ecd51 100644 --- a/ng2-components/ng2-alfresco-datatable/package.json +++ b/ng2-components/ng2-alfresco-datatable/package.json @@ -57,12 +57,6 @@ "systemjs": "0.19.27", "zone.js": "^0.6.23", - "intl": "1.2.4", - "dialog-polyfill": "^0.4.3", - "element.scrollintoviewifneeded-polyfill": "^1.0.1", - "material-design-icons": "2.2.3", - "material-design-lite": "1.2.1", - "ng2-translate": "2.5.0", "alfresco-js-api": "^0.4.0", "ng2-alfresco-core": "0.4.0" diff --git a/ng2-components/ng2-alfresco-documentlist/demo/package.json b/ng2-components/ng2-alfresco-documentlist/demo/package.json index 706b59d511..474f95bf82 100644 --- a/ng2-components/ng2-alfresco-documentlist/demo/package.json +++ b/ng2-components/ng2-alfresco-documentlist/demo/package.json @@ -30,12 +30,6 @@ "systemjs": "0.19.27", "zone.js": "^0.6.23", - "intl": "1.2.4", - "dialog-polyfill": "^0.4.3", - "element.scrollintoviewifneeded-polyfill": "^1.0.1", - "material-design-icons": "2.2.3", - "material-design-lite": "1.2.1", - "ng2-translate": "2.5.0", "alfresco-js-api": "^0.4.0", "ng2-alfresco-core": "0.4.0", diff --git a/ng2-components/ng2-alfresco-documentlist/package.json b/ng2-components/ng2-alfresco-documentlist/package.json index 21ecdaed27..48bfe89336 100644 --- a/ng2-components/ng2-alfresco-documentlist/package.json +++ b/ng2-components/ng2-alfresco-documentlist/package.json @@ -65,12 +65,6 @@ "systemjs": "0.19.27", "zone.js": "^0.6.23", - "intl": "1.2.4", - "dialog-polyfill": "^0.4.3", - "element.scrollintoviewifneeded-polyfill": "^1.0.1", - "material-design-icons": "2.2.3", - "material-design-lite": "1.2.1", - "ng2-translate": "2.5.0", "alfresco-js-api": "^0.4.0", "ng2-alfresco-core": "0.4.0", diff --git a/ng2-components/ng2-alfresco-login/package.json b/ng2-components/ng2-alfresco-login/package.json index c07b0dfea1..4aca0f6899 100644 --- a/ng2-components/ng2-alfresco-login/package.json +++ b/ng2-components/ng2-alfresco-login/package.json @@ -69,12 +69,6 @@ "systemjs": "0.19.27", "zone.js": "^0.6.23", - "intl": "1.2.4", - "dialog-polyfill": "^0.4.3", - "element.scrollintoviewifneeded-polyfill": "^1.0.1", - "material-design-icons": "2.2.3", - "material-design-lite": "1.2.1", - "ng2-translate": "2.5.0", "alfresco-js-api": "^0.4.0", "ng2-alfresco-core": "0.4.0" diff --git a/ng2-components/ng2-alfresco-search/package.json b/ng2-components/ng2-alfresco-search/package.json index 6f13f155a3..15be099297 100644 --- a/ng2-components/ng2-alfresco-search/package.json +++ b/ng2-components/ng2-alfresco-search/package.json @@ -67,12 +67,6 @@ "systemjs": "0.19.27", "zone.js": "^0.6.23", - "intl": "1.2.4", - "dialog-polyfill": "^0.4.3", - "element.scrollintoviewifneeded-polyfill": "^1.0.1", - "material-design-icons": "2.2.3", - "material-design-lite": "1.2.1", - "ng2-translate": "2.5.0", "alfresco-js-api": "^0.4.0", "ng2-alfresco-core": "0.4.0" diff --git a/ng2-components/ng2-alfresco-tag/package.json b/ng2-components/ng2-alfresco-tag/package.json index 7abd22fa60..2cb12b7839 100644 --- a/ng2-components/ng2-alfresco-tag/package.json +++ b/ng2-components/ng2-alfresco-tag/package.json @@ -44,12 +44,6 @@ "systemjs": "0.19.27", "zone.js": "^0.6.23", - "intl": "1.2.4", - "dialog-polyfill": "^0.4.3", - "element.scrollintoviewifneeded-polyfill": "^1.0.1", - "material-design-icons": "2.2.3", - "material-design-lite": "1.2.1", - "ng2-translate": "2.5.0", "alfresco-js-api": "^0.4.0", "ng2-alfresco-core": "0.4.0" diff --git a/ng2-components/ng2-alfresco-upload/package.json b/ng2-components/ng2-alfresco-upload/package.json index 865efb01b9..bc45335e72 100644 --- a/ng2-components/ng2-alfresco-upload/package.json +++ b/ng2-components/ng2-alfresco-upload/package.json @@ -66,12 +66,6 @@ "systemjs": "0.19.27", "zone.js": "^0.6.23", - "intl": "1.2.4", - "dialog-polyfill": "^0.4.3", - "element.scrollintoviewifneeded-polyfill": "^1.0.1", - "material-design-icons": "2.2.3", - "material-design-lite": "1.2.1", - "ng2-translate": "2.5.0", "alfresco-js-api": "^0.4.0", "ng2-alfresco-core": "0.4.0" diff --git a/ng2-components/ng2-alfresco-userinfo/package.json b/ng2-components/ng2-alfresco-userinfo/package.json index 73d3f46619..8f7f1eefa2 100644 --- a/ng2-components/ng2-alfresco-userinfo/package.json +++ b/ng2-components/ng2-alfresco-userinfo/package.json @@ -44,12 +44,6 @@ "systemjs": "0.19.27", "zone.js": "^0.6.23", - "intl": "1.2.4", - "dialog-polyfill": "^0.4.3", - "element.scrollintoviewifneeded-polyfill": "^1.0.1", - "material-design-icons": "2.2.3", - "material-design-lite": "1.2.1", - "ng2-translate": "2.5.0", "alfresco-js-api": "^0.4.0", "ng2-alfresco-core": "0.4.0" diff --git a/ng2-components/ng2-alfresco-viewer/package.json b/ng2-components/ng2-alfresco-viewer/package.json index cc9c2c07b7..28b8036e47 100644 --- a/ng2-components/ng2-alfresco-viewer/package.json +++ b/ng2-components/ng2-alfresco-viewer/package.json @@ -59,12 +59,6 @@ "systemjs": "0.19.27", "zone.js": "^0.6.23", - "intl": "1.2.4", - "dialog-polyfill": "^0.4.3", - "element.scrollintoviewifneeded-polyfill": "^1.0.1", - "material-design-icons": "2.2.3", - "material-design-lite": "1.2.1", - "ng2-translate": "2.5.0", "alfresco-js-api": "^0.4.0", "ng2-alfresco-core": "0.4.0", diff --git a/ng2-components/ng2-alfresco-webscript/package.json b/ng2-components/ng2-alfresco-webscript/package.json index 6cc9f0a4df..92e3f27742 100644 --- a/ng2-components/ng2-alfresco-webscript/package.json +++ b/ng2-components/ng2-alfresco-webscript/package.json @@ -44,12 +44,6 @@ "systemjs": "0.19.27", "zone.js": "^0.6.23", - "intl": "1.2.4", - "dialog-polyfill": "^0.4.3", - "element.scrollintoviewifneeded-polyfill": "^1.0.1", - "material-design-icons": "2.2.3", - "material-design-lite": "1.2.1", - "ng2-translate": "2.5.0", "alfresco-js-api": "^0.4.0", "ng2-alfresco-core": "0.4.0", From 4c95ed1f71eaf1dc720869b343756c6850a3d223 Mon Sep 17 00:00:00 2001 From: Denys Vuika Date: Mon, 14 Nov 2016 14:47:13 +0000 Subject: [PATCH 006/103] #967 initial support for dynamic components (wip) - form rendering service to control field-component type mappings - special component with dynamic content creation based on mapped types - migrated component to dynamic creation --- ng2-components/ng2-activiti-form/index.ts | 9 ++- .../activiti-start-form.component.spec.ts | 2 + .../form-field/form-field.component.ts | 68 +++++++++++++++++++ .../widgets/container/container.widget.html | 2 +- .../container/container.widget.spec.ts | 3 +- .../widgets/tabs/tabs.widget.spec.ts | 3 +- .../src/services/form-rendering.service.ts | 57 ++++++++++++++++ 7 files changed, 140 insertions(+), 4 deletions(-) create mode 100644 ng2-components/ng2-activiti-form/src/components/form-field/form-field.component.ts create mode 100644 ng2-components/ng2-activiti-form/src/services/form-rendering.service.ts diff --git a/ng2-components/ng2-activiti-form/index.ts b/ng2-components/ng2-activiti-form/index.ts index 519cc0e2c3..dc0f622b19 100644 --- a/ng2-components/ng2-activiti-form/index.ts +++ b/ng2-components/ng2-activiti-form/index.ts @@ -19,12 +19,14 @@ import { NgModule, ModuleWithProviders } from '@angular/core'; import { CoreModule } from 'ng2-alfresco-core'; import { ActivitiForm } from './src/components/activiti-form.component'; +import { FormFieldComponent } from './src/components/form-field/form-field.component'; import { ActivitiStartForm } from './src/components/activiti-start-form.component'; import { FormService } from './src/services/form.service'; import { EcmModelService } from './src/services/ecm-model.service'; import { NodeService } from './src/services/node.service'; import { WidgetVisibilityService } from './src/services/widget-visibility.service'; import { ActivitiAlfrescoContentService } from './src/services/activiti-alfresco.service'; +import { FormRenderingService } from './src/services/form-rendering.service'; import { HttpModule } from '@angular/http'; import { WIDGET_DIRECTIVES } from './src/components/widgets/index'; @@ -38,6 +40,7 @@ export * from './src/services/node.service'; export const ACTIVITI_FORM_DIRECTIVES: any[] = [ ActivitiForm, ActivitiStartForm, + FormFieldComponent, ...WIDGET_DIRECTIVES ]; @@ -46,7 +49,8 @@ export const ACTIVITI_FORM_PROVIDERS: any[] = [ EcmModelService, NodeService, WidgetVisibilityService, - ActivitiAlfrescoContentService + ActivitiAlfrescoContentService, + FormRenderingService ]; @NgModule({ @@ -57,6 +61,9 @@ export const ACTIVITI_FORM_PROVIDERS: any[] = [ declarations: [ ...ACTIVITI_FORM_DIRECTIVES ], + entryComponents: [ + ...WIDGET_DIRECTIVES + ], providers: [ ...ACTIVITI_FORM_PROVIDERS ], diff --git a/ng2-components/ng2-activiti-form/src/components/activiti-start-form.component.spec.ts b/ng2-components/ng2-activiti-form/src/components/activiti-start-form.component.spec.ts index 46d20208d6..76701f658b 100644 --- a/ng2-components/ng2-activiti-form/src/components/activiti-start-form.component.spec.ts +++ b/ng2-components/ng2-activiti-form/src/components/activiti-start-form.component.spec.ts @@ -20,6 +20,7 @@ import { ComponentFixture, TestBed, async } from '@angular/core/testing'; import { Observable } from 'rxjs/Rx'; import { ActivitiStartForm } from './activiti-start-form.component'; +import { FormFieldComponent } from './form-field/form-field.component'; import { WIDGET_DIRECTIVES } from './widgets/index'; import { FormService } from './../services/form.service'; import { EcmModelService } from './../services/ecm-model.service'; @@ -43,6 +44,7 @@ describe('ActivitiStartForm', () => { imports: [ CoreModule ], declarations: [ ActivitiStartForm, + FormFieldComponent, ...WIDGET_DIRECTIVES ], providers: [ diff --git a/ng2-components/ng2-activiti-form/src/components/form-field/form-field.component.ts b/ng2-components/ng2-activiti-form/src/components/form-field/form-field.component.ts new file mode 100644 index 0000000000..1a34a49e03 --- /dev/null +++ b/ng2-components/ng2-activiti-form/src/components/form-field/form-field.component.ts @@ -0,0 +1,68 @@ +/*! + * @license + * Copyright 2016 Alfresco Software, Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { Component, OnInit, ViewChild, ViewContainerRef, Input, ComponentRef, ComponentFactoryResolver, Output, EventEmitter/*, Injector*/ } from '@angular/core'; +import { WidgetVisibilityService } from './../../services/widget-visibility.service'; +import { FormRenderingService } from './../../services/form-rendering.service'; +import { WidgetComponent } from './../widgets/widget.component'; +import { FormFieldModel/*, FormWidgetModel*/ } from './../widgets/core/index'; + +@Component({ + selector: 'form-field', + template: `
` +}) +export class FormFieldComponent implements OnInit { + + @ViewChild('container', { read: ViewContainerRef }) + container: ViewContainerRef; + + @Input() + field: FormFieldModel = null; + + /** @deprecated component handles visibilty itself */ + @Output() + fieldChanged: EventEmitter = new EventEmitter(); + + private componentRef: ComponentRef<{}>; + + constructor( + private formRenderingService: FormRenderingService, + private componentFactoryResolver: ComponentFactoryResolver, + private visibilityService: WidgetVisibilityService + /*,private injector: Injector*/) { + } + + ngOnInit() { + if (this.field) { + let componentType = this.formRenderingService.getComponentType(this.field.type); + if (componentType) { + let factory = this.componentFactoryResolver.resolveComponentFactory(componentType); + this.componentRef = this.container.createComponent(factory/*, 0, this.injector*/); + let instance = this.componentRef.instance; + instance.field = this.field; + instance.fieldChanged.subscribe(args => { + if (this.field && this.field.form) { + this.visibilityService.refreshVisibility(this.field.form); + } + /** @deprecated */ + this.fieldChanged.emit(args); + }); + } + } + } + +} 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 ccab11975e..761b7dfd0c 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 @@ -20,7 +20,7 @@
- +
diff --git a/ng2-components/ng2-activiti-form/src/components/widgets/container/container.widget.spec.ts b/ng2-components/ng2-activiti-form/src/components/widgets/container/container.widget.spec.ts index e3da7ed9c2..3d7b483660 100644 --- a/ng2-components/ng2-activiti-form/src/components/widgets/container/container.widget.spec.ts +++ b/ng2-components/ng2-activiti-form/src/components/widgets/container/container.widget.spec.ts @@ -23,6 +23,7 @@ import { FormFieldModel } from './../core/form-field.model'; import { ComponentFixture, TestBed, async } from '@angular/core/testing'; import { CoreModule } from 'ng2-alfresco-core'; import { WIDGET_DIRECTIVES } from '../index'; +import { FormFieldComponent } from './../../form-field/form-field.component'; import { fakeFormJson } from '../../../services/assets/widget-visibility.service.mock'; describe('ContainerWidget', () => { @@ -122,7 +123,7 @@ describe('ContainerWidget', () => { beforeEach(async(() => { TestBed.configureTestingModule({ imports: [CoreModule], - declarations: [WIDGET_DIRECTIVES] + declarations: [FormFieldComponent, WIDGET_DIRECTIVES] }).compileComponents().then(() => { fixture = TestBed.createComponent(ContainerWidget); containerWidgetComponent = fixture.componentInstance; diff --git a/ng2-components/ng2-activiti-form/src/components/widgets/tabs/tabs.widget.spec.ts b/ng2-components/ng2-activiti-form/src/components/widgets/tabs/tabs.widget.spec.ts index c61bf2c9ce..510b4c5b1f 100644 --- a/ng2-components/ng2-activiti-form/src/components/widgets/tabs/tabs.widget.spec.ts +++ b/ng2-components/ng2-activiti-form/src/components/widgets/tabs/tabs.widget.spec.ts @@ -22,6 +22,7 @@ import { fakeFormJson } from '../../../services/assets/widget-visibility.service import { TabsWidget } from './tabs.widget'; import { TabModel } from '../core/tab.model'; import { WIDGET_DIRECTIVES } from '../index'; +import { FormFieldComponent } from './../../form-field/form-field.component'; import { CoreModule } from 'ng2-alfresco-core'; describe('TabsWidget', () => { @@ -102,7 +103,7 @@ describe('TabsWidget', () => { beforeEach(async(() => { TestBed.configureTestingModule({ imports: [CoreModule], - declarations: [WIDGET_DIRECTIVES] + declarations: [FormFieldComponent, WIDGET_DIRECTIVES] }).compileComponents().then(() => { fixture = TestBed.createComponent(TabsWidget); tabWidgetComponent = fixture.componentInstance; diff --git a/ng2-components/ng2-activiti-form/src/services/form-rendering.service.ts b/ng2-components/ng2-activiti-form/src/services/form-rendering.service.ts new file mode 100644 index 0000000000..d4d7e6ca3b --- /dev/null +++ b/ng2-components/ng2-activiti-form/src/services/form-rendering.service.ts @@ -0,0 +1,57 @@ +/*! + * @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, Type } from '@angular/core'; + +import { TextWidget } from './../components/widgets/text/text.widget'; + +@Injectable() +export class FormRenderingService { + + private types: { [key: string]: Type<{}> } = { + 'text': TextWidget + }; + + getComponentType(fieldType: string): Type<{}> { + if (fieldType) { + return this.types[fieldType] || null; + } + return null; + } + + setComponentType(fieldType: string, componentType: Type<{}>, override: boolean = false) { + if (!fieldType) { + throw new Error(`fieldType is null or not defined`); + } + + if (!componentType) { + throw new Error(`componentType is null or not defined`); + } + + let existing = this.types[fieldType]; + if (existing && !override) { + throw new Error(`componentType is already mapped, use override option if you intend replacing existing mapping.`); + } + + this.types[fieldType] = componentType; + } + + constructor() { + this.setComponentType('xx', TextWidget); + } + +} From 8174de8fc8a8a6c95664ade421605796185c8d98 Mon Sep 17 00:00:00 2001 From: Will Abson Date: Mon, 14 Nov 2016 17:10:02 +0000 Subject: [PATCH 007/103] Allow use of nginx on Windows - Remove headers_more module lines (not needed) - Improve docs --- PREREQUISITES.md | 36 ++++++++++++++++++++++++----------- nginx.conf | 49 +----------------------------------------------- 2 files changed, 26 insertions(+), 59 deletions(-) diff --git a/PREREQUISITES.md b/PREREQUISITES.md index 0bb6211056..f4fb366f79 100644 --- a/PREREQUISITES.md +++ b/PREREQUISITES.md @@ -6,6 +6,7 @@ The [Angular 2](https://angular.io/) based application development framework req - [Download and install Activiti](https://www.alfresco.com/products/bpm/alfresco-activiti/trial) - [Node.js](https://nodejs.org/en/) JavaScript runtime. - [npm](https://www.npmjs.com/) package manager for JavaScript. +- local nginx proxy to avoid cross-origin browser restrictions (see below) - (If you use ECM and BPM together) Make sure your user has the same username and password in both system *Note: Default username for activiti is "admin@app.activiti.com" and "admin" for Alfresco, and also the default password are different. Change them to be equal.* @@ -25,26 +26,39 @@ $ node -v v5.12.0 ``` -## Configure Nginx +## Installing nginx -To correctly configure Nginx use the following file [nginx.conf](/nginx.conf). -This will put Activiti, Alfresco and the app dev framework under the same domain. +Most Linux distributions will come with nginx available to install via your +package manager and on Mac OS you can use [Homebrew](http://brew.sh/). + +If you want to install manually however you can follow the instructions on the +[download page](http://nginx.org/en/download.html). See also the specific information for +[windows users](http://nginx.org/en/docs/windows.html). + +### Start nginx + +Start nginx using the supplied configuration in [nginx.conf](nginx.conf) + + nginx -c nginx.conf + +### Review nginx configuration + +To correctly configure nginx use the following file [nginx.conf](/nginx.conf). +This will host Activiti, Alfresco and the app dev framework under the same origin. * ECM : http://localhost:8888/alfresco/ * BPM : http://localhost:8888/activiti/ -To make everything work, you have to change the address of the ECM and BPM. In the demo app you can do that clicking on the top left menu and changing the bottom left options: ECM host and BPM host. +To make everything work, you have to change the address of the ECM and BPM. In the demo app you can do that clicking on the top right settings menu and changing the bottom left options: *ECM host* and *BPM host*. This configuration assumes few things: * Port mapping: - * Nginx entry point: 8888 - * Demo Shell: 3000 - * Alfresco: 8080 - * Activiti: 9999 + * nginx entry point: 0.0.0.0:8888 + * Demo Shell: locathost:3000 + * Alfresco: locathost:8080 + * Activiti: locathost:9999 All those values can be modified at their respective `location` directive on the [nginx.conf](/nginx.conf) file. -It also need to be compiled with the [Headers More](https://www.nginx.com/resources/wiki/modules/headers_more/) module , which add more control over sending headers to the backend. - -If you want to know more on how to install and configure Nginx to work with the Application Development Framework can be found [here](https://community.alfresco.com/community/application-development-framework/blog/2016/09/28/adf-development-set-up-with-nginx-proxy) +If you want to know more on how to install and configure nginx to work with the Application Development Framework can be found [here](https://community.alfresco.com/community/application-development-framework/blog/2016/09/28/adf-development-set-up-with-nginx-proxy) diff --git a/nginx.conf b/nginx.conf index b5bead4f8e..e9ae64fe3f 100644 --- a/nginx.conf +++ b/nginx.conf @@ -35,7 +35,7 @@ http { server { listen 8888; server_name dev-platform-proxy; - + #set $allowOriginSite http://127.0.0.1:3000; set $allowOriginSite *; @@ -55,26 +55,6 @@ http { proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_pass_header Set-Cookie; - - if ($request_method = 'OPTIONS') { - more_set_headers 'Access-Control-Allow-Origin: $allowOriginSite'; - # - # Om nom nom cookies - # - more_set_headers 'Access-Control-Allow-Credentials: true'; - more_set_headers 'Access-Control-Allow-Methods: GET, POST, PUT, DELETE, OPTIONS'; - # - # Custom headers and headers various browsers *should* be OK with but aren't - # - more_set_headers 'Access-Control-Allow-Headers: DNT,X-CustomHeader,Keep-Alive,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type, Content-Range, Content-Disposition, Content-Description, X-CSRF-TOKEN, Authorization'; - # - # Tell client that this pre-flight info is valid for 20 days - # - more_set_headers 'Access-Control-Max-Age: 1728000'; - more_set_headers 'Content-Type: text/plain charset=UTF-8'; - more_set_headers 'Content-Length 0'; - return 204; - } } location /activiti/ { @@ -87,33 +67,6 @@ http { proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_pass_header Set-Cookie; proxy_pass_request_headers on; - - if ($request_method = 'OPTIONS') { - more_set_headers 'Access-Control-Allow-Origin: $allowOriginSite'; - # - # Om nom nom cookies - # - more_set_headers 'Access-Control-Allow-Credentials: true'; - more_set_headers 'Access-Control-Allow-Methods: GET, POST, PUT, DELETE, OPTIONS'; - # - # Custom headers and headers various browsers *should* be OK with but aren't - # - more_set_headers 'Access-Control-Allow-Headers: DNT,X-CustomHeader,Keep-Alive,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type, Content-Range, Content-Disposition, Content-Description, X-CSRF-TOKEN, Authorization'; - # - # Tell client that this pre-flight info is valid for 20 days - # - more_set_headers 'Access-Control-Max-Age: 1728000'; - more_set_headers 'Content-Type: text/plain charset=UTF-8'; - more_set_headers 'Content-Length 0'; - return 204; - } - - if ($request_method = 'POST') { - more_set_headers 'Access-Control-Allow-Origin: $allowOriginSite'; - more_set_headers 'Access-Control-Allow-Credentials: true'; - more_set_headers 'Access-Control-Allow-Methods: GET, POST, OPTIONS, DELETE'; - more_set_headers 'Access-Control-Allow-Headers: DNT,X-CustomHeader,Keep-Alive,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type, Content-Range, Content-Disposition, Content-Description, X-CSRF-TOKEN, Authorization'; - } } location / { From a66d4d44e892428708f96eeee2facfb543049189 Mon Sep 17 00:00:00 2001 From: mauriziovitale84 Date: Mon, 14 Nov 2016 17:21:39 +0000 Subject: [PATCH 008/103] #987 flatten FilterRepresentationModel --- .../activiti/activiti-demo.component.html | 8 ++- .../activiti-tasklist.component.html | 4 +- .../components/activiti-tasklist.component.ts | 56 +++++++++++-------- .../src/models/filter.model.ts | 4 ++ 4 files changed, 45 insertions(+), 27 deletions(-) diff --git a/demo-shell-ng2/app/components/activiti/activiti-demo.component.html b/demo-shell-ng2/app/components/activiti/activiti-demo.component.html index 11f6544900..ff8e279604 100644 --- a/demo-shell-ng2/app/components/activiti/activiti-demo.component.html +++ b/demo-shell-ng2/app/components/activiti/activiti-demo.component.html @@ -36,7 +36,13 @@
Task List -
diff --git a/ng2-components/ng2-activiti-tasklist/src/components/activiti-tasklist.component.html b/ng2-components/ng2-activiti-tasklist/src/components/activiti-tasklist.component.html index 9dbfa195b6..a92efe7e67 100644 --- a/ng2-components/ng2-activiti-tasklist/src/components/activiti-tasklist.component.html +++ b/ng2-components/ng2-activiti-tasklist/src/components/activiti-tasklist.component.html @@ -1,5 +1,5 @@ -
{{ 'TASK_FILTERS.MESSAGES.NONE' | translate }}
-
+
{{ 'TASK_FILTERS.MESSAGES.NONE' | translate }}
+
{ requestNode.size = res.total; @@ -191,14 +199,14 @@ export class ActivitiTaskList implements OnInit, OnChanges { return tasks; } - private convertTaskUserToTaskQuery(userTask: FilterRepresentationModel) { + private createRequestNode() { let requestNode = { - appDefinitionId: userTask.appId, - processDefinitionId: userTask.filter.processDefinitionId, - text: userTask.filter.name, - assignment: userTask.filter.assignment, - state: userTask.filter.state, - sort: userTask.filter.sort + appDefinitionId: this.appId, + processDefinitionId: this.processDefinitionId, + text: this.name, + assignment: this.assignment, + state: this.state, + sort: this.sort }; return new TaskQueryRequestRepresentationModel(requestNode); } diff --git a/ng2-components/ng2-activiti-tasklist/src/models/filter.model.ts b/ng2-components/ng2-activiti-tasklist/src/models/filter.model.ts index 72fd681bcd..09a8c88256 100644 --- a/ng2-components/ng2-activiti-tasklist/src/models/filter.model.ts +++ b/ng2-components/ng2-activiti-tasklist/src/models/filter.model.ts @@ -70,6 +70,10 @@ export class FilterRepresentationModel { this.filter = new FilterParamRepresentationModel(obj.filter); this.index = obj && obj.index; } + + hasFilter() { + return this.filter ? true : false; + } } /** From f844b0d65fcd1591bf7e034373aac70e607334f7 Mon Sep 17 00:00:00 2001 From: mauriziovitale84 Date: Mon, 14 Nov 2016 17:21:57 +0000 Subject: [PATCH 009/103] #987 fix unit test --- .../activiti-tasklist.component.spec.ts | 157 +++++++++++------- 1 file changed, 100 insertions(+), 57 deletions(-) diff --git a/ng2-components/ng2-activiti-tasklist/src/components/activiti-tasklist.component.spec.ts b/ng2-components/ng2-activiti-tasklist/src/components/activiti-tasklist.component.spec.ts index bb7bfed213..7f0ab7c960 100644 --- a/ng2-components/ng2-activiti-tasklist/src/components/activiti-tasklist.component.spec.ts +++ b/ng2-components/ng2-activiti-tasklist/src/components/activiti-tasklist.component.spec.ts @@ -15,17 +15,17 @@ * limitations under the License. */ -import { SimpleChange } from '@angular/core'; +import { ComponentFixture, TestBed, async } from '@angular/core/testing'; +import { AlfrescoTranslationService, CoreModule } from 'ng2-alfresco-core'; +import { DataTableModule } from 'ng2-alfresco-datatable'; import { ActivitiTaskList } from './activiti-tasklist.component'; -import { ActivitiTaskListService } from '../services/activiti-tasklist.service'; -import { FilterRepresentationModel } from '../models/filter.model'; import { Observable } from 'rxjs/Rx'; import { ObjectDataRow, DataRowEvent, ObjectDataTableAdapter } from 'ng2-alfresco-datatable'; +import { TranslationMock } from './../assets/translation.service.mock'; +import { ActivitiTaskListService } from '../services/activiti-tasklist.service'; describe('ActivitiTaskList', () => { - let taskList: ActivitiTaskList; - let fakeGlobalTask = { size: 2, total: 2, start: 0, data: [ @@ -65,86 +65,114 @@ describe('ActivitiTaskList', () => { reject(fakeErrorTaskList); }); + let componentHandler: any; + let component: ActivitiTaskList; + let fixture: ComponentFixture; + + beforeEach(async(() => { + TestBed.configureTestingModule({ + imports: [ + CoreModule, + DataTableModule + ], + declarations: [ + ActivitiTaskList + ], + providers: [ + { provide: AlfrescoTranslationService, useClass: TranslationMock }, + ActivitiTaskListService + ] + }).compileComponents(); + })); + beforeEach(() => { - let activitiSerevice = new ActivitiTaskListService(null); - taskList = new ActivitiTaskList(null, activitiSerevice); + + fixture = TestBed.createComponent(ActivitiTaskList); + component = fixture.componentInstance; + + componentHandler = jasmine.createSpyObj('componentHandler', [ + 'upgradeAllRegistered', + 'upgradeElement' + ]); + window['componentHandler'] = componentHandler; }); it('should use the default schemaColumn as default', () => { - taskList.ngOnInit(); - expect(taskList.data.getColumns()).toBeDefined(); - expect(taskList.data.getColumns().length).toEqual(4); + component.ngOnInit(); + expect(component.data.getColumns()).toBeDefined(); + expect(component.data.getColumns().length).toEqual(4); }); it('should use the schemaColumn passed in input', () => { - taskList.data = new ObjectDataTableAdapter( + component.data = new ObjectDataTableAdapter( [], [ {type: 'text', key: 'fake-id', title: 'Name'} ] ); - taskList.ngOnInit(); - expect(taskList.data.getColumns()).toBeDefined(); - expect(taskList.data.getColumns().length).toEqual(1); + component.ngOnInit(); + expect(component.data.getColumns()).toBeDefined(); + expect(component.data.getColumns().length).toEqual(1); }); - it('should return an empty task list when the taskFilter is not passed', () => { - taskList.ngOnInit(); - expect(taskList.data).toBeDefined(); - expect(taskList.isTaskListEmpty()).toBeTruthy(); + it('should return an empty task list when no input parameters are passed', () => { + component.ngOnInit(); + expect(component.data).toBeDefined(); + expect(component.isTaskListEmpty()).toBeTruthy(); }); - it('should return the filtered task list when the taskFilter is passed', (done) => { - spyOn(taskList.activiti, 'getTotalTasks').and.returnValue(Observable.fromPromise(fakeGlobalTotalTasksPromise)); - spyOn(taskList.activiti, 'getTasks').and.returnValue(Observable.fromPromise(fakeGlobalTaskPromise)); - taskList.taskFilter = new FilterRepresentationModel({filter: { state: 'open', assignment: 'fake-assignee'}}); - - taskList.onSuccess.subscribe( (res) => { + it('should return the filtered task list when the input parameters are passed', (done) => { + spyOn(component.activiti, 'getTotalTasks').and.returnValue(Observable.fromPromise(fakeGlobalTotalTasksPromise)); + spyOn(component.activiti, 'getTasks').and.returnValue(Observable.fromPromise(fakeGlobalTaskPromise)); + component.state = 'open'; + component.assignment = 'fake-assignee'; + component.onSuccess.subscribe( (res) => { expect(res).toBeDefined(); - expect(taskList.data).toBeDefined(); - expect(taskList.isTaskListEmpty()).not.toBeTruthy(); - expect(taskList.data.getRows().length).toEqual(2); - expect(taskList.data.getRows()[0].getValue('name')).toEqual('fake-long-name-fake-long-name-fake-long-name-fak50...'); - expect(taskList.data.getRows()[1].getValue('name')).toEqual('Nameless task'); + expect(component.data).toBeDefined(); + expect(component.isTaskListEmpty()).not.toBeTruthy(); + expect(component.data.getRows().length).toEqual(2); + expect(component.data.getRows()[0].getValue('name')).toEqual('fake-long-name-fake-long-name-fake-long-name-fak50...'); + expect(component.data.getRows()[1].getValue('name')).toEqual('Nameless task'); done(); }); - taskList.ngOnInit(); + component.ngOnInit(); }); it('should return a currentId null when the taskList is empty', () => { - taskList.selectFirstTask(); - expect(taskList.getCurrentTaskId()).toBeNull(); + component.selectFirstTask(); + expect(component.getCurrentTaskId()).toBeNull(); }); it('should throw an exception when the response is wrong', (done) => { - spyOn(taskList.activiti, 'getTotalTasks').and.returnValue(Observable.fromPromise(fakeErrorTaskPromise)); - taskList.taskFilter = new FilterRepresentationModel({filter: { state: 'open', assignment: 'fake-assignee'}}); - - taskList.onError.subscribe( (err) => { + spyOn(component.activiti, 'getTotalTasks').and.returnValue(Observable.fromPromise(fakeErrorTaskPromise)); + component.state = 'open'; + component.assignment = 'fake-assignee'; + component.onError.subscribe( (err) => { expect(err).toBeDefined(); done(); }); - taskList.ngOnInit(); + component.ngOnInit(); }); it('should reload tasks when reload() is called', (done) => { - spyOn(taskList.activiti, 'getTotalTasks').and.returnValue(Observable.fromPromise(fakeGlobalTotalTasksPromise)); - spyOn(taskList.activiti, 'getTasks').and.returnValue(Observable.fromPromise(fakeGlobalTaskPromise)); - taskList.taskFilter = new FilterRepresentationModel({filter: { state: 'open', assignment: 'fake-assignee'}}); - taskList.ngOnInit(); - taskList.onSuccess.subscribe( (res) => { + spyOn(component.activiti, 'getTotalTasks').and.returnValue(Observable.fromPromise(fakeGlobalTotalTasksPromise)); + spyOn(component.activiti, 'getTasks').and.returnValue(Observable.fromPromise(fakeGlobalTaskPromise)); + component.state = 'open'; + component.assignment = 'fake-assignee'; + component.ngOnInit(); + component.onSuccess.subscribe( (res) => { expect(res).toBeDefined(); - expect(taskList.data).toBeDefined(); - expect(taskList.isTaskListEmpty()).not.toBeTruthy(); - expect(taskList.data.getRows().length).toEqual(2); - expect(taskList.data.getRows()[0].getValue('name')).toEqual('fake-long-name-fake-long-name-fake-long-name-fak50...'); - expect(taskList.data.getRows()[1].getValue('name')).toEqual('Nameless task'); + expect(component.data).toBeDefined(); + expect(component.isTaskListEmpty()).not.toBeTruthy(); + expect(component.data.getRows().length).toEqual(2); + expect(component.data.getRows()[0].getValue('name')).toEqual('fake-long-name-fake-long-name-fake-long-name-fak50...'); + expect(component.data.getRows()[1].getValue('name')).toEqual('Nameless task'); done(); }); - taskList.reload(); + component.reload(); }); it('should emit row click event', (done) => { @@ -153,23 +181,38 @@ describe('ActivitiTaskList', () => { }); let rowEvent = {value: row}; - taskList.rowClick.subscribe(taskId => { + component.rowClick.subscribe(taskId => { expect(taskId).toEqual(999); - expect(taskList.getCurrentTaskId()).toEqual(999); + expect(component.getCurrentTaskId()).toEqual(999); done(); }); - taskList.onRowClick(rowEvent); + component.onRowClick(rowEvent); }); - it('should reload task list by filter on binding changes', () => { - spyOn(taskList, 'load').and.stub(); - const taskFilter = new FilterRepresentationModel({filter: { state: 'open', assignment: 'fake-assignee'}}); + it('should reload the task list when the input parameters changes', (done) => { + spyOn(component.activiti, 'getTotalTasks').and.returnValue(Observable.fromPromise(fakeGlobalTotalTasksPromise)); + spyOn(component.activiti, 'getTasks').and.returnValue(Observable.fromPromise(fakeGlobalTaskPromise)); - let change = new SimpleChange(null, taskFilter); - taskList.ngOnChanges({ 'taskFilter': change }); + component.data = new ObjectDataTableAdapter( + [], + [ + {type: 'text', key: 'fake-id', title: 'Name'} + ] + ); + component.state = 'open'; + component.assignment = 'fake-assignee'; + component.onSuccess.subscribe( (res) => { + expect(res).toBeDefined(); + expect(component.data).toBeDefined(); + expect(component.isTaskListEmpty()).not.toBeTruthy(); + expect(component.data.getRows().length).toEqual(2); + expect(component.data.getRows()[0].getValue('name')).toEqual('fake-long-name-fake-long-name-fake-long-name-fak50...'); + expect(component.data.getRows()[1].getValue('name')).toEqual('Nameless task'); + done(); + }); - expect(taskList.load).toHaveBeenCalled(); + component.ngOnChanges({}); }); }); From 9d30db9017dc0e52291462339def2efed7a6697d Mon Sep 17 00:00:00 2001 From: Vito Albano Date: Mon, 14 Nov 2016 17:27:07 +0000 Subject: [PATCH 010/103] added changes to reflect the default option for dropdown --- .../src/components/widgets/core/form-field.model.spec.ts | 6 +++--- .../src/components/widgets/core/form-field.model.ts | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) 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 90d2a9eece..4fdf3cdfad 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 @@ -163,12 +163,12 @@ describe('FormFieldModel', () => { id: 'dropdown-2', type: FormFieldTypes.DROPDOWN, options: [ - { id: 'opt1', value: 'Option 1' }, - { id: 'opt2', value: 'Option 2' } + { id: 'opt1', name: 'Option 1' }, + { id: 'opt2', name: 'Option 2' } ] }); - field.value = 'opt2'; + field.value = 'Option 2'; expect(form.values['dropdown-2']).toEqual(field.options[1]); }); 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 11bd17fe82..4acd1bc54d 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 @@ -234,7 +234,7 @@ export class FormFieldModel extends FormWidgetModel { if (this.value === 'empty' || this.value === '') { this.form.values[this.id] = {}; } else { - let entry: FormFieldOption[] = this.options.filter(opt => opt.id === this.value); + let entry: FormFieldOption[] = this.options.filter(opt => opt.name === this.value); if (entry.length > 0) { this.form.values[this.id] = entry[0]; } From a915c0ad6aa220b71553d0a44a55abe9434e7c89 Mon Sep 17 00:00:00 2001 From: Vito Albano Date: Mon, 14 Nov 2016 17:28:15 +0000 Subject: [PATCH 011/103] Improved form search for visibility service --- .../widget-visibility.service.spec.ts | 20 +++++++++++-------- .../src/services/widget-visibility.service.ts | 19 +++++++++--------- 2 files changed, 22 insertions(+), 17 deletions(-) diff --git a/ng2-components/ng2-activiti-form/src/services/widget-visibility.service.spec.ts b/ng2-components/ng2-activiti-form/src/services/widget-visibility.service.spec.ts index ffd7a8e177..b5ecc21faa 100644 --- a/ng2-components/ng2-activiti-form/src/services/widget-visibility.service.spec.ts +++ b/ng2-components/ng2-activiti-form/src/services/widget-visibility.service.spec.ts @@ -363,10 +363,11 @@ describe('WidgetVisibilityService', () => { expect(formValue).toBe('field_with_condition_value'); }); - it('should return undefined if the field value is not in the form', () => { + it('should return empty string if the field value is not in the form', () => { let formValue = service.searchForm(stubFormWithFields, 'FIELD_MYSTERY'); - expect(formValue).toBeUndefined(); + expect(formValue).not.toBeUndefined(); + expect(formValue).toBe(''); }); it('should search in the form if element value is not in form values', () => { @@ -376,10 +377,11 @@ describe('WidgetVisibilityService', () => { expect(value).toBe('field_with_condition_value'); }); - it('should return undefined if the element is not present anywhere', () => { + it('should return empty string if the element is not present anywhere', () => { let formValue = service.getFormValue(fakeFormWithField, 'FIELD_MYSTERY'); - expect(formValue).toBeUndefined(); + expect(formValue).not.toBeUndefined(); + expect(formValue).toBe(''); }); it('should retrieve the value for the right field when it is a value', () => { @@ -443,10 +445,11 @@ describe('WidgetVisibilityService', () => { expect(leftValue).toBe('value_2'); }); - it('should return undefined for a value that is not on variable or form', () => { + it('should return empty string for a value that is not on variable or form', () => { let leftValue = service.getLeftValue(fakeFormWithField, visibilityObjTest); - expect(leftValue).toBeUndefined(); + expect(leftValue).not.toBeUndefined(); + expect(leftValue).toBe(''); }); it('should evaluate the visibility for the field with single visibility condition between two field values', () => { @@ -467,11 +470,12 @@ describe('WidgetVisibilityService', () => { expect(isVisible).toBeTruthy(); }); - it('should return undefined for a value that is not on variable or form', () => { + it('should return empty string for a value that is not on variable or form', () => { visibilityObjTest.rightFormFieldId = 'NO_FIELD_FORM'; let rightValue = service.getRightValue(fakeFormWithField, visibilityObjTest); - expect(rightValue).toBeUndefined(); + expect(rightValue).not.toBeUndefined(); + expect(rightValue).toBe(''); }); it('should evaluate the visibility for the field with single visibility condition between form values', () => { diff --git a/ng2-components/ng2-activiti-form/src/services/widget-visibility.service.ts b/ng2-components/ng2-activiti-form/src/services/widget-visibility.service.ts index 1bc357e65a..1eb5c1a7cc 100644 --- a/ng2-components/ng2-activiti-form/src/services/widget-visibility.service.ts +++ b/ng2-components/ng2-activiti-form/src/services/widget-visibility.service.ts @@ -119,18 +119,19 @@ export class WidgetVisibilityService { } searchForm(form: FormModel, name: string) { - let res; + let fieldValue = ''; form.json.fields.forEach(columns => { - for (let i in columns.fields) { - if (columns.fields.hasOwnProperty(i)) { - res = columns.fields[i].find(field => field.id === name); - if (res) { - return res.value; + for (let i in columns.fields) { + if (columns.fields.hasOwnProperty(i)) { + let field = columns.fields[i].find(field => field.id === name); + if (field) { + fieldValue = field.value; + } } } } - }); - return res ? res.value : res; + ); + return fieldValue; } getVariableValue(form: FormModel, name: string, processVarList: TaskProcessVariableModel[]) { @@ -212,7 +213,7 @@ export class WidgetVisibilityService { private getRequestOptions(): RequestOptions { let headers = this.getHeaders(); - return new RequestOptions({headers: headers}); + return new RequestOptions({ headers: headers }); } private handleError(error: Response) { From 87d4cfcc414b5add36d1f8cf4be453353afe9d24 Mon Sep 17 00:00:00 2001 From: Vito Albano Date: Mon, 14 Nov 2016 17:28:43 +0000 Subject: [PATCH 012/103] Added changes to select the default value --- .../widgets/dropdown/dropdown.widget.spec.ts | 69 ++++++++++++++----- .../widgets/dropdown/dropdown.widget.ts | 14 ++-- 2 files changed, 62 insertions(+), 21 deletions(-) diff --git a/ng2-components/ng2-activiti-form/src/components/widgets/dropdown/dropdown.widget.spec.ts b/ng2-components/ng2-activiti-form/src/components/widgets/dropdown/dropdown.widget.spec.ts index 4da33f8b69..e160de0adf 100644 --- a/ng2-components/ng2-activiti-form/src/components/widgets/dropdown/dropdown.widget.spec.ts +++ b/ng2-components/ng2-activiti-form/src/components/widgets/dropdown/dropdown.widget.spec.ts @@ -21,15 +21,21 @@ import { DropdownWidget } from './dropdown.widget'; import { FormModel } from './../core/form.model'; import { FormFieldModel } from './../core/form-field.model'; import { FormFieldOption } from './../core/form-field-option'; +import { CoreModule } from 'ng2-alfresco-core'; +import { ComponentFixture, TestBed, async } from '@angular/core/testing'; +import { EcmModelService } from '../../../services/ecm-model.service'; +import { WidgetVisibilityService } from '../../../services/widget-visibility.service'; describe('DropdownWidget', () => { let formService: FormService; let widget: DropdownWidget; + let visibilityService: WidgetVisibilityService; beforeEach(() => { formService = new FormService(null, null); - widget = new DropdownWidget(formService); + visibilityService = new WidgetVisibilityService(null, null, null); + widget = new DropdownWidget(formService, visibilityService); widget.field = new FormFieldModel(new FormModel()); }); @@ -104,45 +110,74 @@ describe('DropdownWidget', () => { let fixture: ComponentFixture; let element: HTMLElement; let componentHandler; + let stubFormService; + let fakeOptionList: FormFieldOption[] = [{ id: 'opt_1', name: 'option_1' }, { + id: 'opt_2', + name: 'option_2' + }, { id: 'opt_3', name: 'option_3' }]; beforeEach(async(() => { componentHandler = jasmine.createSpyObj('componentHandler', ['upgradeAllRegistered', 'upgradeElement']); window['componentHandler'] = componentHandler; TestBed.configureTestingModule({ imports: [CoreModule], - declarations: [DropdownWidget] + declarations: [DropdownWidget], + providers: [FormService, EcmModelService, WidgetVisibilityService] }).compileComponents().then(() => { fixture = TestBed.createComponent(DropdownWidget); - dateWidget = fixture.componentInstance; + dropDownWidget = fixture.componentInstance; element = fixture.nativeElement; }); })); - beforeEach(() => { - spyOn(dateWidget, 'setupMaterialTextField').and.stub(); - dateWidget.field = new FormFieldModel(new FormModel(), { - id: 'date-field-id', + beforeEach(async(() => { + stubFormService = fixture.debugElement.injector.get(FormService); + visibilityService = fixture.debugElement.injector.get(WidgetVisibilityService); + spyOn(visibilityService, 'refreshVisibility').and.stub(); + spyOn(stubFormService, 'getRestFieldValues').and.returnValue(Observable.of(fakeOptionList)); + dropDownWidget.field = new FormFieldModel(new FormModel({ taskId: 'fake-task-id' }), { + id: 'dropdown-id', name: 'date-name', - value: '9-9-9999', - type: 'date', - readOnly: 'false' + type: 'dropdown', + readOnly: 'false', + restUrl: 'fake-rest-url' }); - dateWidget.field.isVisible = true; + dropDownWidget.field.isVisible = true; fixture.detectChanges(); - }); + })); afterEach(() => { fixture.destroy(); TestBed.resetTestingModule(); }); - it('should show visible date widget', async(() => { + it('should show visible dropdown widget', async(() => { + expect(element.querySelector('#dropdown-id')).toBeDefined(); + expect(element.querySelector('#dropdown-id')).not.toBeNull(); + expect(element.querySelector('#opt_1')).not.toBeNull(); + expect(element.querySelector('#opt_2')).not.toBeNull(); + expect(element.querySelector('#opt_3')).not.toBeNull(); + })); + + it('should select the default value', async(() => { + dropDownWidget.field.value = 'option_2'; + fixture.detectChanges(); fixture.whenStable() .then(() => { - expect(element.querySelector('#date-field-id')).toBeDefined(); - expect(element.querySelector('#date-field-id')).not.toBeNull(); - let dateElement: any = element.querySelector('#date-field-id'); - expect(dateElement.value).toEqual('9-9-9999'); + let dropDownElement: HTMLSelectElement = element.querySelector('#dropdown-id'); + expect(dropDownElement).not.toBeNull(); + expect(element.querySelector('#opt_2')).not.toBeNull(); + expect(dropDownElement.value).toBe('option_2'); + }); + })); + + it('should be not visibile when isVisible is false', async(() => { + dropDownWidget.field.isVisible = false; + fixture.detectChanges(); + fixture.whenStable() + .then(() => { + let dropDownElement: HTMLSelectElement = element.querySelector('#dropdown-id'); + expect(dropDownElement).toBeNull(); }); })); diff --git a/ng2-components/ng2-activiti-form/src/components/widgets/dropdown/dropdown.widget.ts b/ng2-components/ng2-activiti-form/src/components/widgets/dropdown/dropdown.widget.ts index f20345f8a5..3a624ae99e 100644 --- a/ng2-components/ng2-activiti-form/src/components/widgets/dropdown/dropdown.widget.ts +++ b/ng2-components/ng2-activiti-form/src/components/widgets/dropdown/dropdown.widget.ts @@ -19,6 +19,7 @@ import { Component, OnInit } from '@angular/core'; import { FormService } from '../../../services/form.service'; import { WidgetComponent } from './../widget.component'; import { FormFieldOption } from './../core/form-field-option'; +import { WidgetVisibilityService } from '../../../services/widget-visibility.service'; @Component({ moduleId: module.id, @@ -28,16 +29,17 @@ import { FormFieldOption } from './../core/form-field-option'; }) export class DropdownWidget extends WidgetComponent implements OnInit { - constructor(private formService: FormService) { + constructor(private formService: FormService, + private visibilityService: WidgetVisibilityService) { super(); } ngOnInit() { if (this.field && this.field.restUrl) { - if (this.field.form.processDefinitionId) { - this.getValuesByProcessDefinitionId(); - } else { + if (this.field.form.taskId) { this.getValuesByTaskId(); + } else { + this.getValuesByProcessDefinitionId(); } } } @@ -90,6 +92,10 @@ export class DropdownWidget extends WidgetComponent implements OnInit { return optionValue; } + checkVisibility() { + this.visibilityService.refreshVisibility(this.field.form); + } + handleError(error: any) { console.error(error); } From f5164b1ed619b75c3099d3dd9201e0ab9a6ab05c Mon Sep 17 00:00:00 2001 From: mauriziovitale84 Date: Mon, 14 Nov 2016 17:36:09 +0000 Subject: [PATCH 013/103] #987 fix demo code --- ng2-components/ng2-activiti-tasklist/demo/src/main.ts | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/ng2-components/ng2-activiti-tasklist/demo/src/main.ts b/ng2-components/ng2-activiti-tasklist/demo/src/main.ts index 0653dd4c1e..c734a35d62 100644 --- a/ng2-components/ng2-activiti-tasklist/demo/src/main.ts +++ b/ng2-components/ng2-activiti-tasklist/demo/src/main.ts @@ -80,8 +80,13 @@ import { ObjectDataTableAdapter, DataSorting } from 'ng2-alfresco-datatable';
Task List - @@ -210,7 +215,7 @@ class MyDemoApp implements OnInit { } onFormCompleted(form) { - this.activititasklist.load(this.taskFilter); + this.activititasklist.reload(); this.currentTaskId = null; } From 6265c80c982eebeb6b8e439c4ebc9b78199bdae8 Mon Sep 17 00:00:00 2001 From: Mario Romano Date: Mon, 14 Nov 2016 17:44:55 +0000 Subject: [PATCH 014/103] #1089 add diagram link --- appveyor.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/appveyor.yml b/appveyor.yml index eb683012f0..5bac593a50 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -36,6 +36,7 @@ install: - IF %COMPONENT_NAME% EQU ng2-activiti-tasklist (cd ng2-components/ng2-alfresco-datatable && npm link ng2-alfresco-core && npm install && npm link && cd ../../) - IF %COMPONENT_NAME% EQU ng2-activiti-tasklist (cd ng2-components/ng2-activiti-form && npm link ng2-alfresco-core && npm install && npm link && cd ../../) - IF %COMPONENT_NAME% EQU ng2-alfresco-webscript (cd ng2-components/ng2-alfresco-datatable && npm link ng2-alfresco-core && npm install && npm link && cd ../../) + - IF %COMPONENT_NAME% EQU ng2-activiti-analytics (cd ng2-components/ng2-activiti-diagrams && npm link ng2-activiti-diagrams && npm install && npm link && cd ../../) - cd ng2-components/%COMPONENT_NAME% - IF %COMPONENT_NAME% NEQ ng2-alfresco-core (npm link ng2-alfresco-core) - IF %COMPONENT_NAME% EQU ng2-alfresco-documentlist (npm link ng2-alfresco-datatable) From 4a96561167629750c118785c65fd65546617fe63 Mon Sep 17 00:00:00 2001 From: Mario Romano Date: Mon, 14 Nov 2016 17:55:24 +0000 Subject: [PATCH 015/103] #1089 remove only master from appveyor --- appveyor.yml | 4 ---- 1 file changed, 4 deletions(-) diff --git a/appveyor.yml b/appveyor.yml index 5bac593a50..377c40aaf6 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -1,8 +1,4 @@ # Test against this version of Node.js -branches: - only: - - master - environment: nodejs_version: "5" From 8328863dabe991b3663d59a4c7e06a3fbbf3352d Mon Sep 17 00:00:00 2001 From: Mario Romano Date: Mon, 14 Nov 2016 18:02:47 +0000 Subject: [PATCH 016/103] #1089 check if folder exist --- appveyor.yml | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/appveyor.yml b/appveyor.yml index 377c40aaf6..50fa88df70 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -52,3 +52,21 @@ test_script: # Don't actually build. build: off + +cache: + - node_modules + - C:\projects\alfresco-ng2-components\ng2-components\ng2-activiti-form\node_modules + - C:\projects\alfresco-ng2-components\ng2-components\ng2-activiti-processlist\node_modules + - C:\projects\alfresco-ng2-components\ng2-components\ng2-activiti-tasklist\node_modules + - C:\projects\alfresco-ng2-components\ng2-components\ng2-alfresco-core\node_modules + - C:\projects\alfresco-ng2-components\ng2-components\ng2-alfresco-datatable\node_modules + - C:\projects\alfresco-ng2-components\ng2-components\ng2-alfresco-documentlist\node_modules + - C:\projects\alfresco-ng2-components\ng2-components\ng2-alfresco-login\node_modules + - C:\projects\alfresco-ng2-components\ng2-components\ng2-alfresco-search\node_modules + - C:\projects\alfresco-ng2-components\ng2-components\ng2-alfresco-upload\node_modules + - C:\projects\alfresco-ng2-components\ng2-components\ng2-alfresco-viewer\node_modules + - C:\projects\alfresco-ng2-components\ng2-components\ng2-alfresco-webscript\node_modules + - C:\projects\alfresco-ng2-components\ng2-components\ng2-alfresco-tag\node_modules + - C:\projects\alfresco-ng2-components\ng2-components\ng2-activiti-analytics\node_modules + - C:\projects\alfresco-ng2-components\ng2-components\ng2-alfresco-userinfo\node_modules + - C:\projects\alfresco-ng2-components\ng2-components\ng2-activiti-diagrams\node_modules From c8e5c07d7689de844f4ae3bb5bdce1512a689317 Mon Sep 17 00:00:00 2001 From: Vito Albano Date: Mon, 14 Nov 2016 18:33:51 +0000 Subject: [PATCH 017/103] Improved test coverage for dropdown --- .../widgets/dropdown/dropdown.widget.spec.ts | 169 +++++++++++++----- 1 file changed, 124 insertions(+), 45 deletions(-) diff --git a/ng2-components/ng2-activiti-form/src/components/widgets/dropdown/dropdown.widget.spec.ts b/ng2-components/ng2-activiti-form/src/components/widgets/dropdown/dropdown.widget.spec.ts index e160de0adf..97f58b2a03 100644 --- a/ng2-components/ng2-activiti-form/src/components/widgets/dropdown/dropdown.widget.spec.ts +++ b/ng2-components/ng2-activiti-form/src/components/widgets/dropdown/dropdown.widget.spec.ts @@ -111,7 +111,10 @@ describe('DropdownWidget', () => { let element: HTMLElement; let componentHandler; let stubFormService; - let fakeOptionList: FormFieldOption[] = [{ id: 'opt_1', name: 'option_1' }, { + let fakeOptionList: FormFieldOption[] = [{ + id: 'opt_1', + name: 'option_1' + }, { id: 'opt_2', name: 'option_2' }, { id: 'opt_3', name: 'option_3' }]; @@ -130,56 +133,132 @@ describe('DropdownWidget', () => { }); })); - beforeEach(async(() => { - stubFormService = fixture.debugElement.injector.get(FormService); - visibilityService = fixture.debugElement.injector.get(WidgetVisibilityService); - spyOn(visibilityService, 'refreshVisibility').and.stub(); - spyOn(stubFormService, 'getRestFieldValues').and.returnValue(Observable.of(fakeOptionList)); - dropDownWidget.field = new FormFieldModel(new FormModel({ taskId: 'fake-task-id' }), { - id: 'dropdown-id', - name: 'date-name', - type: 'dropdown', - readOnly: 'false', - restUrl: 'fake-rest-url' - }); - dropDownWidget.field.isVisible = true; - fixture.detectChanges(); - })); + describe('and dropdown is populated via taskId', () => { - afterEach(() => { - fixture.destroy(); - TestBed.resetTestingModule(); + beforeEach(async(() => { + stubFormService = fixture.debugElement.injector.get(FormService); + visibilityService = fixture.debugElement.injector.get(WidgetVisibilityService); + spyOn(visibilityService, 'refreshVisibility').and.stub(); + spyOn(stubFormService, 'getRestFieldValues').and.returnValue(Observable.of(fakeOptionList)); + dropDownWidget.field = new FormFieldModel(new FormModel({ taskId: 'fake-task-id' }), { + id: 'dropdown-id', + name: 'date-name', + type: 'dropdown', + readOnly: 'false', + restUrl: 'fake-rest-url' + }); + dropDownWidget.field.emptyOption = { id: 'empty', name: 'Choose one...' }; + dropDownWidget.field.isVisible = true; + fixture.detectChanges(); + })); + + it('should show visible dropdown widget', async(() => { + expect(element.querySelector('#dropdown-id')).toBeDefined(); + expect(element.querySelector('#dropdown-id')).not.toBeNull(); + expect(element.querySelector('#opt_1')).not.toBeNull(); + expect(element.querySelector('#opt_2')).not.toBeNull(); + expect(element.querySelector('#opt_3')).not.toBeNull(); + })); + + it('should select the default value when an option is chosen as default', async(() => { + dropDownWidget.field.value = 'option_2'; + fixture.detectChanges(); + fixture.whenStable() + .then(() => { + let dropDownElement: HTMLSelectElement = element.querySelector('#dropdown-id'); + expect(dropDownElement).not.toBeNull(); + expect(element.querySelector('#opt_2')).not.toBeNull(); + expect(dropDownElement.value).toBe('option_2'); + expect(dropDownElement.selectedOptions[0].textContent).toBe('option_2'); + }); + })); + + it('should select the empty value when no default is chosen', async(() => { + dropDownWidget.field.value = 'empty'; + fixture.detectChanges(); + fixture.whenStable() + .then(() => { + let dropDownElement: HTMLSelectElement = element.querySelector('#dropdown-id'); + expect(dropDownElement).not.toBeNull(); + expect(dropDownElement.value).toBe('empty'); + expect(dropDownElement.selectedOptions[0].textContent).toBe('Choose one...'); + }); + })); + + it('should be not visibile when isVisible is false', async(() => { + dropDownWidget.field.isVisible = false; + fixture.detectChanges(); + fixture.whenStable() + .then(() => { + let dropDownElement: HTMLSelectElement = element.querySelector('#dropdown-id'); + expect(dropDownElement).toBeNull(); + }); + })); + + it('should became visibile when isVisible is true', async(() => { + dropDownWidget.field.isVisible = false; + fixture.detectChanges(); + expect(element.querySelector('#dropdown-id')).toBeNull(); + dropDownWidget.field.isVisible = true; + fixture.detectChanges(); + fixture.whenStable() + .then(() => { + expect(element.querySelector('#dropdown-id')).not.toBeNull(); + }); + })); }); - it('should show visible dropdown widget', async(() => { - expect(element.querySelector('#dropdown-id')).toBeDefined(); - expect(element.querySelector('#dropdown-id')).not.toBeNull(); - expect(element.querySelector('#opt_1')).not.toBeNull(); - expect(element.querySelector('#opt_2')).not.toBeNull(); - expect(element.querySelector('#opt_3')).not.toBeNull(); - })); + describe('and dropdown is populated via processDefinitionId', () => { - it('should select the default value', async(() => { - dropDownWidget.field.value = 'option_2'; - fixture.detectChanges(); - fixture.whenStable() - .then(() => { - let dropDownElement: HTMLSelectElement = element.querySelector('#dropdown-id'); - expect(dropDownElement).not.toBeNull(); - expect(element.querySelector('#opt_2')).not.toBeNull(); - expect(dropDownElement.value).toBe('option_2'); + beforeEach(async(() => { + stubFormService = fixture.debugElement.injector.get(FormService); + visibilityService = fixture.debugElement.injector.get(WidgetVisibilityService); + spyOn(visibilityService, 'refreshVisibility').and.stub(); + spyOn(stubFormService, 'getRestFieldValuesByProcessId').and.returnValue(Observable.of(fakeOptionList)); + dropDownWidget.field = new FormFieldModel(new FormModel({ processDefinitionId: 'fake-process-id' }), { + id: 'dropdown-id', + name: 'date-name', + type: 'dropdown', + readOnly: 'false', + restUrl: 'fake-rest-url' }); - })); + dropDownWidget.field.emptyOption = { id: 'empty', name: 'Choose one...' }; + dropDownWidget.field.isVisible = true; + fixture.detectChanges(); + })); - it('should be not visibile when isVisible is false', async(() => { - dropDownWidget.field.isVisible = false; - fixture.detectChanges(); - fixture.whenStable() - .then(() => { - let dropDownElement: HTMLSelectElement = element.querySelector('#dropdown-id'); - expect(dropDownElement).toBeNull(); - }); - })); + it('should show visible dropdown widget', async(() => { + expect(element.querySelector('#dropdown-id')).toBeDefined(); + expect(element.querySelector('#dropdown-id')).not.toBeNull(); + expect(element.querySelector('#opt_1')).not.toBeNull(); + expect(element.querySelector('#opt_2')).not.toBeNull(); + expect(element.querySelector('#opt_3')).not.toBeNull(); + })); + it('should select the default value when an option is chosen as default', async(() => { + dropDownWidget.field.value = 'option_2'; + fixture.detectChanges(); + fixture.whenStable() + .then(() => { + let dropDownElement: HTMLSelectElement = element.querySelector('#dropdown-id'); + expect(dropDownElement).not.toBeNull(); + expect(element.querySelector('#opt_2')).not.toBeNull(); + expect(dropDownElement.value).toBe('option_2'); + expect(dropDownElement.selectedOptions[0].textContent).toBe('option_2'); + }); + })); + + it('should select the empty value when no default is chosen', async(() => { + dropDownWidget.field.value = 'empty'; + fixture.detectChanges(); + fixture.whenStable() + .then(() => { + let dropDownElement: HTMLSelectElement = element.querySelector('#dropdown-id'); + expect(dropDownElement).not.toBeNull(); + expect(dropDownElement.value).toBe('empty'); + expect(dropDownElement.selectedOptions[0].textContent).toBe('Choose one...'); + }); + })); + }); }); }); From f49902c3de8a5d9731237323895dec6d955f5f0d Mon Sep 17 00:00:00 2001 From: Will Abson Date: Fri, 11 Nov 2016 09:57:28 +0000 Subject: [PATCH 018/103] Externalise processlist styles Refs #849 --- .../src/components/activiti-processlist.component.css | 3 +++ .../src/components/activiti-processlist.component.ts | 8 +------- 2 files changed, 4 insertions(+), 7 deletions(-) create mode 100644 ng2-components/ng2-activiti-processlist/src/components/activiti-processlist.component.css diff --git a/ng2-components/ng2-activiti-processlist/src/components/activiti-processlist.component.css b/ng2-components/ng2-activiti-processlist/src/components/activiti-processlist.component.css new file mode 100644 index 0000000000..c2742d1471 --- /dev/null +++ b/ng2-components/ng2-activiti-processlist/src/components/activiti-processlist.component.css @@ -0,0 +1,3 @@ +:host h1 { + font-size:22px +} diff --git a/ng2-components/ng2-activiti-processlist/src/components/activiti-processlist.component.ts b/ng2-components/ng2-activiti-processlist/src/components/activiti-processlist.component.ts index 5d7836cf22..d100a2d422 100644 --- a/ng2-components/ng2-activiti-processlist/src/components/activiti-processlist.component.ts +++ b/ng2-components/ng2-activiti-processlist/src/components/activiti-processlist.component.ts @@ -24,13 +24,7 @@ import { ActivitiProcessService } from '../services/activiti-process.service'; @Component({ moduleId: module.id, selector: 'activiti-process-instance-list', - styles: [ - ` - :host h1 { - font-size:22px - } - ` - ], + styleUrls: [ './activiti-processlist.component.css' ], templateUrl: './activiti-processlist.component.html' }) export class ActivitiProcessInstanceListComponent implements OnInit, OnChanges { From 7fa92e250db033cdf241ede42706531fad6a64c2 Mon Sep 17 00:00:00 2001 From: Will Abson Date: Fri, 11 Nov 2016 09:59:12 +0000 Subject: [PATCH 019/103] Add processlist tests Refs #849 --- .../activiti-processlist.component.spec.ts | 100 ++++++++++++++++++ .../activiti-processlist.component.ts | 2 +- 2 files changed, 101 insertions(+), 1 deletion(-) create mode 100644 ng2-components/ng2-activiti-processlist/src/components/activiti-processlist.component.spec.ts diff --git a/ng2-components/ng2-activiti-processlist/src/components/activiti-processlist.component.spec.ts b/ng2-components/ng2-activiti-processlist/src/components/activiti-processlist.component.spec.ts new file mode 100644 index 0000000000..d67e13acbe --- /dev/null +++ b/ng2-components/ng2-activiti-processlist/src/components/activiti-processlist.component.spec.ts @@ -0,0 +1,100 @@ +/*! + * @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 { DebugElement, SimpleChange } from '@angular/core'; +import { ComponentFixture, TestBed, async } from '@angular/core/testing'; +import { Observable } from 'rxjs/Rx'; +import { ActivitiProcessInstanceListComponent } from './activiti-processlist.component'; +import { TranslationMock } from './../assets/translation.service.mock'; +import { FilterRepresentationModel } from 'ng2-activiti-tasklist'; +import { ActivitiProcessService } from '../services/activiti-process.service'; +import { AlfrescoTranslationService, CoreModule } from 'ng2-alfresco-core'; +import { DataTableModule } from 'ng2-alfresco-datatable'; + +describe('ActivitiProcessInstanceListComponent', () => { + + let fixture: ComponentFixture; + let component: ActivitiProcessInstanceListComponent; + let element: DebugElement; + let service: ActivitiProcessService; + + let mockFilter = new FilterRepresentationModel({ + appId: '1', + filter: { + name: '', + state: '', + sort: '' + } + }); + + beforeEach(async(() => { + TestBed.configureTestingModule({ + imports: [ + CoreModule, + DataTableModule + ], + declarations: [ ActivitiProcessInstanceListComponent ], // declare the test component + providers: [ + ActivitiProcessService, + {provide: AlfrescoTranslationService, useClass: TranslationMock} + ] + }).compileComponents().then(() => { + fixture = TestBed.createComponent(ActivitiProcessInstanceListComponent); + component = fixture.componentInstance; + element = fixture.debugElement; + service = element.injector.get(ActivitiProcessService); + }); + })); + + it('should initialise data table', () => { + fixture.detectChanges(); + }); + + it('should fetch process instances when a filter is provided', () => { + let getProcessInstancesSpy = spyOn(service, 'getProcessInstances').and.returnValue(Observable.of([])); + component.filter = mockFilter; + fixture.detectChanges(); + expect(getProcessInstancesSpy).toHaveBeenCalled(); + }); + + it('should NOT fetch process instances if filter not provided', () => { + let getProcessInstancesSpy = spyOn(service, 'getProcessInstances').and.returnValue(Observable.of([])); + fixture.detectChanges(); + expect(getProcessInstancesSpy).not.toHaveBeenCalled(); + }); + + describe('component changes', () => { + + it('should fetch new process instances when filter changed', () => { + component.filter = new FilterRepresentationModel({}); + fixture.detectChanges(); + let getProcessInstancesSpy = spyOn(service, 'getProcessInstances').and.returnValue(Observable.of([])); + component.ngOnChanges({ filter: new SimpleChange(mockFilter, mockFilter) }); + expect(getProcessInstancesSpy).toHaveBeenCalled(); + }); + + it('should NOT fetch new process instances when properties apart from filter changed', () => { + component.filter = mockFilter; + fixture.detectChanges(); + let getProcessInstancesSpy = spyOn(service, 'getProcessInstances').and.returnValue(Observable.of([])); + component.ngOnChanges({}); + expect(getProcessInstancesSpy).not.toHaveBeenCalled(); + }); + + }); + +}); diff --git a/ng2-components/ng2-activiti-processlist/src/components/activiti-processlist.component.ts b/ng2-components/ng2-activiti-processlist/src/components/activiti-processlist.component.ts index d100a2d422..958e677bff 100644 --- a/ng2-components/ng2-activiti-processlist/src/components/activiti-processlist.component.ts +++ b/ng2-components/ng2-activiti-processlist/src/components/activiti-processlist.component.ts @@ -87,7 +87,7 @@ export class ActivitiProcessInstanceListComponent implements OnInit, OnChanges { ); } - load(requestNode: TaskQueryRequestRepresentationModel) { + private load(requestNode: TaskQueryRequestRepresentationModel) { this.processService.getProcessInstances(requestNode) .subscribe( (processInstances) => { From 5f60760cd5cd5748af5f4249581e76237c6c7513 Mon Sep 17 00:00:00 2001 From: Will Abson Date: Fri, 11 Nov 2016 17:24:10 +0000 Subject: [PATCH 020/103] New tests for processlist components Refs #849 --- .../data/processlist-datatable-adapter.ts | 123 ----------- .../ng2-activiti-processlist/karma.conf.js | 2 +- .../src/assets/activiti-process.model.mock.ts | 19 +- .../src/assets/task-details.mock.ts | 192 ++++++++++++++++ .../activiti-comments.component.html | 2 +- .../activiti-comments.component.spec.ts | 191 ++++++++++++++++ .../components/activiti-comments.component.ts | 44 ++-- .../activiti-filters.component.spec.ts | 160 ++++++++++++++ ...ti-process-instance-details.component.html | 4 + ...process-instance-details.component.spec.ts | 165 ++++++++++++++ ...viti-process-instance-details.component.ts | 5 +- ...iti-process-instance-header.component.html | 14 +- ...-process-instance-header.component.spec.ts | 108 +++++++++ ...iviti-process-instance-header.component.ts | 6 +- ...viti-process-instance-tasks.component.html | 8 +- ...i-process-instance-tasks.component.spec.ts | 206 ++++++++++++++++++ ...tiviti-process-instance-tasks.component.ts | 6 +- .../activiti-processlist.component.spec.ts | 20 +- .../src/components/placeholder.spec.ts | 22 -- .../ng2-activiti-processlist/src/i18n/en.json | 1 + .../src/models/process-instance.ts | 21 ++ 21 files changed, 1138 insertions(+), 181 deletions(-) delete mode 100644 ng2-components/ng2-activiti-processlist/data/processlist-datatable-adapter.ts create mode 100644 ng2-components/ng2-activiti-processlist/src/assets/task-details.mock.ts create mode 100644 ng2-components/ng2-activiti-processlist/src/components/activiti-comments.component.spec.ts create mode 100644 ng2-components/ng2-activiti-processlist/src/components/activiti-filters.component.spec.ts create mode 100644 ng2-components/ng2-activiti-processlist/src/components/activiti-process-instance-details.component.spec.ts create mode 100644 ng2-components/ng2-activiti-processlist/src/components/activiti-process-instance-header.component.spec.ts create mode 100644 ng2-components/ng2-activiti-processlist/src/components/activiti-process-instance-tasks.component.spec.ts delete mode 100644 ng2-components/ng2-activiti-processlist/src/components/placeholder.spec.ts diff --git a/ng2-components/ng2-activiti-processlist/data/processlist-datatable-adapter.ts b/ng2-components/ng2-activiti-processlist/data/processlist-datatable-adapter.ts deleted file mode 100644 index 521fc7bab1..0000000000 --- a/ng2-components/ng2-activiti-processlist/data/processlist-datatable-adapter.ts +++ /dev/null @@ -1,123 +0,0 @@ -/*! - * @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 { DatePipe } from '@angular/common'; -import { - DataTableAdapter, ObjectDataTableAdapter, ObjectDataColumn, - DataRow, DataColumn, DataSorting -} from 'ng2-alfresco-datatable'; - -export class ProcessListDataTableAdapter extends ObjectDataTableAdapter implements DataTableAdapter { - - ERR_ROW_NOT_FOUND: string = 'Row not found'; - ERR_COL_NOT_FOUND: string = 'Column not found'; - - DEFAULT_DATE_FORMAT: string = 'medium'; - - private sorting: DataSorting; - private rows: DataRow[]; - private columns: DataColumn[]; - - constructor(rows: any, schema: DataColumn[]) { - super(rows, schema); - this.rows = rows; - this.columns = schema || []; - } - - getRows(): Array { - return this.rows; - } - - // TODO: disable this api - setRows(rows: Array) { - this.rows = rows || []; - this.sort(); - } - - getColumns(): Array { - return this.columns; - } - - setColumns(columns: Array) { - this.columns = columns || []; - } - - getValue(row: DataRow, col: DataColumn): any { - if (!row) { - throw new Error(this.ERR_ROW_NOT_FOUND); - } - if (!col) { - throw new Error(this.ERR_COL_NOT_FOUND); - } - let value = row.getValue(col.key); - - if (col.type === 'date') { - let datePipe = new DatePipe('en-US'); - let format = ((col)).format || this.DEFAULT_DATE_FORMAT; - try { - return datePipe.transform(value, format); - } catch (err) { - console.error(`Error parsing date ${value} to format ${format}`); - } - } - - return value; - } - - getSorting(): DataSorting { - return this.sorting; - } - - setSorting(sorting: DataSorting): void { - this.sorting = sorting; - - if (sorting && sorting.key && this.rows && this.rows.length > 0) { - this.rows.sort((a: DataRow, b: DataRow) => { - let left = a.getValue(sorting.key); - if (left) { - left = (left instanceof Date) ? left.valueOf().toString() : left.toString(); - } else { - left = ''; - } - - let right = b.getValue(sorting.key); - if (right) { - right = (right instanceof Date) ? right.valueOf().toString() : right.toString(); - } else { - right = ''; - } - - return sorting.direction === 'asc' - ? left.localeCompare(right) - : right.localeCompare(left); - }); - } - } - - sort(key?: string, direction?: string): void { - let sorting = this.sorting || new DataSorting(); - if (key) { - sorting.key = key; - sorting.direction = direction || 'asc'; - } - this.setSorting(sorting); - } -} - -export class ActivitiDataColumn extends ObjectDataColumn { - format: string; -} diff --git a/ng2-components/ng2-activiti-processlist/karma.conf.js b/ng2-components/ng2-activiti-processlist/karma.conf.js index 3eb9845474..c97ec7d13f 100644 --- a/ng2-components/ng2-activiti-processlist/karma.conf.js +++ b/ng2-components/ng2-activiti-processlist/karma.conf.js @@ -45,7 +45,7 @@ module.exports = function (config) { // ng2-components { pattern: 'node_modules/ng2-alfresco-core/dist/**/*.*', included: false, served: true, watched: false }, { pattern: 'node_modules/ng2-alfresco-datatable/dist/**/*.*', included: false, served: true, watched: false }, - { pattern: 'node_modules/ng2-activiti-tasklist/dist/**/*.js', included: false, served: true, watched: false }, + { pattern: 'node_modules/ng2-activiti-tasklist/dist/**/*.*', included: false, served: true, watched: false }, { pattern: 'node_modules/ng2-activiti-form/dist/**/*.*', included: false, served: true, watched: false }, // paths to support debugging with source maps in dev tools diff --git a/ng2-components/ng2-activiti-processlist/src/assets/activiti-process.model.mock.ts b/ng2-components/ng2-activiti-processlist/src/assets/activiti-process.model.mock.ts index 6eba34a88e..909d2ea6ef 100644 --- a/ng2-components/ng2-activiti-processlist/src/assets/activiti-process.model.mock.ts +++ b/ng2-components/ng2-activiti-processlist/src/assets/activiti-process.model.mock.ts @@ -31,9 +31,22 @@ export class ProcessList { export class SingleProcessList extends ProcessList { constructor(name?: string) { - let instance = new ProcessInstance(); - instance.id = '123'; - instance.name = name; + let instance = new ProcessInstance({ + id: '123', + name: name + }); super([instance]); } } + +export var exampleProcess = new ProcessInstance({ + id: '123', + name: 'Process 123', + started: '2016-11-10T03:37:30.010+0000', + startedBy: { + id: 1001, + firstName: 'Bob', + lastName: 'Jones', + email: 'bob@app.activiti.com' + } +}); diff --git a/ng2-components/ng2-activiti-processlist/src/assets/task-details.mock.ts b/ng2-components/ng2-activiti-processlist/src/assets/task-details.mock.ts new file mode 100644 index 0000000000..ef07e36a07 --- /dev/null +++ b/ng2-components/ng2-activiti-processlist/src/assets/task-details.mock.ts @@ -0,0 +1,192 @@ +/*! + * @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 var taskDetailsMock = { + 'id': '91', + 'name': 'Request translation', + 'description': null, + 'category': null, + 'assignee': {'id': 1001, 'firstName': 'Wilbur', 'lastName': 'Adams', 'email': 'wilbur@app.activiti.com'}, + 'created': '2016-11-03T15:25:42.749+0000', + 'dueDate': null, + 'endDate': null, + 'duration': null, + 'priority': 50, + 'parentTaskId': null, + 'parentTaskName': null, + 'processInstanceId': '86', + 'processInstanceName': null, + 'processDefinitionId': 'TranslationProcess:2:8', + 'processDefinitionName': 'Translation Process', + 'processDefinitionDescription': null, + 'processDefinitionKey': 'TranslationProcess', + 'processDefinitionCategory': 'http://www.activiti.org/processdef', + 'processDefinitionVersion': 2, + 'processDefinitionDeploymentId': '5', + 'formKey': '4', + 'processInstanceStartUserId': '1001', + 'initiatorCanCompleteTask': false, + 'adhocTaskCanBeReassigned': false, + 'taskDefinitionKey': 'sid-DDECD9E4-0299-433F-9193-C3D905C3EEBE', + 'executionId': '86', + 'involvedPeople': [], + 'memberOfCandidateUsers': false, + 'managerOfCandidateGroup': false, + 'memberOfCandidateGroup': false +}; + +export var taskFormMock = { + 'id': 4, + 'name': 'Translation request', + 'processDefinitionId': 'TranslationProcess:2:8', + 'processDefinitionName': 'Translation Process', + 'processDefinitionKey': 'TranslationProcess', + 'taskId': '91', + 'taskName': 'Request translation', + 'taskDefinitionKey': 'sid-DDECD9E4-0299-433F-9193-C3D905C3EEBE', + 'tabs': [], + 'fields': [{ + 'fieldType': 'ContainerRepresentation', + 'id': '1478093984155', + 'name': 'Label', + 'type': 'container', + 'value': null, + 'required': false, + 'readOnly': false, + 'overrideId': false, + 'colspan': 1, + 'placeholder': null, + 'minLength': 0, + 'maxLength': 0, + 'minValue': null, + 'maxValue': null, + 'regexPattern': null, + 'optionType': null, + 'hasEmptyValue': null, + 'options': null, + 'restUrl': null, + 'restResponsePath': null, + 'restIdProperty': null, + 'restLabelProperty': null, + 'tab': null, + 'className': null, + 'dateDisplayFormat': null, + 'layout': null, + 'sizeX': 2, + 'sizeY': 1, + 'row': -1, + 'col': -1, + 'visibilityCondition': null, + 'numberOfColumns': 2, + 'fields': { + '1': [{ + 'fieldType': 'AttachFileFieldRepresentation', + 'id': 'originalcontent', + 'name': 'Original content', + 'type': 'upload', + 'value': [], + 'required': true, + 'readOnly': false, + 'overrideId': false, + 'colspan': 1, + 'placeholder': null, + 'minLength': 0, + 'maxLength': 0, + 'minValue': null, + 'maxValue': null, + 'regexPattern': null, + 'optionType': null, + 'hasEmptyValue': null, + 'options': null, + 'restUrl': null, + 'restResponsePath': null, + 'restIdProperty': null, + 'restLabelProperty': null, + 'tab': null, + 'className': null, + 'params': { + }, + 'dateDisplayFormat': null, + 'layout': {'row': -1, 'column': -1, 'colspan': 1}, + 'sizeX': 1, + 'sizeY': 1, + 'row': -1, + 'col': -1, + 'visibilityCondition': null, + 'metaDataColumnDefinitions': [] + }], + '2': [{ + 'fieldType': 'RestFieldRepresentation', + 'id': 'language', + 'name': 'Language', + 'type': 'dropdown', + 'value': 'Choose one...', + 'required': true, + 'readOnly': false, + 'overrideId': false, + 'colspan': 1, + 'placeholder': null, + 'minLength': 0, + 'maxLength': 0, + 'minValue': null, + 'maxValue': null, + 'regexPattern': null, + 'optionType': null, + 'hasEmptyValue': true, + 'options': [{'id': 'empty', 'name': 'Choose one...'}, {'id': 'fr', 'name': 'French'}, { + 'id': 'de', + 'name': 'German' + }, {'id': 'es', 'name': 'Spanish'}], + 'restUrl': null, + 'restResponsePath': null, + 'restIdProperty': null, + 'restLabelProperty': null, + 'tab': null, + 'className': null, + 'params': {'existingColspan': 1, 'maxColspan': 1}, + 'dateDisplayFormat': null, + 'layout': {'row': -1, 'column': -1, 'colspan': 1}, + 'sizeX': 1, + 'sizeY': 1, + 'row': -1, + 'col': -1, + 'visibilityCondition': null, + 'endpoint': null, + 'requestHeaders': null + }] + } + }], + 'outcomes': [], + 'javascriptEvents': [], + 'className': '', + 'style': '', + 'customFieldTemplates': {}, + 'metadata': {}, + 'variables': [], + 'gridsterForm': false, + 'globalDateFormat': 'D-M-YYYY' +}; + +export var tasksMock = { + data: [ + taskDetailsMock + ] +}; + +export var noDataMock = { + data: [] +}; diff --git a/ng2-components/ng2-activiti-processlist/src/components/activiti-comments.component.html b/ng2-components/ng2-activiti-processlist/src/components/activiti-comments.component.html index 169719612e..c24ffd50ce 100644 --- a/ng2-components/ng2-activiti-processlist/src/components/activiti-comments.component.html +++ b/ng2-components/ng2-activiti-processlist/src/components/activiti-comments.component.html @@ -15,7 +15,7 @@
-
+
{{ 'DETAILS.COMMENTS.NONE' | translate }}
diff --git a/ng2-components/ng2-activiti-processlist/src/components/activiti-comments.component.spec.ts b/ng2-components/ng2-activiti-processlist/src/components/activiti-comments.component.spec.ts new file mode 100644 index 0000000000..80332649b0 --- /dev/null +++ b/ng2-components/ng2-activiti-processlist/src/components/activiti-comments.component.spec.ts @@ -0,0 +1,191 @@ +/*! + * @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 { SimpleChange } from '@angular/core'; +import { ComponentFixture, TestBed, async } from '@angular/core/testing'; +import { By } from '@angular/platform-browser'; +import { Observable } from 'rxjs/Rx'; + +import { AlfrescoTranslationService, CoreModule } from 'ng2-alfresco-core'; +import { ActivitiFormModule } from 'ng2-activiti-form'; + +import { ActivitiComments } from './activiti-comments.component'; +import { ActivitiProcessService } from './../services/activiti-process.service'; +import { TranslationMock } from './../assets/translation.service.mock'; + +describe('ActivitiProcessInstanceComments', () => { + + let componentHandler: any; + let service: ActivitiProcessService; + let component: ActivitiComments; + let fixture: ComponentFixture; + let getCommentsSpy: jasmine.Spy; + let addCommentSpy: jasmine.Spy; + + beforeEach(async(() => { + TestBed.configureTestingModule({ + imports: [ + CoreModule, + ActivitiFormModule + ], + declarations: [ + ActivitiComments + ], + providers: [ + { provide: AlfrescoTranslationService, useClass: TranslationMock }, + ActivitiProcessService + ] + }).compileComponents(); + })); + + beforeEach(() => { + + fixture = TestBed.createComponent(ActivitiComments); + component = fixture.componentInstance; + service = fixture.debugElement.injector.get(ActivitiProcessService); + + getCommentsSpy = spyOn(service, 'getProcessInstanceComments').and.returnValue(Observable.of([{ + message: 'Test1' + }, { + message: 'Test2' + }, { + message: 'Test3' + }])); + addCommentSpy = spyOn(service, 'addProcessInstanceComment').and.returnValue(Observable.of({id: 123, message: 'Test'})); + + componentHandler = jasmine.createSpyObj('componentHandler', [ + 'upgradeAllRegistered', + 'upgradeElement' + ]); + window['componentHandler'] = componentHandler; + }); + + it('should load comments when processInstanceId specified', () => { + component.processInstanceId = '123'; + fixture.detectChanges(); + expect(getCommentsSpy).toHaveBeenCalled(); + }); + + it('should emit an error when an error occurs loading comments', () => { + let emitSpy = spyOn(component.error, 'emit'); + getCommentsSpy.and.returnValue(Observable.throw({})); + component.processInstanceId = '123'; + fixture.detectChanges(); + expect(emitSpy).toHaveBeenCalled(); + }); + + it('should not comments when no processInstanceId is specified', () => { + fixture.detectChanges(); + expect(getCommentsSpy).not.toHaveBeenCalled(); + }); + + it('should display comments when the process has comments', async(() => { + component.processInstanceId = '123'; + fixture.detectChanges(); + fixture.whenStable().then(() => { + fixture.detectChanges(); + expect(fixture.debugElement.queryAll(By.css('ul.mdl-list li')).length).toBe(3); + }); + })); + + it('should not display comments when the process has no comments', async(() => { + component.processInstanceId = '123'; + getCommentsSpy.and.returnValue(Observable.of([])); + fixture.detectChanges(); + fixture.whenStable().then(() => { + fixture.detectChanges(); + expect(fixture.debugElement.queryAll(By.css('ul.mdl-list li')).length).toBe(0); + }); + })); + + describe('change detection', () => { + + let change = new SimpleChange('123', '456'); + let nullChange = new SimpleChange('123', null); + + beforeEach(async(() => { + component.processInstanceId = '123'; + fixture.detectChanges(); + fixture.whenStable().then(() => { + getCommentsSpy.calls.reset(); + }); + })); + + it('should fetch new comments when processInstanceId changed', () => { + component.ngOnChanges({ 'processInstanceId': change }); + expect(getCommentsSpy).toHaveBeenCalledWith('456'); + }); + + it('should NOT fetch new comments when empty changeset made', () => { + component.ngOnChanges({}); + expect(getCommentsSpy).not.toHaveBeenCalled(); + }); + + it('should NOT fetch new comments when processInstanceId changed to null', () => { + component.ngOnChanges({ 'processInstanceId': nullChange }); + expect(getCommentsSpy).not.toHaveBeenCalled(); + }); + + it('should set a placeholder message when processInstanceId changed to null', () => { + component.ngOnChanges({ 'processInstanceId': nullChange }); + fixture.detectChanges(); + expect(fixture.debugElement.query(By.css('[data-automation-id="comments-none"]'))).not.toBeNull(); + }); + }); + + describe('Add comment', () => { + + beforeEach(async(() => { + component.processInstanceId = '123'; + fixture.detectChanges(); + fixture.whenStable(); + })); + + it('should display a dialog to the user when the Add button clicked', () => { + let dialogEl = fixture.debugElement.query(By.css('.mdl-dialog')).nativeElement; + let showSpy: jasmine.Spy = spyOn(dialogEl, 'showModal'); + component.showDialog(); + expect(showSpy).toHaveBeenCalled(); + }); + + it('should call service to add a comment', () => { + component.showDialog(); + component.message = 'Test comment'; + component.add(); + expect(addCommentSpy).toHaveBeenCalledWith('123', 'Test comment'); + }); + + it('should emit an error when an error occurs adding the comment', () => { + let emitSpy = spyOn(component.error, 'emit'); + addCommentSpy.and.returnValue(Observable.throw({})); + component.showDialog(); + component.message = 'Test comment'; + component.add(); + expect(emitSpy).toHaveBeenCalled(); + }); + + it('should close add dialog when close button clicked', () => { + let dialogEl = fixture.debugElement.query(By.css('.mdl-dialog')).nativeElement; + let closeSpy: jasmine.Spy = spyOn(dialogEl, 'close'); + component.showDialog(); + component.cancel(); + expect(closeSpy).toHaveBeenCalled(); + }); + + }); + +}); diff --git a/ng2-components/ng2-activiti-processlist/src/components/activiti-comments.component.ts b/ng2-components/ng2-activiti-processlist/src/components/activiti-comments.component.ts index 29683e609a..50b38fdc48 100644 --- a/ng2-components/ng2-activiti-processlist/src/components/activiti-comments.component.ts +++ b/ng2-components/ng2-activiti-processlist/src/components/activiti-comments.component.ts @@ -15,7 +15,7 @@ * limitations under the License. */ -import { Component, Input, OnInit, ViewChild, OnChanges, SimpleChanges } from '@angular/core'; +import { Component, EventEmitter, Input, Output, OnInit, ViewChild, OnChanges, SimpleChanges } from '@angular/core'; import { AlfrescoTranslationService } from 'ng2-alfresco-core'; import { ActivitiProcessService } from './../services/activiti-process.service'; import { Comment } from 'ng2-activiti-tasklist'; @@ -23,6 +23,7 @@ import { Observer } from 'rxjs/Observer'; import { Observable } from 'rxjs/Observable'; declare let componentHandler: any; +declare let dialogPolyfill: any; @Component({ selector: 'activiti-process-instance-comments', @@ -36,6 +37,9 @@ export class ActivitiComments implements OnInit, OnChanges { @Input() processInstanceId: string; + @Output() + error: EventEmitter = new EventEmitter(); + @ViewChild('dialog') dialog: any; @@ -48,8 +52,8 @@ export class ActivitiComments implements OnInit, OnChanges { /** * Constructor - * @param auth - * @param translate + * @param translate Translation service + * @param activitiProcess Process service */ constructor(private translate: AlfrescoTranslationService, private activitiProcess: ActivitiProcessService) { @@ -66,17 +70,24 @@ export class ActivitiComments implements OnInit, OnChanges { this.comment$.subscribe((comment: Comment) => { this.comments.push(comment); }); - } - - ngOnChanges(changes: SimpleChanges) { - let processInstanceId = changes['processInstanceId']; - if (processInstanceId && processInstanceId.currentValue) { - this.getProcessComments(processInstanceId.currentValue); + if (this.processInstanceId) { + this.getProcessComments(this.processInstanceId); return; } } - public getProcessComments(processInstanceId: string) { + ngOnChanges(changes: SimpleChanges) { + let processInstanceId = changes['processInstanceId']; + if (processInstanceId) { + if (processInstanceId.currentValue) { + this.getProcessComments(processInstanceId.currentValue); + } else { + this.resetComments(); + } + } + } + + private getProcessComments(processInstanceId: string) { this.comments = []; if (processInstanceId) { this.activitiProcess.getProcessInstanceComments(processInstanceId).subscribe( @@ -86,15 +97,22 @@ export class ActivitiComments implements OnInit, OnChanges { }); }, (err) => { - console.log(err); + this.error.emit(err); } ); } else { - this.comments = []; + this.resetComments(); } } + private resetComments() { + this.comments = []; + } + public showDialog() { + if (!this.dialog.nativeElement.showModal) { + dialogPolyfill.registerDialog(this.dialog.nativeElement); + } if (this.dialog) { this.dialog.nativeElement.showModal(); } @@ -107,7 +125,7 @@ export class ActivitiComments implements OnInit, OnChanges { this.message = ''; }, (err) => { - console.log(err); + this.error.emit(err); } ); this.cancel(); diff --git a/ng2-components/ng2-activiti-processlist/src/components/activiti-filters.component.spec.ts b/ng2-components/ng2-activiti-processlist/src/components/activiti-filters.component.spec.ts new file mode 100644 index 0000000000..cbbb5adefe --- /dev/null +++ b/ng2-components/ng2-activiti-processlist/src/components/activiti-filters.component.spec.ts @@ -0,0 +1,160 @@ +/*! + * @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 { SimpleChange } from '@angular/core'; +import { ActivitiProcessFilters } from './activiti-filters.component'; +import { ActivitiProcessService } from '../services/activiti-process.service'; +import { Observable } from 'rxjs/Rx'; +import { FilterRepresentationModel } from 'ng2-activiti-tasklist'; + +describe('ActivitiFilters', () => { + + let filterList: ActivitiProcessFilters; + let activitiService: ActivitiProcessService; + + let fakeGlobalFilter = []; + fakeGlobalFilter.push(new FilterRepresentationModel({name: 'FakeInvolvedTasks', filter: { state: 'open', assignment: 'fake-involved'}})); + fakeGlobalFilter.push(new FilterRepresentationModel({name: 'FakeMyTasks', filter: { state: 'open', assignment: 'fake-assignee'}})); + + let fakeGlobalFilterPromise = new Promise(function (resolve, reject) { + resolve(fakeGlobalFilter); + }); + + let fakeErrorFilterList = { + error: 'wrong request' + }; + + let fakeErrorFilterPromise = new Promise(function (resolve, reject) { + reject(fakeErrorFilterList); + }); + + beforeEach(() => { + activitiService = new ActivitiProcessService(null); + filterList = new ActivitiProcessFilters(null, activitiService); + }); + + it('should return the filter task list', (done) => { + spyOn(activitiService, 'getProcessFilters').and.returnValue(Observable.fromPromise(fakeGlobalFilterPromise)); + + filterList.onSuccess.subscribe((res) => { + expect(res).toBeDefined(); + expect(filterList.filters).toBeDefined(); + expect(filterList.filters.length).toEqual(2); + expect(filterList.filters[0].name).toEqual('FakeInvolvedTasks'); + expect(filterList.filters[1].name).toEqual('FakeMyTasks'); + done(); + }); + + filterList.ngOnInit(); + }); + + it('should return the filter task list, filtered By Name', (done) => { + + let fakeDeployedApplicationsPromise = new Promise(function (resolve, reject) { + resolve({}); + }); + + spyOn(activitiService, 'getDeployedApplications').and.returnValue(Observable.fromPromise(fakeDeployedApplicationsPromise)); + spyOn(activitiService, 'getProcessFilters').and.returnValue(Observable.fromPromise(fakeGlobalFilterPromise)); + + filterList.appName = 'test'; + + filterList.onSuccess.subscribe((res) => { + let deployApp: any = activitiService.getDeployedApplications; + expect(deployApp.calls.count()).toEqual(1); + expect(res).toBeDefined(); + done(); + }); + + filterList.ngOnInit(); + }); + + it('should emit an error with a bad response', (done) => { + filterList.appId = '1'; + spyOn(activitiService, 'getProcessFilters').and.returnValue(Observable.fromPromise(fakeErrorFilterPromise)); + + filterList.onError.subscribe((err) => { + expect(err).toBeDefined(); + done(); + }); + + filterList.ngOnInit(); + }); + + it('should emit an error with a bad response', (done) => { + filterList.appName = 'fake-app'; + spyOn(activitiService, 'getDeployedApplications').and.returnValue(Observable.fromPromise(fakeErrorFilterPromise)); + + filterList.onError.subscribe((err) => { + expect(err).toBeDefined(); + done(); + }); + + filterList.ngOnInit(); + }); + + it('should emit an event when a filter is selected', (done) => { + let currentFilter = new FilterRepresentationModel({filter: { state: 'open', assignment: 'fake-involved'}}); + + filterList.filterClick.subscribe((filter: FilterRepresentationModel) => { + expect(filter).toBeDefined(); + expect(filter).toEqual(currentFilter); + expect(filterList.currentFilter).toEqual(currentFilter); + done(); + }); + + filterList.selectFilter(currentFilter); + }); + + it('should reload filters by appId on binding changes', () => { + spyOn(filterList, 'getFiltersByAppId').and.stub(); + const appId = '1'; + + let change = new SimpleChange(null, appId); + filterList.ngOnChanges({ 'appId': change }); + + expect(filterList.getFiltersByAppId).toHaveBeenCalledWith(appId); + }); + + it('should reload filters by appId null on binding changes', () => { + spyOn(filterList, 'getFiltersByAppId').and.stub(); + const appId = null; + + let change = new SimpleChange(null, appId); + filterList.ngOnChanges({ 'appId': change }); + + expect(filterList.getFiltersByAppId).toHaveBeenCalledWith(appId); + }); + + it('should reload filters by app name on binding changes', () => { + spyOn(filterList, 'getFiltersByAppName').and.stub(); + const appName = 'fake-app-name'; + + let change = new SimpleChange(null, appName); + filterList.ngOnChanges({ 'appName': change }); + + expect(filterList.getFiltersByAppName).toHaveBeenCalledWith(appName); + }); + + it('should return the current filter after one is selected', () => { + let filter = new FilterRepresentationModel({name: 'FakeMyTasks', filter: { state: 'open', assignment: 'fake-assignee'}}); + expect(filterList.currentFilter).toBeUndefined(); + filterList.selectFilter(filter); + expect(filterList.getCurrentFilter()).toBe(filter); + }); + +}); diff --git a/ng2-components/ng2-activiti-processlist/src/components/activiti-process-instance-details.component.html b/ng2-components/ng2-activiti-processlist/src/components/activiti-process-instance-details.component.html index 34fe93ed19..9cb9341be6 100644 --- a/ng2-components/ng2-activiti-processlist/src/components/activiti-process-instance-details.component.html +++ b/ng2-components/ng2-activiti-processlist/src/components/activiti-process-instance-details.component.html @@ -4,7 +4,11 @@
+<<<<<<< HEAD +======= + +>>>>>>> New tests for processlist components
diff --git a/ng2-components/ng2-activiti-processlist/src/components/activiti-process-instance-details.component.spec.ts b/ng2-components/ng2-activiti-processlist/src/components/activiti-process-instance-details.component.spec.ts new file mode 100644 index 0000000000..d18a719465 --- /dev/null +++ b/ng2-components/ng2-activiti-processlist/src/components/activiti-process-instance-details.component.spec.ts @@ -0,0 +1,165 @@ +/*! + * @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 { NO_ERRORS_SCHEMA, DebugElement, SimpleChange } from '@angular/core'; +import { ComponentFixture, TestBed, async } from '@angular/core/testing'; +import { By } from '@angular/platform-browser'; +import { Observable } from 'rxjs/Rx'; + +import { AlfrescoTranslationService, CoreModule } from 'ng2-alfresco-core'; +import { ActivitiFormModule, FormModel, FormOutcomeEvent, FormOutcomeModel, FormService } from 'ng2-activiti-form'; +import { ActivitiTaskListModule } from 'ng2-activiti-tasklist'; + +import { ActivitiProcessInstanceDetails } from './activiti-process-instance-details.component'; +import { ActivitiProcessService } from './../services/activiti-process.service'; +import { TranslationMock } from './../assets/translation.service.mock'; +import { exampleProcess } from './../assets/activiti-process.model.mock'; + +describe('ActivitiProcessInstanceDetails', () => { + + let componentHandler: any; + let service: ActivitiProcessService; + let formService: FormService; + let component: ActivitiProcessInstanceDetails; + let fixture: ComponentFixture; + let getProcessSpy: jasmine.Spy; + + beforeEach(async(() => { + TestBed.configureTestingModule({ + imports: [ + CoreModule, + ActivitiFormModule, + ActivitiTaskListModule + ], + declarations: [ + ActivitiProcessInstanceDetails + ], + providers: [ + { provide: AlfrescoTranslationService, useClass: TranslationMock }, + ActivitiProcessService + ], + schemas: [ NO_ERRORS_SCHEMA ] + }).compileComponents(); + })); + + beforeEach(() => { + + fixture = TestBed.createComponent(ActivitiProcessInstanceDetails); + component = fixture.componentInstance; + service = fixture.debugElement.injector.get(ActivitiProcessService); + formService = fixture.debugElement.injector.get(FormService); + + getProcessSpy = spyOn(service, 'getProcess').and.returnValue(Observable.of(exampleProcess)); + + componentHandler = jasmine.createSpyObj('componentHandler', [ + 'upgradeAllRegistered', + 'upgradeElement' + ]); + window['componentHandler'] = componentHandler; + }); + + it('should load task details when processInstanceId specified', () => { + component.processInstanceId = '123'; + fixture.detectChanges(); + expect(getProcessSpy).toHaveBeenCalled(); + }); + + it('should not load task details when no processInstanceId is specified', () => { + fixture.detectChanges(); + expect(getProcessSpy).not.toHaveBeenCalled(); + }); + + it('should set a placeholder message when processInstanceId not initialised', () => { + fixture.detectChanges(); + expect(fixture.nativeElement.innerText).toBe('DETAILS.MESSAGES.NONE'); + }); + + it('should display a header when the processInstanceId is provided', async(() => { + component.processInstanceId = '123'; + fixture.detectChanges(); + fixture.whenStable().then(() => { + fixture.detectChanges(); + let headerEl: DebugElement = fixture.debugElement.query(By.css('h2')); + expect(headerEl).not.toBeNull(); + expect(headerEl.nativeElement.innerText).toBe('Process 123'); + }); + })); + + describe('change detection', () => { + + let change = new SimpleChange('123', '456'); + let nullChange = new SimpleChange('123', null); + + beforeEach(async(() => { + component.processInstanceId = '123'; + fixture.detectChanges(); + component.tasksList = jasmine.createSpyObj('tasksList', ['load']); + fixture.whenStable().then(() => { + getProcessSpy.calls.reset(); + }); + })); + + it('should fetch new process details when processInstanceId changed', () => { + component.ngOnChanges({ 'processInstanceId': change }); + expect(getProcessSpy).toHaveBeenCalledWith('456'); + }); + + it('should reload tasks list when processInstanceId changed', () => { + component.ngOnChanges({ 'processInstanceId': change }); + expect(component.tasksList.load).toHaveBeenCalled(); + }); + + it('should NOT fetch new process details when empty changeset made', () => { + component.ngOnChanges({}); + expect(getProcessSpy).not.toHaveBeenCalled(); + }); + + it('should NOT fetch new process details when processInstanceId changed to null', () => { + component.ngOnChanges({ 'processInstanceId': nullChange }); + expect(getProcessSpy).not.toHaveBeenCalled(); + }); + + it('should set a placeholder message when processInstanceId changed to null', () => { + component.ngOnChanges({ 'processInstanceId': nullChange }); + fixture.detectChanges(); + expect(fixture.nativeElement.innerText).toBe('DETAILS.MESSAGES.NONE'); + }); + }); + + describe('events', () => { + + beforeEach(async(() => { + component.processInstanceId = '123'; + fixture.detectChanges(); + fixture.whenStable(); + })); + + it('should emit a task form completed event when task form completed', () => { + let emitSpy: jasmine.Spy = spyOn(component.taskFormCompleted, 'emit'); + component.bubbleTaskFormCompleted(new FormModel()); + expect(emitSpy).toHaveBeenCalled(); + }); + + it('should emit a outcome execution event when task form outcome executed', () => { + let emitSpy: jasmine.Spy = spyOn(component.processCancelled, 'emit'); + component.bubbleProcessCancelled(new FormOutcomeEvent(new FormOutcomeModel(new FormModel()))); + expect(emitSpy).toHaveBeenCalled(); + }); + + }); + +}); diff --git a/ng2-components/ng2-activiti-processlist/src/components/activiti-process-instance-details.component.ts b/ng2-components/ng2-activiti-processlist/src/components/activiti-process-instance-details.component.ts index a511fb37a3..e27dc7634b 100644 --- a/ng2-components/ng2-activiti-processlist/src/components/activiti-process-instance-details.component.ts +++ b/ng2-components/ng2-activiti-processlist/src/components/activiti-process-instance-details.component.ts @@ -61,9 +61,8 @@ export class ActivitiProcessInstanceDetails implements OnInit, OnChanges { /** * Constructor - * @param auth - * @param translate - * @param activitiProcess + * @param translate Translation service + * @param activitiProcess Process service */ constructor(private translate: AlfrescoTranslationService, private activitiProcess: ActivitiProcessService) { diff --git a/ng2-components/ng2-activiti-processlist/src/components/activiti-process-instance-header.component.html b/ng2-components/ng2-activiti-processlist/src/components/activiti-process-instance-header.component.html index a786d753d0..386989af35 100644 --- a/ng2-components/ng2-activiti-processlist/src/components/activiti-process-instance-header.component.html +++ b/ng2-components/ng2-activiti-processlist/src/components/activiti-process-instance-header.component.html @@ -1,15 +1,19 @@
-
+
{{ 'DETAILS.LABELS.STARTED_BY' | translate }}: - {{getStartedByFullName()}} + {{getStartedByFullName()}}
-
+
{{ 'DETAILS.LABELS.STARTED' | translate }}: - {{getFormatDate(processInstance.started, 'medium')}} + {{getFormatDate(processInstance.started, 'medium')}}
-
+
+
+ {{ 'DETAILS.LABELS.ENDED' | translate }}: + {{getFormatDate(processInstance.ended, 'medium')}} +
diff --git a/ng2-components/ng2-activiti-processlist/src/components/activiti-process-instance-header.component.spec.ts b/ng2-components/ng2-activiti-processlist/src/components/activiti-process-instance-header.component.spec.ts new file mode 100644 index 0000000000..92d0d53a8b --- /dev/null +++ b/ng2-components/ng2-activiti-processlist/src/components/activiti-process-instance-header.component.spec.ts @@ -0,0 +1,108 @@ +/*! + * @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 { ComponentFixture, TestBed, async } from '@angular/core/testing'; +import { By } from '@angular/platform-browser'; + +import { AlfrescoTranslationService, CoreModule } from 'ng2-alfresco-core'; + +import { ActivitiProcessInstanceHeader } from './activiti-process-instance-header.component'; +import { TranslationMock } from './../assets/translation.service.mock'; +import { exampleProcess } from './../assets/activiti-process.model.mock'; +import { ProcessInstance } from './../models/process-instance'; +import { ActivitiProcessService } from './../services/activiti-process.service'; + +describe('ActivitiProcessInstanceHeader', () => { + + let componentHandler: any; + let component: ActivitiProcessInstanceHeader; + let fixture: ComponentFixture; + + beforeEach(async(() => { + TestBed.configureTestingModule({ + imports: [ + CoreModule + ], + declarations: [ + ActivitiProcessInstanceHeader + ], + providers: [ + { provide: AlfrescoTranslationService, useClass: TranslationMock }, + ActivitiProcessService + ] + }).compileComponents(); + })); + + beforeEach(() => { + + fixture = TestBed.createComponent(ActivitiProcessInstanceHeader); + component = fixture.componentInstance; + + component.processInstance = new ProcessInstance(exampleProcess); + + componentHandler = jasmine.createSpyObj('componentHandler', [ + 'upgradeAllRegistered', + 'upgradeElement' + ]); + window['componentHandler'] = componentHandler; + }); + + it('should render empty component if no form details provided', () => { + component.processInstance = undefined; + fixture.detectChanges(); + expect(fixture.debugElement.children.length).toBe(0); + }); + + it('should display started by user', () => { + fixture.detectChanges(); + let formValueEl = fixture.debugElement.query(By.css('[data-automation-id="header-started-by"] .activiti-process-header__value')); + expect(formValueEl).not.toBeNull(); + expect(formValueEl.nativeElement.innerText).toBe('Bob Jones'); + }); + + it('should display empty started by user if user unknown', () => { + component.processInstance.startedBy = null; + fixture.detectChanges(); + let formValueEl = fixture.debugElement.query(By.css('[data-automation-id="header-started-by"] .activiti-process-header__value')); + expect(formValueEl).not.toBeNull(); + expect(formValueEl.nativeElement.innerText).toBe(''); + }); + + it('should display process start date', () => { + component.processInstance.started = '2016-11-10T03:37:30.010+0000'; + fixture.detectChanges(); + let formValueEl = fixture.debugElement.query(By.css('[data-automation-id="header-started"] .activiti-process-header__value')); + expect(formValueEl).not.toBeNull(); + expect(formValueEl.nativeElement.innerText).toBe('Nov 10, 2016, 3:37:30 AM'); + }); + + it('should display cancel button if process is running', () => { + component.processInstance.ended = null; + fixture.detectChanges(); + let buttonEl = fixture.debugElement.query(By.css('[data-automation-id="header-status"] button')); + expect(buttonEl).not.toBeNull(); + }); + + it('should display ended date if process is ended', () => { + component.processInstance.ended = '2016-11-10T03:37:30.010+0000'; + fixture.detectChanges(); + let formValueEl = fixture.debugElement.query(By.css('[data-automation-id="header-status"] .activiti-process-header__value')); + expect(formValueEl).not.toBeNull(); + expect(formValueEl.nativeElement.innerText).toBe('Nov 10, 2016, 3:37:30 AM'); + }); + +}); diff --git a/ng2-components/ng2-activiti-processlist/src/components/activiti-process-instance-header.component.ts b/ng2-components/ng2-activiti-processlist/src/components/activiti-process-instance-header.component.ts index 292d8a08be..f6b5793f16 100644 --- a/ng2-components/ng2-activiti-processlist/src/components/activiti-process-instance-header.component.ts +++ b/ng2-components/ng2-activiti-processlist/src/components/activiti-process-instance-header.component.ts @@ -48,7 +48,7 @@ export class ActivitiProcessInstanceHeader { } } - getStartedByFullName() { + getStartedByFullName(): string { if (this.processInstance && this.processInstance.startedBy) { return (this.processInstance.startedBy.firstName && this.processInstance.startedBy.firstName !== 'null' ? this.processInstance.startedBy.firstName + ' ' : '') + @@ -66,6 +66,10 @@ export class ActivitiProcessInstanceHeader { } } + isRunning(): boolean { + return this.processInstance && !this.processInstance.ended; + } + cancelProcess() { this.activitiProcess.cancelProcess(this.processInstance.id).subscribe( (res) => { diff --git a/ng2-components/ng2-activiti-processlist/src/components/activiti-process-instance-tasks.component.html b/ng2-components/ng2-activiti-processlist/src/components/activiti-process-instance-tasks.component.html index 00b896928b..9ad8462d1c 100644 --- a/ng2-components/ng2-activiti-processlist/src/components/activiti-process-instance-tasks.component.html +++ b/ng2-components/ng2-activiti-processlist/src/components/activiti-process-instance-tasks.component.html @@ -10,7 +10,7 @@ {{ 'DETAILS.LABELS.TASKS_ACTIVE'|translate }} - diff --git a/ng2-components/ng2-activiti-form/src/components/widgets/unknown/unknown.widget.ts b/ng2-components/ng2-activiti-form/src/components/widgets/unknown/unknown.widget.ts new file mode 100644 index 0000000000..7f94fb1a52 --- /dev/null +++ b/ng2-components/ng2-activiti-form/src/components/widgets/unknown/unknown.widget.ts @@ -0,0 +1,31 @@ +/*! + * @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'; +import { WidgetComponent } from './../widget.component'; + +@Component({ + selector: 'unknown-widget', + template: ` +
+ error_outline + Unknown type: {{field.type}} +
+ ` +}) +export class UnknownWidget extends WidgetComponent { +} diff --git a/ng2-components/ng2-activiti-form/src/services/form-rendering.service.ts b/ng2-components/ng2-activiti-form/src/services/form-rendering.service.ts index d4d7e6ca3b..2edd1fb5b5 100644 --- a/ng2-components/ng2-activiti-form/src/services/form-rendering.service.ts +++ b/ng2-components/ng2-activiti-form/src/services/form-rendering.service.ts @@ -17,41 +17,104 @@ import { Injectable, Type } from '@angular/core'; -import { TextWidget } from './../components/widgets/text/text.widget'; +import { + FormFieldModel, + UnknownWidget, + TextWidget, + MultilineTextWidget, + NumberWidget, + CheckboxWidget, + DropdownWidget, + DateWidget, + AmountWidget, + RadioButtonsWidget, + HyperlinkWidget, + DisplayValueWidget, + DisplayTextWidget, + TypeaheadWidget, + PeopleWidget, + FunctionalGroupWidget, + DynamicTableWidget, + AttachWidget, + UploadWidget +} from './../components/widgets/index'; @Injectable() export class FormRenderingService { - private types: { [key: string]: Type<{}> } = { - 'text': TextWidget + private types: { [key: string]: ComponentTypeResolver } = { + 'text': DefaultTypeResolver.fromType(TextWidget), + 'integer': DefaultTypeResolver.fromType(NumberWidget), + 'multi-line-text': DefaultTypeResolver.fromType(MultilineTextWidget), + 'boolean': DefaultTypeResolver.fromType(CheckboxWidget), + 'dropdown': DefaultTypeResolver.fromType(DropdownWidget), + 'date': DefaultTypeResolver.fromType(DateWidget), + 'amount': DefaultTypeResolver.fromType(AmountWidget), + 'radio-buttons': DefaultTypeResolver.fromType(RadioButtonsWidget), + 'hyperlink': DefaultTypeResolver.fromType(HyperlinkWidget), + 'readonly': DefaultTypeResolver.fromType(DisplayValueWidget), + 'readonly-text': DefaultTypeResolver.fromType(DisplayTextWidget), + 'typeahead': DefaultTypeResolver.fromType(TypeaheadWidget), + 'people': DefaultTypeResolver.fromType(PeopleWidget), + 'functional-group': DefaultTypeResolver.fromType(FunctionalGroupWidget), + 'dynamic-table': DefaultTypeResolver.fromType(DynamicTableWidget) }; - getComponentType(fieldType: string): Type<{}> { - if (fieldType) { - return this.types[fieldType] || null; - } - return null; + constructor() { + this.types['upload'] = (field: FormFieldModel): Type<{}> => { + if (field) { + let params = field.params; + if (params && params.link) { + return AttachWidget; + } + return UploadWidget; + } + return null; + }; } - setComponentType(fieldType: string, componentType: Type<{}>, override: boolean = false) { + getComponentTypeResolver(fieldType: string, defaultValue: Type<{}> = UnknownWidget): ComponentTypeResolver { + if (fieldType) { + return this.types[fieldType] || DefaultTypeResolver.fromType(defaultValue); + } + return DefaultTypeResolver.fromType(defaultValue); + } + + setComponentTypeResolver(fieldType: string, resolver: ComponentTypeResolver, override: boolean = false) { if (!fieldType) { throw new Error(`fieldType is null or not defined`); } - if (!componentType) { - throw new Error(`componentType is null or not defined`); + if (!resolver) { + throw new Error(`resolver is null or not defined`); } let existing = this.types[fieldType]; if (existing && !override) { - throw new Error(`componentType is already mapped, use override option if you intend replacing existing mapping.`); + throw new Error(`already mapped, use override option if you intend replacing existing mapping.`); } - this.types[fieldType] = componentType; + this.types[fieldType] = resolver; } - constructor() { - this.setComponentType('xx', TextWidget); + resolveComponentType(field: FormFieldModel, defaultValue: Type<{}> = UnknownWidget): Type<{}> { + if (field) { + let resolver = this.getComponentTypeResolver(field.type, defaultValue); + return resolver(field); + } + return defaultValue; } } + +export interface ComponentTypeResolver { + (field: FormFieldModel): Type<{}>; +} + +export class DefaultTypeResolver { + static fromType(type: Type<{}>): ComponentTypeResolver { + return (field: FormFieldModel) => { + return type; + }; + } +} From 084d9622305d2a66574bb5698af1b44804c1ea7d Mon Sep 17 00:00:00 2001 From: Denys Vuika Date: Tue, 15 Nov 2016 10:46:49 +0000 Subject: [PATCH 026/103] #967 dynamic container resolution --- .../components/activiti-form.component.html | 15 +------------ .../activiti-start-form.component.html | 18 +-------------- .../container/container.widget.spec.ts | 12 +++++----- .../widgets/container/container.widget.ts | 22 +++++++++---------- .../src/components/widgets/core/form.model.ts | 1 + .../dynamic-table/dynamic-table.widget.ts | 11 +++++++--- .../components/widgets/tabs/tabs.widget.html | 15 +------------ .../components/widgets/widget.component.ts | 5 +++++ .../src/services/form-rendering.service.ts | 7 ++++-- 9 files changed, 38 insertions(+), 68 deletions(-) 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 acbafc7105..48411ae393 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 @@ -15,20 +15,7 @@
-
-
- -
-
- -
-
- -
-
- -
-
+
diff --git a/ng2-components/ng2-activiti-form/src/components/activiti-start-form.component.html b/ng2-components/ng2-activiti-form/src/components/activiti-start-form.component.html index 2dd449b9b6..5914fefde0 100644 --- a/ng2-components/ng2-activiti-form/src/components/activiti-start-form.component.html +++ b/ng2-components/ng2-activiti-form/src/components/activiti-start-form.component.html @@ -12,23 +12,7 @@
-
-
- -
-
- -
-
- -
-
- -
-
- UNKNOWN WIDGET TYPE: {{field.type}} -
-
+
diff --git a/ng2-components/ng2-activiti-form/src/components/widgets/container/container.widget.spec.ts b/ng2-components/ng2-activiti-form/src/components/widgets/container/container.widget.spec.ts index 3d7b483660..e6b91febfd 100644 --- a/ng2-components/ng2-activiti-form/src/components/widgets/container/container.widget.spec.ts +++ b/ng2-components/ng2-activiti-form/src/components/widgets/container/container.widget.spec.ts @@ -103,14 +103,14 @@ describe('ContainerWidget', () => { let widget = new ContainerWidget(); let fakeForm = new FormModel(); let fakeField = new FormFieldModel(fakeForm, {id: 'fakeField', value: 'fakeValue'}); - widget.formValueChanged.subscribe(field => { + widget.fieldChanged.subscribe(field => { expect(field).not.toBe(null); expect(field.id).toBe('fakeField'); expect(field.value).toBe('fakeValue'); done(); }); - widget.fieldChanged(fakeField); + widget.onFieldChanged(fakeField); }); describe('when template is ready', () => { @@ -180,7 +180,7 @@ describe('ContainerWidget', () => { it('should hide header when it becomes not visible', async(() => { containerWidgetComponent.content = fakeContainerVisible; fixture.detectChanges(); - containerWidgetComponent.formValueChanged.subscribe((res) => { + containerWidgetComponent.fieldChanged.subscribe((res) => { containerWidgetComponent.content.field.isVisible = false; fixture.detectChanges(); fixture.whenStable() @@ -189,12 +189,12 @@ describe('ContainerWidget', () => { expect(element.querySelector('#container-header-label')).toBeNull(); }); }); - containerWidgetComponent.fieldChanged(null); + containerWidgetComponent.onFieldChanged(null); })); it('should show header when it becomes visible', async(() => { containerWidgetComponent.content = fakeContainerInvisible; - containerWidgetComponent.formValueChanged.subscribe((res) => { + containerWidgetComponent.fieldChanged.subscribe((res) => { containerWidgetComponent.content.field.isVisible = true; fixture.detectChanges(); fixture.whenStable() @@ -205,7 +205,7 @@ describe('ContainerWidget', () => { expect(element.querySelector('#container-header-label').innerHTML).toContain('fake-cont-2-name'); }); }); - containerWidgetComponent.fieldChanged(null); + containerWidgetComponent.onFieldChanged(null); })); }); diff --git a/ng2-components/ng2-activiti-form/src/components/widgets/container/container.widget.ts b/ng2-components/ng2-activiti-form/src/components/widgets/container/container.widget.ts index 713de93949..f4ed5d4b19 100644 --- a/ng2-components/ng2-activiti-form/src/components/widgets/container/container.widget.ts +++ b/ng2-components/ng2-activiti-form/src/components/widgets/container/container.widget.ts @@ -15,8 +15,9 @@ * limitations under the License. */ -import { Component, Input, AfterViewInit, Output, EventEmitter } from '@angular/core'; -import { ContainerModel, FormFieldModel } from './../core/index'; +import { Component, AfterViewInit, OnInit } from '@angular/core'; +import { ContainerModel } from './../core/index'; +import { WidgetComponent } from './../widget.component'; @Component({ moduleId: module.id, @@ -24,20 +25,22 @@ import { ContainerModel, FormFieldModel } from './../core/index'; templateUrl: './container.widget.html', styleUrls: ['./container.widget.css'] }) -export class ContainerWidget implements AfterViewInit { +export class ContainerWidget extends WidgetComponent implements OnInit, AfterViewInit { - @Input() content: ContainerModel; - @Output() - formValueChanged: EventEmitter = new EventEmitter(); - onExpanderClicked() { if (this.content && this.content.isCollapsible()) { this.content.isExpanded = !this.content.isExpanded; } } + ngOnInit() { + if (this.field) { + this.content = new ContainerModel(this.field.form, this.field.json); + } + } + ngAfterViewInit() { this.setupMaterialComponents(); } @@ -50,9 +53,4 @@ export class ContainerWidget implements AfterViewInit { } return false; } - - fieldChanged(field: FormFieldModel) { - this.formValueChanged.emit(field); - } - } diff --git a/ng2-components/ng2-activiti-form/src/components/widgets/core/form.model.ts b/ng2-components/ng2-activiti-form/src/components/widgets/core/form.model.ts index 003b2cfc62..09c9100bc6 100644 --- a/ng2-components/ng2-activiti-form/src/components/widgets/core/form.model.ts +++ b/ng2-components/ng2-activiti-form/src/components/widgets/core/form.model.ts @@ -43,6 +43,7 @@ export class FormModel { readOnly: boolean = false; tabs: TabModel[] = []; + /** Stores root containers */ fields: FormWidgetModel[] = []; outcomes: FormOutcomeModel[] = []; diff --git a/ng2-components/ng2-activiti-form/src/components/widgets/dynamic-table/dynamic-table.widget.ts b/ng2-components/ng2-activiti-form/src/components/widgets/dynamic-table/dynamic-table.widget.ts index 14bbf832f1..e6382ca9e0 100644 --- a/ng2-components/ng2-activiti-form/src/components/widgets/dynamic-table/dynamic-table.widget.ts +++ b/ng2-components/ng2-activiti-form/src/components/widgets/dynamic-table/dynamic-table.widget.ts @@ -15,7 +15,7 @@ * limitations under the License. */ -import { Component, Input, ElementRef } from '@angular/core'; +import { Component, ElementRef, OnInit } from '@angular/core'; import { WidgetComponent } from './../widget.component'; import { DynamicTableModel, DynamicTableRow, DynamicTableColumn } from './../core/index'; @@ -25,11 +25,10 @@ import { DynamicTableModel, DynamicTableRow, DynamicTableColumn } from './../cor templateUrl: './dynamic-table.widget.html', styleUrls: ['./dynamic-table.widget.css'] }) -export class DynamicTableWidget extends WidgetComponent { +export class DynamicTableWidget extends WidgetComponent implements OnInit { ERROR_MODEL_NOT_FOUND = 'Table model not found'; - @Input() content: DynamicTableModel; editMode: boolean = false; @@ -39,6 +38,12 @@ export class DynamicTableWidget extends WidgetComponent { super(); } + ngOnInit() { + if (this.field) { + this.content = new DynamicTableModel(this.field.form, this.field.json); + } + } + isValid() { let result = true; diff --git a/ng2-components/ng2-activiti-form/src/components/widgets/tabs/tabs.widget.html b/ng2-components/ng2-activiti-form/src/components/widgets/tabs/tabs.widget.html index d532485a07..799829fde4 100644 --- a/ng2-components/ng2-activiti-form/src/components/widgets/tabs/tabs.widget.html +++ b/ng2-components/ng2-activiti-form/src/components/widgets/tabs/tabs.widget.html @@ -13,20 +13,7 @@ [class.is-active]="isFirst" [attr.id]="tab.id">
-
-
- -
-
- -
-
- -
-
- -
-
+
diff --git a/ng2-components/ng2-activiti-form/src/components/widgets/widget.component.ts b/ng2-components/ng2-activiti-form/src/components/widgets/widget.component.ts index b3d6f4e54d..ea96638258 100644 --- a/ng2-components/ng2-activiti-form/src/components/widgets/widget.component.ts +++ b/ng2-components/ng2-activiti-form/src/components/widgets/widget.component.ts @@ -79,10 +79,15 @@ export class WidgetComponent implements AfterViewInit { return false; } + /** @deprecated use onFieldChanged instead */ checkVisibility(field: FormFieldModel) { this.fieldChanged.emit(field); } + onFieldChanged(field: FormFieldModel) { + this.fieldChanged.emit(field); + } + protected getHyperlinkUrl(field: FormFieldModel) { let url = WidgetComponent.DEFAULT_HYPERLINK_URL; if (field && field.hyperlinkUrl) { diff --git a/ng2-components/ng2-activiti-form/src/services/form-rendering.service.ts b/ng2-components/ng2-activiti-form/src/services/form-rendering.service.ts index 2edd1fb5b5..d502aa3bcb 100644 --- a/ng2-components/ng2-activiti-form/src/services/form-rendering.service.ts +++ b/ng2-components/ng2-activiti-form/src/services/form-rendering.service.ts @@ -36,7 +36,8 @@ import { FunctionalGroupWidget, DynamicTableWidget, AttachWidget, - UploadWidget + UploadWidget, + ContainerWidget } from './../components/widgets/index'; @Injectable() @@ -57,7 +58,9 @@ export class FormRenderingService { 'typeahead': DefaultTypeResolver.fromType(TypeaheadWidget), 'people': DefaultTypeResolver.fromType(PeopleWidget), 'functional-group': DefaultTypeResolver.fromType(FunctionalGroupWidget), - 'dynamic-table': DefaultTypeResolver.fromType(DynamicTableWidget) + 'dynamic-table': DefaultTypeResolver.fromType(DynamicTableWidget), + 'container': DefaultTypeResolver.fromType(ContainerWidget), + 'group': DefaultTypeResolver.fromType(ContainerWidget) }; constructor() { From f81f78d311929ef89583b1d2c688ec27627a5936 Mon Sep 17 00:00:00 2001 From: Denys Vuika Date: Tue, 15 Nov 2016 13:08:55 +0000 Subject: [PATCH 027/103] #967 container widgets reworked - moved internals of container widget to corresponding folder - moved internals of dynamic table to corresponding folder --- .../container-column.model.spec.ts | 4 +- .../container-column.model.ts | 2 +- .../container/container.widget.model.spec.ts | 147 ++++++++++++++++++ .../container/container.widget.model.ts | 98 ++++++++++++ .../container/container.widget.spec.ts | 16 +- .../widgets/container/container.widget.ts | 6 +- .../widgets/core/container.model.spec.ts | 110 ------------- .../widgets/core/container.model.ts | 73 +-------- .../widgets/core/dynamic-table-column.ts | 48 ------ .../widgets/core/dynamic-table-row.ts | 24 --- .../widgets/core/form-field.model.ts | 1 + .../widgets/core/form.model.spec.ts | 4 +- .../src/components/widgets/core/form.model.ts | 23 +-- .../src/components/widgets/core/index.ts | 4 - .../display-value.widget.spec.ts | 3 +- .../display-value/display-value.widget.ts | 3 +- .../dynamic-table.widget.model.ts} | 46 +++++- .../dynamic-table.widget.spec.ts | 3 +- .../dynamic-table/dynamic-table.widget.ts | 2 +- .../editors/boolean/boolean.editor.spec.ts | 2 +- .../editors/boolean/boolean.editor.ts | 2 +- .../dynamic-table/editors/cell.editor.ts | 2 +- .../editors/date/date.editor.spec.ts | 2 +- .../editors/dropdown/dropdown.editor.spec.ts | 10 +- .../editors/dropdown/dropdown.editor.ts | 2 +- .../dynamic-table/editors/row.editor.spec.ts | 2 +- .../dynamic-table/editors/row.editor.ts | 2 +- .../editors/text/text.editor.spec.ts | 2 +- .../dynamic-table/editors/text/text.editor.ts | 2 +- .../widget-visibility.service.spec.ts | 2 + 30 files changed, 331 insertions(+), 316 deletions(-) rename ng2-components/ng2-activiti-form/src/components/widgets/{core => container}/container-column.model.spec.ts (91%) rename ng2-components/ng2-activiti-form/src/components/widgets/{core => container}/container-column.model.ts (92%) create mode 100644 ng2-components/ng2-activiti-form/src/components/widgets/container/container.widget.model.spec.ts create mode 100644 ng2-components/ng2-activiti-form/src/components/widgets/container/container.widget.model.ts delete mode 100644 ng2-components/ng2-activiti-form/src/components/widgets/core/dynamic-table-column.ts delete mode 100644 ng2-components/ng2-activiti-form/src/components/widgets/core/dynamic-table-row.ts rename ng2-components/ng2-activiti-form/src/components/widgets/{core/dynamic-table.model.ts => dynamic-table/dynamic-table.widget.model.ts} (87%) diff --git a/ng2-components/ng2-activiti-form/src/components/widgets/core/container-column.model.spec.ts b/ng2-components/ng2-activiti-form/src/components/widgets/container/container-column.model.spec.ts similarity index 91% rename from ng2-components/ng2-activiti-form/src/components/widgets/core/container-column.model.spec.ts rename to ng2-components/ng2-activiti-form/src/components/widgets/container/container-column.model.spec.ts index 2a983fae37..beef5ba952 100644 --- a/ng2-components/ng2-activiti-form/src/components/widgets/core/container-column.model.spec.ts +++ b/ng2-components/ng2-activiti-form/src/components/widgets/container/container-column.model.spec.ts @@ -16,8 +16,8 @@ */ import { ContainerColumnModel } from './container-column.model'; -import { FormModel } from './form.model'; -import { FormFieldModel } from './form-field.model'; +import { FormModel } from './../core/form.model'; +import { FormFieldModel } from './../core/form-field.model'; describe('ContainerColumnModel', () => { diff --git a/ng2-components/ng2-activiti-form/src/components/widgets/core/container-column.model.ts b/ng2-components/ng2-activiti-form/src/components/widgets/container/container-column.model.ts similarity index 92% rename from ng2-components/ng2-activiti-form/src/components/widgets/core/container-column.model.ts rename to ng2-components/ng2-activiti-form/src/components/widgets/container/container-column.model.ts index 94216ed655..cbad0a523c 100644 --- a/ng2-components/ng2-activiti-form/src/components/widgets/core/container-column.model.ts +++ b/ng2-components/ng2-activiti-form/src/components/widgets/container/container-column.model.ts @@ -15,7 +15,7 @@ * limitations under the License. */ -import { FormFieldModel } from './form-field.model'; +import { FormFieldModel } from './../core/form-field.model'; export class ContainerColumnModel { diff --git a/ng2-components/ng2-activiti-form/src/components/widgets/container/container.widget.model.spec.ts b/ng2-components/ng2-activiti-form/src/components/widgets/container/container.widget.model.spec.ts new file mode 100644 index 0000000000..a1cb578dd1 --- /dev/null +++ b/ng2-components/ng2-activiti-form/src/components/widgets/container/container.widget.model.spec.ts @@ -0,0 +1,147 @@ +/*! + * @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 { ContainerWidgetModel } from './container.widget.model'; +import { FormModel } from './../core/form.model'; +import { FormFieldTypes } from './../core/form-field-types'; + +describe('ContainerWidgetModel', () => { + + it('should store the form reference', () => { + let form = new FormModel(); + let model = new ContainerWidgetModel(form); + expect(model.form).toBe(form); + }); + + it('should store original json', () => { + let json = {}; + let model = new ContainerWidgetModel(null, json); + expect(model.json).toBe(json); + }); + + it('should have 1 column layout by default', () => { + let container = new ContainerWidgetModel(null, null); + expect(container.numberOfColumns).toBe(1); + }); + + it('should be expanded by default', () => { + let container = new ContainerWidgetModel(null, null); + expect(container.isExpanded).toBeTruthy(); + }); + + /* + it('should setup with json config', () => { + let json = { + fieldType: '', + id: '', + name: '', + type: '', + tab: '', + numberOfColumns: 2, + params: {} + }; + let container = new ContainerWidgetModel(null, json); + Object.keys(json).forEach(key => { + expect(container[key]).toEqual(json[key]); + }); + }); + */ + + it('should wrap fields into columns on setup', () => { + let form = new FormModel(); + let json = { + fieldType: '', + id: '', + name: '', + type: '', + tab: '', + numberOfColumns: 3, + params: {}, + visibilityCondition: {}, + fields: { + '1': [ + { id: 'field-1' }, + { id: 'field-3' } + ], + '2': [ + { id: 'field-2' } + ], + '3': null + } + }; + let container = new ContainerWidgetModel(form, json); + expect(container.columns.length).toBe(3); + + let col1 = container.columns[0]; + expect(col1.fields.length).toBe(2); + expect(col1.fields[0].id).toBe('field-1'); + expect(col1.fields[1].id).toBe('field-3'); + + let col2 = container.columns[1]; + expect(col2.fields.length).toBe(1); + expect(col2.fields[0].id).toBe('field-2'); + + let col3 = container.columns[2]; + expect(col3.fields.length).toBe(0); + }); + + it('should allow collapsing only when of a group type', () => { + let container = new ContainerWidgetModel(new FormModel(), { + type: FormFieldTypes.CONTAINER, + params: { + allowCollapse: true + } + }); + + expect(container.isCollapsible()).toBeFalsy(); + container = new ContainerWidgetModel(new FormModel(), { + type: FormFieldTypes.GROUP, + params: { + allowCollapse: true + } + }); + expect(container.isCollapsible()).toBeTruthy(); + }); + + it('should allow collapsing only when explicitly defined in params', () => { + let container = new ContainerWidgetModel(new FormModel(), { + type: FormFieldTypes.GROUP, + params: {} + }); + expect(container.isCollapsible()).toBeFalsy(); + + container = new ContainerWidgetModel(new FormModel(), { + type: FormFieldTypes.GROUP, + params: { + allowCollapse: true + } + }); + expect(container.isCollapsible()).toBeTruthy(); + }); + + it('should be collapsed by default', () => { + let container = new ContainerWidgetModel(new FormModel(), { + type: FormFieldTypes.GROUP, + params: { + allowCollapse: true, + collapseByDefault: true + } + }); + expect(container.isCollapsedByDefault()).toBeTruthy(); + }); + +}); diff --git a/ng2-components/ng2-activiti-form/src/components/widgets/container/container.widget.model.ts b/ng2-components/ng2-activiti-form/src/components/widgets/container/container.widget.model.ts new file mode 100644 index 0000000000..bd57023af9 --- /dev/null +++ b/ng2-components/ng2-activiti-form/src/components/widgets/container/container.widget.model.ts @@ -0,0 +1,98 @@ +/*! + * @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 { ContainerModel } from './../core/container.model'; +import { FormModel } from './../core/form.model'; +import { ContainerColumnModel } from './container-column.model'; +import { FormFieldTypes } from './../core/form-field-types'; +import { FormFieldModel } from './../core/form-field.model'; + +export class ContainerWidgetModel extends ContainerModel { + + numberOfColumns: number = 1; + columns: ContainerColumnModel[] = []; + isExpanded: boolean = true; + + isGroup(): boolean { + return this.type === FormFieldTypes.GROUP; + } + + isCollapsible(): boolean { + let allowCollapse = false; + + if (this.isGroup() && this.field.params['allowCollapse']) { + allowCollapse = this.field.params['allowCollapse']; + } + + return allowCollapse; + } + + isCollapsedByDefault(): boolean { + let collapseByDefault = false; + + if (this.isCollapsible() && this.field.params['collapseByDefault']) { + collapseByDefault = this.field.params['collapseByDefault']; + } + + return collapseByDefault; + } + + constructor(form: FormModel, json?: any) { + super(form, json); + + if (json) { + this.numberOfColumns = json.numberOfColumns; + + let columnSize: number = 12; + if (this.numberOfColumns > 1) { + columnSize = 12 / this.numberOfColumns; + } + + for (let i = 0; i < this.numberOfColumns; i++) { + let col = new ContainerColumnModel(); + col.size = columnSize; + this.columns.push(col); + } + + if (json.fields) { + Object.keys(json.fields).map(key => { + let fields = (json.fields[key] || []).map(f => new FormFieldModel(form, f)); + let col = this.columns[parseInt(key, 10) - 1]; + col.fields = fields; + }); + } + + this.isExpanded = !this.isCollapsedByDefault(); + this.children = this.getFormFields(); + } + } + + private getFormFields(): FormFieldModel[] { + let result: FormFieldModel[] = []; + + for (let j = 0; j < this.columns.length; j++) { + let column = this.columns[j]; + for (let k = 0; k < column.fields.length; k++) { + let field = column.fields[k]; + result.push(field); + } + } + + return result; + } + +} diff --git a/ng2-components/ng2-activiti-form/src/components/widgets/container/container.widget.spec.ts b/ng2-components/ng2-activiti-form/src/components/widgets/container/container.widget.spec.ts index e6b91febfd..151edc98b1 100644 --- a/ng2-components/ng2-activiti-form/src/components/widgets/container/container.widget.spec.ts +++ b/ng2-components/ng2-activiti-form/src/components/widgets/container/container.widget.spec.ts @@ -16,8 +16,8 @@ */ import { ContainerWidget } from './container.widget'; +import { ContainerWidgetModel } from './container.widget.model'; import { FormModel } from './../core/form.model'; -import { ContainerModel } from './../core/container.model'; import { FormFieldTypes } from './../core/form-field-types'; import { FormFieldModel } from './../core/form-field.model'; import { ComponentFixture, TestBed, async } from '@angular/core/testing'; @@ -53,7 +53,7 @@ describe('ContainerWidget', () => { }); it('should toggle underlying group container', () => { - let container = new ContainerModel(new FormModel(), { + let container = new ContainerWidgetModel(new FormModel(), { type: FormFieldTypes.GROUP, params: { allowCollapse: true @@ -71,7 +71,7 @@ describe('ContainerWidget', () => { }); it('should toggle only collapsible container', () => { - let container = new ContainerModel(new FormModel(), { + let container = new ContainerWidgetModel(new FormModel(), { type: FormFieldTypes.GROUP }); @@ -84,7 +84,7 @@ describe('ContainerWidget', () => { }); it('should toggle only group container', () => { - let container = new ContainerModel(new FormModel(), { + let container = new ContainerWidgetModel(new FormModel(), { type: FormFieldTypes.CONTAINER, params: { allowCollapse: true @@ -117,8 +117,8 @@ describe('ContainerWidget', () => { let containerWidgetComponent: ContainerWidget; let fixture: ComponentFixture; let element: HTMLElement; - let fakeContainerVisible: ContainerModel; - let fakeContainerInvisible: ContainerModel; + let fakeContainerVisible: ContainerWidgetModel; + let fakeContainerInvisible: ContainerWidgetModel; beforeEach(async(() => { TestBed.configureTestingModule({ @@ -134,13 +134,13 @@ describe('ContainerWidget', () => { beforeEach(() => { componentHandler = jasmine.createSpyObj('componentHandler', ['upgradeAllRegistered', 'upgradeElement']); window['componentHandler'] = componentHandler; - fakeContainerVisible = new ContainerModel(new FormModel(fakeFormJson), { + fakeContainerVisible = new ContainerWidgetModel(new FormModel(fakeFormJson), { fieldType: FormFieldTypes.GROUP, id: 'fake-cont-id-1', name: 'fake-cont-1-name', type: FormFieldTypes.GROUP }); - fakeContainerInvisible = new ContainerModel(new FormModel(fakeFormJson), { + fakeContainerInvisible = new ContainerWidgetModel(new FormModel(fakeFormJson), { fieldType: FormFieldTypes.GROUP, id: 'fake-cont-id-2', name: 'fake-cont-2-name', diff --git a/ng2-components/ng2-activiti-form/src/components/widgets/container/container.widget.ts b/ng2-components/ng2-activiti-form/src/components/widgets/container/container.widget.ts index f4ed5d4b19..f5bde61620 100644 --- a/ng2-components/ng2-activiti-form/src/components/widgets/container/container.widget.ts +++ b/ng2-components/ng2-activiti-form/src/components/widgets/container/container.widget.ts @@ -16,7 +16,7 @@ */ import { Component, AfterViewInit, OnInit } from '@angular/core'; -import { ContainerModel } from './../core/index'; +import { ContainerWidgetModel } from './container.widget.model'; import { WidgetComponent } from './../widget.component'; @Component({ @@ -27,7 +27,7 @@ import { WidgetComponent } from './../widget.component'; }) export class ContainerWidget extends WidgetComponent implements OnInit, AfterViewInit { - content: ContainerModel; + content: ContainerWidgetModel; onExpanderClicked() { if (this.content && this.content.isCollapsible()) { @@ -37,7 +37,7 @@ export class ContainerWidget extends WidgetComponent implements OnInit, AfterVie ngOnInit() { if (this.field) { - this.content = new ContainerModel(this.field.form, this.field.json); + this.content = new ContainerWidgetModel(this.field.form, this.field.json); } } diff --git a/ng2-components/ng2-activiti-form/src/components/widgets/core/container.model.spec.ts b/ng2-components/ng2-activiti-form/src/components/widgets/core/container.model.spec.ts index cdea916fda..5c5b2447d2 100644 --- a/ng2-components/ng2-activiti-form/src/components/widgets/core/container.model.spec.ts +++ b/ng2-components/ng2-activiti-form/src/components/widgets/core/container.model.spec.ts @@ -17,7 +17,6 @@ import { ContainerModel } from './container.model'; import { FormModel } from './form.model'; -import { FormFieldTypes } from './form-field-types'; describe('ContainerModel', () => { @@ -33,113 +32,4 @@ describe('ContainerModel', () => { expect(model.json).toBe(json); }); - it('should have 1 column layout by default', () => { - let container = new ContainerModel(null, null); - expect(container.numberOfColumns).toBe(1); - }); - - it('should be expanded by default', () => { - let container = new ContainerModel(null, null); - expect(container.isExpanded).toBeTruthy(); - }); - - it('should setup with json config', () => { - let json = { - fieldType: '', - id: '', - name: '', - type: '', - tab: '', - numberOfColumns: 2, - params: {} - }; - let container = new ContainerModel(null, json); - Object.keys(json).forEach(key => { - expect(container[key]).toEqual(json[key]); - }); - }); - - it('should wrap fields into columns on setup', () => { - let form = new FormModel(); - let json = { - fieldType: '', - id: '', - name: '', - type: '', - tab: '', - numberOfColumns: 3, - params: {}, - visibilityCondition: {}, - fields: { - '1': [ - { id: 'field-1' }, - { id: 'field-3' } - ], - '2': [ - { id: 'field-2' } - ], - '3': null - } - }; - let container = new ContainerModel(form, json); - expect(container.columns.length).toBe(3); - - let col1 = container.columns[0]; - expect(col1.fields.length).toBe(2); - expect(col1.fields[0].id).toBe('field-1'); - expect(col1.fields[1].id).toBe('field-3'); - - let col2 = container.columns[1]; - expect(col2.fields.length).toBe(1); - expect(col2.fields[0].id).toBe('field-2'); - - let col3 = container.columns[2]; - expect(col3.fields.length).toBe(0); - }); - - it('should allow collapsing only when of a group type', () => { - let container = new ContainerModel(new FormModel(), { - type: FormFieldTypes.CONTAINER, - params: { - allowCollapse: true - } - }); - - expect(container.isCollapsible()).toBeFalsy(); - container = new ContainerModel(new FormModel(), { - type: FormFieldTypes.GROUP, - params: { - allowCollapse: true - } - }); - expect(container.isCollapsible()).toBeTruthy(); - }); - - it('should allow collapsing only when explicitly defined in params', () => { - let container = new ContainerModel(new FormModel(), { - type: FormFieldTypes.GROUP, - params: {} - }); - expect(container.isCollapsible()).toBeFalsy(); - - container = new ContainerModel(new FormModel(), { - type: FormFieldTypes.GROUP, - params: { - allowCollapse: true - } - }); - expect(container.isCollapsible()).toBeTruthy(); - }); - - it('should be collapsed by default', () => { - let container = new ContainerModel(new FormModel(), { - type: FormFieldTypes.GROUP, - params: { - allowCollapse: true, - collapseByDefault: true - } - }); - expect(container.isCollapsedByDefault()).toBeTruthy(); - }); - }); diff --git a/ng2-components/ng2-activiti-form/src/components/widgets/core/container.model.ts b/ng2-components/ng2-activiti-form/src/components/widgets/core/container.model.ts index 4de70c6642..a4e96116f4 100644 --- a/ng2-components/ng2-activiti-form/src/components/widgets/core/container.model.ts +++ b/ng2-components/ng2-activiti-form/src/components/widgets/core/container.model.ts @@ -16,95 +16,24 @@ */ import { FormWidgetModel } from './form-widget.model'; -import { FormFieldMetadata } from './form-field-metadata'; -import { ContainerColumnModel } from './container-column.model'; -import { FormFieldTypes } from './form-field-types'; import { FormModel } from './form.model'; import { FormFieldModel } from './form-field.model'; export class ContainerModel extends FormWidgetModel { field: FormFieldModel; - numberOfColumns: number = 1; - params: FormFieldMetadata = {}; - - columns: ContainerColumnModel[] = []; - isExpanded: boolean = true; + children: FormFieldModel[] = []; get isVisible(): boolean { return this.field.isVisible; } - isGroup(): boolean { - return this.type === FormFieldTypes.GROUP; - } - - isCollapsible(): boolean { - let allowCollapse = false; - - if (this.isGroup() && this.params['allowCollapse']) { - allowCollapse = this.params['allowCollapse']; - } - - return allowCollapse; - } - - isCollapsedByDefault(): boolean { - let collapseByDefault = false; - - if (this.isCollapsible() && this.params['collapseByDefault']) { - collapseByDefault = this.params['collapseByDefault']; - } - - return collapseByDefault; - } - constructor(form: FormModel, json?: any) { super(form, json); if (json) { this.field = new FormFieldModel(form, json); - this.numberOfColumns = json.numberOfColumns; - this.params = json.params || {}; - - let columnSize: number = 12; - if (this.numberOfColumns > 1) { - columnSize = 12 / this.numberOfColumns; - } - - for (let i = 0; i < this.numberOfColumns; i++) { - let col = new ContainerColumnModel(); - col.size = columnSize; - this.columns.push(col); - } - - if (json.fields) { - Object.keys(json.fields).map(key => { - let fields = (json.fields[key] || []).map(f => new FormFieldModel(form, f)); - let col = this.columns[parseInt(key, 10) - 1]; - col.fields = fields; - }); - } - - this.isExpanded = !this.isCollapsedByDefault(); } } - getFormFields(): FormFieldModel[] { - let result: FormFieldModel[] = []; - - if (this.field) { - result.push(this.field); - } - - for (let j = 0; j < this.columns.length; j++) { - let column = this.columns[j]; - for (let k = 0; k < column.fields.length; k++) { - let field = column.fields[k]; - result.push(field); - } - } - - return result; - } } diff --git a/ng2-components/ng2-activiti-form/src/components/widgets/core/dynamic-table-column.ts b/ng2-components/ng2-activiti-form/src/components/widgets/core/dynamic-table-column.ts deleted file mode 100644 index a5b4692f8f..0000000000 --- a/ng2-components/ng2-activiti-form/src/components/widgets/core/dynamic-table-column.ts +++ /dev/null @@ -1,48 +0,0 @@ -/*! - * @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. - */ - -// maps to: com.activiti.model.editor.form.ColumnDefinitionRepresentation -export interface DynamicTableColumn { - - id: string; - name: string; - type: string; - value: any; - optionType: string; - options: DynamicTableColumnOption[]; - restResponsePath: string; - restUrl: string; - restIdProperty: string; - restLabelProperty: string; - amountCurrency: string; - amountEnableFractions: boolean; - required: boolean; - editable: boolean; - sortable: boolean; - visible: boolean; - - // TODO: com.activiti.domain.idm.EndpointConfiguration.EndpointConfigurationRepresentation - endpoint: any; - // TODO: com.activiti.model.editor.form.RequestHeaderRepresentation - requestHeaders: any; -} - -// maps to: com.activiti.model.editor.form.OptionRepresentation -export interface DynamicTableColumnOption { - id: string; - name: string; -} diff --git a/ng2-components/ng2-activiti-form/src/components/widgets/core/dynamic-table-row.ts b/ng2-components/ng2-activiti-form/src/components/widgets/core/dynamic-table-row.ts deleted file mode 100644 index ce471b13b2..0000000000 --- a/ng2-components/ng2-activiti-form/src/components/widgets/core/dynamic-table-row.ts +++ /dev/null @@ -1,24 +0,0 @@ -/*! - * @license - * Copyright 2016 Alfresco Software, Ltd. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -export interface DynamicTableRow { - - isNew: boolean; - selected: boolean; - value: any; - -} 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 4acd1bc54d..a77a985dc4 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 @@ -37,6 +37,7 @@ import { declare var moment: any; +// Maps to FormFieldRepresentation export class FormFieldModel extends FormWidgetModel { private _value: string; diff --git a/ng2-components/ng2-activiti-form/src/components/widgets/core/form.model.spec.ts b/ng2-components/ng2-activiti-form/src/components/widgets/core/form.model.spec.ts index 7fabcd0722..f61ab81c1c 100644 --- a/ng2-components/ng2-activiti-form/src/components/widgets/core/form.model.spec.ts +++ b/ng2-components/ng2-activiti-form/src/components/widgets/core/form.model.spec.ts @@ -19,7 +19,7 @@ import { FormModel } from './form.model'; import { TabModel } from './tab.model'; import { ContainerModel } from './container.model'; import { FormOutcomeModel } from './form-outcome.model'; -import { FormValues } from './form-values'; +// import { FormValues } from './form-values'; import { FormFieldTypes } from './form-field-types'; describe('FormModel', () => { @@ -197,6 +197,7 @@ describe('FormModel', () => { expect(tab2.fields[0].id).toBe('field2'); }); + /* it('should apply external data', () => { let data: FormValues = { field1: 'one', @@ -259,6 +260,7 @@ describe('FormModel', () => { expect(field3.id).toBe('field3'); expect(field3.value).toBe('original-value'); }); + */ it('should create standard form outcomes', () => { let json = { diff --git a/ng2-components/ng2-activiti-form/src/components/widgets/core/form.model.ts b/ng2-components/ng2-activiti-form/src/components/widgets/core/form.model.ts index 09c9100bc6..bdc555d69c 100644 --- a/ng2-components/ng2-activiti-form/src/components/widgets/core/form.model.ts +++ b/ng2-components/ng2-activiti-form/src/components/widgets/core/form.model.ts @@ -22,7 +22,6 @@ import { TabModel } from './tab.model'; import { FormOutcomeModel } from './form-outcome.model'; import { FormFieldModel } from './form-field.model'; import { FormFieldTypes } from './form-field-types'; -import { DynamicTableModel } from './dynamic-table.model'; export class FormModel { @@ -123,14 +122,10 @@ export class FormModel { for (let i = 0; i < this.fields.length; i++) { let field = this.fields[i]; - if (field.type === FormFieldTypes.CONTAINER || field.type === FormFieldTypes.GROUP) { + if (field instanceof ContainerModel) { let container = field; - result.push(...container.getFormFields()); - } - - if (field.type === FormFieldTypes.DYNAMIC_TABLE) { - let dynamicTable = field; - result.push(dynamicTable.field); + result.push(container.field); + result.push(...container.children); } } @@ -159,7 +154,7 @@ export class FormModel { this.validateForm(); } - // Activiti supports 2 types of root fields: 'container' and 'dynamic-table'. + // Activiti supports 3 types of root fields: container|group|dynamic-table private parseRootFields(json: any): FormWidgetModel[] { let fields = []; @@ -172,18 +167,16 @@ export class FormModel { let result: FormWidgetModel[] = []; for (let field of fields) { - if (field.type === FormFieldTypes.CONTAINER || field.type === FormFieldTypes.GROUP ) { - result.push(new ContainerModel(this, field)); - } else if (field.type === FormFieldTypes.DYNAMIC_TABLE) { - result.push(new DynamicTableModel(this, field)); - } else if (field.type === FormFieldTypes.DISPLAY_VALUE) { + if (field.type === FormFieldTypes.DISPLAY_VALUE) { // workaround for dynamic table on a completed/readonly form if (field.params) { let originalField = field.params['field']; if (originalField.type === FormFieldTypes.DYNAMIC_TABLE) { - result.push(new DynamicTableModel(this, field)); + result.push(new ContainerModel(this, field)); } } + } else { + result.push(new ContainerModel(this, field)); } } diff --git a/ng2-components/ng2-activiti-form/src/components/widgets/core/index.ts b/ng2-components/ng2-activiti-form/src/components/widgets/core/index.ts index 902340e910..3db8211a73 100644 --- a/ng2-components/ng2-activiti-form/src/components/widgets/core/index.ts +++ b/ng2-components/ng2-activiti-form/src/components/widgets/core/index.ts @@ -22,12 +22,8 @@ export * from './form-field-option'; export * from './form-widget.model'; export * from './form-field.model'; export * from './form.model'; -export * from './container-column.model'; export * from './container.model'; export * from './tab.model'; export * from './form-outcome.model'; export * from './form-outcome-event.model'; export * from './form-field-validator'; -export * from './dynamic-table.model'; -export * from './dynamic-table-column'; -export * from './dynamic-table-row'; 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 6466a6c143..f132a3f376 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 @@ -21,8 +21,7 @@ import { FormService } from '../../../services/form.service'; import { FormFieldModel } from './../core/form-field.model'; import { FormFieldTypes } from '../core/form-field-types'; import { FormModel } from '../core/form.model'; -import { DynamicTableRow } from './../core/dynamic-table-row'; -import { DynamicTableColumn } from './../core/dynamic-table-column'; +import { DynamicTableColumn, DynamicTableRow } from './../dynamic-table/dynamic-table.widget.model'; describe('DisplayValueWidget', () => { 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 d41159be74..100eda566c 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 @@ -20,8 +20,7 @@ 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 } from './../core/dynamic-table-column'; -import { DynamicTableRow } from './../core/dynamic-table-row'; +import { DynamicTableColumn, DynamicTableRow } from './../dynamic-table/dynamic-table.widget.model'; @Component({ moduleId: module.id, diff --git a/ng2-components/ng2-activiti-form/src/components/widgets/core/dynamic-table.model.ts b/ng2-components/ng2-activiti-form/src/components/widgets/dynamic-table/dynamic-table.widget.model.ts similarity index 87% rename from ng2-components/ng2-activiti-form/src/components/widgets/core/dynamic-table.model.ts rename to ng2-components/ng2-activiti-form/src/components/widgets/dynamic-table/dynamic-table.widget.model.ts index 257beb93ae..46c22c1039 100644 --- a/ng2-components/ng2-activiti-form/src/components/widgets/core/dynamic-table.model.ts +++ b/ng2-components/ng2-activiti-form/src/components/widgets/dynamic-table/dynamic-table.widget.model.ts @@ -15,11 +15,9 @@ * limitations under the License. */ -import { FormWidgetModel } from './form-widget.model'; -import { FormModel } from './form.model'; -import { FormFieldModel } from './form-field.model'; -import { DynamicTableColumn } from './dynamic-table-column'; -import { DynamicTableRow } from './dynamic-table-row'; +import { FormWidgetModel } from './../core/form-widget.model'; +import { FormModel } from './../core/form.model'; +import { FormFieldModel } from './../core/form-field.model'; export class DynamicTableModel extends FormWidgetModel { @@ -285,3 +283,41 @@ export class NumberCellValidator implements CellValidator { return true; } } + +// maps to: com.activiti.model.editor.form.ColumnDefinitionRepresentation +export interface DynamicTableColumn { + + id: string; + name: string; + type: string; + value: any; + optionType: string; + options: DynamicTableColumnOption[]; + restResponsePath: string; + restUrl: string; + restIdProperty: string; + restLabelProperty: string; + amountCurrency: string; + amountEnableFractions: boolean; + required: boolean; + editable: boolean; + sortable: boolean; + visible: boolean; + + // TODO: com.activiti.domain.idm.EndpointConfiguration.EndpointConfigurationRepresentation + endpoint: any; + // TODO: com.activiti.model.editor.form.RequestHeaderRepresentation + requestHeaders: any; +} + +// maps to: com.activiti.model.editor.form.OptionRepresentation +export interface DynamicTableColumnOption { + id: string; + name: string; +} + +export interface DynamicTableRow { + isNew: boolean; + selected: boolean; + value: any; +} diff --git a/ng2-components/ng2-activiti-form/src/components/widgets/dynamic-table/dynamic-table.widget.spec.ts b/ng2-components/ng2-activiti-form/src/components/widgets/dynamic-table/dynamic-table.widget.spec.ts index c5cbdc9ecb..9ecb13e1d6 100644 --- a/ng2-components/ng2-activiti-form/src/components/widgets/dynamic-table/dynamic-table.widget.spec.ts +++ b/ng2-components/ng2-activiti-form/src/components/widgets/dynamic-table/dynamic-table.widget.spec.ts @@ -16,7 +16,8 @@ */ import { DynamicTableWidget } from './dynamic-table.widget'; -import { DynamicTableModel, DynamicTableRow, DynamicTableColumn, FormModel, FormFieldTypes } from './../core/index'; +import { DynamicTableModel, DynamicTableRow, DynamicTableColumn } from './dynamic-table.widget.model'; +import { FormModel, FormFieldTypes } from './../core/index'; describe('DynamicTableWidget', () => { diff --git a/ng2-components/ng2-activiti-form/src/components/widgets/dynamic-table/dynamic-table.widget.ts b/ng2-components/ng2-activiti-form/src/components/widgets/dynamic-table/dynamic-table.widget.ts index e6382ca9e0..71f56fa10b 100644 --- a/ng2-components/ng2-activiti-form/src/components/widgets/dynamic-table/dynamic-table.widget.ts +++ b/ng2-components/ng2-activiti-form/src/components/widgets/dynamic-table/dynamic-table.widget.ts @@ -17,7 +17,7 @@ import { Component, ElementRef, OnInit } from '@angular/core'; import { WidgetComponent } from './../widget.component'; -import { DynamicTableModel, DynamicTableRow, DynamicTableColumn } from './../core/index'; +import { DynamicTableModel, DynamicTableRow, DynamicTableColumn } from './dynamic-table.widget.model'; @Component({ moduleId: module.id, diff --git a/ng2-components/ng2-activiti-form/src/components/widgets/dynamic-table/editors/boolean/boolean.editor.spec.ts b/ng2-components/ng2-activiti-form/src/components/widgets/dynamic-table/editors/boolean/boolean.editor.spec.ts index 052b64914d..6451f712a1 100644 --- a/ng2-components/ng2-activiti-form/src/components/widgets/dynamic-table/editors/boolean/boolean.editor.spec.ts +++ b/ng2-components/ng2-activiti-form/src/components/widgets/dynamic-table/editors/boolean/boolean.editor.spec.ts @@ -16,7 +16,7 @@ */ import { BooleanEditorComponent } from './boolean.editor'; -import { DynamicTableRow, DynamicTableColumn } from './../../../core/index'; +import { DynamicTableRow, DynamicTableColumn } from './../../dynamic-table.widget.model'; describe('BooleanEditorComponent', () => { diff --git a/ng2-components/ng2-activiti-form/src/components/widgets/dynamic-table/editors/boolean/boolean.editor.ts b/ng2-components/ng2-activiti-form/src/components/widgets/dynamic-table/editors/boolean/boolean.editor.ts index eb65f03598..a1d6e9a821 100644 --- a/ng2-components/ng2-activiti-form/src/components/widgets/dynamic-table/editors/boolean/boolean.editor.ts +++ b/ng2-components/ng2-activiti-form/src/components/widgets/dynamic-table/editors/boolean/boolean.editor.ts @@ -17,7 +17,7 @@ import { Component } from '@angular/core'; import { CellEditorComponent } from './../cell.editor'; -import { DynamicTableRow, DynamicTableColumn } from './../../../core/index'; +import { DynamicTableRow, DynamicTableColumn } from './../../dynamic-table.widget.model'; @Component({ moduleId: module.id, diff --git a/ng2-components/ng2-activiti-form/src/components/widgets/dynamic-table/editors/cell.editor.ts b/ng2-components/ng2-activiti-form/src/components/widgets/dynamic-table/editors/cell.editor.ts index ed3bbab266..7eb30d93f6 100644 --- a/ng2-components/ng2-activiti-form/src/components/widgets/dynamic-table/editors/cell.editor.ts +++ b/ng2-components/ng2-activiti-form/src/components/widgets/dynamic-table/editors/cell.editor.ts @@ -16,7 +16,7 @@ */ import { Input } from '@angular/core'; -import { DynamicTableModel, DynamicTableRow, DynamicTableColumn } from './../../core/index'; +import { DynamicTableModel, DynamicTableRow, DynamicTableColumn } from './../dynamic-table.widget.model'; export abstract class CellEditorComponent { diff --git a/ng2-components/ng2-activiti-form/src/components/widgets/dynamic-table/editors/date/date.editor.spec.ts b/ng2-components/ng2-activiti-form/src/components/widgets/dynamic-table/editors/date/date.editor.spec.ts index cdfd64229f..3b97794534 100644 --- a/ng2-components/ng2-activiti-form/src/components/widgets/dynamic-table/editors/date/date.editor.spec.ts +++ b/ng2-components/ng2-activiti-form/src/components/widgets/dynamic-table/editors/date/date.editor.spec.ts @@ -17,7 +17,7 @@ import { ElementRef } from '@angular/core'; import { DateEditorComponent } from './date.editor'; -import { DynamicTableModel, DynamicTableRow, DynamicTableColumn } from './../../../core/index'; +import { DynamicTableModel, DynamicTableRow, DynamicTableColumn } from './../../dynamic-table.widget.model'; describe('DateEditorComponent', () => { diff --git a/ng2-components/ng2-activiti-form/src/components/widgets/dynamic-table/editors/dropdown/dropdown.editor.spec.ts b/ng2-components/ng2-activiti-form/src/components/widgets/dynamic-table/editors/dropdown/dropdown.editor.spec.ts index 71e0335523..1ab3605eec 100644 --- a/ng2-components/ng2-activiti-form/src/components/widgets/dynamic-table/editors/dropdown/dropdown.editor.spec.ts +++ b/ng2-components/ng2-activiti-form/src/components/widgets/dynamic-table/editors/dropdown/dropdown.editor.spec.ts @@ -17,14 +17,8 @@ import { Observable } from 'rxjs/Rx'; import { DropdownEditorComponent } from './dropdown.editor'; -import { - DynamicTableModel, - DynamicTableRow, - DynamicTableColumn, - DynamicTableColumnOption, - FormFieldModel, - FormModel -} from './../../../core/index'; +import { DynamicTableModel, DynamicTableRow, DynamicTableColumn, DynamicTableColumnOption } from './../../dynamic-table.widget.model'; +import { FormFieldModel, FormModel } from './../../../core/index'; import { FormService } from './../../../../../services/form.service'; describe('DropdownEditorComponent', () => { diff --git a/ng2-components/ng2-activiti-form/src/components/widgets/dynamic-table/editors/dropdown/dropdown.editor.ts b/ng2-components/ng2-activiti-form/src/components/widgets/dynamic-table/editors/dropdown/dropdown.editor.ts index 640855ed81..0014cdb16b 100644 --- a/ng2-components/ng2-activiti-form/src/components/widgets/dynamic-table/editors/dropdown/dropdown.editor.ts +++ b/ng2-components/ng2-activiti-form/src/components/widgets/dynamic-table/editors/dropdown/dropdown.editor.ts @@ -17,7 +17,7 @@ import { Component, OnInit } from '@angular/core'; import { CellEditorComponent } from './../cell.editor'; -import { DynamicTableRow, DynamicTableColumn, DynamicTableColumnOption } from './../../../core/index'; +import { DynamicTableRow, DynamicTableColumn, DynamicTableColumnOption } from './../../dynamic-table.widget.model'; import { FormService } from './../../../../../services/form.service'; @Component({ diff --git a/ng2-components/ng2-activiti-form/src/components/widgets/dynamic-table/editors/row.editor.spec.ts b/ng2-components/ng2-activiti-form/src/components/widgets/dynamic-table/editors/row.editor.spec.ts index c460d25fc5..6fb5e95cec 100644 --- a/ng2-components/ng2-activiti-form/src/components/widgets/dynamic-table/editors/row.editor.spec.ts +++ b/ng2-components/ng2-activiti-form/src/components/widgets/dynamic-table/editors/row.editor.spec.ts @@ -16,7 +16,7 @@ */ import { RowEditorComponent } from './row.editor'; -import { DynamicTableModel, DynamicTableRow, DynamicTableColumn, DynamicRowValidationSummary } from './../../core/index'; +import { DynamicTableModel, DynamicTableRow, DynamicTableColumn, DynamicRowValidationSummary } from './../dynamic-table.widget.model'; describe('RowEditorComponent', () => { diff --git a/ng2-components/ng2-activiti-form/src/components/widgets/dynamic-table/editors/row.editor.ts b/ng2-components/ng2-activiti-form/src/components/widgets/dynamic-table/editors/row.editor.ts index 6ca74f59b8..323bb2770c 100644 --- a/ng2-components/ng2-activiti-form/src/components/widgets/dynamic-table/editors/row.editor.ts +++ b/ng2-components/ng2-activiti-form/src/components/widgets/dynamic-table/editors/row.editor.ts @@ -16,7 +16,7 @@ */ import { Component, Input, Output, EventEmitter } from '@angular/core'; -import { DynamicTableModel, DynamicTableRow, DynamicTableColumn, DynamicRowValidationSummary } from './../../core/index'; +import { DynamicTableModel, DynamicTableRow, DynamicTableColumn, DynamicRowValidationSummary } from './../dynamic-table.widget.model'; @Component({ moduleId: module.id, diff --git a/ng2-components/ng2-activiti-form/src/components/widgets/dynamic-table/editors/text/text.editor.spec.ts b/ng2-components/ng2-activiti-form/src/components/widgets/dynamic-table/editors/text/text.editor.spec.ts index 7bfdfaf374..cb141327cb 100644 --- a/ng2-components/ng2-activiti-form/src/components/widgets/dynamic-table/editors/text/text.editor.spec.ts +++ b/ng2-components/ng2-activiti-form/src/components/widgets/dynamic-table/editors/text/text.editor.spec.ts @@ -16,7 +16,7 @@ */ import { TextEditorComponent } from './text.editor'; -import { DynamicTableRow, DynamicTableColumn } from './../../../core/index'; +import { DynamicTableRow, DynamicTableColumn } from './../../dynamic-table.widget.model'; describe('TextEditorComponent', () => { diff --git a/ng2-components/ng2-activiti-form/src/components/widgets/dynamic-table/editors/text/text.editor.ts b/ng2-components/ng2-activiti-form/src/components/widgets/dynamic-table/editors/text/text.editor.ts index 8e0bdf35e3..b7c9d069e2 100644 --- a/ng2-components/ng2-activiti-form/src/components/widgets/dynamic-table/editors/text/text.editor.ts +++ b/ng2-components/ng2-activiti-form/src/components/widgets/dynamic-table/editors/text/text.editor.ts @@ -17,7 +17,7 @@ import { Component, OnInit } from '@angular/core'; import { CellEditorComponent } from './../cell.editor'; -import { DynamicTableRow, DynamicTableColumn } from './../../../core/index'; +import { DynamicTableRow, DynamicTableColumn } from './../../dynamic-table.widget.model'; @Component({ moduleId: module.id, diff --git a/ng2-components/ng2-activiti-form/src/services/widget-visibility.service.spec.ts b/ng2-components/ng2-activiti-form/src/services/widget-visibility.service.spec.ts index b5ecc21faa..7f1fde01e7 100644 --- a/ng2-components/ng2-activiti-form/src/services/widget-visibility.service.spec.ts +++ b/ng2-components/ng2-activiti-form/src/services/widget-visibility.service.spec.ts @@ -620,6 +620,7 @@ describe('WidgetVisibilityService', () => { expect(res).toBe('value_1'); }); + /* it('should refresh the visibility for field', () => { visibilityObjTest.leftFormFieldId = 'FIELD_TEST'; visibilityObjTest.operator = '!='; @@ -637,6 +638,7 @@ describe('WidgetVisibilityService', () => { expect(column0.fields[2].isVisible).toBeTruthy(); expect(column1.fields[0].isVisible).toBeTruthy(); }); + */ it('should refresh the visibility for tab in forms', () => { visibilityObjTest.leftFormFieldId = 'FIELD_TEST'; From 29c5b61c0069986af3f09342eee712ae4ce32222 Mon Sep 17 00:00:00 2001 From: mauriziovitale84 Date: Tue, 15 Nov 2016 13:44:04 +0000 Subject: [PATCH 028/103] #1082 readonly checkbox value --- .../display-value/display-value.widget.html | 1 + .../display-value.widget.spec.ts | 77 +++++++++++++++++++ 2 files changed, 78 insertions(+) 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 cbcd9b815d..2c5b1365b2 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 @@ -3,6 +3,7 @@