diff --git a/demo-shell/resources/i18n/en.json b/demo-shell/resources/i18n/en.json
index 7e4240ec39..72fd75c4fd 100644
--- a/demo-shell/resources/i18n/en.json
+++ b/demo-shell/resources/i18n/en.json
@@ -51,6 +51,9 @@
"TITLE": "Metadata"
}
},
+ "COMMENTS": {
+ "ADD_COMMENT": "ADD"
+ },
"APP_LAYOUT": {
"APP_NAME": "ADF Demo Application",
"HOME": "Home",
diff --git a/e2e/pages/adf/process_services/taskDetailsPage.js b/e2e/pages/adf/process_services/taskDetailsPage.js
index 29528e2b74..fd573c07ce 100644
--- a/e2e/pages/adf/process_services/taskDetailsPage.js
+++ b/e2e/pages/adf/process_services/taskDetailsPage.js
@@ -30,7 +30,8 @@ var TaskDetailsPage = function () {
var descriptionField = element(by.css("span[data-automation-id*='description'] span"));
var dueDateField = element(by.css("span[data-automation-id*='dueDate'] span"));
var activitiesTitle = element(by.css("div[class*='adf-info-drawer-layout-header-title'] div"));
- var commentField = element(by.css("input[id='comment-input']"));
+ var commentField = element(by.id("comment-input"));
+ var addCommentButton = element(by.css("[data-automation-id='comments-input-add']"));
var activityTab = element(by.cssContainingText("div[class*='mat-tab-label ']", "Activity"));
var detailsTab = element(by.cssContainingText("div[class*='mat-tab-label ']", "Details"));
var involvePeopleButton = element(by.css("div[class*='add-people']"));
@@ -116,6 +117,12 @@ var TaskDetailsPage = function () {
this.addComment = function (comment) {
Util.waitUntilElementIsVisible(commentField);
commentField.sendKeys(comment);
+ addCommentButton.click();
+ return this;
+ };
+
+ this.clearComment = function (comment) {
+ Util.waitUntilElementIsVisible(commentField);
commentField.sendKeys(protractor.Key.ENTER);
return this;
};
diff --git a/lib/core/comments/comment-list.component.html b/lib/core/comments/comment-list.component.html
index 8f497a0039..734fa6ea4f 100644
--- a/lib/core/comments/comment-list.component.html
+++ b/lib/core/comments/comment-list.component.html
@@ -21,9 +21,7 @@
-
+
diff --git a/lib/core/comments/comments.component.html b/lib/core/comments/comments.component.html
index 70fc4f4863..5308eb3f13 100644
--- a/lib/core/comments/comments.component.html
+++ b/lib/core/comments/comments.component.html
@@ -4,12 +4,23 @@
-
+
\ No newline at end of file
diff --git a/lib/core/comments/comments.component.scss b/lib/core/comments/comments.component.scss
index de8c836fc1..49041e8b1b 100644
--- a/lib/core/comments/comments.component.scss
+++ b/lib/core/comments/comments.component.scss
@@ -20,6 +20,16 @@
width: calc(100% - 30px);
padding-top: 8px;
border-bottom: $header-border;
+
+ textarea {
+ resize: vertical;
+ }
+ }
+
+ .adf-comments-input-actions {
+ display: flex;
+ justify-content: flex-end;
+ margin-bottom: 10px;
}
.adf-full-width {
diff --git a/lib/core/comments/comments.component.spec.ts b/lib/core/comments/comments.component.spec.ts
index 4fb5b43c33..1787e3c47b 100644
--- a/lib/core/comments/comments.component.spec.ts
+++ b/lib/core/comments/comments.component.spec.ts
@@ -219,11 +219,43 @@ describe('CommentsComponent', () => {
fixture.whenStable();
}));
- 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');
+ it('should sanitize comment when user input contains html elements', async(() => {
+ let element = fixture.nativeElement.querySelector('.adf-comments-input-add');
+ component.message = '';
+ element.dispatchEvent(new Event('click'));
+ fixture.detectChanges();
+ fixture.whenStable().then(() => {
+ fixture.detectChanges();
+ expect(addProcessCommentSpy).toHaveBeenCalledWith('123', 'action');
+ });
+ }));
+
+ it('should normalize comment when user input contains spaces sequence', async(() => {
+ let element = fixture.nativeElement.querySelector('.adf-comments-input-add');
+ component.message = 'test comment';
+ element.dispatchEvent(new Event('click'));
+ fixture.detectChanges();
+ fixture.whenStable().then(() => {
+ fixture.detectChanges();
+ expect(addProcessCommentSpy).toHaveBeenCalledWith('123', 'test comment');
+ });
+ }));
+
+ it('should add break lines to comment when user input contains new line characters', async(() => {
+ let element = fixture.nativeElement.querySelector('.adf-comments-input-add');
+ component.message = 'these\nare\nparagraphs\n';
+ element.dispatchEvent(new Event('click'));
+ fixture.detectChanges();
+ fixture.whenStable().then(() => {
+ fixture.detectChanges();
+ expect(addProcessCommentSpy).toHaveBeenCalledWith('123', 'these
are
paragraphs');
+ });
+ }));
+
+ it('should call service to add a comment when add button is pressed', async(() => {
+ let element = fixture.nativeElement.querySelector('.adf-comments-input-add');
component.message = 'Test Comment';
- element.dispatchEvent(event);
+ element.dispatchEvent(new Event('click'));
fixture.detectChanges();
fixture.whenStable().then(() => {
fixture.detectChanges();
@@ -235,10 +267,9 @@ describe('CommentsComponent', () => {
}));
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');
+ let element = fixture.nativeElement.querySelector('.adf-comments-input-add');
component.message = '';
- element.dispatchEvent(event);
+ element.dispatchEvent(new Event('click'));
fixture.detectChanges();
fixture.whenStable().then(() => {
fixture.detectChanges();
@@ -249,7 +280,6 @@ describe('CommentsComponent', () => {
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';
element.dispatchEvent(event);
fixture.detectChanges();
fixture.whenStable().then(() => {
@@ -277,11 +307,10 @@ describe('CommentsComponent', () => {
fixture.whenStable();
}));
- 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');
+ it('should call service to add a comment when add button is pressed', async(() => {
+ let element = fixture.nativeElement.querySelector('.adf-comments-input-add');
component.message = 'Test Comment';
- element.dispatchEvent(event);
+ element.dispatchEvent(new Event('click'));
fixture.detectChanges();
fixture.whenStable().then(() => {
fixture.detectChanges();
@@ -292,11 +321,43 @@ describe('CommentsComponent', () => {
});
}));
+ it('should sanitize comment when user input contains html elements', async(() => {
+ let element = fixture.nativeElement.querySelector('.adf-comments-input-add');
+ component.message = '';
+ element.dispatchEvent(new Event('click'));
+ fixture.detectChanges();
+ fixture.whenStable().then(() => {
+ fixture.detectChanges();
+ expect(addContentCommentSpy).toHaveBeenCalledWith('123', 'action');
+ });
+ }));
+
+ it('should normalize comment when user input contains spaces sequence', async(() => {
+ let element = fixture.nativeElement.querySelector('.adf-comments-input-add');
+ component.message = 'test comment';
+ element.dispatchEvent(new Event('click'));
+ fixture.detectChanges();
+ fixture.whenStable().then(() => {
+ fixture.detectChanges();
+ expect(addContentCommentSpy).toHaveBeenCalledWith('123', 'test comment');
+ });
+ }));
+
+ it('should add break lines to comment when user input contains new line characters', async(() => {
+ let element = fixture.nativeElement.querySelector('.adf-comments-input-add');
+ component.message = 'these\nare\nparagraphs\n';
+ element.dispatchEvent(new Event('click'));
+ fixture.detectChanges();
+ fixture.whenStable().then(() => {
+ fixture.detectChanges();
+ expect(addContentCommentSpy).toHaveBeenCalledWith('123', 'these
are
paragraphs');
+ });
+ }));
+
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');
+ let element = fixture.nativeElement.querySelector('.adf-comments-input-add');
component.message = '';
- element.dispatchEvent(event);
+ element.dispatchEvent(new Event('click'));
fixture.detectChanges();
fixture.whenStable().then(() => {
fixture.detectChanges();
@@ -307,7 +368,6 @@ describe('CommentsComponent', () => {
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';
element.dispatchEvent(event);
fixture.detectChanges();
fixture.whenStable().then(() => {
diff --git a/lib/core/comments/comments.component.ts b/lib/core/comments/comments.component.ts
index b58fc62bde..5e56f6d341 100644
--- a/lib/core/comments/comments.component.ts
+++ b/lib/core/comments/comments.component.ts
@@ -126,9 +126,11 @@ export class CommentsComponent implements OnChanges {
add(): void {
if (this.message && this.message.trim() && !this.beingAdded) {
+ const comment = this.sanitize(this.message);
+
this.beingAdded = true;
if (this.isATask()) {
- this.commentProcessService.addTaskComment(this.taskId, this.message)
+ this.commentProcessService.addTaskComment(this.taskId, comment)
.subscribe(
(res: CommentModel) => {
this.comments.unshift(res);
@@ -144,7 +146,7 @@ export class CommentsComponent implements OnChanges {
}
if (this.isANode()) {
- this.commentContentService.addNodeComment(this.nodeId, this.message)
+ this.commentContentService.addNodeComment(this.nodeId, comment)
.subscribe(
(res: CommentModel) => {
this.comments.unshift(res);
@@ -176,4 +178,10 @@ export class CommentsComponent implements OnChanges {
isANode(): boolean {
return this.nodeId ? true : false;
}
+
+ private sanitize(input: string) {
+ return input.replace(/<[^>]+>/g, '')
+ .replace(/^\s+|\s+$|\s+(?=\s)/g, '')
+ .replace(/\r?\n/g, '
');
+ }
}