diff --git a/demo-shell-ng2/app/components/tasks/tasks-demo.component.ts b/demo-shell-ng2/app/components/tasks/tasks-demo.component.ts index 007906cbcb..2d608bc846 100644 --- a/demo-shell-ng2/app/components/tasks/tasks-demo.component.ts +++ b/demo-shell-ng2/app/components/tasks/tasks-demo.component.ts @@ -16,65 +16,36 @@ */ import { Component, OnInit } from '@angular/core'; -import { ActivitiService } from './activiti.service'; -import { - ALFRESCO_DATATABLE_DIRECTIVES, - ObjectDataTableAdapter -} from 'ng2-alfresco-datatable'; - -import { - AlfrescoAuthenticationService -} from 'ng2-alfresco-core'; +import { ActivitiTaskList } from 'ng2-activiti-tasklist'; +import { ObjectDataTableAdapter, ObjectDataColumn } from 'ng2-alfresco-datatable'; @Component({ selector: 'tasks-demo', template: `
- +
`, - directives: [ALFRESCO_DATATABLE_DIRECTIVES], - providers: [ActivitiService], + directives: [ActivitiTaskList], styles: [':host > .container { padding: 10px; }'] }) export class TasksDemoComponent implements OnInit { - tasks: ObjectDataTableAdapter; - - constructor( - private activitiService: ActivitiService, - private auth: AlfrescoAuthenticationService) {} - - ngOnInit() { - if (this.auth.isLoggedIn('BPM')) { - this.activitiService - .getTasks() - .then((data) => { - let tasks = data || []; - console.log(tasks); - this.loadTasks(tasks); - }); - } else { - console.error('User unauthorized'); - } - + data: ObjectDataTableAdapter; + constructor() { + this.data = new ObjectDataTableAdapter([], []); } - private loadTasks(tasks: any[]) { - tasks = tasks.map(t => { - t.name = t.name || 'Nameless task'; - if (t.name.length > 50) { - t.name = t.name.substring(0, 50) + '...'; - } - return t; - }); + ngOnInit() { + let schema = [ + {type: 'text', key: 'id', title: 'Id'}, + {type: 'text', key: 'name', title: 'Name', cssClass: 'full-width name-column', sortable: true}, + {type: 'text', key: 'formKey', title: 'Form Key', sortable: true}, + {type: 'text', key: 'created', title: 'Created', sortable: true} + ]; - this.tasks = new ObjectDataTableAdapter(tasks, [ - { type: 'text', key: 'id', title: 'Id'}, - { type: 'text', key: 'name', title: 'Name', cssClass: 'full-width name-column', sortable: true }, - { type: 'text', key: 'formKey', title: 'Form Key', sortable: true }, - { type: 'text', key: 'created', title: 'Created', sortable: true } - ]); + let columns = schema.map(col => new ObjectDataColumn(col)); + this.data.setColumns(columns); } } diff --git a/demo-shell-ng2/package.json b/demo-shell-ng2/package.json index 6e5456d8b9..7cffed234d 100644 --- a/demo-shell-ng2/package.json +++ b/demo-shell-ng2/package.json @@ -83,6 +83,7 @@ "ng2-alfresco-upload": "0.2.0", "ng2-alfresco-viewer": "0.2.0", "ng2-activiti-form": "0.2.0", + "ng2-activiti-tasklist": "0.2.0", "ng2-alfresco-webscript": "file:../ng2-components/ng2-alfresco-webscript" }, "devDependencies": { diff --git a/demo-shell-ng2/systemjs.config.js b/demo-shell-ng2/systemjs.config.js index 99598649bb..020ebdbd3e 100644 --- a/demo-shell-ng2/systemjs.config.js +++ b/demo-shell-ng2/systemjs.config.js @@ -19,7 +19,8 @@ 'ng2-alfresco-upload': 'node_modules/ng2-alfresco-upload/dist', 'ng2-activiti-form': 'node_modules/ng2-activiti-form/dist', 'ng2-alfresco-viewer': 'node_modules/ng2-alfresco-viewer/dist', - 'ng2-alfresco-webscript': 'node_modules/ng2-alfresco-webscript/dist' + 'ng2-alfresco-webscript': 'node_modules/ng2-alfresco-webscript/dist', + 'ng2-activiti-tasklist': 'node_modules/ng2-activiti-tasklist/dist' }; // packages tells the System loader how to load when no filename and/or no extension var packages = { @@ -37,6 +38,7 @@ 'ng2-alfresco-upload': { main: 'index.js', defaultExtension: 'js'}, 'ng2-alfresco-viewer': { main: 'index.js', defaultExtension: 'js'}, 'ng2-activiti-form': { main: 'index.js', defaultExtension: 'js'}, + 'ng2-activiti-tasklist': { main: 'index.js', defaultExtension: 'js'}, 'ng2-alfresco-webscript': { main: 'index.js', defaultExtension: 'js'} }; var ngPackageNames = [ diff --git a/ng2-components/ng2-activiti-tasklist/.editorconfig b/ng2-components/ng2-activiti-tasklist/.editorconfig new file mode 100644 index 0000000000..75a2477db7 --- /dev/null +++ b/ng2-components/ng2-activiti-tasklist/.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-tasklist/.gitignore b/ng2-components/ng2-activiti-tasklist/.gitignore new file mode 100644 index 0000000000..13324e66b9 --- /dev/null +++ b/ng2-components/ng2-activiti-tasklist/.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-tasklist/.npmignore b/ng2-components/ng2-activiti-tasklist/.npmignore new file mode 100644 index 0000000000..16ba3e61e5 --- /dev/null +++ b/ng2-components/ng2-activiti-tasklist/.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-tasklist/LICENSE b/ng2-components/ng2-activiti-tasklist/LICENSE new file mode 100644 index 0000000000..430d42bbea --- /dev/null +++ b/ng2-components/ng2-activiti-tasklist/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-tasklist/README.md b/ng2-components/ng2-activiti-tasklist/README.md new file mode 100644 index 0000000000..b2226ddc09 --- /dev/null +++ b/ng2-components/ng2-activiti-tasklist/README.md @@ -0,0 +1 @@ +# Activiti Task List Component for Angular 2 diff --git a/ng2-components/ng2-activiti-tasklist/assets/license_header.txt b/ng2-components/ng2-activiti-tasklist/assets/license_header.txt new file mode 100644 index 0000000000..83fd1531a3 --- /dev/null +++ b/ng2-components/ng2-activiti-tasklist/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-tasklist/demo/.gitignore b/ng2-components/ng2-activiti-tasklist/demo/.gitignore new file mode 100644 index 0000000000..25beca4c27 --- /dev/null +++ b/ng2-components/ng2-activiti-tasklist/demo/.gitignore @@ -0,0 +1,6 @@ +node_modules +.idea +coverage +dist +typings +!systemjs.config.js diff --git a/ng2-components/ng2-activiti-tasklist/demo/.npmignore b/ng2-components/ng2-activiti-tasklist/demo/.npmignore new file mode 100644 index 0000000000..c51c008259 --- /dev/null +++ b/ng2-components/ng2-activiti-tasklist/demo/.npmignore @@ -0,0 +1,3 @@ +node_modules +dist +typings \ No newline at end of file diff --git a/ng2-components/ng2-activiti-tasklist/demo/README.md b/ng2-components/ng2-activiti-tasklist/demo/README.md new file mode 100644 index 0000000000..28b3ffd976 --- /dev/null +++ b/ng2-components/ng2-activiti-tasklist/demo/README.md @@ -0,0 +1,13 @@ +# DataTable demo + +Install: + +``` +npm install +``` + +Run the project: + +``` +npm start +``` \ No newline at end of file diff --git a/ng2-components/ng2-activiti-tasklist/demo/index.html b/ng2-components/ng2-activiti-tasklist/demo/index.html new file mode 100644 index 0000000000..5b926def7a --- /dev/null +++ b/ng2-components/ng2-activiti-tasklist/demo/index.html @@ -0,0 +1,34 @@ + + + + + Angular 2 TaskList - Demo + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/ng2-components/ng2-activiti-tasklist/demo/package.json b/ng2-components/ng2-activiti-tasklist/demo/package.json new file mode 100644 index 0000000000..ad89d4a646 --- /dev/null +++ b/ng2-components/ng2-activiti-tasklist/demo/package.json @@ -0,0 +1,78 @@ +{ + "name": "ng2-activiti-tasklist-demo", + "description": "Alfresco Angular2 DataTable Component - Demo", + "version": "0.1.0", + "author": "Alfresco Software, Ltd.", + "contributors": [ + { + "name": "Maurizio Vitale", + "email": "maurizio.vitale84@gmail.com" + } + ], + "main": "index.js", + "scripts": { + "clean": "rimraf dist node_modules typings", + "postinstall": "npm run typings && npm run build", + "typings": "typings install", + "start": "rimraf dist && npm install && npm run server", + "server": "wsrv -o", + "build": "npm run tslint && rimraf dist && tsc", + "tslint": "npm run tslint-src && npm run tslint-root", + "tslint-src": "tslint -c tslint.json src/{,**/}**.ts", + "tslint-root": "tslint -c tslint.json *.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", + + "ng2-alfresco-datatable": "^0.1.12", + "ng2-alfresco-core": "^0.1.36" + }, + "devDependencies": { + "browser-sync": "2.10.0", + "concurrently": "2.0.0", + "rimraf": "2.5.2", + "tslint": "3.8.1", + "typescript": "1.8.10", + "typings": "1.0.4", + "wsrv": "0.1.3" + }, + "keywords": [ + "angular2", + "typescript" + ], + "license-check-config": { + "src": [ + "**/*.js", + "**/*.ts", + "!/**/coverage/**/*", + "!/**/demo/**/*", + "!/**/node_modules/**/*", + "!/**/typings/**/*", + "!*.js" + ], + "path": "assets/license_header.txt", + "blocking": true, + "logInfo": false, + "logError": true + } +} diff --git a/ng2-components/ng2-activiti-tasklist/demo/src/main.ts b/ng2-components/ng2-activiti-tasklist/demo/src/main.ts new file mode 100644 index 0000000000..d1ff854273 --- /dev/null +++ b/ng2-components/ng2-activiti-tasklist/demo/src/main.ts @@ -0,0 +1,64 @@ +/*! + * @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 } from '@angular/core'; +import { HTTP_PROVIDERS } from '@angular/http'; +import { ALFRESCO_CORE_PROVIDERS, AlfrescoAuthenticationService, AlfrescoSettingsService } from 'ng2-alfresco-core'; +import { bootstrap } from '@angular/platform-browser-dynamic'; +import { ActivitiTaskList } from 'ng2-activiti-tasklist'; +import { ObjectDataTableAdapter, ObjectDataColumn } from 'ng2-alfresco-datatable'; + +declare let AlfrescoApi: any; + +@Component({ + selector: 'activiti-tasklist-demo', + template: ` + + `, + styles: [ + ':host > .container {padding: 10px}', + '.p-10 { padding: 10px; }' + ], + directives: [ActivitiTaskList], + providers: [AlfrescoAuthenticationService] +}) +class ActivitiTaskListDemo implements OnInit { + data: ObjectDataTableAdapter; + + constructor(private setting: AlfrescoSettingsService) { + this.setting.setProviders(['BPM']); + this.data = new ObjectDataTableAdapter([], []); + } + + ngOnInit() { + let schema = [ + {type: 'text', key: 'id', title: 'Id'}, + {type: 'text', key: 'name', title: 'Name', cssClass: 'full-width name-column', sortable: true}, + {type: 'text', key: 'formKey', title: 'Form Key', sortable: true}, + {type: 'text', key: 'created', title: 'Created', sortable: true} + ]; + + let columns = schema.map(col => new ObjectDataColumn(col)); + this.data.setColumns(columns); + } + +} + +bootstrap(ActivitiTaskListDemo, [ + HTTP_PROVIDERS, + ALFRESCO_CORE_PROVIDERS] +); diff --git a/ng2-components/ng2-activiti-tasklist/demo/systemjs.config.js b/ng2-components/ng2-activiti-tasklist/demo/systemjs.config.js new file mode 100644 index 0000000000..4a716d3e2a --- /dev/null +++ b/ng2-components/ng2-activiti-tasklist/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-translate': 'node_modules/ng2-translate', + 'ng2-alfresco-core': 'node_modules/ng2-alfresco-core/dist', + 'ng2-alfresco-datatable': 'node_modules/ng2-alfresco-datatable/dist', + 'ng2-activiti-tasklist': 'node_modules/ng2-activiti-tasklist/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-alfresco-datatable': { main: 'index.js', defaultExtension: 'js' }, + 'ng2-activiti-tasklist': { main: 'index.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-tasklist/demo/tsconfig.json b/ng2-components/ng2-activiti-tasklist/demo/tsconfig.json new file mode 100644 index 0000000000..f6761b5218 --- /dev/null +++ b/ng2-components/ng2-activiti-tasklist/demo/tsconfig.json @@ -0,0 +1,19 @@ +{ + "compilerOptions": { + "target": "ES5", + "module": "system", + "moduleResolution": "node", + "emitDecoratorMetadata": true, + "experimentalDecorators": true, + "sourceMap": true, + "removeComments": true, + "declaration": true, + "outDir": "dist" + }, + "exclude": [ + "dist", + "node_modules", + "typings/main", + "typings/main.d.ts" + ] +} diff --git a/ng2-components/ng2-activiti-tasklist/demo/tslint.json b/ng2-components/ng2-activiti-tasklist/demo/tslint.json new file mode 100644 index 0000000000..8c48e76469 --- /dev/null +++ b/ng2-components/ng2-activiti-tasklist/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-tasklist/demo/typings.json b/ng2-components/ng2-activiti-tasklist/demo/typings.json new file mode 100644 index 0000000000..d8954c2485 --- /dev/null +++ b/ng2-components/ng2-activiti-tasklist/demo/typings.json @@ -0,0 +1,7 @@ +{ + "globalDependencies": { + "core-js": "registry:dt/core-js#0.0.0+20160317120654", + "jasmine": "registry:dt/jasmine#2.2.0+20160505161446", + "node": "registry:dt/node#4.0.0+20160509154515" + } +} diff --git a/ng2-components/ng2-activiti-tasklist/index.ts b/ng2-components/ng2-activiti-tasklist/index.ts new file mode 100644 index 0000000000..f9c4e4a420 --- /dev/null +++ b/ng2-components/ng2-activiti-tasklist/index.ts @@ -0,0 +1,22 @@ +/*! + * @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 { ActivitiTaskList } from './src/components/activiti-tasklist.component'; + +export * from './src/components/activiti-tasklist.component'; + +export const ALFRESCO_TASKLIST_DIRECTIVES: [any] = [ActivitiTaskList]; diff --git a/ng2-components/ng2-activiti-tasklist/karma-test-shim.js b/ng2-components/ng2-activiti-tasklist/karma-test-shim.js new file mode 100644 index 0000000000..bffeaa9753 --- /dev/null +++ b/ng2-components/ng2-activiti-tasklist/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-alfresco-core': '/base/node_modules/ng2-alfresco-core/dist', + 'ng2-alfresco-datatable': '/base/node_modules/ng2-alfresco-datatable/dist' +}; + +var packages = { + 'app': { main: 'main.js', defaultExtension: 'js' }, + 'rxjs': { defaultExtension: 'js' }, + 'ng2-translate': { defaultExtension: 'js' }, + 'ng2-alfresco-core': { main: 'index.js', defaultExtension: 'js' }, + 'ng2-alfresco-datatable': { 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-tasklist/karma.conf.js b/ng2-components/ng2-activiti-tasklist/karma.conf.js new file mode 100644 index 0000000000..ee5d5a7808 --- /dev/null +++ b/ng2-components/ng2-activiti-tasklist/karma.conf.js @@ -0,0 +1,99 @@ +'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-alfresco-datatable/dist/**/*.js', included: false, served: true, watched: false}, + {pattern: 'node_modules/ng2-translate/**/*.js', included: false, served: 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', 'coveralls', '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-tasklist/package.json b/ng2-components/ng2-activiti-tasklist/package.json new file mode 100644 index 0000000000..dbc160e03f --- /dev/null +++ b/ng2-components/ng2-activiti-tasklist/package.json @@ -0,0 +1,111 @@ +{ + "name": "ng2-activiti-tasklist", + "description": "Activiti Angular2 Task List Component", + "version": "0.2.0", + "author": "Alfresco Software, Ltd.", + "scripts": { + "clean": "rimraf dist node_modules typings", + "typings": "typings install", + "build": "npm run tslint && typings install && rimraf dist && tsc && npm run copytemplates && license-check", + "build:w": "npm run tslint && typings install && rimraf dist && npm run watch-task", + "watch-task": "concurrently \"npm run tsc:w\" \"npm run copytemplates:w\" \"license-check\"", + "tslint": "npm run tslint-src && npm run tslint-root", + "tslint-src": "tslint -c tslint.json src/{,**/}**.ts", + "tslint-root": "tslint -c tslint.json *.ts", + "copytemplates": "npm run copy-html-css && npm run copy-i18n && npm run copy-images", + "copytemplates:w": "concurrently \"npm run copy-html-css:w\" \"npm run copy-images:w\" \"npm run copy-i18n:w\"", + "copy-html-css": "cpx \"./src/**/*.{html,css}\" ./dist/src", + "copy-html-css:w": "cpx \"./src/**/*.{html,css}\" ./dist/src -w", + "copy-i18n": "cpx \"./i18n/**/*.json\" ./dist/i18n", + "copy-i18n:w": "cpx \"./i18n/**/*.json\" ./dist/i18n -w", + "copy-images": "cpx \"./src/**/*.{png,jpg,gif,svg}\" ./dist/src", + "copy-images:w": "cpx \"./src/**/*.{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": "npm link ng2-alfresco-core ng2-alfresco-datatable" + }, + "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": "Maurizio Vitale", + "email": "maurizio.vitale84@gmail.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", + "rimraf": "2.5.2", + "ng2-translate": "2.2.2", + "ng2-alfresco-core": "0.2.0", + "ng2-alfresco-datatable": "0.2.0", + "alfresco-js-api": "^0.1.0" + }, + "peerDependencies": { + "material-design-icons": "^2.2.3", + "material-design-lite": "^1.1.3" + }, + "devDependencies": { + "concurrently": "2.1.0", + "coveralls": "2.11.9", + "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-coveralls": "1.1.2", + "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", + "remap-istanbul": "0.6.3", + "traceur": "0.0.91", + "tslint": "3.8.1", + "typescript": "1.8.10", + "typings": "1.0.4", + "wsrv": "0.1.3" + }, + "license-check-config": { + "src": [ + "./dist/**/*.js" + ], + "path": "assets/license_header.txt", + "blocking": true, + "logInfo": false, + "logError": true + } +} diff --git a/ng2-components/ng2-activiti-tasklist/src/assets/translation.service.mock.ts b/ng2-components/ng2-activiti-tasklist/src/assets/translation.service.mock.ts new file mode 100644 index 0000000000..3ddf9a9050 --- /dev/null +++ b/ng2-components/ng2-activiti-tasklist/src/assets/translation.service.mock.ts @@ -0,0 +1,37 @@ +/*! + * @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 { Observable } from 'rxjs/Rx'; +import { EventEmitter } from '@angular/core'; + +export interface LangChangeEvent { + lang: string; + translations: any; +} + +export class TranslationMock { + + public onLangChange: EventEmitter = new EventEmitter(); + + addTranslationFolder() { + + } + + public get(key: string|Array, interpolateParams?: Object): Observable { + return Observable.of(key); + } +} 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 new file mode 100644 index 0000000000..71515f833f --- /dev/null +++ b/ng2-components/ng2-activiti-tasklist/src/components/activiti-tasklist.component.html @@ -0,0 +1,9 @@ + + + \ No newline at end of file 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 new file mode 100644 index 0000000000..fd32032863 --- /dev/null +++ b/ng2-components/ng2-activiti-tasklist/src/components/activiti-tasklist.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 { + it, + describe, + expect, + beforeEach +} from '@angular/core/testing'; + +import { ActivitiTaskList } from './activiti-tasklist.component'; +import { ActivitiTaskListService } from '../services/activiti-tasklist.service'; +import { FilterModel } from '../models/filter.model'; +import { Observable } from 'rxjs/Rx'; + + +describe('ActivitiTaskList', () => { + + let taskList: ActivitiTaskList; + + let fakeGlobalFilter = { + size: 2, total: 2, start: 0, + data: [ + { + id: 1, name: 'FakeInvolvedTasks', recent: false, icon: 'glyphicon-align-left', + filter: {sort: 'created-desc', name: '', state: 'open', assignment: 'fake-involved'} + }, + { + id: 2, name: 'FakeMyTasks', recent: false, icon: 'glyphicon-align-left', + filter: {sort: 'created-desc', name: '', state: 'open', assignment: 'fake-assignee'} + } + ] + }; + + let fakeGlobalTask = { + size: 1, total: 12, start: 0, + data: [ + { + id: 14, name: 'fake-long-name-fake-long-name-fake-long-name-fak50-long-name', description: null, category: null, + assignee: { + id: 1, firstName: null, lastName: 'Administrator', email: 'admin' + } + }, + { + id: 2, name: '', description: null, category: null, + assignee: { + id: 1, firstName: null, lastName: 'Administrator', email: 'admin' + } + } + ] + }; + + let fakeErrorTaskList = { + error: 'wrong request' + }; + + let fakeGlobalFilterPromise = new Promise(function (resolve, reject) { + resolve(fakeGlobalFilter); + }); + + let fakeGlobalTaskPromise = new Promise(function (resolve, reject) { + resolve(fakeGlobalTask); + }); + + let fakeErrorTaskPromise = new Promise(function (resolve, reject) { + reject(fakeErrorTaskList); + }); + + beforeEach(() => { + let activitiSerevice = new ActivitiTaskListService(null); + taskList = new ActivitiTaskList(null, null, activitiSerevice); + }); + + it('should return the default filters', (done) => { + spyOn(taskList.activiti, 'getTaskListFilters').and.returnValue(Observable.fromPromise(fakeGlobalFilterPromise)); + taskList.ngOnInit(); + + taskList.filtersList.subscribe((res: any) => { + expect(res).toBeDefined(); + expect(res.length).toEqual(2); + expect(res[0].name).toEqual('FakeInvolvedTasks'); + expect(res[1].name).toEqual('FakeMyTasks'); + done(); + }); + }); + + it('should subscribe to Filter when a filter is selected', (done) => { + let filterModel: FilterModel = new FilterModel('name', false, 'icon', 'open', 'fake-assignee'); + taskList.filter$.subscribe((filter: FilterModel) => { + expect(filter).toBe(filterModel); + done(); + }); + taskList.selectFilter(filterModel); + }); + + it('should return the tasks when a filter is selected', (done) => { + spyOn(taskList.activiti, 'getTasks').and.returnValue(Observable.fromPromise(fakeGlobalTaskPromise)); + spyOn(taskList.activiti, 'getTaskListFilters').and.returnValue(Observable.fromPromise(fakeGlobalFilterPromise)); + taskList.ngOnInit(); + + let filterModel: FilterModel = new FilterModel('name', false, 'icon', 'open', 'fake-assignee'); + taskList.selectFilter(filterModel); + + taskList.activiti.getTasks(filterModel).subscribe( + (res) => { + expect(res).toBeDefined(); + done(); + }); + }); + + it('should throw an exception when the response is wrong', (done) => { + spyOn(taskList.activiti, 'getTasks').and.returnValue(Observable.fromPromise(fakeErrorTaskPromise)); + spyOn(taskList.activiti, 'getTaskListFilters').and.returnValue(Observable.fromPromise(fakeGlobalFilterPromise)); + taskList.ngOnInit(); + + let filterModel: FilterModel = new FilterModel('name', false, 'icon', 'open', 'fake-assignee'); + taskList.selectFilter(filterModel); + + taskList.activiti.getTasks(filterModel).subscribe( + (res) => { + expect(res).toBeUndefined(); + }, + (err: any) => { + expect(err).toBeDefined(); + expect(err.error).toEqual('wrong request'); + done(); + }); + }); + + it('should optimize the task name when are empty or exceed 50 characters', (done) => { + spyOn(taskList.activiti, 'getTasks').and.returnValue(Observable.fromPromise(fakeGlobalTaskPromise)); + spyOn(taskList.activiti, 'getTaskListFilters').and.returnValue(Observable.fromPromise(fakeGlobalFilterPromise)); + taskList.ngOnInit(); + + let filterModel: FilterModel = new FilterModel('name', false, 'icon', 'open', 'fake-assignee'); + taskList.selectFilter(filterModel); + + taskList.activiti.getTasks(filterModel).subscribe( + (res) => { + expect(res.data[0].name).toEqual('fake-long-name-fake-long-name-fake-long-name-fak50...'); + expect(res.data[1].name).toEqual('Nameless task'); + done(); + }); + }); + +}); 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 new file mode 100644 index 0000000000..90b9bd853b --- /dev/null +++ b/ng2-components/ng2-activiti-tasklist/src/components/activiti-tasklist.component.ts @@ -0,0 +1,115 @@ +/*! + * @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, Input, OnInit} from '@angular/core'; +import { AlfrescoTranslationService, AlfrescoAuthenticationService } from 'ng2-alfresco-core'; +import { ALFRESCO_DATATABLE_DIRECTIVES, ObjectDataTableAdapter, DataTableAdapter, DataRowEvent } from 'ng2-alfresco-datatable'; +import { ActivitiTaskListService } from './../services/activiti-tasklist.service'; +import { FilterModel } from '../models/filter.model'; +import { Observer } from 'rxjs/Observer'; +import { Observable } from 'rxjs/Observable'; + +declare let componentHandler: any; +declare let __moduleName: string; + +@Component({ + selector: 'activiti-tasklist', + moduleId: __moduleName, + templateUrl: './activiti-tasklist.component.html', + directives: [ALFRESCO_DATATABLE_DIRECTIVES], + providers: [ActivitiTaskListService] + +}) +export class ActivitiTaskList implements OnInit { + + @Input() + data: DataTableAdapter; + + private filterObserver: Observer; + + filter$: Observable; + + tasks: ObjectDataTableAdapter; + currentTaskId: string; + + filtersList: Observable; + /** + * Constructor + * @param auth + * @param translate + */ + constructor(private auth: AlfrescoAuthenticationService, + private translate: AlfrescoTranslationService, + public activiti: ActivitiTaskListService) { + this.filter$ = new Observable(observer => this.filterObserver = observer).share(); + + if (translate) { + translate.addTranslationFolder('node_modules/ng2-activiti-tasklist'); + } + } + + ngOnInit() { + this.filtersList = this.activiti.getTaskListFilters().map(res => (res.data)); + + this.filter$.subscribe((filter: FilterModel) => { + this.activiti.getTasks(filter).subscribe( + (res) => { + this.loadTasks(res.data); + }, (err) => { + console.error(err); + }); + }); + } + + /** + * The method call the adapter data table component for render the task list + * @param tasks + */ + private loadTasks(tasks: any[]) { + tasks = this.optimizeTaskName(tasks); + this.tasks = new ObjectDataTableAdapter(tasks, this.data.getColumns()); + } + + /** + * Pass the selected filter as next + * @param filter + */ + public selectFilter(filter: FilterModel) { + this.filterObserver.next(filter); + } + + onRowClick(event: DataRowEvent) { + let item = event; + this.currentTaskId = item.value.getValue('id'); + } + + /** + * Optimize task name field + * @param tasks + * @returns {any[]} + */ + private optimizeTaskName(tasks: any[]) { + tasks = tasks.map(t => { + t.name = t.name || 'Nameless task'; + if (t.name.length > 50) { + t.name = t.name.substring(0, 50) + '...'; + } + return t; + }); + return tasks; + } +} diff --git a/ng2-components/ng2-activiti-tasklist/src/models/filter.model.ts b/ng2-components/ng2-activiti-tasklist/src/models/filter.model.ts new file mode 100644 index 0000000000..5aa422c1a3 --- /dev/null +++ b/ng2-components/ng2-activiti-tasklist/src/models/filter.model.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. + */ + +/** + * + * This object represent the filter. + * + * + * @returns {FilterModel} . + */ +export class FilterModel { + id: number; + name: string; + recent: boolean = false; + icon: string; + filter: FilterParamsModel; + + constructor(name: string, recent: boolean, icon: string, state: string, assignment: string) { + this.name = name; + this.recent = recent; + this.icon = icon; + this.filter = new FilterParamsModel(name, state, assignment); + } +} + +/** + * + * This object represent the parameters of a filter. + * + * + * @returns {FilterModel} . + */ +export class FilterParamsModel { + name: string; + state: string; + assignment: string; + + constructor(name: string, state: string, assignment: string) { + this.name = name; + this.state = state; + this.assignment = assignment; + } +} 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 new file mode 100644 index 0000000000..159fbf8b98 --- /dev/null +++ b/ng2-components/ng2-activiti-tasklist/src/services/activiti-tasklist.service.spec.ts @@ -0,0 +1,161 @@ +/*! + * @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 { it, describe, inject, beforeEach, beforeEachProviders } from '@angular/core/testing'; +import { ActivitiTaskListService } from './activiti-tasklist.service'; +import { AlfrescoSettingsService, AlfrescoAuthenticationService } from 'ng2-alfresco-core'; +import { HTTP_PROVIDERS } from '@angular/http'; + +declare let AlfrescoApi: any; +declare let jasmine: any; + +describe('AlfrescoUploadService', () => { + let service, options: any; + + options = { + host: 'fakehost', + url: '/some/cool/url', + baseUrlPath: 'fakebasepath', + formFields: { + siteid: 'fakeSite', + containerid: 'fakeFolder' + } + }; + + beforeEachProviders(() => { + return [ + HTTP_PROVIDERS, + AlfrescoSettingsService, + AlfrescoAuthenticationService, + ActivitiTaskListService + ]; + }); + + beforeEach( inject([ActivitiTaskListService], (activitiService: ActivitiTaskListService) => { + jasmine.Ajax.install(); + service = activitiService; + })); + + afterEach(() => { + jasmine.Ajax.uninstall(); + }); + + it('should return the task list filters', (done) => { + let fakeFilter = { + size: 2, total: 2, start: 0, + data: [ + { + id: 1, name: 'FakeInvolvedTasks', recent: false, icon: 'glyphicon-align-left', + filter: {sort: 'created-desc', name: '', state: 'open', assignment: 'fake-involved'} + }, + { + id: 2, name: 'FakeMyTasks', recent: false, icon: 'glyphicon-align-left', + filter: {sort: 'created-desc', name: '', state: 'open', assignment: 'fake-assignee'} + } + ] + }; + + let filters = service.getTaskListFilters(); + filters.subscribe(res => { + expect(res).toBeDefined(); + expect(res.size).toEqual(2); + expect(res.total).toEqual(2); + expect(res.data.length).toEqual(2); + expect(res.data[0].name).toEqual('FakeInvolvedTasks'); + expect(res.data[1].name).toEqual('FakeMyTasks'); + done(); + }); + + jasmine.Ajax.requests.mostRecent().respondWith({ + 'status': 200, + contentType: 'application/json', + responseText: JSON.stringify(fakeFilter) + }); + }); + + it('should return the task list filtered', (done) => { + let fakeTaskList = { + size: 1, total: 1, start: 0, + data: [ + { + id: 1, name: 'FakeNameTask', description: null, category: null, + assignee: { + id: 1, + firstName: null, + lastName: 'Fake Admin', + email: 'fake-admin' + }, + created: '2016-07-15T11:19:17.440+0000' + } + ] + }; + + let fakeFilter = { + page: 2, filterId: 2, appDefinitionId: null, + filter: {sort: 'created-desc', name: '', state: 'open', assignment: 'fake-assignee'} + }; + + let taskList = service.getTasks(fakeFilter); + taskList.subscribe(res => { + expect(res).toBeDefined(); + expect(res.size).toEqual(1); + expect(res.total).toEqual(1); + expect(res.data.length).toEqual(1); + expect(res.data[0].name).toEqual('FakeNameTask'); + done(); + }); + + jasmine.Ajax.requests.mostRecent().respondWith({ + 'status': 200, + contentType: 'application/json', + responseText: JSON.stringify(fakeTaskList) + }); + }); + + it('should throw an exception when the response is wrong', (done) => { + let fakeTaskList = { + error: 'wrong request' + }; + + let fakeFilter = { + page: 2, filterId: 2, appDefinitionId: null, + wrongfilter: {sort: 'created-desc', name: '', state: 'open', assignment: 'fake-assignee'} + }; + + let fakePromise = new Promise(function (resolve, reject) { + reject(fakeTaskList); + }); + spyOn(service, 'callApiTasksFiltered').and.returnValue(fakePromise); + + let taskList = service.getTasks(fakeFilter); + + service.getTasks(fakeFilter).subscribe((res) => { + let tasks = res.data; + service.loadTasks(tasks); + }); + taskList.subscribe( + (res) => { + + }, + (err: any) => { + expect(err).toBeDefined(); + expect(err.error).toEqual('wrong request'); + done(); + }); + }); + +}); 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 new file mode 100644 index 0000000000..c691404895 --- /dev/null +++ b/ng2-components/ng2-activiti-tasklist/src/services/activiti-tasklist.service.ts @@ -0,0 +1,93 @@ +/*! + * @license + * Copyright 2016 Alfresco Software, Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { Injectable } from '@angular/core'; +import { Http, Headers, RequestOptions, Response } from '@angular/http'; +import { Observable } from 'rxjs/Rx'; +import { FilterModel } from '../models/filter.model'; + +@Injectable() +export class ActivitiTaskListService { + + constructor(private http: Http) { + } + + /** + * Retrive all the Tasks filters + * @returns {Observable} + */ + getTaskListFilters(): Observable { + return Observable.fromPromise(this.callApiTaskFilters()) + .map((res: Response) => { + return res.json(); + }) + .catch(this.handleError); + } + + /** + * Retrive all the tasks created in activiti + * @returns {any} + */ + getTasks(filter: FilterModel): Observable { + let data: any = {}; + data.filterId = filter.id; + data.filter = filter.filter; + data = JSON.stringify(data); + + return Observable.fromPromise(this.callApiTasksFiltered(data)) + .map((res: Response) => { + return res.json(); + }) + .catch(this.handleError); + } + + private callApiTasksFiltered(data: Object) { + let url = 'http://localhost:9999/activiti-app/app/rest/filter/tasks'; + let headers = new Headers({ + 'Content-Type': 'application/json', + 'Cache-Control': 'no-cache' + }); + let options = new RequestOptions({headers: headers}); + + return this.http + .post(url, data, options).toPromise(); + } + + private callApiTaskFilters() { + let url = 'http://localhost:9999/activiti-app/app/rest/filters/tasks'; + let headers = new Headers({ + 'Content-Type': 'application/json', + 'Cache-Control': 'no-cache' + }); + let options = new RequestOptions({headers: headers}); + + return this.http + .get(url, options).toPromise(); + } + + + /** + * The method write the error in the console browser + * @param error + * @returns {ErrorObservable} + */ + public handleError(error: Response): Observable { + console.error('Error when logging in', error); + return Observable.throw(error || 'Server error'); + } + +} diff --git a/ng2-components/ng2-activiti-tasklist/tsconfig.json b/ng2-components/ng2-activiti-tasklist/tsconfig.json new file mode 100644 index 0000000000..39deca0930 --- /dev/null +++ b/ng2-components/ng2-activiti-tasklist/tsconfig.json @@ -0,0 +1,27 @@ +{ + "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" + }, + "exclude": [ + "demo", + "node_modules", + "typings/main", + "typings/main.d.ts", + "dist" + ] +} diff --git a/ng2-components/ng2-activiti-tasklist/tslint.json b/ng2-components/ng2-activiti-tasklist/tslint.json new file mode 100644 index 0000000000..d9374e0015 --- /dev/null +++ b/ng2-components/ng2-activiti-tasklist/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, + 140 + ], + "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-tasklist/typings.json b/ng2-components/ng2-activiti-tasklist/typings.json new file mode 100644 index 0000000000..d8954c2485 --- /dev/null +++ b/ng2-components/ng2-activiti-tasklist/typings.json @@ -0,0 +1,7 @@ +{ + "globalDependencies": { + "core-js": "registry:dt/core-js#0.0.0+20160317120654", + "jasmine": "registry:dt/jasmine#2.2.0+20160505161446", + "node": "registry:dt/node#4.0.0+20160509154515" + } +} diff --git a/ng2-components/ng2-alfresco-core/src/services/AlfrescoSettingsService.service.ts b/ng2-components/ng2-alfresco-core/src/services/AlfrescoSettingsService.service.ts index c9c590c416..a970cb583b 100644 --- a/ng2-components/ng2-alfresco-core/src/services/AlfrescoSettingsService.service.ts +++ b/ng2-components/ng2-alfresco-core/src/services/AlfrescoSettingsService.service.ts @@ -45,4 +45,8 @@ export class AlfrescoSettingsService { getProviders(): string [] { return this.providers; } + + setProviders(providers: string []) { + this.providers = providers; + } }