From 403d5cea8568a44bbb5e863d85f32bf50b4e7efa Mon Sep 17 00:00:00 2001 From: Deepak Paul Date: Mon, 10 Jul 2017 14:43:24 +0530 Subject: [PATCH] [ADF-497] Improvement to task comment (activiti-comments) component -1829 Github (#2054) * [ADF-497] Improvement to task comment (activiti-comments) component - 1829 Github * Added new design * Removed dialog * Migrated from mdl to md * Created a new component to list comments by using data-table * [ADF-497] Improvement to task comment (activiti-comments) component - 1829 Github * Added documentation * [ADF-497] Improvement to task comment (activiti-comments) component -1829 Github * Improved css class naming * Changed component name AdfCommentList to AdfCommentListComponent * Code refactoring * [ADF-497] Improvement to task comment (activiti-comments) component -1829 Github * Removed extra space at the end * [ADF-497] Improvement to task comment (activiti-comments) component -1829 Github * Import reordering --- .../ng2-activiti-tasklist/README.md | 29 ++++ .../docs/assets/adf-comments.png | Bin 0 -> 20362 bytes ng2-components/ng2-activiti-tasklist/index.ts | 13 +- .../activiti-comments.component.css | 51 +++--- .../activiti-comments.component.html | 41 ++--- .../activiti-comments.component.spec.ts | 124 ++++++++++----- .../components/activiti-comments.component.ts | 61 ++++---- .../components/adf-comment-list.component.css | 64 ++++++++ .../adf-comment-list.component.html | 30 ++++ .../adf-comment-list.component.spec.ts | 148 ++++++++++++++++++ .../components/adf-comment-list.component.ts | 80 ++++++++++ .../src/components/index.ts | 1 + .../ng2-activiti-tasklist/src/i18n/en.json | 1 + 13 files changed, 511 insertions(+), 132 deletions(-) create mode 100644 ng2-components/ng2-activiti-tasklist/docs/assets/adf-comments.png create mode 100644 ng2-components/ng2-activiti-tasklist/src/components/adf-comment-list.component.css create mode 100644 ng2-components/ng2-activiti-tasklist/src/components/adf-comment-list.component.html create mode 100644 ng2-components/ng2-activiti-tasklist/src/components/adf-comment-list.component.spec.ts create mode 100644 ng2-components/ng2-activiti-tasklist/src/components/adf-comment-list.component.ts diff --git a/ng2-components/ng2-activiti-tasklist/README.md b/ng2-components/ng2-activiti-tasklist/README.md index 7d2a86c13d..c36398bb05 100644 --- a/ng2-components/ng2-activiti-tasklist/README.md +++ b/ng2-components/ng2-activiti-tasklist/README.md @@ -39,6 +39,9 @@ - [Task People Component](#task-people-component) * [Properties](#properties-8) + [Events](#events-7) +- [ADF Comments Component](#adf-comments-component) + * [Properties](#properties-9) + + [Events](#events-8) - [Build from sources](#build-from-sources) - [NPM scripts](#npm-scripts) - [Demo](#demo) @@ -460,6 +463,32 @@ This component displays involved users to a specified task No Events +## ADF Comments Component + +This component displays comments entered by involved users to a specified task. It also allows an involved user to add his/her comment to the task. + +```html + + +``` + +![adf-comments](docs/assets/adf-comments.png) + +### Properties + +| Name | Type | Description | +| --- | --- | --- | +| taskId | string | The numeric ID of the task | +| readOnly | boolean | The boolean flag | + +#### Events + +| Name | Description | +| --- | --- | +| error | Raised when an error occurs while displaying/adding a comment | + ## Build from sources You can build component from sources with the following commands: diff --git a/ng2-components/ng2-activiti-tasklist/docs/assets/adf-comments.png b/ng2-components/ng2-activiti-tasklist/docs/assets/adf-comments.png new file mode 100644 index 0000000000000000000000000000000000000000..40a31a3c4d680f4de8feb6b65dcbb4ea97d5e60a GIT binary patch literal 20362 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 X+6-=o&3ytOjF7*pBAtsidGenCQG}qj literal 0 HcmV?d00001 diff --git a/ng2-components/ng2-activiti-tasklist/index.ts b/ng2-components/ng2-activiti-tasklist/index.ts index 70814134a0..92591a486d 100644 --- a/ng2-components/ng2-activiti-tasklist/index.ts +++ b/ng2-components/ng2-activiti-tasklist/index.ts @@ -15,8 +15,9 @@ * limitations under the License. */ +import { DatePipe } from '@angular/common'; import { ModuleWithProviders, NgModule } from '@angular/core'; -import { MdButtonModule, MdIconModule } from '@angular/material'; +import { MdButtonModule, MdIconModule, MdInputModule } from '@angular/material'; import { ActivitiFormModule } from 'ng2-activiti-form'; import { CoreModule } from 'ng2-alfresco-core'; import { DataTableModule } from 'ng2-alfresco-datatable'; @@ -35,6 +36,7 @@ import { ActivitiTaskDetails, ActivitiTaskHeader, ActivitiTaskList, + AdfCommentListComponent, NoTaskDetailsTemplateComponent, PeopleList, TaskAttachmentListComponent @@ -59,7 +61,8 @@ export const ACTIVITI_TASKLIST_DIRECTIVES: any[] = [ ActivitiPeopleSearch, TaskAttachmentListComponent, ActivitiCreateTaskAttachmentComponent, - PeopleList + PeopleList, + AdfCommentListComponent ]; export const ACTIVITI_TASKLIST_PROVIDERS: any[] = [ @@ -73,13 +76,15 @@ export const ACTIVITI_TASKLIST_PROVIDERS: any[] = [ DataTableModule, ActivitiFormModule, MdIconModule, - MdButtonModule + MdButtonModule, + MdInputModule ], declarations: [ ...ACTIVITI_TASKLIST_DIRECTIVES ], providers: [ - ...ACTIVITI_TASKLIST_PROVIDERS + ...ACTIVITI_TASKLIST_PROVIDERS, + DatePipe ], exports: [ ...ACTIVITI_TASKLIST_DIRECTIVES, 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 index 9ca19c95cd..73006380d2 100644 --- a/ng2-components/ng2-activiti-tasklist/src/components/activiti-comments.component.css +++ b/ng2-components/ng2-activiti-tasklist/src/components/activiti-comments.component.css @@ -1,32 +1,25 @@ -:host { +.adf-comments-container { + height: 100%; width: 100%; -} - -.activiti-label { - font-weight: bolder; -} - -.material-icons:hover { - color: rgb(255, 152, 0); -} - -.mdl-tooltip { - will-change: unset; -} - -.material-icons { - cursor: pointer; -} - -.list-wrap { - word-wrap: break-word; - word-break: break-all; - -moz-hyphens:auto; - -webkit-hyphens:auto; - -o-hyphens:auto; - hyphens:auto; -} - -.hide-long-names { overflow: auto; } + +.adf-comments-header { + padding: 10px 20px; + font-size: 14px; + font-family: Muli; + font-weight: 600; + border-bottom: 1px solid #e1e1e1; + color: #a1a1a1; +} + +.adf-comments-input-container { + padding: 0 15px; + width: calc(100% - 30px); + padding-top: 8px; + border-bottom: 1px solid #e1e1e1; +} + +.adf-full-width { + width: 100%; +} \ No newline at end of file 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 index f5670baefb..c17f0c6154 100644 --- a/ng2-components/ng2-activiti-tasklist/src/components/activiti-comments.component.html +++ b/ng2-components/ng2-activiti-tasklist/src/components/activiti-comments.component.html @@ -1,32 +1,13 @@ -{{ 'TASK_DETAILS.LABELS.COMMENTS' |translate }} -
add
-
- {{ 'TASK_DETAILS.COMMENTS.ADD' | translate }} -
- - -
- {{ 'TASK_DETAILS.COMMENTS.NONE' | translate }} -
- - - -

{{ 'TASK_DETAILS.COMMENTS.DIALOG.TITLE' | translate }}

-
-
- - -
+
+
+ {{'TASK_DETAILS.COMMENTS.HEADER' | translate}}({{comments?.length}})
-
- - +
+ + +
-
+ + + + diff --git a/ng2-components/ng2-activiti-tasklist/src/components/activiti-comments.component.spec.ts b/ng2-components/ng2-activiti-tasklist/src/components/activiti-comments.component.spec.ts index 55c448a210..198d0be7eb 100644 --- a/ng2-components/ng2-activiti-tasklist/src/components/activiti-comments.component.spec.ts +++ b/ng2-components/ng2-activiti-tasklist/src/components/activiti-comments.component.spec.ts @@ -17,14 +17,17 @@ import { SimpleChange } from '@angular/core'; import { async, ComponentFixture, TestBed } from '@angular/core/testing'; -import { By } from '@angular/platform-browser'; import { Observable } from 'rxjs/Rx'; import { ActivitiFormModule } from 'ng2-activiti-form'; import { AlfrescoTranslationService, CoreModule } from 'ng2-alfresco-core'; +import { DatePipe } from '@angular/common'; +import { MdInputModule } from '@angular/material'; +import { DataTableModule } from 'ng2-alfresco-datatable'; import { ActivitiTaskListService } from './../services/activiti-tasklist.service'; import { ActivitiComments } from './activiti-comments.component'; +import { AdfCommentListComponent } from './adf-comment-list.component'; describe('ActivitiComments', () => { @@ -39,13 +42,17 @@ describe('ActivitiComments', () => { TestBed.configureTestingModule({ imports: [ CoreModule.forRoot(), - ActivitiFormModule.forRoot() + ActivitiFormModule.forRoot(), + DataTableModule, + MdInputModule ], declarations: [ - ActivitiComments + ActivitiComments, + AdfCommentListComponent ], providers: [ - ActivitiTaskListService + ActivitiTaskListService, + DatePipe ] }).compileComponents(); @@ -60,11 +67,11 @@ describe('ActivitiComments', () => { service = fixture.debugElement.injector.get(ActivitiTaskListService); getCommentsSpy = spyOn(service, 'getTaskComments').and.returnValue(Observable.of([ - { message: 'Test1' }, - { message: 'Test2' }, - { message: 'Test3'} + { message: 'Test1', created: Date.now(), createdBy: {firstName: 'Admin', lastName: 'User'} }, + { message: 'Test2', created: Date.now(), createdBy: {firstName: 'Admin', lastName: 'User'} }, + { message: 'Test3', created: Date.now(), createdBy: {firstName: 'Admin', lastName: 'User'} } ])); - addCommentSpy = spyOn(service, 'addTaskComment').and.returnValue(Observable.of({id: 123, message: 'Test'})); + addCommentSpy = spyOn(service, 'addTaskComment').and.returnValue(Observable.of({id: 123, message: 'Test Comment'})); componentHandler = jasmine.createSpyObj('componentHandler', [ 'upgradeAllRegistered', @@ -90,7 +97,7 @@ describe('ActivitiComments', () => { expect(emitSpy).toHaveBeenCalled(); }); - it('should not comments when no taskId is specified', () => { + it('should not load comments when no taskId is specified', () => { fixture.detectChanges(); expect(getCommentsSpy).not.toHaveBeenCalled(); }); @@ -101,17 +108,45 @@ describe('ActivitiComments', () => { fixture.whenStable().then(() => { fixture.detectChanges(); - expect(fixture.debugElement.queryAll(By.css('ul.mdl-list li')).length).toBe(3); + expect(fixture.nativeElement.querySelectorAll('#comment-message').length).toBe(3); + expect(fixture.nativeElement.querySelector('#comment-message:empty')).toBeNull(); }); })); + it('should display comments count when the task has comments', () => { + let change = new SimpleChange(null, '123', true); + component.ngOnChanges({ 'taskId': change }); + fixture.whenStable().then(() => { + fixture.detectChanges(); + let element = fixture.nativeElement.querySelector('#comment-header'); + expect(element.innerText).toContain('(3)'); + }); + }); + it('should not display comments when the task has no comments', async(() => { component.taskId = '123'; getCommentsSpy.and.returnValue(Observable.of([])); + fixture.whenStable().then(() => { + fixture.detectChanges(); + expect(fixture.nativeElement.querySelector('#comment-container')).toBeNull(); + }); + })); + + it('should display comments input by default', async(() => { + let change = new SimpleChange(null, '123', true); + component.ngOnChanges({ 'taskId': change }); + fixture.whenStable().then(() => { + fixture.detectChanges(); + expect(fixture.nativeElement.querySelector('#comment-input')).not.toBeNull(); + }); + })); + + it('should not display comments input when the task is readonly', async(() => { + component.readOnly = true; fixture.detectChanges(); fixture.whenStable().then(() => { fixture.detectChanges(); - expect(fixture.debugElement.queryAll(By.css('ul.mdl-list li')).length).toBe(0); + expect(fixture.nativeElement.querySelector('#comment-input')).toBeNull(); }); })); @@ -133,21 +168,15 @@ describe('ActivitiComments', () => { expect(getCommentsSpy).toHaveBeenCalledWith('456'); }); - it('should NOT fetch new comments when empty changeset made', () => { + it('should not fetch new comments when empty changeset made', () => { component.ngOnChanges({}); expect(getCommentsSpy).not.toHaveBeenCalled(); }); - it('should NOT fetch new comments when taskId changed to null', () => { + it('should not fetch new comments when taskId changed to null', () => { component.ngOnChanges({ 'taskId': nullChange }); expect(getCommentsSpy).not.toHaveBeenCalled(); }); - - it('should set a placeholder message when taskId changed to null', () => { - component.ngOnChanges({ 'taskId': nullChange }); - fixture.detectChanges(); - expect(fixture.debugElement.query(By.css('[data-automation-id="comments-none"]'))).not.toBeNull(); - }); }); describe('Add comment', () => { @@ -158,37 +187,54 @@ describe('ActivitiComments', () => { fixture.whenStable(); })); - it('should display a dialog to the user when the Add button clicked', () => { - let dialogEl = fixture.debugElement.query(By.css('.mdl-dialog')).nativeElement; - let showSpy: jasmine.Spy = spyOn(dialogEl, 'showModal'); - component.showDialog(); - expect(showSpy).toHaveBeenCalled(); - }); + it('should call service to add a comment when enter key is pressed', async(() => { + let event = new KeyboardEvent('keyup', {'key': 'Enter'}); + let element = fixture.nativeElement.querySelector('#comment-input'); + component.message = 'Test Comment'; + element.dispatchEvent(event); + fixture.detectChanges(); + fixture.whenStable().then(() => { + fixture.detectChanges(); + expect(addCommentSpy).toHaveBeenCalled(); + let elements = fixture.nativeElement.querySelectorAll('#comment-message'); + expect(elements.length).toBe(1); + expect(elements[0].innerText).toBe('Test Comment'); + }); + })); - it('should call service to add a comment', () => { - component.showDialog(); + it('should not call service to add a comment when comment is empty', async(() => { + let event = new KeyboardEvent('keyup', {'key': 'Enter'}); + let element = fixture.nativeElement.querySelector('#comment-input'); + component.message = ''; + element.dispatchEvent(event); + fixture.detectChanges(); + fixture.whenStable().then(() => { + fixture.detectChanges(); + expect(addCommentSpy).not.toHaveBeenCalled(); + }); + })); + + it('should clear comment when escape key is pressed', async(() => { + let event = new KeyboardEvent('keyup', {'key': 'Escape'}); + let element = fixture.nativeElement.querySelector('#comment-input'); component.message = 'Test comment'; - component.add(); - expect(addCommentSpy).toHaveBeenCalledWith('123', 'Test comment'); - }); + element.dispatchEvent(event); + fixture.detectChanges(); + fixture.whenStable().then(() => { + fixture.detectChanges(); + element = fixture.nativeElement.querySelector('#comment-input'); + expect(element.value).toBe(''); + }); + })); it('should emit an error when an error occurs adding the comment', () => { let emitSpy = spyOn(component.error, 'emit'); addCommentSpy.and.returnValue(Observable.throw({})); - component.showDialog(); component.message = 'Test comment'; component.add(); expect(emitSpy).toHaveBeenCalled(); }); - it('should close add dialog when close button clicked', () => { - let dialogEl = fixture.debugElement.query(By.css('.mdl-dialog')).nativeElement; - let closeSpy: jasmine.Spy = spyOn(dialogEl, 'close'); - component.showDialog(); - component.cancel(); - expect(closeSpy).toHaveBeenCalled(); - }); - }); }); diff --git a/ng2-components/ng2-activiti-tasklist/src/components/activiti-comments.component.ts b/ng2-components/ng2-activiti-tasklist/src/components/activiti-comments.component.ts index 86cb09e0b8..b081fc6675 100644 --- a/ng2-components/ng2-activiti-tasklist/src/components/activiti-comments.component.ts +++ b/ng2-components/ng2-activiti-tasklist/src/components/activiti-comments.component.ts @@ -15,13 +15,12 @@ * limitations under the License. */ -import { Component, EventEmitter, Input, OnChanges, Output, SimpleChanges, ViewChild } from '@angular/core'; +import { Component, EventEmitter, Input, OnChanges, Output, SimpleChanges } from '@angular/core'; import { AlfrescoTranslationService } from 'ng2-alfresco-core'; import { Observable, Observer } from 'rxjs/Rx'; -import { Comment } from '../models/comment.model'; -import { ActivitiTaskListService } from './../services/activiti-tasklist.service'; -declare let dialogPolyfill: any; +import { Comment } from '../models/comment.model'; +import { ActivitiTaskListService } from '../services/activiti-tasklist.service'; @Component({ selector: 'adf-comments, activiti-comments', @@ -40,9 +39,6 @@ export class ActivitiComments implements OnChanges { @Output() error: EventEmitter = new EventEmitter(); - @ViewChild('dialog') - dialog: any; - comments: Comment [] = []; private commentObserver: Observer; @@ -50,6 +46,8 @@ export class ActivitiComments implements OnChanges { message: string; + beingAdded: boolean = false; + /** * Constructor * @param translate Translation service @@ -79,11 +77,17 @@ export class ActivitiComments implements OnChanges { } } - private getTaskComments(taskId: string) { + private getTaskComments(taskId: string): void { this.resetComments(); if (taskId) { this.activitiTaskList.getTaskComments(taskId).subscribe( (res: Comment[]) => { + res = res.sort((comment1: Comment, comment2: Comment) => { + let date1 = new Date(comment1.created); + let date2 = new Date(comment2.created); + return date1 > date2 ? -1 : date1 < date2 ? 1 : 0; + }); + res.forEach((comment) => { this.commentObserver.next(comment); }); @@ -92,38 +96,35 @@ export class ActivitiComments implements OnChanges { this.error.emit(err); } ); - } else { - this.resetComments(); } } - private resetComments() { + private resetComments(): void { this.comments = []; } - public showDialog() { - if (!this.dialog.nativeElement.showModal) { - dialogPolyfill.registerDialog(this.dialog.nativeElement); + add(): void { + if (this.message && this.message.trim() && !this.beingAdded) { + this.beingAdded = true; + this.activitiTaskList.addTaskComment(this.taskId, this.message).subscribe( + (res: Comment) => { + this.comments.unshift(res); + this.message = ''; + this.beingAdded = false; + }, + (err) => { + this.error.emit(err); + this.beingAdded = false; + } + ); } - this.dialog.nativeElement.showModal(); } - public add() { - this.activitiTaskList.addTaskComment(this.taskId, this.message).subscribe( - (res: Comment) => { - this.comments.push(res); - this.message = ''; - }, - (err) => { - this.error.emit(err); - } - ); - this.cancel(); + clear(): void { + this.message = ''; } - public cancel() { - if (this.dialog) { - this.dialog.nativeElement.close(); - } + isReadOnly(): boolean { + return this.readOnly; } } diff --git a/ng2-components/ng2-activiti-tasklist/src/components/adf-comment-list.component.css b/ng2-components/ng2-activiti-tasklist/src/components/adf-comment-list.component.css new file mode 100644 index 0000000000..662e6a8cfe --- /dev/null +++ b/ng2-components/ng2-activiti-tasklist/src/components/adf-comment-list.component.css @@ -0,0 +1,64 @@ +.adf-comment-img-container { + float: left; + width: 40px; + padding: 5px 10px; + height: 100%; +} + +.adf-comment-user-icon { + padding: 10px 5px; + width: 30px; + background-color: #01bcd4; + border-radius: 50%; + font-family: Muli; + font-size: 16px; + color: #fff; + text-align: center; + height: 18px; +} + +.adf-comment-user-name { + float: left; + width: calc(100% - 120px); + padding: 2px 10px; + font-family: Muli; + font-weight: 600; + color: #595959; +} + +.adf-comment-message { + float: left; + width: calc(100% - 20px); + padding: 2px 10px; + font-family: Muli; + font-style: italic; + color: #595959; + white-space: initial; +} + +.adf-comment-message-time { + float: left; + width: calc(100% - 120px); + padding: 2px 10px; + font-family: Muli; + font-size: 12px; + color: #595959; +} + +.adf-comment-contents { + float: left; + width: calc(100% - 60px); +} + +adf-datatable >>> table thead { + display: none; +} + +adf-datatable >>> table { + border: none; +} + +adf-datatable >>> table tbody td { + padding: 0px!important; + border-top: none; +} diff --git a/ng2-components/ng2-activiti-tasklist/src/components/adf-comment-list.component.html b/ng2-components/ng2-activiti-tasklist/src/components/adf-comment-list.component.html new file mode 100644 index 0000000000..73956721ca --- /dev/null +++ b/ng2-components/ng2-activiti-tasklist/src/components/adf-comment-list.component.html @@ -0,0 +1,30 @@ + + + + + +
+
{{getUserShortName(entry.row.obj.createdBy)}}
+
+
+
+ + +
+
+ {{entry.row.obj.createdBy?.firstName}} {{entry.row.obj.createdBy?.lastName}} +
+
+ {{entry.row.obj.message}} +
+
+ {{transformDate(entry.row.obj.created)}} +
+
+
+
+
+ +
\ No newline at end of file diff --git a/ng2-components/ng2-activiti-tasklist/src/components/adf-comment-list.component.spec.ts b/ng2-components/ng2-activiti-tasklist/src/components/adf-comment-list.component.spec.ts new file mode 100644 index 0000000000..c1eadccc7b --- /dev/null +++ b/ng2-components/ng2-activiti-tasklist/src/components/adf-comment-list.component.spec.ts @@ -0,0 +1,148 @@ +/*! + * @license + * Copyright 2016 Alfresco Software, Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { DatePipe } from '@angular/common'; +import { async, ComponentFixture, TestBed } from '@angular/core/testing'; +import { CoreModule } from 'ng2-alfresco-core'; +import { DataRowEvent, DataTableModule, ObjectDataRow } from 'ng2-alfresco-datatable'; +import { Comment, User } from '../models/index'; +import { AdfCommentListComponent } from './adf-comment-list.component'; + +declare let jasmine: any; + +const testUser: User = new User({ + id: '1', + firstName: 'Test', + lastName: 'User', + email: 'tu@domain.com' +}); +const testDate = new Date(); +const testComment: Comment = new Comment(1, 'Test Comment', testDate.toDateString(), testUser); + +describe('AdfCommentListComponent', () => { + + let commentList: AdfCommentListComponent; + let fixture: ComponentFixture; + let element: HTMLElement; + let componentHandler; + + beforeEach(async(() => { + TestBed.configureTestingModule({ + imports: [ + CoreModule.forRoot(), + DataTableModule + ], + declarations: [ + AdfCommentListComponent + ], + providers: [ + DatePipe + ] + }).compileComponents().then(() => { + + fixture = TestBed.createComponent(AdfCommentListComponent); + commentList = fixture.componentInstance; + element = fixture.nativeElement; + componentHandler = jasmine.createSpyObj('componentHandler', [ + 'upgradeAllRegistered' + ]); + + window['componentHandler'] = componentHandler; + fixture.detectChanges(); + }); + })); + + it('should emit row click event', (done) => { + let row = new ObjectDataRow(testComment); + let rowEvent = new DataRowEvent(row, null); + + commentList.clickRow.subscribe(selectedComment => { + expect(selectedComment.id).toEqual(1); + expect(selectedComment.message).toEqual('Test Comment'); + expect(selectedComment.createdBy).toEqual(testUser); + expect(selectedComment.created).toEqual(testDate.toDateString()); + done(); + }); + + commentList.selectComment(rowEvent); + }); + + it('should not show comment list if no input is given', () => { + fixture.detectChanges(); + expect(fixture.nativeElement.querySelector('adf-datatable')).toBeNull(); + }); + + it('should show comment message when input is given', () => { + commentList.comments = [testComment]; + fixture.detectChanges(); + let elements = fixture.nativeElement.querySelectorAll('#comment-message'); + expect(elements.length).toBe(1); + expect(elements[0].innerText).toBe(testComment.message); + expect(fixture.nativeElement.querySelector('#comment-message:empty')).toBeNull(); + }); + + it('should show comment user when input is given', () => { + commentList.comments = [testComment]; + fixture.detectChanges(); + let elements = fixture.nativeElement.querySelectorAll('#comment-user'); + expect(elements.length).toBe(1); + expect(elements[0].innerText).toBe(testComment.createdBy.firstName + ' ' + testComment.createdBy.lastName); + expect(fixture.nativeElement.querySelector('#comment-user:empty')).toBeNull(); + }); + + it('should show comment date time when input is given', () => { + commentList.comments = [testComment]; + fixture.detectChanges(); + let elements = fixture.nativeElement.querySelectorAll('#comment-time'); + expect(elements.length).toBe(1); + expect(elements[0].innerText).toBe(commentList.transformDate(testDate.toDateString())); + expect(fixture.nativeElement.querySelector('#comment-time:empty')).toBeNull(); + }); + + it('comment date time should start with Today when comment date is today', () => { + commentList.comments = [testComment]; + fixture.detectChanges(); + element = fixture.nativeElement.querySelector('#comment-time'); + expect(element.innerText).toContain('Today'); + }); + + it('comment date time should start with Yesterday when comment date is yesterday', () => { + testComment.created = (Date.now() - 24 * 3600 * 1000).toString(); + commentList.comments = [testComment]; + fixture.detectChanges(); + element = fixture.nativeElement.querySelector('#comment-time'); + expect(element.innerText).toContain('Yesterday'); + }); + + it('comment date time should not start with Today/Yesterday when comment date is before yesterday', () => { + testComment.created = (Date.now() - 24 * 3600 * 1000 * 2).toString(); + commentList.comments = [testComment]; + fixture.detectChanges(); + element = fixture.nativeElement.querySelector('#comment-time'); + expect(element.innerText).not.toContain('Today'); + expect(element.innerText).not.toContain('Yesterday'); + }); + + it('should show user icon when input is given', () => { + commentList.comments = [testComment]; + fixture.detectChanges(); + let elements = fixture.nativeElement.querySelectorAll('#comment-user-icon'); + expect(elements.length).toBe(1); + expect(elements[0].innerText).toContain(commentList.getUserShortName(testComment.createdBy)); + expect(fixture.nativeElement.querySelector('#comment-user-icon:empty')).toBeNull(); + }); +}); diff --git a/ng2-components/ng2-activiti-tasklist/src/components/adf-comment-list.component.ts b/ng2-components/ng2-activiti-tasklist/src/components/adf-comment-list.component.ts new file mode 100644 index 0000000000..5b44ef5f1e --- /dev/null +++ b/ng2-components/ng2-activiti-tasklist/src/components/adf-comment-list.component.ts @@ -0,0 +1,80 @@ +/*! + * @license + * Copyright 2016 Alfresco Software, Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { DatePipe } from '@angular/common'; +import { Component, EventEmitter, Input, Output } from '@angular/core'; +import { Comment, User } from '../models/index'; + +@Component({ + selector: 'adf-comment-list', + templateUrl: './adf-comment-list.component.html', + styleUrls: ['./adf-comment-list.component.css'] +}) + +export class AdfCommentListComponent { + + @Input() + comments: Comment[]; + + @Output() + clickRow: EventEmitter = new EventEmitter(); + + selectedComment: Comment; + + constructor(private datePipe: DatePipe) { + } + + selectComment(event: any): void { + this.selectedComment = event.value.obj; + this.clickRow.emit(this.selectedComment); + } + + getUserShortName(user: User): string { + let shortName = ''; + if (user) { + if (user.firstName) { + shortName = user.firstName[0].toUpperCase(); + } + if (user.lastName) { + shortName += user.lastName[0].toUpperCase(); + } + } + return shortName; + } + + transformDate(aDate: string): string { + let formattedDate: string; + let givenDate = Number.parseInt(this.datePipe.transform(aDate, 'yMMdd')); + let today = Number.parseInt(this.datePipe.transform(Date.now(), 'yMMdd')); + if (givenDate === today) { + formattedDate = 'Today, ' + this.datePipe.transform(aDate, 'hh:mm a'); + }else { + let yesterday = Number.parseInt(this.datePipe.transform(Date.now() - 24 * 3600 * 1000, 'yMMdd')); + if (givenDate === yesterday) { + formattedDate = 'Yesterday, ' + this.datePipe.transform(aDate, 'hh:mm a'); + }else { + formattedDate = this.datePipe.transform(aDate, 'MMM dd y, hh:mm a'); + } + } + return formattedDate; + } + + hasComments(): boolean { + return this.comments && this.comments.length && true; + } + +} diff --git a/ng2-components/ng2-activiti-tasklist/src/components/index.ts b/ng2-components/ng2-activiti-tasklist/src/components/index.ts index 9429b9990f..140f54bfc5 100644 --- a/ng2-components/ng2-activiti-tasklist/src/components/index.ts +++ b/ng2-components/ng2-activiti-tasklist/src/components/index.ts @@ -29,3 +29,4 @@ export * from './activiti-start-task.component'; export * from './activiti-people-search.component'; export * from './adf-create-task-attachment.component'; export * from './adf-people-list.component'; +export * from './adf-comment-list.component'; diff --git a/ng2-components/ng2-activiti-tasklist/src/i18n/en.json b/ng2-components/ng2-activiti-tasklist/src/i18n/en.json index 11d5d39917..5a8f83c021 100644 --- a/ng2-components/ng2-activiti-tasklist/src/i18n/en.json +++ b/ng2-components/ng2-activiti-tasklist/src/i18n/en.json @@ -43,6 +43,7 @@ "COMMENTS": { "NONE": "No comments.", "ADD": "Add a comment", + "HEADER": "Comments", "DIALOG": { "TITLE": "New comment", "LABELS": {