diff --git a/.travis.yml b/.travis.yml index 9c3f5bad81..01b318ed4f 100644 --- a/.travis.yml +++ b/.travis.yml @@ -31,6 +31,7 @@ env: - MODULE=ng2-activiti-form - MODULE=ng2-activiti-tasklist - MODULE=ng2-activiti-processlist + - MODULE=ng2-activiti-analytics before_script: - if ([ "$MODULE" != "ng2-alfresco-core" ]); then @@ -81,3 +82,4 @@ cache: - ng2-components/ng2-alfresco-viewer/node_modules - ng2-components/ng2-alfresco-webscript/node_modules - ng2-components/ng2-alfresco-tag/node_modules + - ng2-components/ng2-alfresco-analytics/node_modules 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 382a4ec4cf..fd462fa8bd 100644 --- a/demo-shell-ng2/app/components/activiti/activiti-demo.component.html +++ b/demo-shell-ng2/app/components/activiti/activiti-demo.component.html @@ -1,30 +1,31 @@
-
-
-
+
+
-
+
Task Filters +
Task List -
@@ -36,7 +37,7 @@
-
+
@@ -61,7 +62,7 @@
-
+
diff --git a/demo-shell-ng2/app/components/activiti/activiti-demo.component.ts b/demo-shell-ng2/app/components/activiti/activiti-demo.component.ts index 55e2405e49..107d8d525a 100644 --- a/demo-shell-ng2/app/components/activiti/activiti-demo.component.ts +++ b/demo-shell-ng2/app/components/activiti/activiti-demo.component.ts @@ -20,7 +20,8 @@ import { AppDefinitionRepresentationModel, FilterRepresentationModel, UserTaskFilterRepresentationModel, - ActivitiApps + ActivitiApps, + ActivitiTaskList } from 'ng2-activiti-tasklist'; import { ActivatedRoute } from '@angular/router'; import { Subscription } from 'rxjs/Rx'; @@ -40,8 +41,6 @@ declare var componentHandler; }) export class ActivitiDemoComponent implements AfterViewChecked { - currentChoice: string = 'task-list'; - @ViewChild('activitiapps') activitiapps: ActivitiApps; @@ -52,7 +51,7 @@ export class ActivitiDemoComponent implements AfterViewChecked { activitidetails: any; @ViewChild('activititasklist') - activititasklist: any; + activititasklist: ActivitiTaskList; @ViewChild('activitiprocessfilter') activitiprocessfilter: any; @@ -63,6 +62,15 @@ export class ActivitiDemoComponent implements AfterViewChecked { @ViewChild('activitiprocessdetails') activitiprocessdetails: any; + @ViewChild('tabmain') + tabMain: any; + + @ViewChild('tabheader') + tabHeader: any; + + @Input() + appId: number; + layoutType: string; currentTaskId: string; currentProcessInstanceId: string; @@ -78,21 +86,6 @@ export class ActivitiDemoComponent implements AfterViewChecked { dataTasks: ObjectDataTableAdapter; dataProcesses: ObjectDataTableAdapter; - @Input() - appId: number; - - setChoice($event) { - this.currentChoice = $event.target.value; - } - - isProcessListSelected() { - return this.currentChoice === 'process-list'; - } - - isTaskListSelected() { - return this.currentChoice === 'task-list'; - } - constructor(private route: ActivatedRoute) { this.dataTasks = new ObjectDataTableAdapter( [], @@ -131,6 +124,16 @@ export class ActivitiDemoComponent implements AfterViewChecked { this.processFilter = null; this.currentProcessInstanceId = null; + + this.changeTab('apps', 'tasks'); + } + + changeTab(origin: string, destination: string) { + this.tabMain.nativeElement.children[origin].classList.remove('is-active'); + this.tabMain.nativeElement.children[destination].classList.add('is-active'); + + this.tabHeader.nativeElement.children[`${origin}-header`].classList.remove('is-active'); + this.tabHeader.nativeElement.children[`${destination}-header`].classList.add('is-active'); } onTaskFilterClick(event: FilterRepresentationModel) { @@ -141,6 +144,10 @@ export class ActivitiDemoComponent implements AfterViewChecked { this.taskFilter = this.activitifilter.getCurrentFilter(); } + onStartTaskSuccess(event: any) { + this.activititasklist.reload(); + } + onSuccessTaskList(event: UserTaskFilterRepresentationModel) { this.currentTaskId = this.activititasklist.getCurrentTaskId(); } diff --git a/demo-shell-ng2/app/components/login/login-demo.component.ts b/demo-shell-ng2/app/components/login/login-demo.component.ts index a2dc0a7ef7..64e1eef1ca 100644 --- a/demo-shell-ng2/app/components/login/login-demo.component.ts +++ b/demo-shell-ng2/app/components/login/login-demo.component.ts @@ -38,7 +38,7 @@ export class LoginDemoComponent implements OnInit { constructor(public router: Router) { this.customValidation = { - username: ['', Validators.compose([Validators.required, Validators.minLength(4), Validators.maxLength(15)])], + username: ['', Validators.compose([Validators.required, Validators.minLength(4)])], password: ['', Validators.required] }; } @@ -46,7 +46,6 @@ export class LoginDemoComponent implements OnInit { ngOnInit() { this.alfrescologin.addCustomValidationError('username', 'required', 'LOGIN.MESSAGES.USERNAME-REQUIRED'); this.alfrescologin.addCustomValidationError('username', 'minlength', 'LOGIN.MESSAGES.USERNAME-MIN'); - this.alfrescologin.addCustomValidationError('username', 'maxlength', 'Username must not be longer than 11 characters.'); this.alfrescologin.addCustomValidationError('password', 'required', 'LOGIN.MESSAGES.PASSWORD-REQUIRED'); } diff --git a/ng2-components/README.md b/ng2-components/README.md index 56ef91ae5f..b31c28df84 100644 --- a/ng2-components/README.md +++ b/ng2-components/README.md @@ -54,3 +54,38 @@ You can browse all the components at the following address: http://devproducts.alfresco.com/ + +## How to test a change to a generic component in its own demo + +Let's suppose that for some reason you have changed a component and you want to test this changes. +The example is based on the ng2-alfresco-login component, but you can use the same steps for any component. + + +1. Move inside the component folder and link it. +```sh + +cd ng2-alfresco-login +npm link + +``` + +2. Build the component with the watcher enabled. +```sh + +npm run build:w + +``` + +3. Move inside the demo folder and link the component to the local node_modules folder. +```sh + +cd demo +npm link ng2-alfresco-login + +``` + +4. Start the demo project. +```sh + +npm run start +``` diff --git a/ng2-components/ng2-activiti-analytics/.editorconfig b/ng2-components/ng2-activiti-analytics/.editorconfig new file mode 100644 index 0000000000..75a2477db7 --- /dev/null +++ b/ng2-components/ng2-activiti-analytics/.editorconfig @@ -0,0 +1,23 @@ +# http://editorconfig.org + +root = true + +[*] +charset = utf-8 +indent_style = space +indent_size = 4 +end_of_line = lf +insert_final_newline = true +trim_trailing_whitespace = true + +[package.json] +indent_style = space +indent_size = 2 + +[karma.conf.js] +indent_style = space +indent_size = 2 + +[*.md] +insert_final_newline = false +trim_trailing_whitespace = false diff --git a/ng2-components/ng2-activiti-analytics/.gitignore b/ng2-components/ng2-activiti-analytics/.gitignore new file mode 100644 index 0000000000..13324e66b9 --- /dev/null +++ b/ng2-components/ng2-activiti-analytics/.gitignore @@ -0,0 +1,15 @@ +npm-debug.log +node_modules +.idea +typings +coverage +dist +src/**/*.js +src/**/*.js.map +src/**/*.d.ts +demo/**/*.js +demo/**/*.js.map +demo/**/*.d.ts +index.js +index.js.map +!systemjs.config.js diff --git a/ng2-components/ng2-activiti-analytics/.npmignore b/ng2-components/ng2-activiti-analytics/.npmignore new file mode 100644 index 0000000000..16ba3e61e5 --- /dev/null +++ b/ng2-components/ng2-activiti-analytics/.npmignore @@ -0,0 +1,16 @@ +npm-debug.log +.idea + +assets/ +coverage/ +node_modules +typings/ +fonts/ + +/.editorconfig +/.travis.yml +/*.js +/*.json +/*.ts +/*.js.map +/.npmignore diff --git a/ng2-components/ng2-activiti-analytics/LICENSE b/ng2-components/ng2-activiti-analytics/LICENSE new file mode 100644 index 0000000000..430d42bbea --- /dev/null +++ b/ng2-components/ng2-activiti-analytics/LICENSE @@ -0,0 +1,177 @@ + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + +TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + +1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + +2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + +3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + +4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + +5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + +6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + +7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + +8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + +9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + +END OF TERMS AND CONDITIONS diff --git a/ng2-components/ng2-activiti-analytics/README.md b/ng2-components/ng2-activiti-analytics/README.md new file mode 100644 index 0000000000..ac208e5422 --- /dev/null +++ b/ng2-components/ng2-activiti-analytics/README.md @@ -0,0 +1,90 @@ +# Activiti Analytics Component for Angular 2 + +## Prerequisites + +Before you start using this development framework, make sure you have installed all required software and done all the +necessary configuration, see this [page](https://github.com/Alfresco/alfresco-ng2-components/blob/master/PREREQUISITES.md). + +## Install + +```sh +npm install --save ng2-activiti-analytics +``` + +#### Ng2-Charts + +```sh +npm install ng2-charts chart.js --save +``` + +Also make sure you include these dependencies in your `index.html` file: + +```html + +``` + +#### Material Design Lite + +The style of this component is based on [material design](https://getmdl.io/), so if you want to visualize it correctly you have to add the material +design dependency to your project: + +```sh +npm install --save material-design-icons material-design-lite +``` + +Also make sure you include these dependencies in your `index.html` file: + +```html + + + + +``` + +## Basic usage example Activiti Analytics + +```html + +``` + +#### Events + + +#### Options + + +## Build from sources + +Alternatively you can build component from sources with the following commands: + +```sh +npm install +npm run build +``` + +### Build the files and keep watching for changes + +```sh +$ npm run build:w +``` + +### Running unit tests + +```sh +npm test +``` + +### Running unit tests in browser + +```sh +npm test-browser +``` + +This task rebuilds all the code, runs tslint, license checks and other quality check tools +before performing unit testing. + +### Code coverage + +```sh +npm run coverage +``` diff --git a/ng2-components/ng2-activiti-analytics/assets/license_header.txt b/ng2-components/ng2-activiti-analytics/assets/license_header.txt new file mode 100644 index 0000000000..83fd1531a3 --- /dev/null +++ b/ng2-components/ng2-activiti-analytics/assets/license_header.txt @@ -0,0 +1,16 @@ +/*! + * @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. + */ \ No newline at end of file diff --git a/ng2-components/ng2-activiti-analytics/demo/.gitignore b/ng2-components/ng2-activiti-analytics/demo/.gitignore new file mode 100644 index 0000000000..25beca4c27 --- /dev/null +++ b/ng2-components/ng2-activiti-analytics/demo/.gitignore @@ -0,0 +1,6 @@ +node_modules +.idea +coverage +dist +typings +!systemjs.config.js diff --git a/ng2-components/ng2-activiti-analytics/demo/.npmignore b/ng2-components/ng2-activiti-analytics/demo/.npmignore new file mode 100644 index 0000000000..c51c008259 --- /dev/null +++ b/ng2-components/ng2-activiti-analytics/demo/.npmignore @@ -0,0 +1,3 @@ +node_modules +dist +typings \ No newline at end of file diff --git a/ng2-components/ng2-activiti-analytics/demo/README.md b/ng2-components/ng2-activiti-analytics/demo/README.md new file mode 100644 index 0000000000..cd01855a98 --- /dev/null +++ b/ng2-components/ng2-activiti-analytics/demo/README.md @@ -0,0 +1,13 @@ +# Activiti Analytics demo + +Install: + +``` +npm install +``` + +Run the project: + +``` +npm start +``` \ No newline at end of file diff --git a/ng2-components/ng2-activiti-analytics/demo/index.html b/ng2-components/ng2-activiti-analytics/demo/index.html new file mode 100644 index 0000000000..40958146d8 --- /dev/null +++ b/ng2-components/ng2-activiti-analytics/demo/index.html @@ -0,0 +1,38 @@ + + + + + Angular 2 Activiti Analitics - Demo + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/ng2-components/ng2-activiti-analytics/demo/package.json b/ng2-components/ng2-activiti-analytics/demo/package.json new file mode 100644 index 0000000000..b5ca93725d --- /dev/null +++ b/ng2-components/ng2-activiti-analytics/demo/package.json @@ -0,0 +1,82 @@ +{ + "name": "ng2-activiti-analytics-demo", + "description": "Alfresco Angular2 Analytics Component - Demo", + "version": "0.1.0", + "author": "Alfresco Software, Ltd.", + "main": "index.js", + "scripts": { + "clean": "rimraf dist node_modules", + "postinstall": "npm run build", + "start": "npm run build && concurrently \"npm run tsc:w\" \"npm run server\" ", + "server": "wsrv -o -s -l", + "build": "npm run tslint && rimraf dist && npm run tsc", + "tsc": "tsc", + "tsc:w": "tsc -w", + "tslint": "tslint -c tslint.json *.ts && tslint -c tslint.json src/{,**/}**.ts" + }, + "license": "Apache-2.0", + "dependencies": { + "@angular/common": "2.0.0-rc.3", + "@angular/compiler": "2.0.0-rc.3", + "@angular/core": "2.0.0-rc.3", + "@angular/forms": "0.1.1", + "@angular/http": "2.0.0-rc.3", + "@angular/platform-browser": "2.0.0-rc.3", + "@angular/platform-browser-dynamic": "2.0.0-rc.3", + "@angular/router": "3.0.0-alpha.7", + "@angular/router-deprecated": "2.0.0-rc.2", + "@angular/upgrade": "2.0.0-rc.3", + "systemjs": "0.19.27", + "core-js": "2.4.0", + "reflect-metadata": "0.1.3", + "rxjs": "5.0.0-beta.6", + "zone.js": "0.6.12", + "license-check": "1.1.5", + "material-design-icons": "2.2.3", + "material-design-lite": "1.1.3", + "ng2-translate": "2.2.2", + "alfresco-js-api": "^0.3.0", + "ng2-alfresco-core": "^0.3.0", + "ng2-activiti-analytics": "^0.3.0", + "chart.js": "^2.1.4", + "ng2-charts": "1.1.0" + }, + "devDependencies": { + "@types/core-js": "^0.9.32", + "@types/jasmine": "^2.2.33", + "concurrently": "^2.2.0", + "rimraf": "2.5.2", + "tslint": "3.8.1", + "typescript": "^2.0.2", + "wsrv": "^0.1.5" + }, + "keywords": [ + "angular2", + "typescript" + ], + "license-check-config": { + "src": [ + "**/*.js", + "**/*.ts", + "!/**/coverage/**/*", + "!/**/demo/**/*", + "!/**/node_modules/**/*", + "!/**/typings/**/*", + "!*.js" + ], + "contributors": [ + { + "name": "Maurizio Vitale", + "email": "maurizio.vitale84@gmail.com" + }, + { + "name": "Eugenio Romano", + "email": "eugenio.romano@alfresco.com" + } + ], + "path": "assets/license_header.txt", + "blocking": true, + "logInfo": false, + "logError": true + } +} diff --git a/ng2-components/ng2-activiti-analytics/demo/src/main.ts b/ng2-components/ng2-activiti-analytics/demo/src/main.ts new file mode 100644 index 0000000000..18646719c7 --- /dev/null +++ b/ng2-components/ng2-activiti-analytics/demo/src/main.ts @@ -0,0 +1,33 @@ +/*! + * @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 { bootstrap } from '@angular/platform-browser-dynamic'; +import { Component } from '@angular/core'; +import { ALFRESCO_CORE_PROVIDERS } from 'ng2-alfresco-core'; +import { AnalyticsComponent } from 'ng2-activiti-analytics'; + +@Component({ + selector: 'activiti-analytics-demo', + template: ``, + directives: [AnalyticsComponent] +}) +class ActivitiAnalyticsDemo { +} + +bootstrap(ActivitiAnalyticsDemo, [ + ALFRESCO_CORE_PROVIDERS] +); diff --git a/ng2-components/ng2-activiti-analytics/demo/systemjs.config.js b/ng2-components/ng2-activiti-analytics/demo/systemjs.config.js new file mode 100644 index 0000000000..9cb172062c --- /dev/null +++ b/ng2-components/ng2-activiti-analytics/demo/systemjs.config.js @@ -0,0 +1,57 @@ +/** + * System configuration for Angular 2 samples + * Adjust as necessary for your application needs. + */ +(function(global) { + // map tells the System loader where to look for things + var map = { + 'app': 'dist', // 'dist', + '@angular': 'node_modules/@angular', + 'angular2-in-memory-web-api': 'node_modules/angular2-in-memory-web-api', + 'rxjs': 'node_modules/rxjs', + + 'ng2-charts': 'node_modules/ng2-charts', + 'ng2-translate': 'node_modules/ng2-translate', + 'ng2-alfresco-core': 'node_modules/ng2-alfresco-core/dist', + 'ng2-activiti-analytics': 'node_modules/ng2-activiti-analytics/dist' + }; + // packages tells the System loader how to load when no filename and/or no extension + var packages = { + 'app': { main: 'main.js', defaultExtension: 'js' }, + 'rxjs': { defaultExtension: 'js' }, + 'angular2-in-memory-web-api': { main: 'index.js', defaultExtension: 'js' }, + + 'ng2-translate': { defaultExtension: 'js' }, + 'ng2-alfresco-core': { main: 'index.js', defaultExtension: 'js' }, + 'ng2-activiti-analytics': { main: 'index.js', defaultExtension: 'js' }, + 'ng2-charts': { main: 'ng2-charts.js', defaultExtension: 'js'} + }; + var ngPackageNames = [ + 'common', + 'compiler', + 'core', + 'http', + 'platform-browser', + 'platform-browser-dynamic', + 'router', + 'router-deprecated', + 'upgrade' + ]; + // Individual files (~300 requests): + function packIndex(pkgName) { + packages['@angular/'+pkgName] = { main: 'index.js', defaultExtension: 'js' }; + } + // Bundled (~40 requests): + function packUmd(pkgName) { + packages['@angular/'+pkgName] = { main: '/bundles/' + pkgName + '.umd.js', defaultExtension: 'js' }; + } + // Most environments should use UMD; some (Karma) need the individual index files + var setPackageConfig = System.packageWithIndex ? packIndex : packUmd; + // Add package entries for angular packages + ngPackageNames.forEach(setPackageConfig); + var config = { + map: map, + packages: packages + }; + System.config(config); +})(this); diff --git a/ng2-components/ng2-activiti-analytics/demo/tsconfig.json b/ng2-components/ng2-activiti-analytics/demo/tsconfig.json new file mode 100644 index 0000000000..769b0067ef --- /dev/null +++ b/ng2-components/ng2-activiti-analytics/demo/tsconfig.json @@ -0,0 +1,18 @@ +{ + "compilerOptions": { + "target": "ES5", + "module": "system", + "moduleResolution": "node", + "emitDecoratorMetadata": true, + "experimentalDecorators": true, + "sourceMap": true, + "removeComments": true, + "declaration": true, + "outDir": "dist", + "types": ["core-js", "jasmine"] + }, + "exclude": [ + "dist", + "node_modules" + ] +} diff --git a/ng2-components/ng2-activiti-analytics/demo/tslint.json b/ng2-components/ng2-activiti-analytics/demo/tslint.json new file mode 100644 index 0000000000..8c48e76469 --- /dev/null +++ b/ng2-components/ng2-activiti-analytics/demo/tslint.json @@ -0,0 +1,124 @@ +{ + "rules": { + "align": [ + true, + "parameters", + "arguments", + "statements" + ], + "ban": false, + "class-name": true, + "comment-format": [ + true, + "check-space", + "check-lowercase" + ], + "curly": true, + "eofline": true, + "forin": true, + "indent": [ + true, + "spaces" + ], + "interface-name": false, + "jsdoc-format": true, + "label-position": true, + "label-undefined": true, + "max-line-length": [ + true, + 140 + ], + "member-ordering": [ + true, + "public-before-private", + "static-before-instance", + "variables-before-functions" + ], + "no-any": false, + "no-arg": true, + "no-bitwise": true, + "no-conditional-assignment": true, + "no-consecutive-blank-lines": false, + "no-console": [ + true, + "debug", + "info", + "time", + "timeEnd", + "trace" + ], + "no-construct": true, + "no-constructor-vars": false, + "no-debugger": true, + "no-duplicate-key": true, + "no-duplicate-variable": true, + "no-empty": true, + "no-eval": true, + "no-inferrable-types": false, + "no-internal-module": true, + "no-require-imports": true, + "no-shadowed-variable": true, + "no-switch-case-fall-through": true, + "no-trailing-whitespace": true, + "no-unreachable": true, + "no-unused-expression": true, + "no-unused-variable": true, + "no-use-before-declare": true, + "no-var-keyword": true, + "no-var-requires": true, + "object-literal-sort-keys": false, + "one-line": [ + true, + "check-open-brace", + "check-catch", + "check-else", + "check-whitespace" + ], + "quotemark": [ + true, + "single", + "avoid-escape" + ], + "radix": true, + "semicolon": true, + "switch-default": true, + "trailing-comma": [ + true, + { + "multiline": "never", + "singleline": "never" + } + ], + "triple-equals": [ + true, + "allow-null-check" + ], + "typedef": false, + "typedef-whitespace": [ + true, + { + "call-signature": "nospace", + "index-signature": "nospace", + "parameter": "nospace", + "property-declaration": "nospace", + "variable-declaration": "nospace" + } + ], + "use-strict": false, + "variable-name": [ + true, + "check-format", + "allow-leading-underscore", + "ban-keywords" + ], + "whitespace": [ + true, + "check-branch", + "check-operator", + "check-separator", + "check-type", + "check-module", + "check-decl" + ] + } +} diff --git a/ng2-components/ng2-activiti-analytics/index.ts b/ng2-components/ng2-activiti-analytics/index.ts new file mode 100644 index 0000000000..001531d6b3 --- /dev/null +++ b/ng2-components/ng2-activiti-analytics/index.ts @@ -0,0 +1,18 @@ +/*! + * @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 * from './src/components/analytics.component'; diff --git a/ng2-components/ng2-activiti-analytics/karma-test-shim.js b/ng2-components/ng2-activiti-analytics/karma-test-shim.js new file mode 100644 index 0000000000..5a6d23240a --- /dev/null +++ b/ng2-components/ng2-activiti-analytics/karma-test-shim.js @@ -0,0 +1,109 @@ +// Tun on full stack traces in errors to help debugging +Error.stackTraceLimit = Infinity; + +jasmine.DEFAULT_TIMEOUT_INTERVAL = 1000; + +__karma__.loaded = function() {}; + +var map = { + 'app': 'base/dist', + 'rxjs': 'base/node_modules/rxjs', + '@angular': 'base/node_modules/@angular', + 'ng2-translate' : '/base/node_modules/ng2-translate', + 'ng2-charts' : '/base/node_modules/ng2-charts', + 'ng2-alfresco-core': '/base/node_modules/ng2-alfresco-core/dist' +}; + +var packages = { + 'app': { main: 'main.js', defaultExtension: 'js' }, + 'rxjs': { defaultExtension: 'js' }, + 'ng2-translate': { defaultExtension: 'js' }, + 'ng2-charts': { defaultExtension: 'js' }, + 'ng2-alfresco-core': { main: 'index.js', defaultExtension: 'js' } +}; + +var packageNames = [ + '@angular/common', + '@angular/compiler', + '@angular/core', + '@angular/http', + '@angular/platform-browser', + '@angular/platform-browser-dynamic', + '@angular/router', + '@angular/router-deprecated', + '@angular/testing', + '@angular/upgrade' +]; + +packageNames.forEach(function(pkgName) { + packages[pkgName] = { main: 'index.js', defaultExtension: 'js' }; +}); + +packages['base/dist'] = { + defaultExtension: 'js', + format: 'register', + map: Object.keys(window.__karma__.files).filter(onlyAppFiles).reduce(createPathRecords, {}) +}; + +var config = { + map: map, + packages: packages +}; + +System.config(config); + +System.import('@angular/platform-browser/src/browser/browser_adapter') + .then(function(browser_adapter) { browser_adapter.BrowserDomAdapter.makeCurrent(); }) + .then(function () { + return Promise.all([ + System.import('@angular/core/testing'), + System.import('@angular/platform-browser-dynamic/testing') + ]) + }) + .then(function (providers) { + var testing = providers[0]; + var testingBrowser = providers[1]; + + testing.setBaseTestProviders( + testingBrowser.TEST_BROWSER_DYNAMIC_PLATFORM_PROVIDERS, + testingBrowser.TEST_BROWSER_DYNAMIC_APPLICATION_PROVIDERS); + + }) + .then(function() { return Promise.all(resolveTestFiles()); }) + .then( + function() { + __karma__.start(); + }, + function(error) { + if(typeof __karma__.error == 'function') { + __karma__.error(error.stack || error); + }else{ + console.error(error); + } + } + ); +function createPathRecords(pathsMapping, appPath) { + var pathParts = appPath.split('/'); + var moduleName = './' + pathParts.slice(Math.max(pathParts.length - 2, 1)).join('/'); + moduleName = moduleName.replace(/\.js$/, ''); + pathsMapping[moduleName] = appPath + '?' + window.__karma__.files[appPath]; + return pathsMapping; +} + +function onlyAppFiles(filePath) { + return /\/base\/dist\/(?!.*\.spec\.js$).*\.js$/.test(filePath); +} + +function onlySpecFiles(path) { + return /\.spec\.js$/.test(path); +} + +function resolveTestFiles() { + return Object.keys(window.__karma__.files) // All files served by Karma. + .filter(onlySpecFiles) + .map(function(moduleName) { + // loads all spec files via their global module names (e.g. + // 'base/dist/vg-player/vg-player.spec') + return System.import(moduleName); + }); +} diff --git a/ng2-components/ng2-activiti-analytics/karma.conf.js b/ng2-components/ng2-activiti-analytics/karma.conf.js new file mode 100644 index 0000000000..9f91a8ed86 --- /dev/null +++ b/ng2-components/ng2-activiti-analytics/karma.conf.js @@ -0,0 +1,100 @@ +'use strict'; + +module.exports = function (config) { + var configuration = { + basePath: '.', + + frameworks: ['jasmine-ajax', 'jasmine'], + + files: [ + // paths loaded by Karma + {pattern: 'node_modules/reflect-metadata/Reflect.js', included: true, watched: true}, + {pattern: 'node_modules/systemjs/dist/system.src.js', included: true, watched: false}, + {pattern: 'node_modules/zone.js/dist/zone.js', included: true, watched: true}, + {pattern: 'node_modules/rxjs/**/*.js', included: false, watched: false}, + {pattern: 'node_modules/rxjs/**/*.map', included: false, watched: false}, + {pattern: 'node_modules/@angular/**/*.js', included: false, watched: false}, + {pattern: 'node_modules/@angular/**/*.map', included: false, watched: false}, + {pattern: 'node_modules/ng2-alfresco-core/dist/**/*.js', included: false, served: true, watched: false}, + {pattern: 'node_modules/ng2-translate/**/*.js', included: false, served: true, watched: false}, + {pattern: 'node_modules/ng2-charts/**/*.js', included: false, served: true, watched: false}, + {pattern: 'node_modules/alfresco-js-api/dist/alfresco-js-api.js', included: true, watched: false}, + + {pattern: 'karma-test-shim.js', included: true, watched: true}, + + // paths loaded via module imports + {pattern: 'dist/**/*.js', included: false, watched: true}, + {pattern: 'dist/**/*.html', included: true, served: true, watched: true}, + {pattern: 'dist/**/*.css', included: true, served: true, watched: true}, + + // paths to support debugging with source maps in dev tools + {pattern: 'src/**/*.ts', included: false, watched: false}, + {pattern: 'dist/**/*.js.map', included: false, watched: false} + ], + + exclude: [ + 'node_modules/**/*spec.js' + ], + + // proxied base paths + proxies: { + // required for component assets fetched by Angular's compiler + '/src/': '/base/src/' + }, + + port: 9876, + + // level of logging + // possible values: config.LOG_DISABLE || config.LOG_ERROR || config.LOG_WARN || config.LOG_INFO || config.LOG_DEBUG + logLevel: config.LOG_INFO, + + colors: true, + + autoWatch: true, + + browsers: ['Chrome'], + + customLaunchers: { + Chrome_travis_ci: { + base: 'Chrome', + flags: ['--no-sandbox'] + } + }, + + // Karma plugins loaded + plugins: [ + 'karma-jasmine', + 'karma-coverage', + 'karma-jasmine-ajax', + 'karma-chrome-launcher', + 'karma-mocha-reporter', + 'karma-jasmine-html-reporter' + ], + + // Coverage reporter generates the coverage + reporters: ['mocha', 'coverage', 'kjhtml'], + + // Source files that you wanna generate coverage for. + // Do not include tests or libraries (these files will be instrumented by Istanbul) + preprocessors: { + 'dist/**/!(*spec).js': ['coverage'] + }, + + coverageReporter: { + dir: 'coverage/', + subdir: 'report', + reporters: [ + {type: 'text'}, + {type: 'json', file: 'coverage-final.json'}, + {type: 'html'}, + {type: 'lcov'} + ] + } + }; + + if (process.env.TRAVIS) { + configuration.browsers = ['Chrome_travis_ci']; + } + + config.set(configuration) +}; diff --git a/ng2-components/ng2-activiti-analytics/package.json b/ng2-components/ng2-activiti-analytics/package.json new file mode 100644 index 0000000000..11a5f10465 --- /dev/null +++ b/ng2-components/ng2-activiti-analytics/package.json @@ -0,0 +1,98 @@ +{ + "name": "ng2-activiti-analytics", + "description": "Activiti Angular2 Analytics Component", + "version": "0.3.3", + "author": "Alfresco Software, Ltd.", + "scripts": { + "clean": "rimraf dist node_modules", + "build": "npm run tslint && rimraf dist && tsc && npm run copy-dist && license-check", + "build:w": "npm run tslint && rimraf dist && npm run watch-task", + "watch-task": "concurrently \"npm run tsc:w\" \"npm run copy-dist:w\" \"license-check\"", + "tslint": "tslint -c tslint.json *.ts && tslint -c tslint.json 'src/{,**/}**.ts'", + "copy-dist": "cpx \"./src/**/*.{html,css,json,png,jpg,gif,svg}\" ./dist/src", + "copy-dist:w": "cpx \"./src/**/*.{html,css,json,png,jpg,gif,svg}\" ./dist/src -w", + "tsc": "tsc", + "tsc:w": "tsc -w", + "pretest": "npm run build", + "test": "karma start karma.conf.js --reporters mocha,coverage --single-run", + "test-browser": "concurrently \"karma start karma.conf.js --reporters kjhtml\" \"npm run watch-task\"", + "posttest": "node_modules/.bin/remap-istanbul -i coverage/report/coverage-final.json -o coverage/report -t html && node_modules/.bin/remap-istanbul -i coverage/report/coverage-final.json -o coverage/report/coverage-final.json", + "coverage": "npm run test && wsrv -o -p 9875 ./coverage/report", + "prepublish": "npm run build", + "travis": "echo 'placeholder'" + }, + "main": "./dist/index.js", + "typings": "./dist/index.d.ts", + "repository": { + "type": "git", + "url": "https://github.com/Alfresco/alfresco-ng2-components.git" + }, + "bugs": { + "url": "https://github.com/Alfresco/alfresco-ng2-components/issues" + }, + "license": "Apache-2.0", + "contributors": [ + { + "name": "Mario Romano", + "email": "mario.romnao@alfresco.com" + } + ], + "keywords": [ + "ng2", + "angular", + "angular2", + "alfresco" + ], + "dependencies": { + "@angular/common": "2.0.0-rc.3", + "@angular/compiler": "2.0.0-rc.3", + "@angular/core": "2.0.0-rc.3", + "@angular/forms": "0.1.1", + "@angular/http": "2.0.0-rc.3", + "@angular/platform-browser": "2.0.0-rc.3", + "@angular/platform-browser-dynamic": "2.0.0-rc.3", + "@angular/router": "3.0.0-alpha.7", + "@angular/router-deprecated": "2.0.0-rc.2", + "@angular/upgrade": "2.0.0-rc.3", + "systemjs": "0.19.27", + "core-js": "2.4.0", + "reflect-metadata": "0.1.3", + "rxjs": "5.0.0-beta.6", + "zone.js": "0.6.12", + "chart.js": "^2.1.4", + "ng2-charts": "1.1.0", + "ng2-translate": "2.2.2", + "ng2-alfresco-core": "0.3.2", + "alfresco-js-api": "^0.3.0" + }, + "devDependencies": { + "@types/core-js": "^0.9.32", + "@types/jasmine": "^2.2.33", + "concurrently": "^2.2.0", + "cpx": "1.3.1", + "jasmine-core": "2.4.1", + "karma": "0.13.22", + "karma-chrome-launcher": "1.0.1", + "karma-coverage": "1.0.0", + "karma-jasmine": "1.0.2", + "karma-jasmine-ajax": "0.1.13", + "karma-mocha-reporter": "2.0.3", + "karma-jasmine-html-reporter": "0.2.0", + "license-check": "1.1.5", + "rimraf": "2.5.2", + "remap-istanbul": "0.6.3", + "traceur": "0.0.91", + "tslint": "3.8.1", + "typescript": "^2.0.2", + "wsrv": "^0.1.5" + }, + "license-check-config": { + "src": [ + "./dist/**/*.js" + ], + "path": "assets/license_header.txt", + "blocking": true, + "logInfo": false, + "logError": true + } +} diff --git a/ng2-components/ng2-activiti-analytics/src/components/analytics.component.html b/ng2-components/ng2-activiti-analytics/src/components/analytics.component.html new file mode 100644 index 0000000000..5bb81bc756 --- /dev/null +++ b/ng2-components/ng2-activiti-analytics/src/components/analytics.component.html @@ -0,0 +1,21 @@ +
+ + +
+
+ +
+
+ +
diff --git a/ng2-components/ng2-activiti-analytics/src/components/analytics.component.spec.ts b/ng2-components/ng2-activiti-analytics/src/components/analytics.component.spec.ts new file mode 100644 index 0000000000..e79859d36d --- /dev/null +++ b/ng2-components/ng2-activiti-analytics/src/components/analytics.component.spec.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 { describe, expect, it, inject } from '@angular/core/testing'; +import { TestComponentBuilder } from '@angular/compiler/testing'; +import { AnalyticsComponent } from './analytics.component'; + +describe('Show component HTML', () => { + it('Display component tag base-chart', inject([TestComponentBuilder], (tcb: TestComponentBuilder) => { + return tcb + .createAsync(AnalyticsComponent) + .then((fixture) => { + let element = fixture.nativeElement; + expect(element.getElementsByTagName('base-chart')[0].innerHTML).toBeDefined(); + }); + })); +}); diff --git a/ng2-components/ng2-activiti-analytics/src/components/analytics.component.ts b/ng2-components/ng2-activiti-analytics/src/components/analytics.component.ts new file mode 100644 index 0000000000..dae27819a5 --- /dev/null +++ b/ng2-components/ng2-activiti-analytics/src/components/analytics.component.ts @@ -0,0 +1,62 @@ +/*! + * @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 { CORE_DIRECTIVES, FORM_DIRECTIVES, NgClass } from '@angular/common'; + +import { CHART_DIRECTIVES } from 'ng2-charts/ng2-charts'; + +declare let __moduleName: string; + +@Component({ + moduleId: __moduleName, + selector: 'activiti-analytics', + templateUrl: './analytics.component.html', + directives: [CHART_DIRECTIVES, NgClass, CORE_DIRECTIVES, FORM_DIRECTIVES] +}) +export class AnalyticsComponent { + + constructor() { + console.log('AnalyticsComponent'); + } + + // lineChart + public lineChartData: Array = [ + [65, 59, 80, 81, 56, 55, 40], + [28, 48, 40, 19, 86, 27, 90] + ]; + public lineChartLabels: Array = ['January', 'February', 'March', 'April', 'May', 'June', 'July']; + public lineChartType: string = 'line'; + public pieChartType: string = 'pie'; + + // Pie + public pieChartLabels: string[] = ['Download Sales', 'In-Store Sales', 'Mail Sales']; + public pieChartData: number[] = [300, 500, 100]; + + public randomizeType(): void { + this.lineChartType = this.lineChartType === 'line' ? 'bar' : 'line'; + this.pieChartType = this.pieChartType === 'doughnut' ? 'pie' : 'doughnut'; + } + + public chartClicked(e: any): void { + console.log(e); + } + + public chartHovered(e: any): void { + console.log(e); + } +} diff --git a/ng2-components/ng2-activiti-analytics/src/i18n/en.json b/ng2-components/ng2-activiti-analytics/src/i18n/en.json new file mode 100644 index 0000000000..3afc878e36 --- /dev/null +++ b/ng2-components/ng2-activiti-analytics/src/i18n/en.json @@ -0,0 +1,5 @@ +{ + "ANALYTICS": { + "TTILE": "ANALYTICS" + } +} diff --git a/ng2-components/ng2-activiti-analytics/src/i18n/it.json b/ng2-components/ng2-activiti-analytics/src/i18n/it.json new file mode 100644 index 0000000000..15c05b6832 --- /dev/null +++ b/ng2-components/ng2-activiti-analytics/src/i18n/it.json @@ -0,0 +1,5 @@ +{ + "ANALYTICS": { + "TTILE": "ANALYTICS" + } +} diff --git a/ng2-components/ng2-activiti-analytics/tsconfig.json b/ng2-components/ng2-activiti-analytics/tsconfig.json new file mode 100644 index 0000000000..b1effea355 --- /dev/null +++ b/ng2-components/ng2-activiti-analytics/tsconfig.json @@ -0,0 +1,26 @@ +{ + "compilerOptions": { + "target": "es5", + "module": "system", + "moduleResolution": "node", + "emitDecoratorMetadata": true, + "experimentalDecorators": true, + "sourceMap": true, + "removeComments": true, + "declaration": true, + "noLib": false, + "allowUnreachableCode": false, + "allowUnusedLabels": false, + "noImplicitAny": false, + "noImplicitReturns": false, + "noImplicitUseStrict": false, + "noFallthroughCasesInSwitch": true, + "outDir": "dist", + "types": ["core-js", "jasmine"] + }, + "exclude": [ + "demo", + "node_modules", + "dist" + ] +} diff --git a/ng2-components/ng2-activiti-analytics/tslint.json b/ng2-components/ng2-activiti-analytics/tslint.json new file mode 100644 index 0000000000..85e9df53c1 --- /dev/null +++ b/ng2-components/ng2-activiti-analytics/tslint.json @@ -0,0 +1,121 @@ +{ + "rules": { + "align": [ + true, + "parameters", + "statements" + ], + "ban": false, + "class-name": true, + "comment-format": [ + true, + "check-space" + ], + "curly": true, + "eofline": true, + "forin": true, + "indent": [ + true, + "spaces" + ], + "interface-name": false, + "jsdoc-format": true, + "label-position": true, + "label-undefined": true, + "max-line-length": [ + true, + 180 + ], + "member-ordering": [ + true, + "static-before-instance", + "variables-before-functions" + ], + "no-any": false, + "no-arg": true, + "no-bitwise": false, + "no-conditional-assignment": true, + "no-consecutive-blank-lines": false, + "no-console": [ + true, + "debug", + "info", + "time", + "timeEnd", + "trace" + ], + "no-construct": true, + "no-constructor-vars": false, + "no-debugger": true, + "no-duplicate-key": true, + "no-duplicate-variable": true, + "no-empty": false, + "no-eval": true, + "no-inferrable-types": false, + "no-internal-module": true, + "no-require-imports": true, + "no-shadowed-variable": true, + "no-switch-case-fall-through": true, + "no-trailing-whitespace": true, + "no-unreachable": true, + "no-unused-expression": true, + "no-unused-variable": true, + "no-use-before-declare": true, + "no-var-keyword": true, + "no-var-requires": true, + "object-literal-sort-keys": false, + "one-line": [ + true, + "check-open-brace", + "check-catch", + "check-else", + "check-whitespace" + ], + "quotemark": [ + true, + "single", + "avoid-escape" + ], + "radix": true, + "semicolon": true, + "switch-default": true, + "trailing-comma": [ + true, + { + "multiline": "never", + "singleline": "never" + } + ], + "triple-equals": [ + true, + "allow-null-check" + ], + "typedef": false, + "typedef-whitespace": [ + true, + { + "call-signature": "nospace", + "index-signature": "nospace", + "parameter": "nospace", + "property-declaration": "nospace", + "variable-declaration": "nospace" + } + ], + "use-strict": false, + "variable-name": [ + true, + "check-format", + "allow-leading-underscore", + "ban-keywords" + ], + "whitespace": [ + true, + "check-branch", + "check-operator", + "check-separator", + "check-type", + "check-module", + "check-decl" + ] + } +} diff --git a/ng2-components/ng2-activiti-form/src/components/widgets/upload/upload.widget.ts b/ng2-components/ng2-activiti-form/src/components/widgets/upload/upload.widget.ts index 57d355bfc6..b8981b9f90 100644 --- a/ng2-components/ng2-activiti-form/src/components/widgets/upload/upload.widget.ts +++ b/ng2-components/ng2-activiti-form/src/components/widgets/upload/upload.widget.ts @@ -30,13 +30,14 @@ declare var componentHandler; }) export class UploadWidget extends WidgetComponent implements OnInit { + hasFile: boolean; + fileName: string; + constructor(private settingsService: AlfrescoSettingsService, private authService: AlfrescoAuthenticationService) { super(); } - hasFile: boolean; - fileName: string; ngOnInit() { if (this.field && 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 56249235b4..ae7a235960 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 @@ -81,7 +81,7 @@ export class WidgetVisibilityService { private getLeftValue(form: FormModel, visibilityObj: WidgetVisibilityModel) { if ( visibilityObj.leftRestResponseId ) { - return this.getValueFromVariable(form, visibilityObj.leftRestResponseId); + return this.getValueFromVariable(form, visibilityObj.leftRestResponseId, this.processVarList); } return this.getValueOField(form, visibilityObj.leftFormFieldId); } @@ -89,7 +89,7 @@ export class WidgetVisibilityService { private getRightValue(form: FormModel, visibilityObj: WidgetVisibilityModel) { let valueFound = null; if ( visibilityObj.rightRestResponseId ) { - valueFound = this.getValueFromVariable(form, visibilityObj.rightRestResponseId); + valueFound = this.getValueFromVariable(form, visibilityObj.rightRestResponseId, this.processVarList); }else if ( visibilityObj.rightFormFieldId ) { valueFound = this.getValueOField(form, visibilityObj.rightFormFieldId); }else { @@ -116,18 +116,29 @@ export class WidgetVisibilityService { } } } - return null; } - private getValueFromVariable(form: FormModel, name: string) { - let formVariable = form.json.variables.find(formVar => formVar.name === name); - if ( !formVariable && this.processVarList ) { - formVariable = this.processVarList.find(variable => variable.id === name); - } - if ( formVariable ) { - return formVariable.value; - } - return null; + private getValueFromVariable( form: FormModel, name: string, processVarList: TaskProcessVariableModel[] ) { + return this.getFormVariableValue(form, name) || + this.getProcessVariableValue(name, processVarList); + } + + private getFormVariableValue(form: FormModel, name: string ) { + if ( form.json.variables) { + let variableFromForm = form.json.variables.find(formVar => formVar.name === name); + if ( variableFromForm ) { + return variableFromForm ? variableFromForm.value : variableFromForm; + } + } + } + + private getProcessVariableValue(name: string, processVarList: TaskProcessVariableModel[]) { + if ( this.processVarList ) { + let variableFromProcess = this.processVarList.find(variable => variable.id === name); + if ( variableFromProcess ) { + return variableFromProcess ? variableFromProcess.value : variableFromProcess; + } + } } private evaluateLogicalOperation(logicOp, previousValue, newValue): boolean { @@ -168,7 +179,7 @@ export class WidgetVisibilityService { console.error( 'NO valid operation!' ); break; } - return null; + return; } getTaskProcessVariableModelsForTask(taskId: string): Observable { diff --git a/ng2-components/ng2-activiti-processlist/src/components/activiti-filters.component.ts b/ng2-components/ng2-activiti-processlist/src/components/activiti-filters.component.ts index 4d13f3e5ef..b249be68a5 100644 --- a/ng2-components/ng2-activiti-processlist/src/components/activiti-filters.component.ts +++ b/ng2-components/ng2-activiti-processlist/src/components/activiti-filters.component.ts @@ -68,33 +68,43 @@ export class ActivitiProcessFilters implements OnInit, OnChanges { this.filters.push(filter); }); - this.load(); + this.getFilters(this.appId, this.appName); } ngOnChanges(changes: SimpleChanges) { let appId = changes['appId']; - if (appId && appId.currentValue) { - this.load(); + if (appId && (appId.currentValue || appId.currentValue === null)) { + this.getFiltersByAppId(appId.currentValue); + return; + } + let appName = changes['appName']; + if (appName && appName.currentValue) { + this.getFiltersByAppName(appName.currentValue); return; } } /** - * The method call the adapter data table component for render the task list - * @param tasks + * Return the task list filtered by appId or by appName + * @param appId + * @param appName */ - private load() { - this.resetFilter(); - if (this.appName) { - this.filterByAppName(); + getFilters(appId?: string, appName?: string) { + if (appName) { + this.getFiltersByAppName(appName); } else { - this.filterByAppId(this.appId); + this.getFiltersByAppId(appId); } } - private filterByAppId(appId) { + /** + * Return the filter list filtered by appId + * @param appId - optional + */ + getFiltersByAppId(appId?: string) { this.activiti.getProcessFilters(appId).subscribe( (res: FilterRepresentationModel[]) => { + this.resetFilter(); res.forEach((filter) => { this.filterObserver.next(filter); }); @@ -108,10 +118,14 @@ export class ActivitiProcessFilters implements OnInit, OnChanges { ); } - private filterByAppName() { - this.activiti.getDeployedApplications(this.appName).subscribe( + /** + * Return the filter list filtered by appName + * @param appName + */ + getFiltersByAppName(appName: string) { + this.activiti.getDeployedApplications(appName).subscribe( application => { - this.filterByAppId(application.id); + this.getFiltersByAppId(application.id); this.selectFirstFilter(); }, (err) => { diff --git a/ng2-components/ng2-activiti-processlist/src/components/activiti-start-process.component.html b/ng2-components/ng2-activiti-processlist/src/components/activiti-start-process.component.html index e5ca33e2be..f33ad4fb17 100644 --- a/ng2-components/ng2-activiti-processlist/src/components/activiti-start-process.component.html +++ b/ng2-components/ng2-activiti-processlist/src/components/activiti-start-process.component.html @@ -12,7 +12,7 @@
- +
diff --git a/ng2-components/ng2-activiti-tasklist/README.md b/ng2-components/ng2-activiti-tasklist/README.md index 374581a818..c8b225ebc9 100644 --- a/ng2-components/ng2-activiti-tasklist/README.md +++ b/ng2-components/ng2-activiti-tasklist/README.md @@ -106,8 +106,13 @@ The component shows the details of the task id passed in input #### Options -**taskId**: { string } required) The id of the task details that we -are asking for. +**taskId**: { string } required) The id of the task details that we are asking for. +**showNextTask**: { boolean } optional) Automatically render the next one, when the task is completed. +**showFormTitle**: { boolean } optional) Toggle rendering of the form title. +**readOnlyForm**: { boolean } optional) Toggle readonly state of the form. Enforces all form widgets render readonly if enabled. +**showFormRefreshButton**: { boolean } optional) Toggle rendering of the `Refresh` button. +**showFormSaveButton**: { boolean } optional) Toggle rendering of the `Save` outcome button. +**showFormCompleteButton**: { boolean } optional) Toggle rendering of the Form `Complete` outcome button ### Custom 'empty Activiti Task Details' template diff --git a/ng2-components/ng2-activiti-tasklist/demo/README.md b/ng2-components/ng2-activiti-tasklist/demo/README.md index 28b3ffd976..14d905ea85 100644 --- a/ng2-components/ng2-activiti-tasklist/demo/README.md +++ b/ng2-components/ng2-activiti-tasklist/demo/README.md @@ -1,4 +1,4 @@ -# DataTable demo +# TasK list demo Install: diff --git a/ng2-components/ng2-activiti-tasklist/demo/package.json b/ng2-components/ng2-activiti-tasklist/demo/package.json index 5bc2ee954a..796dd7fc62 100644 --- a/ng2-components/ng2-activiti-tasklist/demo/package.json +++ b/ng2-components/ng2-activiti-tasklist/demo/package.json @@ -1,6 +1,6 @@ { "name": "ng2-activiti-tasklist-demo", - "description": "Alfresco Angular2 DataTable Component - Demo", + "description": "Alfresco Angular2 Task List Component - Demo", "version": "0.1.0", "author": "Alfresco Software, Ltd.", "main": "index.js", diff --git a/ng2-components/ng2-activiti-tasklist/index.ts b/ng2-components/ng2-activiti-tasklist/index.ts index 520c7e71ba..b6c3b1cf53 100644 --- a/ng2-components/ng2-activiti-tasklist/index.ts +++ b/ng2-components/ng2-activiti-tasklist/index.ts @@ -29,7 +29,8 @@ import { ActivitiChecklist, ActivitiComments, ActivitiPeople, - ActivitiTaskHeader + ActivitiTaskHeader, + ActivitiStartProcessButton } from './src/components/index'; import { ActivitiTaskListService } from './src/services/activiti-tasklist.service'; @@ -47,7 +48,8 @@ export const ACTIVITI_TASKLIST_DIRECTIVES: any[] = [ ActivitiChecklist, ActivitiComments, ActivitiPeople, - ActivitiTaskHeader + ActivitiTaskHeader, + ActivitiStartProcessButton ]; export const ACTIVITI_TASKLIST_PROVIDERS: any[] = [ diff --git a/ng2-components/ng2-activiti-tasklist/src/components/activiti-filters.component.spec.ts b/ng2-components/ng2-activiti-tasklist/src/components/activiti-filters.component.spec.ts index 99e0b0de99..747897f6c8 100644 --- a/ng2-components/ng2-activiti-tasklist/src/components/activiti-filters.component.spec.ts +++ b/ng2-components/ng2-activiti-tasklist/src/components/activiti-filters.component.spec.ts @@ -15,6 +15,7 @@ * limitations under the License. */ +import { SimpleChange } from '@angular/core'; import { ActivitiFilters } from './activiti-filters.component'; import { ActivitiTaskListService } from '../services/activiti-tasklist.service'; import { Observable } from 'rxjs/Rx'; @@ -82,6 +83,7 @@ describe('ActivitiFilters', () => { }); it('should emit an error with a bad response', (done) => { + filterList.appId = '1'; spyOn(filterList.activiti, 'getTaskListFilters').and.returnValue(Observable.fromPromise(fakeErrorFilterPromise)); filterList.onError.subscribe((err) => { @@ -92,6 +94,18 @@ describe('ActivitiFilters', () => { filterList.ngOnInit(); }); + it('should emit an error with a bad response', (done) => { + filterList.appName = 'fake-app'; + spyOn(filterList.activiti, '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'}}); @@ -105,4 +119,41 @@ describe('ActivitiFilters', () => { 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-tasklist/src/components/activiti-filters.component.ts b/ng2-components/ng2-activiti-tasklist/src/components/activiti-filters.component.ts index 8d814fb95b..9355ee363d 100644 --- a/ng2-components/ng2-activiti-tasklist/src/components/activiti-filters.component.ts +++ b/ng2-components/ng2-activiti-tasklist/src/components/activiti-filters.component.ts @@ -77,37 +77,47 @@ export class ActivitiFilters implements OnInit, OnChanges { this.filters.push(filter); }); - this.load(); + this.getFilters(this.appId, this.appName); } ngOnChanges(changes: SimpleChanges) { let appId = changes['appId']; - if (appId) { - this.load(); + if (appId && (appId.currentValue || appId.currentValue === null)) { + this.getFiltersByAppId(appId.currentValue); + return; + } + let appName = changes['appName']; + if (appName && appName.currentValue) { + this.getFiltersByAppName(appName.currentValue); return; } } /** - * The method call the adapter data table component for render the task list - * @param tasks + * Return the task list filtered by appId or by appName + * @param appId + * @param appName */ - private load() { - this.resetFilter(); - if (this.appName) { - this.filterByAppName(); + getFilters(appId?: string, appName?: string) { + if (appName) { + this.getFiltersByAppName(appName); } else { - this.filterByAppId(this.appId); + this.getFiltersByAppId(appId); } } - private filterByAppId(appId) { + /** + * Return the filter list filtered by appId + * @param appId - optional + */ + getFiltersByAppId(appId?: string) { this.activiti.getTaskListFilters(appId).subscribe( (res: FilterRepresentationModel[]) => { + this.resetFilter(); res.forEach((filter) => { this.filterObserver.next(filter); - this.selectFirstFilter(); }); + this.selectFirstFilter(); this.onSuccess.emit(res); }, (err) => { @@ -117,10 +127,14 @@ export class ActivitiFilters implements OnInit, OnChanges { ); } - private filterByAppName() { - this.activiti.getDeployedApplications(this.appName).subscribe( + /** + * Return the filter list filtered by appName + * @param appName + */ + getFiltersByAppName(appName: string) { + this.activiti.getDeployedApplications(appName).subscribe( application => { - this.filterByAppId(application.id); + this.getFiltersByAppId(application.id); this.selectFirstFilter(); }, (err) => { diff --git a/ng2-components/ng2-activiti-tasklist/src/components/activiti-start-task.component.css b/ng2-components/ng2-activiti-tasklist/src/components/activiti-start-task.component.css new file mode 100644 index 0000000000..ff0f8dd865 --- /dev/null +++ b/ng2-components/ng2-activiti-tasklist/src/components/activiti-start-task.component.css @@ -0,0 +1,7 @@ +:host { + width: 100%; +} + +.activiti-label { + font-weight: bolder; +} diff --git a/ng2-components/ng2-activiti-tasklist/src/components/activiti-start-task.component.html b/ng2-components/ng2-activiti-tasklist/src/components/activiti-start-task.component.html new file mode 100644 index 0000000000..837e1730fb --- /dev/null +++ b/ng2-components/ng2-activiti-tasklist/src/components/activiti-start-task.component.html @@ -0,0 +1,19 @@ + + + +

{{'START_TASK.DIALOG.TITLE'|translate}}

+
+
+ + +
+
+ + +
+
+
+ + +
+
diff --git a/ng2-components/ng2-activiti-tasklist/src/components/activiti-start-task.component.ts b/ng2-components/ng2-activiti-tasklist/src/components/activiti-start-task.component.ts new file mode 100644 index 0000000000..d5af543e2b --- /dev/null +++ b/ng2-components/ng2-activiti-tasklist/src/components/activiti-start-task.component.ts @@ -0,0 +1,104 @@ +/*! + * @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, EventEmitter, Input, OnInit, Output, ViewChild } from '@angular/core'; +import { AlfrescoTranslationService, AlfrescoAuthenticationService } from 'ng2-alfresco-core'; +import { TaskDetailsModel } from '../models/task-details.model'; +import { ActivitiTaskListService } from './../services/activiti-tasklist.service'; + +declare let componentHandler: any; +declare let __moduleName: string; + +@Component({ + selector: 'activiti-start-task', + moduleId: __moduleName, + templateUrl: './activiti-start-task.component.html', + styleUrls: ['./activiti-start-task.component.css'] +}) +export class ActivitiStartProcessButton implements OnInit { + + @Input() + appId: string; + + @Output() + onSuccess: EventEmitter = new EventEmitter(); + + @ViewChild('dialog') + dialog: any; + + name: string; + description: string; + + /** + * Constructor + * @param auth + * @param translate + * @param taskService + */ + constructor(private auth: AlfrescoAuthenticationService, + private translate: AlfrescoTranslationService, + private taskService: ActivitiTaskListService) { + + if (translate) { + translate.addTranslationFolder('node_modules/ng2-activiti-tasklist/src'); + } + } + + ngOnInit() { + } + + public start() { + if (this.name) { + this.taskService.createNewTask(new TaskDetailsModel({ + name: this.name, + description: this.description, + category: this.appId ? '' + this.appId : null + })).subscribe( + (res: any) => { + this.onSuccess.emit(res); + this.closeDialog(); + this.resetForm(); + }, + (err) => { + window.alert('An error occurred while trying to add the task'); + console.log(err); + } + ); + } + } + + public cancel() { + this.closeDialog(); + } + + public showDialog() { + if (this.dialog) { + this.dialog.nativeElement.showModal(); + } + } + + private closeDialog() { + if (this.dialog) { + this.dialog.nativeElement.close(); + } + } + + private resetForm() { + this.name = ''; + this.description = ''; + } +} diff --git a/ng2-components/ng2-activiti-tasklist/src/components/activiti-task-details.component.html b/ng2-components/ng2-activiti-tasklist/src/components/activiti-task-details.component.html index cd52a0fe3c..a9a22ec813 100644 --- a/ng2-components/ng2-activiti-tasklist/src/components/activiti-task-details.component.html +++ b/ng2-components/ng2-activiti-tasklist/src/components/activiti-task-details.component.html @@ -15,24 +15,26 @@
- +
- +
- - + diff --git a/ng2-components/ng2-activiti-tasklist/src/components/activiti-task-details.component.ts b/ng2-components/ng2-activiti-tasklist/src/components/activiti-task-details.component.ts index c9dbca9522..b8db5fec3c 100644 --- a/ng2-components/ng2-activiti-tasklist/src/components/activiti-task-details.component.ts +++ b/ng2-components/ng2-activiti-tasklist/src/components/activiti-task-details.component.ts @@ -16,11 +16,16 @@ */ import { Component, Input, OnInit, ViewChild, Output, EventEmitter, TemplateRef, OnChanges, SimpleChanges } from '@angular/core'; -import { AlfrescoTranslationService } from 'ng2-alfresco-core'; +import { AlfrescoTranslationService, AlfrescoAuthenticationService } from 'ng2-alfresco-core'; import { ActivitiTaskListService } from './../services/activiti-tasklist.service'; +import { ActivitiTaskHeader } from './activiti-task-header.component'; +import { ActivitiComments } from './activiti-comments.component'; +import { ActivitiChecklist } from './activiti-checklist.component'; +import { ActivitiPeople } from './activiti-people.component'; import { TaskDetailsModel } from '../models/task-details.model'; import { User } from '../models/user.model'; -import { FormModel } from 'ng2-activiti-form'; +import { ActivitiForm, FormModel, FormService } from 'ng2-activiti-form'; +import { TaskQueryRequestRepresentationModel } from '../models/filter.model'; declare let componentHandler: any; @@ -30,13 +35,12 @@ declare let __moduleName: string; selector: 'activiti-task-details', moduleId: __moduleName, templateUrl: './activiti-task-details.component.html', - styleUrls: ['./activiti-task-details.component.css'] + styleUrls: ['./activiti-task-details.component.css'], + providers: [ActivitiTaskListService, FormService], + directives: [ActivitiTaskHeader, ActivitiPeople, ActivitiComments, ActivitiChecklist, ActivitiForm] }) export class ActivitiTaskDetails implements OnInit, OnChanges { - @Input() - taskId: string; - @ViewChild('activiticomments') activiticomments: any; @@ -44,19 +48,25 @@ export class ActivitiTaskDetails implements OnInit, OnChanges { activitichecklist: any; @Input() - showTitle: boolean = true; + taskId: string; @Input() - showCompleteButton: boolean = true; + showNextTask: boolean = true; @Input() - showSaveButton: boolean = true; + showFormTitle: boolean = true; @Input() - readOnly: boolean = false; + showFormCompleteButton: boolean = true; @Input() - showRefreshButton: boolean = true; + showFormSaveButton: boolean = true; + + @Input() + readOnlyForm: boolean = false; + + @Input() + showFormRefreshButton: boolean = true; @Output() formSaved = new EventEmitter(); @@ -81,8 +91,16 @@ export class ActivitiTaskDetails implements OnInit, OnChanges { noTaskDetailsTemplateComponent: TemplateRef; - constructor(private translate: AlfrescoTranslationService, + /** + * Constructor + * @param auth + * @param translate + */ + constructor(private auth: AlfrescoAuthenticationService, + private translate: AlfrescoTranslationService, + private activitiForm: FormService, private activitiTaskList: ActivitiTaskListService) { + if (translate) { translate.addTranslationFolder('node_modules/ng2-activiti-tasklist/src'); } @@ -113,10 +131,18 @@ export class ActivitiTaskDetails implements OnInit, OnChanges { this.taskDetails = null; } + /** + * Check if the task has a form + * @returns {TaskDetailsModel|string|boolean} + */ hasFormKey() { - return this.taskDetails + return (this.taskDetails && this.taskDetails.formKey - && this.taskDetails.formKey !== 'null'; + && this.taskDetails.formKey !== 'null'); + } + + isTaskActive() { + return this.taskDetails && this.taskDetails.duration === null; } /** @@ -132,7 +158,7 @@ export class ActivitiTaskDetails implements OnInit, OnChanges { this.taskDetails = res; let endDate: any = res.endDate; - this.readOnly = !!(endDate && !isNaN(endDate.getTime())); + this.readOnlyForm = !!(endDate && !isNaN(endDate.getTime())); if (this.taskDetails && this.taskDetails.involvedPeople) { this.taskDetails.involvedPeople.forEach((user) => { @@ -146,7 +172,6 @@ export class ActivitiTaskDetails implements OnInit, OnChanges { if (this.activitichecklist) { this.activitichecklist.load(this.taskDetails.id); } - console.log(this.taskDetails); } ); @@ -155,6 +180,31 @@ export class ActivitiTaskDetails implements OnInit, OnChanges { } } + /** + * Retrieve the next open task + * @param processInstanceId + * @param processDefinitionId + */ + loadNextTask(processInstanceId: string, processDefinitionId: string) { + let requestNode = new TaskQueryRequestRepresentationModel( + { + processInstanceId: processInstanceId, + processDefinitionId: processDefinitionId + } + ); + this.activitiTaskList.getTasks(requestNode).subscribe( + (response) => { + if (response.data && response.data.length > 0) { + this.taskDetails = response.data[0]; + } else { + this.reset(); + } + }, (error) => { + console.error(error); + this.onError.emit(error); + }); + } + /** * Complete the activiti task */ @@ -162,6 +212,7 @@ export class ActivitiTaskDetails implements OnInit, OnChanges { this.activitiTaskList.completeTask(this.taskId).subscribe( (res) => { console.log(res); + this.formCompleted.emit(res); } ); } @@ -180,6 +231,9 @@ export class ActivitiTaskDetails implements OnInit, OnChanges { */ formCompletedEmitter(data: any) { this.formCompleted.emit(data); + if (this.isShowNextTask()) { + this.loadNextTask(this.taskDetails.processInstanceId, this.taskDetails.processDefinitionId); + } } /** @@ -190,11 +244,27 @@ export class ActivitiTaskDetails implements OnInit, OnChanges { this.formLoaded.emit(data); } + /** + * Emit the error event of the form + * @param data + */ onErrorEmitter(err: any) { this.onError.emit(err); } + /** + * Emit the execute outcome of the form + * @param data + */ executeOutcomeEmitter(data: any) { this.executeOutcome.emit(data); } + + /** + * Return the showNexTask value + * @returns {boolean} + */ + isShowNextTask(): boolean { + return this.showNextTask; + } } diff --git a/ng2-components/ng2-activiti-tasklist/src/components/activiti-task-header.component.html b/ng2-components/ng2-activiti-tasklist/src/components/activiti-task-header.component.html index c098c1d8c3..785a438d5c 100644 --- a/ng2-components/ng2-activiti-tasklist/src/components/activiti-task-header.component.html +++ b/ng2-components/ng2-activiti-tasklist/src/components/activiti-task-header.component.html @@ -10,9 +10,5 @@ {{taskDetails?.dueDate ? taskDetails.dueDate : ('TASK_DETAILS.DUE.NONE' |translate) }} -
- {{ 'TASK_DETAILS.LABELS.FORM' | translate }}: - {{taskForm?.name ? taskForm.name : ('TASK_DETAILS.FORM.NONE' | translate) }} -
\ No newline at end of file diff --git a/ng2-components/ng2-activiti-tasklist/src/components/activiti-task-header.component.ts b/ng2-components/ng2-activiti-tasklist/src/components/activiti-task-header.component.ts index 90ff4498d8..043725d4b3 100644 --- a/ng2-components/ng2-activiti-tasklist/src/components/activiti-task-header.component.ts +++ b/ng2-components/ng2-activiti-tasklist/src/components/activiti-task-header.component.ts @@ -15,10 +15,9 @@ * limitations under the License. */ -import { Component, Input, OnInit, OnChanges } from '@angular/core'; +import { Component, Input, OnInit } from '@angular/core'; import { AlfrescoTranslationService, AlfrescoAuthenticationService } from 'ng2-alfresco-core'; import { TaskDetailsModel } from '../models/task-details.model'; -import { FormModel, FormService } from 'ng2-activiti-form'; declare let componentHandler: any; declare let __moduleName: string; @@ -27,23 +26,19 @@ declare let __moduleName: string; selector: 'activiti-task-header', moduleId: __moduleName, templateUrl: './activiti-task-header.component.html', - styleUrls: ['./activiti-task-header.component.css'], - providers: [ FormService ] + styleUrls: ['./activiti-task-header.component.css'] }) -export class ActivitiTaskHeader implements OnInit, OnChanges { +export class ActivitiTaskHeader implements OnInit { @Input() taskDetails: TaskDetailsModel; - taskForm: FormModel; - /** * Constructor * @param auth * @param translate */ constructor(private auth: AlfrescoAuthenticationService, - private activitiForm: FormService, private translate: AlfrescoTranslationService) { if (translate) { @@ -52,29 +47,7 @@ export class ActivitiTaskHeader implements OnInit, OnChanges { } ngOnInit() { - if (this.taskDetails && this.taskDetails.formKey) { - this.load(this.taskDetails.id); - } + } - ngOnChanges(change) { - if (this.taskDetails && this.taskDetails.formKey) { - this.load(this.taskDetails.id); - } else { - this.taskForm = null; - } - } - - public load(taskId: string) { - if (taskId) { - this.activitiForm.getTaskForm(taskId).subscribe( - (response) => { - this.taskForm = response; - }, - (err) => { - console.error(err); - } - ); - } - } } 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 f68821b43e..25a75f515a 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,6 +15,7 @@ * limitations under the License. */ +import { SimpleChange } from '@angular/core'; import { ActivitiTaskList } from './activiti-tasklist.component'; import { ActivitiTaskListService } from '../services/activiti-tasklist.service'; import { UserTaskFilterRepresentationModel } from '../models/filter.model'; @@ -67,7 +68,7 @@ describe('ActivitiTaskList', () => { beforeEach(() => { let activitiSerevice = new ActivitiTaskListService(null); - taskList = new ActivitiTaskList(null, activitiSerevice); + taskList = new ActivitiTaskList(null, null, activitiSerevice); }); it('should use the default schemaColumn as default', () => { @@ -113,6 +114,11 @@ describe('ActivitiTaskList', () => { taskList.ngOnInit(); }); + it('should return a currentId null when the taskList is empty', () => { + taskList.selectFirstTask(); + expect(taskList.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 UserTaskFilterRepresentationModel({filter: { state: 'open', assignment: 'fake-assignee'}}); @@ -125,6 +131,23 @@ describe('ActivitiTaskList', () => { taskList.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 UserTaskFilterRepresentationModel({filter: { state: 'open', assignment: 'fake-assignee'}}); + taskList.ngOnInit(); + taskList.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'); + done(); + }); + taskList.reload(); + }); + it('should emit row click event', (done) => { let row = new ObjectDataRow({ id: 999 @@ -133,10 +156,21 @@ describe('ActivitiTaskList', () => { taskList.rowClick.subscribe(taskId => { expect(taskId).toEqual(999); + expect(taskList.getCurrentTaskId()).toEqual(999); done(); }); taskList.onRowClick(rowEvent); }); + it('should reload task list by filter on binding changes', () => { + spyOn(taskList, 'load').and.stub(); + const taskFilter = new UserTaskFilterRepresentationModel({filter: { state: 'open', assignment: 'fake-assignee'}}); + + let change = new SimpleChange(null, taskFilter); + taskList.ngOnChanges({ 'taskFilter': change }); + + expect(taskList.load).toHaveBeenCalled(); + }); + }); diff --git a/ng2-components/ng2-activiti-tasklist/src/components/activiti-tasklist.component.ts b/ng2-components/ng2-activiti-tasklist/src/components/activiti-tasklist.component.ts index 46305b49f3..e1b391ebe6 100644 --- a/ng2-components/ng2-activiti-tasklist/src/components/activiti-tasklist.component.ts +++ b/ng2-components/ng2-activiti-tasklist/src/components/activiti-tasklist.component.ts @@ -86,6 +86,13 @@ export class ActivitiTaskList implements OnInit, OnChanges { } } + public reload() { + if (this.taskFilter) { + let requestNode = this.convertTaskUserToTaskQuery(this.taskFilter); + this.load(new TaskQueryRequestRepresentationModel(requestNode)); + } + } + public load(requestNode: TaskQueryRequestRepresentationModel) { this.activiti.getTotalTasks(requestNode).subscribe( (res) => { @@ -136,7 +143,7 @@ export class ActivitiTaskList implements OnInit, OnChanges { /** * Select the first task of a tasklist if present */ - private selectFirstTask() { + selectFirstTask() { if (!this.isTaskListEmpty()) { this.currentTaskId = this.data.getRows()[0].getValue('id'); } else { diff --git a/ng2-components/ng2-activiti-tasklist/src/components/index.ts b/ng2-components/ng2-activiti-tasklist/src/components/index.ts index 5d88aca902..9847cd7f7f 100644 --- a/ng2-components/ng2-activiti-tasklist/src/components/index.ts +++ b/ng2-components/ng2-activiti-tasklist/src/components/index.ts @@ -24,3 +24,4 @@ export * from './activiti-task-header.component'; export * from './no-task-detail-template.component'; export * from './activiti-filters.component'; export * from './activiti-task-details.component'; +export * from './activiti-start-task.component'; diff --git a/ng2-components/ng2-activiti-tasklist/src/i18n/en.json b/ng2-components/ng2-activiti-tasklist/src/i18n/en.json index d83089f9f6..f55ebd1fb9 100644 --- a/ng2-components/ng2-activiti-tasklist/src/i18n/en.json +++ b/ng2-components/ng2-activiti-tasklist/src/i18n/en.json @@ -13,6 +13,9 @@ "COMMENTS": "Comments", "CHECKLIST": "Checklist" }, + "BUTTON": { + "COMPLETE": "Complete" + }, "MESSAGES": { "NONE": "No task details found." }, @@ -36,5 +39,19 @@ "MESSAGES": { "NONE": "No task filter selected." } + }, + "START_TASK": { + "BUTTON": "Start Task", + "DIALOG": { + "TITLE": "Start Task", + "LABEL": { + "NAME": "Name", + "DESCRIPTION": "Description" + }, + "ACTION": { + "START": "Start", + "CANCEL": "Cancel" + } + } } -} \ No newline at end of file +} diff --git a/ng2-components/ng2-activiti-tasklist/src/models/task-details.model.ts b/ng2-components/ng2-activiti-tasklist/src/models/task-details.model.ts index 7fdc4d37a6..e9408e7c6d 100644 --- a/ng2-components/ng2-activiti-tasklist/src/models/task-details.model.ts +++ b/ng2-components/ng2-activiti-tasklist/src/models/task-details.model.ts @@ -64,6 +64,7 @@ export class TaskDetailsModel { this.priority = obj && obj.priority; this.assignee = new User(obj.assignee); this.adhocTaskCanBeReassigned = obj && obj.adhocTaskCanBeReassigned; + this.category = obj && obj.category || null; this.created = obj && obj.created || null; this.description = obj && obj.description || null; this.dueDate = obj && obj.dueDate || null; diff --git a/ng2-components/ng2-activiti-tasklist/src/services/activiti-tasklist.service.spec.ts b/ng2-components/ng2-activiti-tasklist/src/services/activiti-tasklist.service.spec.ts index de38f842fa..c71825153e 100644 --- a/ng2-components/ng2-activiti-tasklist/src/services/activiti-tasklist.service.spec.ts +++ b/ng2-components/ng2-activiti-tasklist/src/services/activiti-tasklist.service.spec.ts @@ -478,5 +478,38 @@ describe('ActivitiTaskListService', () => { }); }); + it('should create a new standalone task ', (done) => { + let taskFake = new TaskDetailsModel({ + name: 'FakeNameTask', + description: 'FakeDescription', + category: '3' + }); + + service.createNewTask(taskFake).subscribe( + (res: TaskDetailsModel) => { + expect(res).toBeDefined(); + expect(res.id).not.toEqual(''); + expect(res.name).toEqual('FakeNameTask'); + expect(res.description).toEqual('FakeDescription'); + expect(res.category).toEqual('3'); + expect(res.created).not.toEqual(''); + done(); + } + ); + + jasmine.Ajax.requests.mostRecent().respondWith({ + 'status': 200, + contentType: 'application/json', + responseText: JSON.stringify({ + id: '777', + name: 'FakeNameTask', + description: 'FakeDescription', + category: '3', + assignee: fakeUser, + created: '2016-07-15T11:19:17.440+0000' + }) + }); + }); + }); */ diff --git a/ng2-components/ng2-activiti-tasklist/src/services/activiti-tasklist.service.ts b/ng2-components/ng2-activiti-tasklist/src/services/activiti-tasklist.service.ts index c6c86e0db7..8bc00c94d6 100644 --- a/ng2-components/ng2-activiti-tasklist/src/services/activiti-tasklist.service.ts +++ b/ng2-components/ng2-activiti-tasklist/src/services/activiti-tasklist.service.ts @@ -216,6 +216,19 @@ export class ActivitiTaskListService { }).catch(this.handleError); } + /** + * Create a new standalone task + * @param task - TaskDetailsModel + * @returns {TaskDetailsModel} + */ + createNewTask(task: TaskDetailsModel): Observable { + return Observable.fromPromise(this.callApiCreateTask(task)) + .map(res => res) + .map((response: TaskDetailsModel) => { + return new TaskDetailsModel(response); + }).catch(this.handleError); + } + private callApiTasksFiltered(requestNode: TaskQueryRequestRepresentationModel) { return this.authService.getAlfrescoApi().activiti.taskApi.listTasks(requestNode); } @@ -256,6 +269,10 @@ export class ActivitiTaskListService { return this.authService.getAlfrescoApi().activiti.taskApi.completeTask(id); } + private callApiCreateTask(task: TaskDetailsModel) { + return this.authService.getAlfrescoApi().activiti.taskApi.createNewTask(task); + } + private handleError(error: any) { console.error(error); return Observable.throw(error || 'Server error'); diff --git a/scripts/npm-build-all.sh b/scripts/npm-build-all.sh index 45f8209f65..40c2f6c32a 100755 --- a/scripts/npm-build-all.sh +++ b/scripts/npm-build-all.sh @@ -14,7 +14,8 @@ for PACKAGE in \ ng2-alfresco-upload \ ng2-alfresco-viewer \ ng2-alfresco-webscript \ - ng2-alfresco-tag + ng2-alfresco-tag \ + ng2-activiti-analytics do DESTDIR="$DIR/../ng2-components/${PACKAGE}" echo "====== build components : ${PACKAGE} =====" diff --git a/scripts/npm-check.sh b/scripts/npm-check.sh index 3819da367e..43dcbc99f3 100755 --- a/scripts/npm-check.sh +++ b/scripts/npm-check.sh @@ -18,7 +18,8 @@ for PACKAGE in \ ng2-alfresco-upload \ ng2-alfresco-viewer \ ng2-alfresco-webscript \ - ng2-alfresco-tag + ng2-alfresco-tag \ + ng2-activiti-analytics do echo "====== Check component: ${PACKAGE} =====" cd "$DIR/../ng2-components/${PACKAGE}" diff --git a/scripts/npm-clean.sh b/scripts/npm-clean.sh index f4d1e78ebc..46f6ee8159 100755 --- a/scripts/npm-clean.sh +++ b/scripts/npm-clean.sh @@ -14,7 +14,8 @@ for PACKAGE in \ ng2-alfresco-upload \ ng2-alfresco-viewer \ ng2-alfresco-webscript \ - ng2-alfresco-tag + ng2-alfresco-tag \ + ng2-activiti-analytics do echo "====== clean component: ${PACKAGE} =====" cd "$DIR/../ng2-components/${PACKAGE}" diff --git a/scripts/npm-link-demo-shell.sh b/scripts/npm-link-demo-shell.sh index c42c0d1740..ef1584c902 100755 --- a/scripts/npm-link-demo-shell.sh +++ b/scripts/npm-link-demo-shell.sh @@ -74,7 +74,8 @@ npm run build for PACKAGE in \ ng2-alfresco-login \ ng2-alfresco-search \ - ng2-alfresco-upload + ng2-alfresco-upload \ + ng2-activiti-analytics do DESTDIR="$DIR/../ng2-components/${PACKAGE}" echo "====== linking component: ${PACKAGE} =====" @@ -99,7 +100,8 @@ for PACKAGE in \ ng2-alfresco-upload \ ng2-alfresco-viewer \ ng2-alfresco-webscript \ - ng2-alfresco-tag + ng2-alfresco-tag \ + ng2-activiti-analytics do DESTDIR="$DIR/../ng2-components/${PACKAGE}" echo "====== demo shell linking: ${PACKAGE} =====" diff --git a/scripts/npm-publish.sh b/scripts/npm-publish.sh index f72018f253..57bba15d31 100755 --- a/scripts/npm-publish.sh +++ b/scripts/npm-publish.sh @@ -16,7 +16,8 @@ for PACKAGE in \ ng2-alfresco-upload \ ng2-alfresco-viewer \ ng2-alfresco-webscript \ - ng2-alfresco-tag + ng2-alfresco-tag \ + ng2-activiti-analytics do DESTDIR="$DIR/../ng2-components/${PACKAGE}" echo "====== PUBLISHING: ${DESTDIR} =====" diff --git a/scripts/update-version.sh b/scripts/update-version.sh index c28f515f4e..cbeb25005a 100755 --- a/scripts/update-version.sh +++ b/scripts/update-version.sh @@ -26,7 +26,8 @@ for PACKAGE in \ ng2-alfresco-upload \ ng2-alfresco-viewer \ ng2-alfresco-webscript \ - ng2-alfresco-tag + ng2-alfresco-tag \ + ng2-activiti-analytics do DESTDIR="$DIR/../ng2-components/${PACKAGE}" echo "====== UPDATE VERSION of ${PACKAGE} to ${VERSION} version in all the package.json ======" @@ -45,7 +46,8 @@ for PACKAGE in \ ng2-alfresco-upload \ ng2-alfresco-viewer \ ng2-alfresco-webscript \ - ng2-alfresco-tag + ng2-alfresco-tag \ + ng2-activiti-analytics do DESTDIR="$DIR/../ng2-components/${PACKAGE}" echo "====== UPDATE VERSION OF ${PACKAGE} to ${VERSION} version ======"