diff --git a/demo-shell-ng2/app/components/activiti/activiti-demo.component.css b/demo-shell-ng2/app/components/activiti/activiti-demo.component.css index 0258de8fe1..88261c858f 100644 --- a/demo-shell-ng2/app/components/activiti/activiti-demo.component.css +++ b/demo-shell-ng2/app/components/activiti/activiti-demo.component.css @@ -2,3 +2,13 @@ cursor: pointer; font-weight: bold; } + +.activiti { + background-color: #f5f5f5; +} + +.task-column { + background-color: #f5f5f5; + padding: 10px 10px 10px 10px; + border: solid 2px rgb(31,188,210); +} 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 bd44038472..04531d9db4 100644 --- a/demo-shell-ng2/app/components/activiti/activiti-demo.component.html +++ b/demo-shell-ng2/app/components/activiti/activiti-demo.component.html @@ -1,22 +1,60 @@ -
- -
-
No tasks found
-
-
    -
  • - - launch - {{task.name || 'Nameless task'}} - -
+
+
+ + -
- -
- -
- + +
+
+
+
+
+ Task Filters + +
+
+ Task List + +
+
+ Task Details + +
+
+
+
+
+
+
+
+
+ Process Filters +
+
+ Process List +
+
+ Process Details +
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
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 db6555809b..f14d1565ad 100644 --- a/demo-shell-ng2/app/components/activiti/activiti-demo.component.ts +++ b/demo-shell-ng2/app/components/activiti/activiti-demo.component.ts @@ -15,9 +15,9 @@ * limitations under the License. */ -import { Component, OnInit, AfterViewChecked } from '@angular/core'; -import { ActivitiForm, FormService } from 'ng2-activiti-form'; - +import { Component, OnInit, AfterViewChecked, ViewChild } from '@angular/core'; +import { ALFRESCO_TASKLIST_DIRECTIVES } from 'ng2-activiti-tasklist'; +import { ActivitiForm } from 'ng2-activiti-form'; declare let __moduleName: string; declare var componentHandler; @@ -27,22 +27,52 @@ declare var componentHandler; selector: 'activiti-demo', templateUrl: './activiti-demo.component.html', styleUrls: ['./activiti-demo.component.css'], - directives: [ActivitiForm], - providers: [FormService] + directives: [ALFRESCO_TASKLIST_DIRECTIVES, ActivitiForm] }) export class ActivitiDemoComponent implements OnInit, AfterViewChecked { - tasks: any[] = []; - selectedTask: any; + currentChoice: string = 'task-list'; - hasTasks(): boolean { - return this.tasks && this.tasks.length > 0; + @ViewChild('activitidetails') + activitidetails: any; + + @ViewChild('activititasklist') + activititasklist: any; + + currentTaskId: string; + + schemaColumn: any [] = []; + + taskFilter: any; + + setChoice($event) { + this.currentChoice = $event.target.value; } - constructor(private formService: FormService) {} + isProcessListSelected() { + return this.currentChoice === 'process-list'; + } - ngOnInit() { - this.formService.getTasks().subscribe(val => this.tasks = val || []); + isTaskListSelected() { + return this.currentChoice === 'task-list'; + } + + constructor() { + console.log('Activiti demo component'); + this.schemaColumn = [ + {type: 'text', key: 'name', title: 'Name', cssClass: 'full-width name-column', sortable: true} + // {type: 'text', key: 'created', title: 'Created', sortable: true} + ]; + } + + onFilterClick(event: any) { + this.taskFilter = event; + this.activititasklist.load(this.taskFilter); + } + + onRowClick(taskId) { + this.currentTaskId = taskId; + this.activitidetails.loadDetails(this.currentTaskId); } ngAfterViewChecked() { @@ -52,8 +82,4 @@ export class ActivitiDemoComponent implements OnInit, AfterViewChecked { } } - onTaskClicked(task, e) { - this.selectedTask = task; - } - } diff --git a/demo-shell-ng2/app/components/tasks/activiti.service.ts b/demo-shell-ng2/app/components/tasks/activiti.service.ts deleted file mode 100644 index 9b8b5d95dc..0000000000 --- a/demo-shell-ng2/app/components/tasks/activiti.service.ts +++ /dev/null @@ -1,85 +0,0 @@ -/*! - * @license - * Copyright 2016 Alfresco Software, Ltd. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -import { Injectable } from '@angular/core'; -import { Http, Headers, RequestOptions, Response } from '@angular/http'; -// import { Observable } from 'rxjs/Rx'; - -@Injectable() -export class ActivitiService { - - constructor(private http: Http) {} - - login(username: string, password: string) { - let url = 'http://localhost:9999/activiti-app/app/authentication'; - let headers = new Headers({ - 'Content-Type': 'application/x-www-form-urlencoded', - 'Cache-Control': 'no-cache' - }); - let options = new RequestOptions({ headers: headers }); - let data = 'j_username=' - + encodeURIComponent(username) - + '&j_password=' - + encodeURIComponent(password) - + '&_spring_security_remember_me=true&submit=Login'; - - return this.http - .post(url, data, options) - .toPromise() - // .then(res => console.log(res)) - .catch(this.handleError); - } - - getTasks() { - // emulate filter value - let data = JSON.stringify({ - 'page': 0, - 'filterId': 3, - 'filter': { - 'sort': 'created-desc', - 'name': '', - 'state': 'open', - 'assignment': 'involved' - }, - 'appDefinitionId': null - }); - - 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() - .then(this.parseJSON) - .catch(this.handleError); - } - - private parseJSON(res: Response) { - let body = res.json(); - return body.data || { }; - } - - private handleError(error: any) { - console.error('An error occurred', error); - return Promise.reject(error.message || error); - } - -} diff --git a/demo-shell-ng2/app/components/tasks/tasks-demo.component.ts b/demo-shell-ng2/app/components/tasks/tasks-demo.component.ts deleted file mode 100644 index 2d608bc846..0000000000 --- a/demo-shell-ng2/app/components/tasks/tasks-demo.component.ts +++ /dev/null @@ -1,51 +0,0 @@ -/*! - * @license - * Copyright 2016 Alfresco Software, Ltd. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -import { Component, OnInit } from '@angular/core'; -import { ActivitiTaskList } from 'ng2-activiti-tasklist'; -import { ObjectDataTableAdapter, ObjectDataColumn } from 'ng2-alfresco-datatable'; - -@Component({ - selector: 'tasks-demo', - template: ` -
- -
- `, - directives: [ActivitiTaskList], - styles: [':host > .container { padding: 10px; }'] -}) -export class TasksDemoComponent implements OnInit { - - data: ObjectDataTableAdapter; - constructor() { - 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); - } - -} diff --git a/ng2-components/ng2-activiti-tasklist/README.md b/ng2-components/ng2-activiti-tasklist/README.md index b2226ddc09..6f6d8a2a15 100644 --- a/ng2-components/ng2-activiti-tasklist/README.md +++ b/ng2-components/ng2-activiti-tasklist/README.md @@ -1 +1,150 @@ # Activiti Task List 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-tasklist +``` + +### Dependencies + +You must separately install the following libraries for your application: + +- [ng2-translate](https://github.com/ocombe/ng2-translate) +- [ng2-alfresco-core](https://www.npmjs.com/package/ng2-alfresco-core) +- [ng2-alfresco-datatable](https://www.npmjs.com/package/ng2-alfresco-datatable) + + +```sh +npm install --save ng2-translate ng2-alfresco-core ng2-alfresco-datatable +``` + +#### 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 Task List +The component shows the list of all the tasks filter by the +FilterModel passed in input. +```html + +``` + +#### Events +**onSuccess**: The event is emitted when the task list is loaded +**rowClick**: The event is emitted when the task in the list is +clicked
+ +#### Options + +**taskFilter**: { FilterModel } required) FilterModel object that +is passed to the task list API to filter the task list. +Example: +```json +{ + "id": 4, + "name": "Involved Tasks", + "recent": false, + "icon": "glyphicon-align-left", + "filter": { + "sort": "created-desc", + "name": "", + "state": "open", + "assignment": "involved" + } +} +``` +**schemaColumn**: { any[] } optional) JSON object that represent +the number and the type of the columns that you want show +Example: +```json +[ + {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} +] +``` + +## Basic usage example Activiti Task Details +The component shows the details of the task id passed in input +```html + +``` + +#### Events +No events + +#### Options + +**taskId**: { string } required) The id of the task details that we +are asking for. + +## Basic usage example Activiti Filter +The component shows all the available filters. + +```html + +``` + +#### Events +**filterClick**: The event is emitted when the filter in the list is + clicked + +#### Options +No 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-tasklist/i18n/en.json b/ng2-components/ng2-activiti-tasklist/i18n/en.json new file mode 100644 index 0000000000..d83089f9f6 --- /dev/null +++ b/ng2-components/ng2-activiti-tasklist/i18n/en.json @@ -0,0 +1,40 @@ +{ + "TASK_LIST": { + "MESSAGES": { + "NONE": "No tasks list found." + } + }, + "TASK_DETAILS": { + "LABELS": { + "ASSIGNEE": "Assignee", + "DUE": "Due", + "FORM": "Form", + "PEOPLE": "People", + "COMMENTS": "Comments", + "CHECKLIST": "Checklist" + }, + "MESSAGES": { + "NONE": "No task details found." + }, + "FORM": { + "NONE": "No form." + }, + "DUE": { + "NONE": "No due date." + }, + "PEOPLE": { + "NONE": "No people involved." + }, + "COMMENTS": { + "NONE": "No comments." + }, + "CHECKLIST": { + "NONE": "No checklist." + } + }, + "TASK_FILTERS": { + "MESSAGES": { + "NONE": "No task filter selected." + } + } +} \ No newline at end of file diff --git a/ng2-components/ng2-activiti-tasklist/i18n/it.json b/ng2-components/ng2-activiti-tasklist/i18n/it.json new file mode 100644 index 0000000000..62021c250d --- /dev/null +++ b/ng2-components/ng2-activiti-tasklist/i18n/it.json @@ -0,0 +1,28 @@ +{ + "TASK_LIST": { + "MESSAGES": { + "NONE": "Nessuna lista tasks trovata." + } + }, + "TASK_DETAILS": { + "LABELS": { + "ASSIGNEE": "Assegnatario", + "DUE": "Scadenza", + "FORM": "Form" + }, + "MESSAGES": { + "NONE": "Nessun dettaglio task trovato." + }, + "FORM": { + "NONE": "Nessuna form." + }, + "DUE": { + "NONE": "Nessuna data di scadenza." + } + }, + "TASK_FILTERS": { + "MESSAGES": { + "NONE": "Nessun filtro task selezionato." + } + } +} \ No newline at end of file diff --git a/ng2-components/ng2-activiti-tasklist/index.ts b/ng2-components/ng2-activiti-tasklist/index.ts index f9c4e4a420..dc72a4b407 100644 --- a/ng2-components/ng2-activiti-tasklist/index.ts +++ b/ng2-components/ng2-activiti-tasklist/index.ts @@ -16,7 +16,9 @@ */ import { ActivitiTaskList } from './src/components/activiti-tasklist.component'; +import { ActivitiTaskDetails } from './src/components/activiti-task-details.component'; +import { ActivitiFilters } from './src/components/activiti-filters.component'; export * from './src/components/activiti-tasklist.component'; -export const ALFRESCO_TASKLIST_DIRECTIVES: [any] = [ActivitiTaskList]; +export const ALFRESCO_TASKLIST_DIRECTIVES: [any] = [ActivitiFilters, ActivitiTaskList, ActivitiTaskDetails]; diff --git a/ng2-components/ng2-activiti-tasklist/package.json b/ng2-components/ng2-activiti-tasklist/package.json index 8e172fb1d6..dda05ee92a 100644 --- a/ng2-components/ng2-activiti-tasklist/package.json +++ b/ng2-components/ng2-activiti-tasklist/package.json @@ -70,7 +70,8 @@ "zone.js": "0.6.12", "ng2-translate": "2.2.2", "ng2-alfresco-core": "0.2.0", - "ng2-alfresco-datatable": "0.2.0", + "ng2-alfresco-datatable": "0.2.0", + "ng2-activiti-form": "0.2.0", "alfresco-js-api": "^0.1.0" }, "peerDependencies": { diff --git a/ng2-components/ng2-activiti-tasklist/src/components/activiti-checklist.component.css b/ng2-components/ng2-activiti-tasklist/src/components/activiti-checklist.component.css new file mode 100644 index 0000000000..7e9e64291f --- /dev/null +++ b/ng2-components/ng2-activiti-tasklist/src/components/activiti-checklist.component.css @@ -0,0 +1,11 @@ +:host { + width: 100%; +} + +.activiti-label { + font-weight: bolder; +} + +.material-icons:hover { + color: rgb(255, 152, 0); +} diff --git a/ng2-components/ng2-activiti-tasklist/src/components/activiti-checklist.component.html b/ng2-components/ng2-activiti-tasklist/src/components/activiti-checklist.component.html new file mode 100644 index 0000000000..9bfdf6e968 --- /dev/null +++ b/ng2-components/ng2-activiti-tasklist/src/components/activiti-checklist.component.html @@ -0,0 +1,33 @@ +{{ 'TASK_DETAILS.LABELS.CHECKLIST' | translate }} +
add
+
+ Add a checklist +
+ +
+ {{ 'TASK_DETAILS.CHECKLIST.NONE' | translate }} +
+ + +

New Task

+
+
+ + +
+
+
+ + +
+
\ No newline at end of file diff --git a/ng2-components/ng2-activiti-tasklist/src/components/activiti-checklist.component.ts b/ng2-components/ng2-activiti-tasklist/src/components/activiti-checklist.component.ts new file mode 100644 index 0000000000..e958e993a1 --- /dev/null +++ b/ng2-components/ng2-activiti-tasklist/src/components/activiti-checklist.component.ts @@ -0,0 +1,120 @@ +/*! + * @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, ViewChild } from '@angular/core'; +import { AlfrescoTranslationService, AlfrescoAuthenticationService, AlfrescoPipeTranslate } from 'ng2-alfresco-core'; +import { ActivitiTaskListService } from './../services/activiti-tasklist.service'; +import { TaskDetailsModel } from '../models/task-details.model'; +import { Observer } from 'rxjs/Observer'; +import { Observable } from 'rxjs/Observable'; + +declare let componentHandler: any; +declare let __moduleName: string; + +@Component({ + selector: 'activiti-checklist', + moduleId: __moduleName, + templateUrl: './activiti-checklist.component.html', + styleUrls: ['./activiti-checklist.component.css'], + providers: [ActivitiTaskListService], + pipes: [AlfrescoPipeTranslate] + +}) +export class ActivitiChecklist implements OnInit { + + @Input() + taskId: string; + + @ViewChild('dialog') + dialog: any; + + taskName: string; + + checklist: TaskDetailsModel [] = []; + + private taskObserver: Observer; + task$: Observable; + + /** + * Constructor + * @param auth + * @param translate + */ + constructor(private auth: AlfrescoAuthenticationService, + private translate: AlfrescoTranslationService, + private activitiTaskList: ActivitiTaskListService) { + + if (translate) { + translate.addTranslationFolder('node_modules/ng2-activiti-tasklist'); + } + this.task$ = new Observable(observer => this.taskObserver = observer).share(); + } + + ngOnInit() { + this.task$.subscribe((task: TaskDetailsModel) => { + this.checklist.push(task); + }); + + if (this.taskId) { + this.load(this.taskId); + } + } + + public load(taskId: string) { + this.checklist = []; + if (this.taskId) { + this.activitiTaskList.getTaskChecklist(this.taskId).subscribe( + (res: TaskDetailsModel[]) => { + res.forEach((task) => { + this.taskObserver.next(task); + }); + }, + (err) => { + console.log(err); + } + ); + } else { + this.checklist = []; + } + } + + public showDialog() { + if (this.dialog) { + this.dialog.nativeElement.showModal(); + } + } + + public add() { + let newTask = new TaskDetailsModel({name: this.taskName, parentTaskId: this.taskId, assignee: {id: '1'}}); + this.activitiTaskList.addTask(newTask).subscribe( + (res: TaskDetailsModel) => { + this.checklist.push(res); + }, + (err) => { + console.log(err); + } + ); + + this.cancel(); + } + + public cancel() { + if (this.dialog) { + this.dialog.nativeElement.close(); + } + } +} diff --git a/ng2-components/ng2-activiti-tasklist/src/components/activiti-comments.component.css b/ng2-components/ng2-activiti-tasklist/src/components/activiti-comments.component.css new file mode 100644 index 0000000000..7e9e64291f --- /dev/null +++ b/ng2-components/ng2-activiti-tasklist/src/components/activiti-comments.component.css @@ -0,0 +1,11 @@ +:host { + width: 100%; +} + +.activiti-label { + font-weight: bolder; +} + +.material-icons:hover { + color: rgb(255, 152, 0); +} diff --git a/ng2-components/ng2-activiti-tasklist/src/components/activiti-comments.component.html b/ng2-components/ng2-activiti-tasklist/src/components/activiti-comments.component.html new file mode 100644 index 0000000000..50fb144e73 --- /dev/null +++ b/ng2-components/ng2-activiti-tasklist/src/components/activiti-comments.component.html @@ -0,0 +1,35 @@ +{{ 'TASK_DETAILS.LABELS.COMMENTS' |translate }} +
add
+
+ Add a comment +
+ + +
+ {{ 'TASK_DETAILS.COMMENTS.NONE' | translate }} +
+ + + +

New comment

+
+
+ + +
+
+
+ + +
+
\ No newline at end of file diff --git a/ng2-components/ng2-activiti-tasklist/src/components/activiti-comments.component.ts b/ng2-components/ng2-activiti-tasklist/src/components/activiti-comments.component.ts new file mode 100644 index 0000000000..1ae99929c2 --- /dev/null +++ b/ng2-components/ng2-activiti-tasklist/src/components/activiti-comments.component.ts @@ -0,0 +1,121 @@ +/*! + * @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, ViewChild } from '@angular/core'; +import { AlfrescoTranslationService, AlfrescoAuthenticationService, AlfrescoPipeTranslate } from 'ng2-alfresco-core'; +import { ActivitiTaskListService } from './../services/activiti-tasklist.service'; +import { Comment } from '../models/comment.model'; +import { Observer } from 'rxjs/Observer'; +import { Observable } from 'rxjs/Observable'; + +declare let componentHandler: any; +declare let __moduleName: string; + +@Component({ + selector: 'activiti-comments', + moduleId: __moduleName, + templateUrl: './activiti-comments.component.html', + styleUrls: ['./activiti-comments.component.css'], + providers: [ActivitiTaskListService], + pipes: [ AlfrescoPipeTranslate ] + +}) +export class ActivitiComments implements OnInit { + + @Input() + taskId: string; + + @ViewChild('dialog') + dialog: any; + + comments: Comment [] = []; + + private commentObserver: Observer; + comment$: Observable; + + message: string; + + /** + * Constructor + * @param auth + * @param translate + */ + constructor(private auth: AlfrescoAuthenticationService, + private translate: AlfrescoTranslationService, + private activitiTaskList: ActivitiTaskListService) { + + if (translate) { + translate.addTranslationFolder('node_modules/ng2-activiti-tasklist'); + } + + this.comment$ = new Observable(observer => this.commentObserver = observer).share(); + + } + + ngOnInit() { + this.comment$.subscribe((comment: Comment) => { + this.comments.push(comment); + }); + + if (this.taskId) { + this.load(this.taskId); + } + } + + public load(taskId: string) { + this.comments = []; + if (this.taskId) { + this.activitiTaskList.getTaskComments(this.taskId).subscribe( + (res: Comment[]) => { + res.forEach((comment) => { + this.commentObserver.next(comment); + }); + }, + (err) => { + console.log(err); + } + ); + } else { + this.comments = []; + } + } + + public showDialog() { + if (this.dialog) { + this.dialog.nativeElement.showModal(); + } + } + + public add() { + this.activitiTaskList.addTaskComment(this.taskId, this.message).subscribe( + (res: Comment) => { + this.comments.push(res); + this.message = ''; + }, + (err) => { + console.log(err); + } + ); + this.cancel(); + } + + public cancel() { + if (this.dialog) { + this.dialog.nativeElement.close(); + } + } +} diff --git a/ng2-components/ng2-activiti-tasklist/src/components/activiti-filters.component.html b/ng2-components/ng2-activiti-tasklist/src/components/activiti-filters.component.html new file mode 100644 index 0000000000..580798c6a3 --- /dev/null +++ b/ng2-components/ng2-activiti-tasklist/src/components/activiti-filters.component.html @@ -0,0 +1,10 @@ + \ No newline at end of file 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 new file mode 100644 index 0000000000..41528c026d --- /dev/null +++ b/ng2-components/ng2-activiti-tasklist/src/components/activiti-filters.component.spec.ts @@ -0,0 +1,96 @@ +/*! + * @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 { ActivitiFilters } from './activiti-filters.component'; +import { ActivitiTaskListService } from '../services/activiti-tasklist.service'; +import { Observable } from 'rxjs/Rx'; +import { FilterModel } from '../models/filter.model'; + +describe('ActivitiFilters', () => { + + let filterList: ActivitiFilters; + + let fakeGlobalFilter = []; + fakeGlobalFilter.push(new FilterModel('FakeInvolvedTasks', false, 'glyphicon-align-left', '', 'open', 'fake-involved')); + fakeGlobalFilter.push(new FilterModel('FakeMyTasks', false, 'glyphicon-align-left', '', 'open', 'fake-assignee')); + + let fakeGlobalFilterPromise = new Promise(function (resolve, reject) { + resolve(fakeGlobalFilter); + }); + + let fakeErrorFilterList = { + error: 'wrong request' + }; + + let fakeErrorFilterPromise = new Promise(function (resolve, reject) { + reject(fakeErrorFilterList); + }); + + beforeEach(() => { + let activitiService = new ActivitiTaskListService(null, null); + filterList = new ActivitiFilters(null, null, activitiService); + }); + + it('should return the filter task list', (done) => { + spyOn(filterList.activiti, 'getTaskListFilters').and.returnValue(Observable.fromPromise(fakeGlobalFilterPromise)); + + filterList.onSuccess.subscribe( (res) => { + expect(res).toBeDefined(); + expect(res).toEqual('Filter task list loaded'); + expect(filterList.filters).toBeDefined(); + expect(filterList.filters.length).toEqual(2); + expect(filterList.filters[0].name).toEqual('FakeInvolvedTasks'); + expect(filterList.filters[1].name).toEqual('FakeMyTasks'); + done(); + }); + + filterList.ngOnInit(); + }); + + it('should emit an error with a bad response', (done) => { + spyOn(filterList.activiti, 'getTaskListFilters').and.returnValue(Observable.fromPromise(fakeErrorFilterPromise)); + + filterList.onError.subscribe( (err) => { + expect(err).toBeDefined(); + expect(err).toEqual('Error to load a task filter list'); + done(); + }); + + filterList.ngOnInit(); + }); + + it('should emit an event when a filter is selected', (done) => { + let currentFilter = new FilterModel('FakeInvolvedTasks', false, 'glyphicon-align-left', '', 'open', 'fake-involved'); + + filterList.filterClick.subscribe((filter: FilterModel) => { + expect(filter).toBeDefined(); + expect(filter).toEqual(currentFilter); + expect(filterList.currentFilter).toEqual(currentFilter); + done(); + }); + + filterList.selectFilter(currentFilter); + }); + +}); 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 new file mode 100644 index 0000000000..68228880b8 --- /dev/null +++ b/ng2-components/ng2-activiti-tasklist/src/components/activiti-filters.component.ts @@ -0,0 +1,103 @@ +/*! + * @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, Output, EventEmitter, OnInit} from '@angular/core'; +import { AlfrescoTranslationService, AlfrescoAuthenticationService, AlfrescoPipeTranslate } from 'ng2-alfresco-core'; +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-filters', + moduleId: __moduleName, + templateUrl: './activiti-filters.component.html', + providers: [ActivitiTaskListService], + pipes: [ AlfrescoPipeTranslate ] + +}) +export class ActivitiFilters implements OnInit { + + @Output() + filterClick: EventEmitter = new EventEmitter(); + + @Output() + onSuccess: EventEmitter = new EventEmitter(); + + @Output() + onError: EventEmitter = new EventEmitter(); + + private filterObserver: Observer; + filter$: Observable; + + currentFilter: FilterModel; + + filters: FilterModel [] = []; + /** + * 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.filter$.subscribe((filter: FilterModel) => { + this.filters.push(filter); + }); + + this.load(); + } + + /** + * The method call the adapter data table component for render the task list + * @param tasks + */ + private load() { + this.activiti.getTaskListFilters().subscribe( + (res: FilterModel[]) => { + res.forEach((filter) => { + this.filterObserver.next(filter); + }); + this.onSuccess.emit('Filter task list loaded'); + }, + (err) => { + console.log(err); + this.onError.emit('Error to load a task filter list'); + } + ); + } + + /** + * Pass the selected filter as next + * @param filter + */ + public selectFilter(filter: FilterModel) { + this.currentFilter = filter; + this.filterClick.emit(filter); + } +} diff --git a/ng2-components/ng2-activiti-tasklist/src/components/activiti-people.component.css b/ng2-components/ng2-activiti-tasklist/src/components/activiti-people.component.css new file mode 100644 index 0000000000..7e9e64291f --- /dev/null +++ b/ng2-components/ng2-activiti-tasklist/src/components/activiti-people.component.css @@ -0,0 +1,11 @@ +:host { + width: 100%; +} + +.activiti-label { + font-weight: bolder; +} + +.material-icons:hover { + color: rgb(255, 152, 0); +} diff --git a/ng2-components/ng2-activiti-tasklist/src/components/activiti-people.component.html b/ng2-components/ng2-activiti-tasklist/src/components/activiti-people.component.html new file mode 100644 index 0000000000..b6d28fa4d5 --- /dev/null +++ b/ng2-components/ng2-activiti-tasklist/src/components/activiti-people.component.html @@ -0,0 +1,33 @@ +{{ 'TASK_DETAILS.LABELS.PEOPLE' | translate }} +
add
+
+ Add a people +
+ +
+ {{ 'TASK_DETAILS.PEOPLE.NONE' | translate }} +
+ + +

New User

+
+
+ + +
+
+
+ + +
+
\ No newline at end of file diff --git a/ng2-components/ng2-activiti-tasklist/src/components/activiti-people.component.ts b/ng2-components/ng2-activiti-tasklist/src/components/activiti-people.component.ts new file mode 100644 index 0000000000..c4e472b3b3 --- /dev/null +++ b/ng2-components/ng2-activiti-tasklist/src/components/activiti-people.component.ts @@ -0,0 +1,84 @@ +/*! + * @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, ViewChild } from '@angular/core'; +import { AlfrescoTranslationService, AlfrescoAuthenticationService, AlfrescoPipeTranslate } from 'ng2-alfresco-core'; +import { User } from '../models/user.model'; +import { Observer } from 'rxjs/Observer'; +import { Observable } from 'rxjs/Observable'; + +declare let componentHandler: any; +declare let __moduleName: string; + +@Component({ + selector: 'activiti-people', + moduleId: __moduleName, + templateUrl: './activiti-people.component.html', + styleUrls: ['./activiti-people.component.css'], + pipes: [ AlfrescoPipeTranslate ] + +}) +export class ActivitiPeople implements OnInit { + + @Input() + people: User [] = []; + + @ViewChild('dialog') + dialog: any; + + private peopleObserver: Observer; + people$: Observable; + + /** + * Constructor + * @param auth + * @param translate + */ + constructor(private auth: AlfrescoAuthenticationService, + private translate: AlfrescoTranslationService) { + + if (translate) { + translate.addTranslationFolder('node_modules/ng2-activiti-tasklist'); + } + this.people$ = new Observable(observer => this.peopleObserver = observer).share(); + } + + ngOnInit() { + this.people$.subscribe((user: User) => { + this.people.push(user); + }); + } + + public showDialog() { + if (this.dialog) { + this.dialog.nativeElement.showModal(); + } + } + + public add() { + alert('add people'); + + this.cancel(); + } + + public cancel() { + if (this.dialog) { + this.dialog.nativeElement.close(); + } + } + +} diff --git a/ng2-components/ng2-activiti-tasklist/src/components/activiti-task-details.component.css b/ng2-components/ng2-activiti-tasklist/src/components/activiti-task-details.component.css new file mode 100644 index 0000000000..07eaf92d80 --- /dev/null +++ b/ng2-components/ng2-activiti-tasklist/src/components/activiti-task-details.component.css @@ -0,0 +1,3 @@ +:host { + width: 100%; +} \ No newline at end of file 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 new file mode 100644 index 0000000000..fd7fdc6d62 --- /dev/null +++ b/ng2-components/ng2-activiti-tasklist/src/components/activiti-task-details.component.html @@ -0,0 +1,17 @@ +
{{ 'TASK_DETAILS.MESSAGES.NONE' | translate }}
+
+

{{taskDetails.name}}

+ +
+
+ +
+
+ +
+
+ +
+
+ +
\ No newline at end of file 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 new file mode 100644 index 0000000000..fff24fdde3 --- /dev/null +++ b/ng2-components/ng2-activiti-tasklist/src/components/activiti-task-details.component.ts @@ -0,0 +1,114 @@ +/*! + * @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, ViewChild } from '@angular/core'; +import { AlfrescoTranslationService, AlfrescoAuthenticationService, AlfrescoPipeTranslate } 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 { ActivitiForm, FormModel, FormService } from 'ng2-activiti-form'; + + +declare let componentHandler: any; +declare let __moduleName: string; + +@Component({ + selector: 'activiti-task-details', + moduleId: __moduleName, + templateUrl: './activiti-task-details.component.html', + styleUrls: ['./activiti-task-details.component.css'], + providers: [ActivitiTaskListService, FormService], + directives: [ActivitiTaskHeader, ActivitiPeople, ActivitiComments, ActivitiChecklist, ActivitiForm], + pipes: [AlfrescoPipeTranslate] + +}) +export class ActivitiTaskDetails implements OnInit { + + @Input() + taskId: string; + + @ViewChild('activiticomments') + activiticomments: any; + + @ViewChild('activitichecklist') + activitichecklist: any; + + taskDetails: TaskDetailsModel; + + taskForm: FormModel; + + taskPeople: User[] = []; + + /** + * 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'); + } + } + + ngOnInit() { + if (this.taskId) { + this.loadDetails(this.taskId); + } + } + + loadDetails(taskId: string) { + this.taskForm = null; + this.taskPeople = []; + if (taskId) { + this.activitiTaskList.getTaskDetails(taskId).subscribe( + (res: TaskDetailsModel) => { + this.taskDetails = res; + if (this.taskDetails && this.taskDetails.involvedPeople) { + this.taskDetails.involvedPeople.forEach((user) => { + this.taskPeople.push(new User(user.id, user.email, user.firstName, user.lastName)); + }); + + if (this.activiticomments) { + this.activiticomments.load(this.taskDetails.id); + } + + if (this.activitichecklist) { + this.activitichecklist.load(this.taskDetails.id); + } + } + console.log(this.taskDetails); + } + ); + } + } + + onComplete() { + this.activitiTaskList.completeTask(this.taskId).subscribe( + (res) => { + console.log(res); + } + ); + } +} diff --git a/ng2-components/ng2-activiti-tasklist/src/components/activiti-task-header.component.css b/ng2-components/ng2-activiti-tasklist/src/components/activiti-task-header.component.css new file mode 100644 index 0000000000..20fbab0626 --- /dev/null +++ b/ng2-components/ng2-activiti-tasklist/src/components/activiti-task-header.component.css @@ -0,0 +1,7 @@ +:host { + width: 100%; +} + +.activiti-label { + font-weight: bolder; +} \ No newline at end of file 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 new file mode 100644 index 0000000000..c098c1d8c3 --- /dev/null +++ b/ng2-components/ng2-activiti-tasklist/src/components/activiti-task-header.component.html @@ -0,0 +1,18 @@ +
+
+
+ {{ 'TASK_DETAILS.LABELS.ASSIGNEE' | translate }}: + {{taskDetails.assignee.lastName }} +
+
+ + {{ 'TASK_DETAILS.LABELS.DUE' | translate }}: + {{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 new file mode 100644 index 0000000000..a1f4d777ee --- /dev/null +++ b/ng2-components/ng2-activiti-tasklist/src/components/activiti-task-header.component.ts @@ -0,0 +1,82 @@ +/*! + * @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, OnChanges } from '@angular/core'; +import { AlfrescoTranslationService, AlfrescoAuthenticationService, AlfrescoPipeTranslate } 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; + +@Component({ + selector: 'activiti-task-header', + moduleId: __moduleName, + templateUrl: './activiti-task-header.component.html', + styleUrls: ['./activiti-task-header.component.css'], + providers: [ FormService ], + pipes: [ AlfrescoPipeTranslate ] + +}) +export class ActivitiTaskHeader implements OnInit, OnChanges { + + @Input() + taskDetails: TaskDetailsModel; + + taskForm: FormModel; + + /** + * Constructor + * @param auth + * @param translate + */ + constructor(private auth: AlfrescoAuthenticationService, + private activitiForm: FormService, + private translate: AlfrescoTranslationService) { + + if (translate) { + translate.addTranslationFolder('node_modules/ng2-activiti-tasklist'); + } + } + + 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.html b/ng2-components/ng2-activiti-tasklist/src/components/activiti-tasklist.component.html index d3d2c96d0c..4f932db173 100644 --- a/ng2-components/ng2-activiti-tasklist/src/components/activiti-tasklist.component.html +++ b/ng2-components/ng2-activiti-tasklist/src/components/activiti-tasklist.component.html @@ -1,12 +1,12 @@ -