mirror of
https://github.com/Alfresco/alfresco-ng2-components.git
synced 2025-05-12 17:04:57 +00:00
[AAE-10768] Make the comments reusable (#7983)
* [AAE-10768] Refactor core comments * [AAE-10768] Add models export in core comments refactor * [AAE-10768] Add comments implementation inside process-services package * [AAE-10768] Add task comments module to process module * [AAE-10768] Add node comments module to content services * [AAE-10768] Add id check to getComments and addComments in adf-core comments component * [AAE-10768] Remove unused service files in process-comments module * [AAE-10768] Remove unused service files in process-comments module * [AAE-10768] Add testing logic to spec files * [AAE-10768] Add comments components readme * [AAE-10768] Add a mock service to inject into the comment stories file * [AAE-10768] Add mock data for comments stories * [AAE-10768] Add mock service to inject into comments stories * [AAE-10768] Rename mock service and mock data * [AAE-10768] change taskId with id into the comments test because taskId is never used * [AAE-10768] Resolve pr suggestions * [AAE-10768] Resolve task-comments pr suggestions * [AAE-10768] Resolve comments pr suggestions * [AAE-10768] Fix merge error in comments.component.html * [AAE-10768] Add missing markdown files * [AAE-10768] Remove events from md files * [AAE-10768] Update upgrade50-60.md with renamed input property Co-authored-by: Amedeo Lepore <amedeo.lepore@hyland.com>
This commit is contained in:
parent
9077572199
commit
3864aaf9cb
@ -4,7 +4,11 @@
|
||||
<adf-info-drawer [title]="'APP.INFO_DRAWER.TITLE' | translate">
|
||||
|
||||
<adf-info-drawer-tab label="APP.INFO_DRAWER.COMMENTS">
|
||||
<adf-comments [nodeId]="nodeId" [readOnly]="!isCommentEnabled"></adf-comments>
|
||||
<adf-node-comments
|
||||
[nodeId]="nodeId"
|
||||
[readOnly]="!isCommentEnabled"
|
||||
>
|
||||
</adf-node-comments>
|
||||
</adf-info-drawer-tab>
|
||||
|
||||
<adf-info-drawer-tab label="APP.INFO_DRAWER.PROPERTIES">
|
||||
|
@ -19,7 +19,7 @@ import { NgModule } from '@angular/core';
|
||||
import { CommonModule } from '@angular/common';
|
||||
import { Routes, RouterModule } from '@angular/router';
|
||||
import { CoreModule, InfoDrawerModule } from '@alfresco/adf-core';
|
||||
import { ContentDirectiveModule, VersionManagerModule, ContentMetadataModule } from '@alfresco/adf-content-services';
|
||||
import { ContentModule, ContentDirectiveModule, VersionManagerModule, ContentMetadataModule } from '@alfresco/adf-content-services';
|
||||
import { FileViewComponent } from './file-view.component';
|
||||
|
||||
const routes: Routes = [
|
||||
@ -35,6 +35,7 @@ const routes: Routes = [
|
||||
RouterModule.forChild(routes),
|
||||
CoreModule,
|
||||
InfoDrawerModule,
|
||||
ContentModule,
|
||||
ContentDirectiveModule,
|
||||
ContentMetadataModule,
|
||||
VersionManagerModule
|
||||
|
29
docs/content-services/components/node-comments.component.md
Normal file
29
docs/content-services/components/node-comments.component.md
Normal file
@ -0,0 +1,29 @@
|
||||
---
|
||||
Title: Node Comments Component
|
||||
Added: v5.1.0
|
||||
Status: Active
|
||||
---
|
||||
|
||||
# [Node Comments Component](../../../lib/content-services/src/lib/node-comments/node-comments.component.ts "Defined in node-comments.component.ts")
|
||||
|
||||
Displays comments from users involved in a specified content and allows an involved user to add a comment to a content.
|
||||
|
||||

|
||||
|
||||
## Basic Usage Task
|
||||
|
||||
```html
|
||||
<adf-node-comments
|
||||
[nodeId]="YOUR_NODE_ID"
|
||||
[readOnly]="YOUR_READ_ONLY_FLAG">
|
||||
</adf-node-comments>
|
||||
```
|
||||
|
||||
## Class members
|
||||
|
||||
### Properties
|
||||
|
||||
| Name | Type | Default value | Description |
|
||||
| ---- | ---- | ------------- | ----------- |
|
||||
| nodeId | `string` | | The numeric ID of the node. |
|
||||
| readOnly | `boolean` | | Are the comments read only? |
|
28
docs/content-services/services/node-comments.service.md
Normal file
28
docs/content-services/services/node-comments.service.md
Normal file
@ -0,0 +1,28 @@
|
||||
---
|
||||
Title: Node Comments Service
|
||||
Added: v6.0.0
|
||||
Status: Active
|
||||
Last reviewed: 2022-12-19
|
||||
---
|
||||
|
||||
# [Node Comments service](../../../lib/content-services/src/lib/node-comments/services/node-comments.service.ts "Defined in node-comments.service.ts")
|
||||
|
||||
Adds and retrieves comments for nodes in Content Services.
|
||||
|
||||
## Class members
|
||||
|
||||
### Methods
|
||||
|
||||
- **add**(id: `string`, message: `string`): [`Observable`](http://reactivex.io/documentation/observable.html)`<`[`CommentModel`](../../../lib/core/src/lib/models/comment.model.ts)`>`<br/>
|
||||
Adds a comment to a task.
|
||||
- _id:_ `string` - ID of the target task
|
||||
- _message:_ `string` - Text for the comment
|
||||
- **Returns** [`Observable`](http://reactivex.io/documentation/observable.html)`<`[`CommentModel`](../../../lib/core/src/lib/models/comment.model.ts)`>` - Details about the comment
|
||||
- **get**(id: `string`): [`Observable`](http://reactivex.io/documentation/observable.html)`<`[`CommentModel`](../../../lib/core/src/lib/models/comment.model.ts)`[]>`<br/>
|
||||
Gets all comments that have been added to a task.
|
||||
- _id:_ `string` - ID of the target task
|
||||
- **Returns** [`Observable`](http://reactivex.io/documentation/observable.html)`<`[`CommentModel`](../../../lib/core/src/lib/models/comment.model.ts)`[]>` - Details for each comment
|
||||
|
||||
## See also
|
||||
|
||||
- [Node comments component](../../../lib/content-services/src/lib/node-comments/node-comments.component.ts)
|
28
docs/content-services/services/task-comments.service.md
Normal file
28
docs/content-services/services/task-comments.service.md
Normal file
@ -0,0 +1,28 @@
|
||||
---
|
||||
Title: Task Comments service
|
||||
Added: v6.0.0
|
||||
Status: Active
|
||||
Last reviewed: 2022-12-19
|
||||
---
|
||||
|
||||
# [Task Comments service](../../../lib/process-services/src/lib/task-comments/services/task-comments.service.ts "Defined in task-comments.service.ts")
|
||||
|
||||
Adds and retrieves comments for task and process instances in Process Services.
|
||||
|
||||
## Class members
|
||||
|
||||
### Methods
|
||||
|
||||
- **get**(id: `string`): [`Observable`](http://reactivex.io/documentation/observable.html)`<`[`CommentModel`](../../../lib/core/models/comment.model.ts)`[]>`<br/>
|
||||
Gets all comments that have been added to a task.
|
||||
- _id:_ `string` - ID of the target task
|
||||
- **Returns** [`Observable`](http://reactivex.io/documentation/observable.html)`<`[`CommentModel`](../../../lib/core/models/comment.model.ts)`[]>` - Details for each comment
|
||||
- **add**(id: `string`, message: `string`): [`Observable`](http://reactivex.io/documentation/observable.html)`<`[`CommentModel`](../../../lib/core/models/comment.model.ts)`>`<br/>
|
||||
Adds a comment to a process instance.
|
||||
- _id:_ `string` - ID of the target task
|
||||
- _message:_ `string` - Text for the comment
|
||||
- **Returns** [`Observable`](http://reactivex.io/documentation/observable.html)`<`[`CommentModel`](../../../lib/core/models/comment.model.ts)`>` - Details of the comment added
|
||||
|
||||
## See also
|
||||
|
||||
- [Task comments component](../../../lib/process-services/src/lib/task-comments/task-comments.component.ts)
|
@ -4,9 +4,9 @@ Added: v2.0.0
|
||||
Status: Active
|
||||
---
|
||||
|
||||
# [Comments Component](lib/core/src/lib/comments/comments.component.ts "Defined in comments.component.ts")
|
||||
# [Comments Component](../../../lib/core/src/lib/comments/comments.component.ts "Defined in comments.component.ts")
|
||||
|
||||
Displays comments from users involved in a specified task or content and allows an involved user to add a comment to a task or a content.
|
||||
Displays comments from users involved in a specified environment and allows an involved user to add a comment to a environment.
|
||||
|
||||

|
||||
|
||||
@ -14,16 +14,7 @@ Displays comments from users involved in a specified task or content and allows
|
||||
|
||||
```html
|
||||
<adf-comments
|
||||
[taskId]="YOUR_TASK_ID"
|
||||
[readOnly]="YOUR_READ_ONLY_FLAG">
|
||||
</adf-comments>
|
||||
```
|
||||
|
||||
## Basic Usage Content
|
||||
|
||||
```html
|
||||
<adf-comments
|
||||
[nodeId]="YOUR_NODE_ID"
|
||||
[id]="YOUR_ID"
|
||||
[readOnly]="YOUR_READ_ONLY_FLAG">
|
||||
</adf-comments>
|
||||
```
|
||||
@ -34,9 +25,8 @@ Displays comments from users involved in a specified task or content and allows
|
||||
|
||||
| Name | Type | Default value | Description |
|
||||
| ---- | ---- | ------------- | ----------- |
|
||||
| nodeId | `string` | | The numeric ID of the node. |
|
||||
| id | `string` | | The numeric ID of the entity. |
|
||||
| readOnly | `boolean` | false | Are the comments read only? |
|
||||
| taskId | `string` | | The numeric ID of the task. |
|
||||
|
||||
### Events
|
||||
|
||||
|
29
docs/process-services/components/task-comments.component.md
Normal file
29
docs/process-services/components/task-comments.component.md
Normal file
@ -0,0 +1,29 @@
|
||||
---
|
||||
Title: Task Comments Component
|
||||
Added: v5.1.0
|
||||
Status: Active
|
||||
---
|
||||
|
||||
# [Task Comments Component](../../../lib/process-services/src/lib/task-comments/task-comments.component.ts "Defined in task-comments.component.ts")
|
||||
|
||||
Displays comments from users involved in a specified task and allows an involved user to add a comment to a task.
|
||||
|
||||

|
||||
|
||||
## Basic Usage Task
|
||||
|
||||
```html
|
||||
<adf-task-comments
|
||||
[taskId]="YOUR_TASK_ID"
|
||||
[readOnly]="YOUR_READ_ONLY_FLAG">
|
||||
</adf-task-comments>
|
||||
```
|
||||
|
||||
## Class members
|
||||
|
||||
### Properties
|
||||
|
||||
| Name | Type | Default value | Description |
|
||||
| ---- | ---- | ------------- | ----------- |
|
||||
| taskId | `string` | | The numeric ID of the task. |
|
||||
| readOnly | `boolean` | | Are the comments read only? |
|
@ -126,7 +126,7 @@ v6.0.0 and after:
|
||||
|
||||
|
||||
### Properties and methods
|
||||
|
||||
- `<adf-comments>`: The `taskId` input has now been renamed as `id`
|
||||
|
||||
### Component selectors
|
||||
|
||||
|
@ -45,6 +45,7 @@ import { VersionCompatibilityModule } from './version-compatibility/version-comp
|
||||
import { versionCompatibilityFactory } from './version-compatibility/version-compatibility-factory';
|
||||
import { VersionCompatibilityService } from './version-compatibility/version-compatibility.service';
|
||||
import { ContentPipeModule } from './pipes/content-pipe.module';
|
||||
import { NodeCommentsModule } from './node-comments/node-comments.module';
|
||||
|
||||
@NgModule({
|
||||
imports: [
|
||||
@ -73,7 +74,8 @@ import { ContentPipeModule } from './pipes/content-pipe.module';
|
||||
TreeViewModule,
|
||||
ContentTypeModule,
|
||||
AspectListModule,
|
||||
VersionCompatibilityModule
|
||||
VersionCompatibilityModule,
|
||||
NodeCommentsModule
|
||||
],
|
||||
providers: [
|
||||
{
|
||||
@ -106,7 +108,8 @@ import { ContentPipeModule } from './pipes/content-pipe.module';
|
||||
TreeViewModule,
|
||||
AspectListModule,
|
||||
ContentTypeModule,
|
||||
VersionCompatibilityModule
|
||||
VersionCompatibilityModule,
|
||||
NodeCommentsModule
|
||||
]
|
||||
})
|
||||
export class ContentModule {
|
||||
|
18
lib/content-services/src/lib/node-comments/index.ts
Normal file
18
lib/content-services/src/lib/node-comments/index.ts
Normal file
@ -0,0 +1,18 @@
|
||||
/*!
|
||||
* @license
|
||||
* Copyright 2019 Alfresco Software, Ltd.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
export * from './public-api';
|
@ -0,0 +1,209 @@
|
||||
/*!
|
||||
* @license
|
||||
* Copyright 2019 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 { CommentModel, EcmCompanyModel, EcmUserModel } from '@alfresco/adf-core';
|
||||
|
||||
export const fakeUser1 = {
|
||||
enabled: true,
|
||||
firstName: 'firstName',
|
||||
lastName: 'lastName',
|
||||
email: 'fake-email@dom.com',
|
||||
emailNotificationsEnabled: true,
|
||||
company: {},
|
||||
id: 'fake-email@dom.com',
|
||||
avatarId: '123-123-123'
|
||||
};
|
||||
|
||||
export const fakeUser2 = {
|
||||
enabled: true,
|
||||
firstName: 'some',
|
||||
lastName: 'one',
|
||||
email: 'some-one@somegroup.com',
|
||||
emailNotificationsEnabled: true,
|
||||
company: {},
|
||||
id: 'fake-email@dom.com',
|
||||
avatarId: '001-001-001'
|
||||
};
|
||||
|
||||
export const fakeContentComments = {
|
||||
list: {
|
||||
pagination: {
|
||||
count: 4,
|
||||
hasMoreItems: false,
|
||||
totalItems: 4,
|
||||
skipCount: 0,
|
||||
maxItems: 100
|
||||
},
|
||||
entries: [{
|
||||
entry: {
|
||||
createdAt: '2018-03-27T10:55:45.725+0000',
|
||||
createdBy: fakeUser1,
|
||||
edited: false,
|
||||
modifiedAt: '2018-03-27T10:55:45.725+0000',
|
||||
canEdit: true,
|
||||
modifiedBy: fakeUser1,
|
||||
canDelete: true,
|
||||
id: '35a0cea7-b6d0-4abc-9030-f4e461dd1ac7',
|
||||
content: 'fake-message-1'
|
||||
}
|
||||
}, {
|
||||
entry: {
|
||||
createdAt: '2018-03-27T10:55:45.725+0000',
|
||||
createdBy: fakeUser2,
|
||||
edited: false,
|
||||
modifiedAt: '2018-03-27T10:55:45.725+0000',
|
||||
canEdit: true,
|
||||
modifiedBy: fakeUser2,
|
||||
canDelete: true,
|
||||
id: '35a0cea7-b6d0-4abc-9030-f4e461dd1ac7',
|
||||
content: 'fake-message-2'
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
};
|
||||
|
||||
export const fakeContentComment = {
|
||||
entry: {
|
||||
createdAt: '2018-03-29T11:49:51.735+0000',
|
||||
createdBy: fakeUser1,
|
||||
edited: false,
|
||||
modifiedAt: '2018-03-29T11:49:51.735+0000',
|
||||
canEdit: true,
|
||||
modifiedBy: fakeUser1,
|
||||
canDelete: true,
|
||||
id: '4d07cdc5-f00c-4391-b39d-a842b12478b2',
|
||||
content: 'fake-comment-message'
|
||||
}
|
||||
};
|
||||
|
||||
const fakeCompany: EcmCompanyModel = {
|
||||
organization: '',
|
||||
address1: '',
|
||||
address2: '',
|
||||
address3: '',
|
||||
postcode: '',
|
||||
telephone: '',
|
||||
fax: '',
|
||||
email: ''
|
||||
};
|
||||
|
||||
const johnDoe: EcmUserModel = {
|
||||
id: '1',
|
||||
email: 'john.doe@alfresco.com',
|
||||
firstName: 'John',
|
||||
lastName: 'Doe',
|
||||
company: fakeCompany,
|
||||
enabled: true,
|
||||
isAdmin: undefined,
|
||||
avatarId: '001'
|
||||
};
|
||||
|
||||
const janeEod: EcmUserModel = {
|
||||
id: '2',
|
||||
email: 'jane.eod@alfresco.com',
|
||||
firstName: 'Jane',
|
||||
lastName: 'Eod',
|
||||
company: fakeCompany,
|
||||
enabled: true,
|
||||
isAdmin: undefined
|
||||
};
|
||||
|
||||
const robertSmith: EcmUserModel = {
|
||||
id: '3',
|
||||
email: 'robert.smith@alfresco.com',
|
||||
firstName: 'Robert',
|
||||
lastName: 'Smith',
|
||||
company: fakeCompany,
|
||||
enabled: true,
|
||||
isAdmin: undefined
|
||||
};
|
||||
|
||||
export const testUser: EcmUserModel = {
|
||||
id: '44',
|
||||
email: 'test.user@hyland.com',
|
||||
firstName: 'Test',
|
||||
lastName: 'User',
|
||||
company: fakeCompany,
|
||||
enabled: true,
|
||||
isAdmin: undefined,
|
||||
avatarId: '044'
|
||||
};
|
||||
|
||||
export const getDateXMinutesAgo = (minutes: number) => new Date(new Date().getTime() - minutes * 60000);
|
||||
|
||||
export const commentsNodeData: CommentModel[] = [
|
||||
{
|
||||
id: 1,
|
||||
message: `I've done this component, is it cool?`,
|
||||
created: getDateXMinutesAgo(30),
|
||||
createdBy: johnDoe,
|
||||
isSelected: false
|
||||
},
|
||||
{
|
||||
id: 2,
|
||||
message: 'Yeah',
|
||||
created: getDateXMinutesAgo(15),
|
||||
createdBy: janeEod,
|
||||
isSelected: false
|
||||
},
|
||||
{
|
||||
id: 3,
|
||||
message: '+1',
|
||||
created: getDateXMinutesAgo(12),
|
||||
createdBy: robertSmith,
|
||||
isSelected: false
|
||||
},
|
||||
{
|
||||
id: 4,
|
||||
message: 'ty',
|
||||
created: new Date(),
|
||||
createdBy: johnDoe,
|
||||
isSelected: false
|
||||
}
|
||||
];
|
||||
|
||||
export const commentsTaskData: CommentModel[] = [
|
||||
{
|
||||
id: 1,
|
||||
message: `I've done this task, what's next?`,
|
||||
created: getDateXMinutesAgo(30),
|
||||
createdBy: johnDoe,
|
||||
isSelected: false
|
||||
},
|
||||
{
|
||||
id: 2,
|
||||
message: `I've assigned you another one 🤠`,
|
||||
created: getDateXMinutesAgo(15),
|
||||
createdBy: janeEod,
|
||||
isSelected: false
|
||||
},
|
||||
{
|
||||
id: 3,
|
||||
message: '+1',
|
||||
created: getDateXMinutesAgo(12),
|
||||
createdBy: robertSmith,
|
||||
isSelected: false
|
||||
},
|
||||
{
|
||||
id: 4,
|
||||
message: 'Cheers',
|
||||
created: new Date(),
|
||||
createdBy: johnDoe,
|
||||
isSelected: false
|
||||
}
|
||||
];
|
@ -0,0 +1,5 @@
|
||||
<adf-comments
|
||||
[readOnly]="readOnly"
|
||||
[id]="nodeId"
|
||||
>
|
||||
</adf-comments>
|
@ -0,0 +1,31 @@
|
||||
/*!
|
||||
* @license
|
||||
* Copyright 2019 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, ViewEncapsulation } from '@angular/core';
|
||||
|
||||
@Component({
|
||||
selector: 'adf-node-comments',
|
||||
templateUrl: './node-comments.component.html',
|
||||
encapsulation: ViewEncapsulation.None
|
||||
})
|
||||
export class NodeCommentsComponent {
|
||||
@Input()
|
||||
nodeId: string;
|
||||
|
||||
@Input()
|
||||
readOnly: boolean;
|
||||
}
|
@ -0,0 +1,38 @@
|
||||
/*!
|
||||
* @license
|
||||
* Copyright 2019 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 { NgModule } from '@angular/core';
|
||||
import { CommonModule } from '@angular/common';
|
||||
import { NodeCommentsComponent } from './node-comments.component';
|
||||
import { ADF_COMMENTS_SERVICE, CoreModule } from '@alfresco/adf-core';
|
||||
import { NodeCommentsService } from './services/node-comments.service';
|
||||
|
||||
@NgModule({
|
||||
imports: [
|
||||
CommonModule,
|
||||
CoreModule
|
||||
],
|
||||
declarations: [NodeCommentsComponent],
|
||||
exports: [NodeCommentsComponent],
|
||||
providers: [
|
||||
{
|
||||
provide: ADF_COMMENTS_SERVICE,
|
||||
useClass: NodeCommentsService
|
||||
}
|
||||
]
|
||||
})
|
||||
export class NodeCommentsModule {}
|
22
lib/content-services/src/lib/node-comments/public-api.ts
Normal file
22
lib/content-services/src/lib/node-comments/public-api.ts
Normal file
@ -0,0 +1,22 @@
|
||||
/*!
|
||||
* @license
|
||||
* Copyright 2019 Alfresco Software, Ltd.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
export * from './node-comments.component';
|
||||
|
||||
export * from './services/node-comments.service';
|
||||
|
||||
export * from './node-comments.module';
|
@ -0,0 +1,88 @@
|
||||
/*!
|
||||
* @license
|
||||
* Copyright 2019 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 { TestBed } from '@angular/core/testing';
|
||||
import { CommentModel, setupTestBed, CoreTestingModule } from '@alfresco/adf-core';
|
||||
import { fakeContentComment, fakeContentComments } from '../mocks/node-comments.mock';
|
||||
import { TranslateModule } from '@ngx-translate/core';
|
||||
import { NodeCommentsService } from './node-comments.service';
|
||||
|
||||
declare let jasmine: any;
|
||||
|
||||
describe('NodeCommentsService', () => {
|
||||
|
||||
let service: NodeCommentsService;
|
||||
|
||||
setupTestBed({
|
||||
imports: [
|
||||
TranslateModule.forRoot(),
|
||||
CoreTestingModule
|
||||
]
|
||||
});
|
||||
|
||||
beforeEach(() => {
|
||||
service = TestBed.inject(NodeCommentsService);
|
||||
|
||||
jasmine.Ajax.install();
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
jasmine.Ajax.uninstall();
|
||||
});
|
||||
|
||||
describe('Node comments', () => {
|
||||
|
||||
it('should add a comment node ', (done) => {
|
||||
service.add('999', 'fake-comment-message').subscribe(
|
||||
(res: CommentModel) => {
|
||||
expect(res).toBeDefined();
|
||||
expect(res.id).not.toEqual(null);
|
||||
expect(res.message).toEqual('fake-comment-message');
|
||||
expect(res.created).not.toEqual(null);
|
||||
expect(res.createdBy.email).toEqual('fake-email@dom.com');
|
||||
expect(res.createdBy.firstName).toEqual('firstName');
|
||||
expect(res.createdBy.lastName).toEqual('lastName');
|
||||
done();
|
||||
}
|
||||
);
|
||||
|
||||
jasmine.Ajax.requests.mostRecent().respondWith({
|
||||
status: 200,
|
||||
contentType: 'application/json',
|
||||
responseText: JSON.stringify(fakeContentComment)
|
||||
});
|
||||
});
|
||||
|
||||
it('should return the nodes comments ', (done) => {
|
||||
service.get('999').subscribe(
|
||||
(res: CommentModel[]) => {
|
||||
expect(res).toBeDefined();
|
||||
expect(res.length).toEqual(2);
|
||||
expect(res[0].message).toEqual('fake-message-1');
|
||||
expect(res[1].message).toEqual('fake-message-2');
|
||||
done();
|
||||
}
|
||||
);
|
||||
|
||||
jasmine.Ajax.requests.mostRecent().respondWith({
|
||||
status: 200,
|
||||
contentType: 'application/json',
|
||||
responseText: JSON.stringify(fakeContentComments)
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
@ -0,0 +1,102 @@
|
||||
/*!
|
||||
* @license
|
||||
* Copyright 2019 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 { AlfrescoApiService, LogService, CommentModel } from '@alfresco/adf-core';
|
||||
import { CommentEntry, CommentsApi, Comment } from '@alfresco/js-api';
|
||||
import { Injectable } from '@angular/core';
|
||||
import { Observable, from, throwError } from 'rxjs';
|
||||
import { map, catchError } from 'rxjs/operators';
|
||||
|
||||
@Injectable({
|
||||
providedIn: 'root'
|
||||
})
|
||||
export class NodeCommentsService {
|
||||
|
||||
private _commentsApi: CommentsApi;
|
||||
get commentsApi(): CommentsApi {
|
||||
this._commentsApi = this._commentsApi ?? new CommentsApi(this.apiService.getInstance());
|
||||
return this._commentsApi;
|
||||
}
|
||||
|
||||
constructor(
|
||||
private apiService: AlfrescoApiService,
|
||||
private logService: LogService
|
||||
) {}
|
||||
|
||||
/**
|
||||
* Gets all comments that have been added to a task.
|
||||
*
|
||||
* @param id ID of the target task
|
||||
* @returns Details for each comment
|
||||
*/
|
||||
get(id: string): Observable<CommentModel[]> {
|
||||
return from(this.commentsApi.listComments(id))
|
||||
.pipe(
|
||||
map((response) => {
|
||||
const comments: CommentModel[] = [];
|
||||
|
||||
response.list.entries.forEach((comment: CommentEntry) => {
|
||||
this.addToComments(comments, comment);
|
||||
});
|
||||
|
||||
return comments;
|
||||
}),
|
||||
catchError(
|
||||
(err: any) => this.handleError(err)
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a comment to a task.
|
||||
*
|
||||
* @param id ID of the target task
|
||||
* @param message Text for the comment
|
||||
* @returns Details about the comment
|
||||
*/
|
||||
add(id: string, message: string): Observable<CommentModel> {
|
||||
return from(this.commentsApi.createComment(id, { content: message }))
|
||||
.pipe(
|
||||
map(
|
||||
(response: CommentEntry) => this.newCommentModel(response.entry)
|
||||
),
|
||||
catchError(
|
||||
(err: any) => this.handleError(err)
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
private addToComments(comments: CommentModel[], comment: CommentEntry): void {
|
||||
const newComment: Comment = comment.entry;
|
||||
|
||||
comments.push(this.newCommentModel(newComment));
|
||||
}
|
||||
|
||||
private newCommentModel(comment: Comment): CommentModel {
|
||||
return new CommentModel({
|
||||
id: comment.id,
|
||||
message: comment.content,
|
||||
created: comment.createdAt,
|
||||
createdBy: comment.createdBy
|
||||
});
|
||||
}
|
||||
|
||||
private handleError(error: any) {
|
||||
this.logService.error(error);
|
||||
return throwError(error || 'Server error');
|
||||
}
|
||||
}
|
@ -35,6 +35,7 @@ export * from './lib/tree-view/index';
|
||||
export * from './lib/group/index';
|
||||
export * from './lib/aspect-list/index';
|
||||
export * from './lib/content-type/index';
|
||||
export * from './lib/node-comments/index';
|
||||
export * from './lib/new-version-uploader';
|
||||
export * from './lib/interfaces/index';
|
||||
export * from './lib/version-compatibility/index';
|
||||
|
@ -1,24 +1,29 @@
|
||||
<div class="adf-comments-container">
|
||||
<div id="comment-header" class="adf-comments-header">
|
||||
{{'COMMENTS.HEADER' | translate: { count: comments?.length} }}
|
||||
{{'COMMENTS.HEADER' | translate: { count: comments?.length } }}
|
||||
</div>
|
||||
<div class="adf-comments-input-container" *ngIf="!isReadOnly()">
|
||||
<div class="adf-comments-input-container" *ngIf="!readOnly">
|
||||
<mat-form-field class="adf-full-width">
|
||||
<textarea id="comment-input"
|
||||
<textarea
|
||||
matInput
|
||||
id="comment-input"
|
||||
[attr.aria-label]="'COMMENTS.ADD' | translate"
|
||||
placeholder="{{'COMMENTS.ADD' | translate}}"
|
||||
[(ngModel)]="message"
|
||||
(keydown.escape)="clear($event)"></textarea>
|
||||
(keydown.escape)="clearMessage($event)"
|
||||
>
|
||||
</textarea>
|
||||
</mat-form-field>
|
||||
|
||||
<div class="adf-comments-input-actions">
|
||||
<button mat-button
|
||||
<button
|
||||
mat-button
|
||||
class="adf-comments-input-add"
|
||||
data-automation-id="comments-input-add"
|
||||
color="primary"
|
||||
(click)="add()"
|
||||
[disabled]="!message">
|
||||
(click)="addComment()"
|
||||
[disabled]="!message"
|
||||
>
|
||||
{{ 'COMMENTS.ADD' | translate }}
|
||||
</button>
|
||||
</div>
|
||||
|
@ -17,100 +17,74 @@
|
||||
|
||||
import { CUSTOM_ELEMENTS_SCHEMA, SimpleChange } from '@angular/core';
|
||||
import { ComponentFixture, TestBed } from '@angular/core/testing';
|
||||
import { of, throwError } from 'rxjs';
|
||||
import { CommentProcessService } from '../services/comment-process.service';
|
||||
import { CommentsComponent } from './comments.component';
|
||||
import { CommentContentService } from '../services/comment-content.service';
|
||||
import { setupTestBed } from '../testing/setup-test-bed';
|
||||
import { CoreTestingModule } from '../testing/core.testing.module';
|
||||
import { TranslateModule } from '@ngx-translate/core';
|
||||
import { CommentModel } from '../models/comment.model';
|
||||
import { CommentsServiceMock, commentsResponseMock } from './mocks/comments.service.mock';
|
||||
import { ADF_COMMENTS_SERVICE, CommentsService } from './interfaces';
|
||||
import { of, throwError } from 'rxjs';
|
||||
|
||||
describe('CommentsComponent', () => {
|
||||
let component: CommentsComponent;
|
||||
let fixture: ComponentFixture<CommentsComponent>;
|
||||
let getProcessCommentsSpy: jasmine.Spy;
|
||||
let addProcessCommentSpy: jasmine.Spy;
|
||||
let addContentCommentSpy: jasmine.Spy;
|
||||
let getContentCommentsSpy: jasmine.Spy;
|
||||
let commentProcessService: CommentProcessService;
|
||||
let commentContentService: CommentContentService;
|
||||
let getCommentSpy: jasmine.Spy;
|
||||
let addCommentSpy: jasmine.Spy;
|
||||
let commentsService: CommentsService;
|
||||
|
||||
setupTestBed({
|
||||
imports: [
|
||||
TranslateModule.forRoot(),
|
||||
CoreTestingModule
|
||||
],
|
||||
schemas: [CUSTOM_ELEMENTS_SCHEMA]
|
||||
schemas: [CUSTOM_ELEMENTS_SCHEMA],
|
||||
providers: [
|
||||
{
|
||||
provide: ADF_COMMENTS_SERVICE,
|
||||
useClass: CommentsServiceMock
|
||||
}
|
||||
]
|
||||
});
|
||||
|
||||
beforeEach(() => {
|
||||
fixture = TestBed.createComponent(CommentsComponent);
|
||||
component = fixture.componentInstance;
|
||||
|
||||
commentProcessService = fixture.debugElement.injector.get(CommentProcessService);
|
||||
commentContentService = fixture.debugElement.injector.get(CommentContentService);
|
||||
commentsService = fixture.componentInstance['commentsService'];
|
||||
|
||||
addContentCommentSpy = spyOn(commentContentService, 'addNodeComment').and.returnValue(of(new CommentModel({
|
||||
id: 123,
|
||||
message: 'Test Comment',
|
||||
createdBy: {id: '999'}
|
||||
})));
|
||||
|
||||
getContentCommentsSpy = spyOn(commentContentService, 'getNodeComments').and.returnValue(of([
|
||||
new CommentModel({message: 'Test1', created: Date.now(), createdBy: {firstName: 'Admin', lastName: 'User'}}),
|
||||
new CommentModel({message: 'Test2', created: Date.now(), createdBy: {firstName: 'Admin', lastName: 'User'}}),
|
||||
new CommentModel({message: 'Test3', created: Date.now(), createdBy: {firstName: 'Admin', lastName: 'User'}})
|
||||
]));
|
||||
|
||||
getProcessCommentsSpy = spyOn(commentProcessService, 'getTaskComments').and.returnValue(of([
|
||||
new CommentModel({message: 'Test1', created: Date.now(), createdBy: {firstName: 'Admin', lastName: 'User'}}),
|
||||
new CommentModel({message: 'Test2', created: Date.now(), createdBy: {firstName: 'Admin', lastName: 'User'}}),
|
||||
new CommentModel({message: 'Test3', created: Date.now(), createdBy: {firstName: 'Admin', lastName: 'User'}})
|
||||
]));
|
||||
addProcessCommentSpy = spyOn(commentProcessService, 'addTaskComment').and.returnValue(of(new CommentModel({
|
||||
id: 123,
|
||||
message: 'Test Comment',
|
||||
createdBy: {id: '999'}
|
||||
})));
|
||||
getCommentSpy = spyOn(commentsService, 'get').and.returnValue(commentsResponseMock.getComments());
|
||||
addCommentSpy = spyOn(commentsService, 'add').and.returnValue(commentsResponseMock.addComment());
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
fixture.destroy();
|
||||
});
|
||||
|
||||
it('should load comments when taskId specified', () => {
|
||||
it('should load comments when id specified', () => {
|
||||
const change = new SimpleChange(null, '123', true);
|
||||
component.ngOnChanges({taskId: change});
|
||||
component.ngOnChanges({id: change});
|
||||
|
||||
expect(getProcessCommentsSpy).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('should load comments when nodeId specified', () => {
|
||||
const change = new SimpleChange(null, '123', true);
|
||||
component.ngOnChanges({nodeId: change});
|
||||
|
||||
expect(getContentCommentsSpy).toHaveBeenCalled();
|
||||
expect(getCommentSpy).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('should emit an error when an error occurs loading comments', () => {
|
||||
const emitSpy = spyOn(component.error, 'emit');
|
||||
getProcessCommentsSpy.and.returnValue(throwError({}));
|
||||
getCommentSpy.and.returnValue(throwError({}));
|
||||
|
||||
const change = new SimpleChange(null, '123', true);
|
||||
component.ngOnChanges({taskId: change});
|
||||
component.ngOnChanges({id: change});
|
||||
|
||||
expect(emitSpy).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('should not load comments when no taskId is specified', () => {
|
||||
it('should not load comments when no id is specified', () => {
|
||||
fixture.detectChanges();
|
||||
expect(getProcessCommentsSpy).not.toHaveBeenCalled();
|
||||
expect(getCommentSpy).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('should display comments when the task has comments', async () => {
|
||||
it('should display comments when the entity has comments', async () => {
|
||||
const change = new SimpleChange(null, '123', true);
|
||||
component.ngOnChanges({taskId: change});
|
||||
component.ngOnChanges({id: change});
|
||||
|
||||
fixture.detectChanges();
|
||||
await fixture.whenStable();
|
||||
@ -119,9 +93,9 @@ describe('CommentsComponent', () => {
|
||||
expect(fixture.nativeElement.querySelector('.adf-comment-message:empty')).toBeNull();
|
||||
});
|
||||
|
||||
it('should display comments count when the task has comments', async () => {
|
||||
it('should display comments count when the entity has comments', async () => {
|
||||
const change = new SimpleChange(null, '123', true);
|
||||
component.ngOnChanges({taskId: change});
|
||||
component.ngOnChanges({id: change});
|
||||
|
||||
fixture.detectChanges();
|
||||
await fixture.whenStable();
|
||||
@ -130,9 +104,9 @@ describe('CommentsComponent', () => {
|
||||
expect(element.innerText).toBe('COMMENTS.HEADER');
|
||||
});
|
||||
|
||||
it('should not display comments when the task has no comments', async () => {
|
||||
component.taskId = '123';
|
||||
getProcessCommentsSpy.and.returnValue(of([]));
|
||||
it('should not display comments when the entity has no comments', async () => {
|
||||
component.id = '123';
|
||||
getCommentSpy.and.returnValue(of([]));
|
||||
|
||||
fixture.detectChanges();
|
||||
await fixture.whenStable();
|
||||
@ -142,7 +116,7 @@ describe('CommentsComponent', () => {
|
||||
|
||||
it('should display comments input by default', async () => {
|
||||
const change = new SimpleChange(null, '123', true);
|
||||
component.ngOnChanges({taskId: change});
|
||||
component.ngOnChanges({id: change});
|
||||
|
||||
fixture.detectChanges();
|
||||
await fixture.whenStable();
|
||||
@ -150,7 +124,7 @@ describe('CommentsComponent', () => {
|
||||
expect(fixture.nativeElement.querySelector('#comment-input')).not.toBeNull();
|
||||
});
|
||||
|
||||
it('should not display comments input when the task is readonly', async () => {
|
||||
it('should not display comments input when the entity is readonly', async () => {
|
||||
component.readOnly = true;
|
||||
|
||||
fixture.detectChanges();
|
||||
@ -159,60 +133,35 @@ describe('CommentsComponent', () => {
|
||||
expect(fixture.nativeElement.querySelector('#comment-input')).toBeNull();
|
||||
});
|
||||
|
||||
describe('change detection taskId', () => {
|
||||
describe('Change detection id', () => {
|
||||
const change = new SimpleChange('123', '456', true);
|
||||
const nullChange = new SimpleChange('123', null, true);
|
||||
|
||||
beforeEach(() => {
|
||||
component.taskId = '123';
|
||||
component.id = '123';
|
||||
fixture.detectChanges();
|
||||
});
|
||||
|
||||
it('should fetch new comments when taskId changed', () => {
|
||||
component.ngOnChanges({taskId: change});
|
||||
expect(getProcessCommentsSpy).toHaveBeenCalledWith('456');
|
||||
it('should fetch new comments when id changed', () => {
|
||||
component.ngOnChanges({id: change});
|
||||
expect(getCommentSpy).toHaveBeenCalledWith('456');
|
||||
});
|
||||
|
||||
it('should not fetch new comments when empty changeset made', () => {
|
||||
component.ngOnChanges({});
|
||||
expect(getProcessCommentsSpy).not.toHaveBeenCalled();
|
||||
expect(getCommentSpy).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('should not fetch new comments when taskId changed to null', () => {
|
||||
component.ngOnChanges({taskId: nullChange});
|
||||
expect(getProcessCommentsSpy).not.toHaveBeenCalled();
|
||||
it('should not fetch new comments when id changed to null', () => {
|
||||
component.ngOnChanges({id: nullChange});
|
||||
expect(getCommentSpy).not.toHaveBeenCalled();
|
||||
});
|
||||
});
|
||||
|
||||
describe('change detection node', () => {
|
||||
const change = new SimpleChange('123', '456', true);
|
||||
const nullChange = new SimpleChange('123', null, true);
|
||||
describe('Add comment', () => {
|
||||
|
||||
beforeEach(() => {
|
||||
component.nodeId = '123';
|
||||
fixture.detectChanges();
|
||||
});
|
||||
|
||||
it('should fetch new comments when nodeId changed', () => {
|
||||
component.ngOnChanges({nodeId: change});
|
||||
expect(getContentCommentsSpy).toHaveBeenCalledWith('456');
|
||||
});
|
||||
|
||||
it('should not fetch new comments when empty changeset made', () => {
|
||||
component.ngOnChanges({});
|
||||
expect(getContentCommentsSpy).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('should not fetch new comments when nodeId changed to null', () => {
|
||||
component.ngOnChanges({nodeId: nullChange});
|
||||
expect(getContentCommentsSpy).not.toHaveBeenCalled();
|
||||
});
|
||||
});
|
||||
|
||||
describe('Add comment task', () => {
|
||||
|
||||
beforeEach(() => {
|
||||
component.taskId = '123';
|
||||
component.id = '123';
|
||||
fixture.detectChanges();
|
||||
fixture.whenStable();
|
||||
});
|
||||
@ -225,18 +174,18 @@ describe('CommentsComponent', () => {
|
||||
fixture.detectChanges();
|
||||
await fixture.whenStable();
|
||||
|
||||
expect(addProcessCommentSpy).toHaveBeenCalledWith('123', 'action');
|
||||
expect(addCommentSpy).toHaveBeenCalledWith('123', 'action');
|
||||
});
|
||||
|
||||
it('should normalize comment when user input contains spaces sequence', async () => {
|
||||
const element = fixture.nativeElement.querySelector('.adf-comments-input-add');
|
||||
component.message = 'test comment';
|
||||
component.message = 'test comment';
|
||||
element.dispatchEvent(new Event('click'));
|
||||
|
||||
fixture.detectChanges();
|
||||
await fixture.whenStable();
|
||||
|
||||
expect(addProcessCommentSpy).toHaveBeenCalledWith('123', 'test comment');
|
||||
expect(addCommentSpy).toHaveBeenCalledWith('123', 'test comment');
|
||||
});
|
||||
|
||||
it('should add break lines to comment when user input contains new line characters', async () => {
|
||||
@ -247,18 +196,21 @@ describe('CommentsComponent', () => {
|
||||
fixture.detectChanges();
|
||||
await fixture.whenStable();
|
||||
|
||||
expect(addProcessCommentSpy).toHaveBeenCalledWith('123', 'these<br/>are<br/>paragraphs');
|
||||
expect(addCommentSpy).toHaveBeenCalledWith('123', 'these<br/>are<br/>paragraphs');
|
||||
});
|
||||
|
||||
it('should call service to add a comment when add button is pressed', async () => {
|
||||
const element = fixture.nativeElement.querySelector('.adf-comments-input-add');
|
||||
|
||||
component.message = 'Test Comment';
|
||||
addCommentSpy.and.returnValue(commentsResponseMock.addComment(component.message));
|
||||
|
||||
element.dispatchEvent(new Event('click'));
|
||||
|
||||
fixture.detectChanges();
|
||||
await fixture.whenStable();
|
||||
|
||||
expect(addProcessCommentSpy).toHaveBeenCalled();
|
||||
expect(addCommentSpy).toHaveBeenCalled();
|
||||
const elements = fixture.nativeElement.querySelectorAll('.adf-comment-message');
|
||||
expect(elements.length).toBe(1);
|
||||
expect(elements[0].innerText).toBe('Test Comment');
|
||||
@ -272,7 +224,7 @@ describe('CommentsComponent', () => {
|
||||
fixture.detectChanges();
|
||||
await fixture.whenStable();
|
||||
|
||||
expect(addProcessCommentSpy).not.toHaveBeenCalled();
|
||||
expect(addCommentSpy).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('should clear comment when escape key is pressed', async () => {
|
||||
@ -289,97 +241,34 @@ describe('CommentsComponent', () => {
|
||||
|
||||
it('should emit an error when an error occurs adding the comment', () => {
|
||||
const emitSpy = spyOn(component.error, 'emit');
|
||||
addProcessCommentSpy.and.returnValue(throwError({}));
|
||||
addCommentSpy.and.returnValue(throwError({}));
|
||||
component.message = 'Test comment';
|
||||
component.add();
|
||||
component.addComment();
|
||||
expect(emitSpy).toHaveBeenCalled();
|
||||
});
|
||||
});
|
||||
|
||||
describe('Add comment node', () => {
|
||||
|
||||
beforeEach(() => {
|
||||
component.nodeId = '123';
|
||||
fixture.detectChanges();
|
||||
fixture.whenStable();
|
||||
it('should set beingAdded variable back to false when an error occurs adding the comment', () => {
|
||||
addCommentSpy.and.returnValue(throwError({}));
|
||||
component.addComment();
|
||||
expect(component.beingAdded).toBeFalse();
|
||||
});
|
||||
|
||||
it('should call service to add a comment when add button is pressed', async () => {
|
||||
const element = fixture.nativeElement.querySelector('.adf-comments-input-add');
|
||||
component.message = 'Test Comment';
|
||||
element.dispatchEvent(new Event('click'));
|
||||
|
||||
fixture.detectChanges();
|
||||
await fixture.whenStable();
|
||||
|
||||
expect(addContentCommentSpy).toHaveBeenCalled();
|
||||
const elements = fixture.nativeElement.querySelectorAll('.adf-comment-message');
|
||||
expect(elements.length).toBe(1);
|
||||
expect(elements[0].innerText).toBe('Test Comment');
|
||||
it('should set beingAdded variable back to false on successful response when adding the comment', () => {
|
||||
addCommentSpy.and.returnValue(commentsResponseMock.addComment());
|
||||
component.addComment();
|
||||
expect(component.beingAdded).toBeFalse();
|
||||
});
|
||||
|
||||
it('should sanitize comment when user input contains html elements', async () => {
|
||||
const element = fixture.nativeElement.querySelector('.adf-comments-input-add');
|
||||
component.message = '<div class="text-class"><button onclick=""><h1>action</h1></button></div>';
|
||||
element.dispatchEvent(new Event('click'));
|
||||
|
||||
fixture.detectChanges();
|
||||
await fixture.whenStable();
|
||||
|
||||
expect(addContentCommentSpy).toHaveBeenCalledWith('123', 'action');
|
||||
it('should not add comment if id is not provided', () => {
|
||||
component.id = '';
|
||||
component.addComment();
|
||||
expect(addCommentSpy).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('should normalize comment when user input contains spaces sequence', async () => {
|
||||
const element = fixture.nativeElement.querySelector('.adf-comments-input-add');
|
||||
component.message = 'test comment';
|
||||
element.dispatchEvent(new Event('click'));
|
||||
|
||||
fixture.detectChanges();
|
||||
await fixture.whenStable();
|
||||
|
||||
expect(addContentCommentSpy).toHaveBeenCalledWith('123', 'test comment');
|
||||
});
|
||||
|
||||
it('should add break lines to comment when user input contains new line characters', async () => {
|
||||
const element = fixture.nativeElement.querySelector('.adf-comments-input-add');
|
||||
component.message = 'these\nare\nparagraphs\n';
|
||||
element.dispatchEvent(new Event('click'));
|
||||
|
||||
fixture.detectChanges();
|
||||
await fixture.whenStable();
|
||||
|
||||
expect(addContentCommentSpy).toHaveBeenCalledWith('123', 'these<br/>are<br/>paragraphs');
|
||||
});
|
||||
|
||||
it('should not call service to add a comment when comment is empty', async () => {
|
||||
const element = fixture.nativeElement.querySelector('.adf-comments-input-add');
|
||||
it('should not add comment if message is empty', () => {
|
||||
component.message = '';
|
||||
element.dispatchEvent(new Event('click'));
|
||||
|
||||
fixture.detectChanges();
|
||||
await fixture.whenStable();
|
||||
|
||||
expect(addContentCommentSpy).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('should clear comment when escape key is pressed', async () => {
|
||||
const event = new KeyboardEvent('keydown', {key: 'Escape'});
|
||||
let element = fixture.nativeElement.querySelector('#comment-input');
|
||||
element.dispatchEvent(event);
|
||||
|
||||
fixture.detectChanges();
|
||||
await fixture.whenStable();
|
||||
|
||||
element = fixture.nativeElement.querySelector('#comment-input');
|
||||
expect(element.value).toBe('');
|
||||
});
|
||||
|
||||
it('should emit an error when an error occurs adding the comment', () => {
|
||||
const emitSpy = spyOn(component.error, 'emit');
|
||||
addContentCommentSpy.and.returnValue(throwError({}));
|
||||
component.message = 'Test comment';
|
||||
component.add();
|
||||
expect(emitSpy).toHaveBeenCalled();
|
||||
component.addComment();
|
||||
expect(addCommentSpy).not.toHaveBeenCalled();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
@ -16,13 +16,13 @@
|
||||
*/
|
||||
|
||||
import { Meta, moduleMetadata, Story } from '@storybook/angular';
|
||||
import { CommentContentService, CommentProcessService, EcmUserService } from '../services';
|
||||
import { EcmUserService } from '../services';
|
||||
import { CoreStoryModule } from '../testing/core.story.module';
|
||||
import { CommentsComponent } from './comments.component';
|
||||
import { CommentsModule } from './comments.module';
|
||||
import { CommentContentServiceMock } from '../mock/comment-content-service.mock';
|
||||
import { CommentProcessServiceMock } from '../mock/comment-process-service.mock';
|
||||
import { commentsTaskData, commentsNodeData } from '../mock/comment-content.mock';
|
||||
import { ADF_COMMENTS_SERVICE } from './interfaces/comments.token';
|
||||
import { commentsStoriesData } from './mocks/comments.stories.mock';
|
||||
import { CommentsServiceStoriesMock } from './mocks/comments.service.stories.mock';
|
||||
|
||||
export default {
|
||||
component: CommentsComponent,
|
||||
@ -31,17 +31,16 @@ export default {
|
||||
moduleMetadata({
|
||||
imports: [CoreStoryModule, CommentsModule],
|
||||
providers: [
|
||||
{ provide: CommentContentService, useClass: CommentContentServiceMock },
|
||||
{ provide: CommentProcessService, useClass: CommentProcessServiceMock },
|
||||
{ provide: EcmUserService, useValue: { getUserProfileImage: () => '../assets/images/logo.png' } }
|
||||
{ provide: EcmUserService, useValue: { getUserProfileImage: () => '../assets/images/logo.png' } },
|
||||
{ provide: ADF_COMMENTS_SERVICE, useClass: CommentsServiceStoriesMock }
|
||||
]
|
||||
})
|
||||
],
|
||||
parameters: {
|
||||
docs: {
|
||||
description: {
|
||||
component: `Displays comments from users involved in a specified task or node.
|
||||
Allows an involved user to add a comment to a task or a node.`
|
||||
component: `Displays comments from users involved in a specified environment.
|
||||
Allows an involved user to add a comment to a environment.`
|
||||
}
|
||||
}
|
||||
},
|
||||
@ -60,21 +59,12 @@ export default {
|
||||
defaultValue: { summary: 'false' }
|
||||
}
|
||||
},
|
||||
nodeId: {
|
||||
id: {
|
||||
control: 'text',
|
||||
description: 'Necessary in order to add a new Node comment',
|
||||
description: 'Necessary in order to add a new comment',
|
||||
table: {
|
||||
type: { summary: 'string' }
|
||||
},
|
||||
if: { arg: 'taskId', exists: false }
|
||||
},
|
||||
taskId: {
|
||||
control: 'text',
|
||||
description: 'Necessary in order to add a new Task comment',
|
||||
table: {
|
||||
type: { summary: 'string' }
|
||||
},
|
||||
if: { arg: 'nodeId', exists: false }
|
||||
}
|
||||
},
|
||||
error: {
|
||||
action: 'error',
|
||||
@ -93,13 +83,13 @@ const template: Story<CommentsComponent> = (args: CommentsComponent) => ({
|
||||
|
||||
export const singleCommentWithAvatar = template.bind({});
|
||||
singleCommentWithAvatar.args = {
|
||||
comments: [commentsNodeData[0]],
|
||||
comments: [commentsStoriesData[0]],
|
||||
readOnly: true
|
||||
};
|
||||
|
||||
export const singleCommentWithoutAvatar = template.bind({});
|
||||
singleCommentWithoutAvatar.args = {
|
||||
comments: [commentsTaskData[1]],
|
||||
comments: [commentsStoriesData[1]],
|
||||
readOnly: true
|
||||
};
|
||||
|
||||
@ -109,14 +99,9 @@ noComments.args = {
|
||||
readOnly: true
|
||||
};
|
||||
|
||||
export const nodeComments = template.bind({});
|
||||
nodeComments.args = {
|
||||
comments: commentsNodeData,
|
||||
nodeId: '-fake-'
|
||||
export const comments = template.bind({});
|
||||
comments.args = {
|
||||
comments: commentsStoriesData,
|
||||
id: '-fake-'
|
||||
};
|
||||
|
||||
export const taskComments = template.bind({});
|
||||
taskComments.args = {
|
||||
comments: commentsTaskData,
|
||||
taskId: '-fake-'
|
||||
};
|
||||
|
@ -15,12 +15,21 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import { CommentProcessService } from '../services/comment-process.service';
|
||||
import { CommentContentService } from '../services/comment-content.service';
|
||||
import { CommentModel } from '../models/comment.model';
|
||||
import { Component, EventEmitter, Input, OnChanges, Output, SimpleChanges, ViewEncapsulation } from '@angular/core';
|
||||
import {
|
||||
Component,
|
||||
EventEmitter,
|
||||
Inject,
|
||||
Input,
|
||||
OnChanges,
|
||||
Output,
|
||||
SimpleChanges,
|
||||
ViewEncapsulation
|
||||
} from '@angular/core';
|
||||
import { Observable, Observer } from 'rxjs';
|
||||
import { share } from 'rxjs/operators';
|
||||
import { ADF_COMMENTS_SERVICE } from './interfaces/comments.token';
|
||||
import { CommentsService } from './interfaces/comments-service.interface';
|
||||
|
||||
@Component({
|
||||
selector: 'adf-comments',
|
||||
@ -32,11 +41,7 @@ export class CommentsComponent implements OnChanges {
|
||||
|
||||
/** The numeric ID of the task. */
|
||||
@Input()
|
||||
taskId: string;
|
||||
|
||||
/** The numeric ID of the node. */
|
||||
@Input()
|
||||
nodeId: string;
|
||||
id: string;
|
||||
|
||||
/** Are the comments read only? */
|
||||
@Input()
|
||||
@ -46,143 +51,129 @@ export class CommentsComponent implements OnChanges {
|
||||
@Output()
|
||||
error: EventEmitter<any> = new EventEmitter<any>();
|
||||
|
||||
comments: CommentModel [] = [];
|
||||
|
||||
private commentObserver: Observer<CommentModel>;
|
||||
comment$: Observable<CommentModel>;
|
||||
comments: CommentModel[] = [];
|
||||
|
||||
message: string;
|
||||
|
||||
beingAdded: boolean = false;
|
||||
|
||||
constructor(private commentProcessService: CommentProcessService,
|
||||
private commentContentService: CommentContentService) {
|
||||
private commentObserver: Observer<CommentModel>;
|
||||
comment$: Observable<CommentModel>;
|
||||
|
||||
constructor(@Inject(ADF_COMMENTS_SERVICE) private commentsService: CommentsService) {
|
||||
this.comment$ = new Observable<CommentModel>((observer) => this.commentObserver = observer)
|
||||
.pipe(share());
|
||||
.pipe(
|
||||
share()
|
||||
);
|
||||
|
||||
this.comment$.subscribe((comment: CommentModel) => {
|
||||
this.comments.push(comment);
|
||||
});
|
||||
}
|
||||
|
||||
ngOnChanges(changes: SimpleChanges) {
|
||||
this.taskId = null;
|
||||
this.nodeId = null;
|
||||
ngOnChanges(changes: SimpleChanges): void {
|
||||
this.id = null;
|
||||
|
||||
this.taskId = changes['taskId'] ? changes['taskId'].currentValue : null;
|
||||
this.nodeId = changes['nodeId'] ? changes['nodeId'].currentValue : null;
|
||||
this.id = changes['id'] ? changes['id'].currentValue : null;
|
||||
|
||||
if (this.taskId || this.nodeId) {
|
||||
this.getComments();
|
||||
if (this.id) {
|
||||
this.loadComments();
|
||||
} else {
|
||||
this.resetComments();
|
||||
}
|
||||
}
|
||||
|
||||
private getComments(): void {
|
||||
loadComments() {
|
||||
this.resetComments();
|
||||
if (this.isATask()) {
|
||||
this.commentProcessService.getTaskComments(this.taskId).subscribe(
|
||||
(comments: CommentModel[]) => {
|
||||
if (comments && comments instanceof Array) {
|
||||
comments = comments.sort((comment1: CommentModel, comment2: CommentModel) => {
|
||||
const date1 = new Date(comment1.created);
|
||||
const date2 = new Date(comment2.created);
|
||||
return date1 > date2 ? -1 : date1 < date2 ? 1 : 0;
|
||||
});
|
||||
comments.forEach((currentComment) => {
|
||||
this.commentObserver.next(currentComment);
|
||||
});
|
||||
}
|
||||
|
||||
if (!this.hasId()) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.commentsService.get(this.id).subscribe(
|
||||
(comments: CommentModel[]) => {
|
||||
if (!this.isArrayInstance(comments)) {
|
||||
return;
|
||||
}
|
||||
|
||||
comments = this.sortedComments(comments);
|
||||
this.addCommentsToObserver(comments);
|
||||
|
||||
},
|
||||
(err) => {
|
||||
this.error.emit(err);
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
addComment() {
|
||||
if (!this.canAddComment()) {
|
||||
return;
|
||||
}
|
||||
|
||||
const comment: string = this.sanitize(this.message);
|
||||
|
||||
this.beingAdded = true;
|
||||
|
||||
this.commentsService.add(this.id, comment)
|
||||
.subscribe(
|
||||
(res: CommentModel) => {
|
||||
this.addToComments(res);
|
||||
this.resetMessage();
|
||||
},
|
||||
(err) => {
|
||||
this.error.emit(err);
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
if (this.isANode()) {
|
||||
this.commentContentService.getNodeComments(this.nodeId).subscribe(
|
||||
(comments: CommentModel[]) => {
|
||||
if (comments && comments instanceof Array) {
|
||||
|
||||
comments = comments.sort((comment1: CommentModel, comment2: CommentModel) => {
|
||||
const date1 = new Date(comment1.created);
|
||||
const date2 = new Date(comment2.created);
|
||||
return date1 > date2 ? -1 : date1 < date2 ? 1 : 0;
|
||||
});
|
||||
comments.forEach((comment) => {
|
||||
this.commentObserver.next(comment);
|
||||
});
|
||||
}
|
||||
},
|
||||
(err) => {
|
||||
this.error.emit(err);
|
||||
() => {
|
||||
this.beingAdded = false;
|
||||
}
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
clearMessage(event: Event): void {
|
||||
event.stopPropagation();
|
||||
this.resetMessage();
|
||||
}
|
||||
|
||||
private addToComments(comment: CommentModel): void {
|
||||
this.comments.unshift(comment);
|
||||
}
|
||||
|
||||
private resetMessage(): void {
|
||||
this.message = '';
|
||||
}
|
||||
|
||||
private canAddComment(): boolean {
|
||||
return this.hasId() && this.message && this.message.trim() && !this.beingAdded;
|
||||
}
|
||||
|
||||
private hasId(): boolean {
|
||||
return !!this.id;
|
||||
}
|
||||
|
||||
private isArrayInstance(entity: any): boolean {
|
||||
return entity && entity instanceof Array;
|
||||
}
|
||||
|
||||
private sortedComments(comments: CommentModel[]): CommentModel[] {
|
||||
return comments.sort((comment1: CommentModel, comment2: CommentModel) => {
|
||||
const date1 = new Date(comment1.created);
|
||||
const date2 = new Date(comment2.created);
|
||||
|
||||
return date1 > date2 ? -1 : date1 < date2 ? 1 : 0;
|
||||
});
|
||||
}
|
||||
|
||||
private addCommentsToObserver(comments: CommentModel[]): void {
|
||||
comments.forEach((currentComment: CommentModel) => {
|
||||
this.commentObserver.next(currentComment);
|
||||
});
|
||||
}
|
||||
|
||||
private resetComments(): void {
|
||||
this.comments = [];
|
||||
}
|
||||
|
||||
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, comment)
|
||||
.subscribe(
|
||||
(res: CommentModel) => {
|
||||
this.comments.unshift(res);
|
||||
this.message = '';
|
||||
this.beingAdded = false;
|
||||
|
||||
},
|
||||
(err) => {
|
||||
this.error.emit(err);
|
||||
this.beingAdded = false;
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
if (this.isANode()) {
|
||||
this.commentContentService.addNodeComment(this.nodeId, comment)
|
||||
.subscribe(
|
||||
(res: CommentModel) => {
|
||||
this.comments.unshift(res);
|
||||
this.message = '';
|
||||
this.beingAdded = false;
|
||||
|
||||
},
|
||||
(err) => {
|
||||
this.error.emit(err);
|
||||
this.beingAdded = false;
|
||||
}
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
clear(event: Event): void {
|
||||
event.stopPropagation();
|
||||
this.message = '';
|
||||
}
|
||||
|
||||
isReadOnly(): boolean {
|
||||
return this.readOnly;
|
||||
}
|
||||
|
||||
isATask(): boolean {
|
||||
return !!this.taskId;
|
||||
}
|
||||
|
||||
isANode(): boolean {
|
||||
return !!this.nodeId;
|
||||
}
|
||||
|
||||
private sanitize(input: string): string {
|
||||
return input.replace(/<[^>]+>/g, '')
|
||||
.replace(/^\s+|\s+$|\s+(?=\s)/g, '')
|
||||
|
@ -0,0 +1,24 @@
|
||||
/*!
|
||||
* @license
|
||||
* Copyright 2019 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';
|
||||
import { CommentModel } from '../../models/comment.model';
|
||||
|
||||
export interface CommentsService {
|
||||
get(id: string): Observable<CommentModel[]>;
|
||||
add(id: string, message: string): Observable<CommentModel>;
|
||||
}
|
20
lib/core/src/lib/comments/interfaces/comments.token.ts
Normal file
20
lib/core/src/lib/comments/interfaces/comments.token.ts
Normal file
@ -0,0 +1,20 @@
|
||||
/*!
|
||||
* @license
|
||||
* Copyright 2019 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 { InjectionToken } from '@angular/core';
|
||||
|
||||
export const ADF_COMMENTS_SERVICE = new InjectionToken('ADF_COMMENTS_SERVICE');
|
18
lib/core/src/lib/comments/interfaces/index.ts
Normal file
18
lib/core/src/lib/comments/interfaces/index.ts
Normal file
@ -0,0 +1,18 @@
|
||||
/*!
|
||||
* @license
|
||||
* Copyright 2019 Alfresco Software, Ltd.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
export * from './public-api';
|
19
lib/core/src/lib/comments/interfaces/public-api.ts
Normal file
19
lib/core/src/lib/comments/interfaces/public-api.ts
Normal file
@ -0,0 +1,19 @@
|
||||
/*!
|
||||
* @license
|
||||
* Copyright 2019 Alfresco Software, Ltd.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
export * from './comments-service.interface';
|
||||
export * from './comments.token';
|
145
lib/core/src/lib/comments/mocks/comments.service.mock.ts
Normal file
145
lib/core/src/lib/comments/mocks/comments.service.mock.ts
Normal file
@ -0,0 +1,145 @@
|
||||
/*!
|
||||
* @license
|
||||
* Copyright 2019 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 { CommentModel, EcmUserModel } from '../../models';
|
||||
import { Observable, of } from 'rxjs';
|
||||
import { CommentsService } from '../interfaces';
|
||||
|
||||
export class CommentsServiceMock implements CommentsService {
|
||||
|
||||
constructor() {}
|
||||
|
||||
get(_id: string): Observable<CommentModel[]> {
|
||||
return commentsResponseMock.getComments();
|
||||
}
|
||||
add(_id: string): Observable<CommentModel> {
|
||||
return commentsResponseMock.addComment();
|
||||
}
|
||||
}
|
||||
|
||||
export const commentsResponseMock = {
|
||||
getComments: () => of([
|
||||
{
|
||||
id: 1,
|
||||
message: 'Test Comment',
|
||||
created: new Date(),
|
||||
createdBy: {
|
||||
enabled: true,
|
||||
firstName: 'hruser',
|
||||
displayName: 'hruser',
|
||||
quota: -1,
|
||||
quotaUsed: 12,
|
||||
emailNotificationsEnabled: true,
|
||||
company: {
|
||||
organization: 'test',
|
||||
address1: 'test',
|
||||
address2: 'test',
|
||||
address3: 'test',
|
||||
postcode: 'test',
|
||||
telephone: 'test',
|
||||
fax: 'test',
|
||||
email: 'test'
|
||||
},
|
||||
id: 'hruser',
|
||||
email: 'test',
|
||||
isAdmin: () => false
|
||||
} as EcmUserModel,
|
||||
isSelected: false
|
||||
} as CommentModel,
|
||||
{
|
||||
id: 2,
|
||||
message: 'Test Comment',
|
||||
created: new Date(),
|
||||
createdBy: {
|
||||
enabled: true,
|
||||
firstName: 'hruser',
|
||||
displayName: 'hruser',
|
||||
quota: -1,
|
||||
quotaUsed: 12,
|
||||
emailNotificationsEnabled: true,
|
||||
company: {
|
||||
organization: 'test',
|
||||
address1: 'test',
|
||||
address2: 'test',
|
||||
address3: 'test',
|
||||
postcode: 'test',
|
||||
telephone: 'test',
|
||||
fax: 'test',
|
||||
email: 'test'
|
||||
},
|
||||
id: 'hruser',
|
||||
email: 'test',
|
||||
isAdmin: () => false
|
||||
} as EcmUserModel,
|
||||
isSelected: false
|
||||
} as CommentModel,
|
||||
{
|
||||
id: 3,
|
||||
message: 'Test Comment',
|
||||
created: new Date(),
|
||||
createdBy: {
|
||||
enabled: true,
|
||||
firstName: 'hruser',
|
||||
displayName: 'hruser',
|
||||
quota: -1,
|
||||
quotaUsed: 12,
|
||||
emailNotificationsEnabled: true,
|
||||
company: {
|
||||
organization: 'test',
|
||||
address1: 'test',
|
||||
address2: 'test',
|
||||
address3: 'test',
|
||||
postcode: 'test',
|
||||
telephone: 'test',
|
||||
fax: 'test',
|
||||
email: 'test'
|
||||
},
|
||||
id: 'hruser',
|
||||
email: 'test',
|
||||
isAdmin: () => false
|
||||
} as EcmUserModel,
|
||||
isSelected: false
|
||||
} as CommentModel
|
||||
]),
|
||||
addComment: (message = 'test comment') => of({
|
||||
id: 1,
|
||||
message,
|
||||
created: new Date(),
|
||||
createdBy: {
|
||||
enabled: true,
|
||||
firstName: 'hruser',
|
||||
displayName: 'hruser',
|
||||
quota: -1,
|
||||
quotaUsed: 12,
|
||||
emailNotificationsEnabled: true,
|
||||
company: {
|
||||
organization: 'test',
|
||||
address1: 'test',
|
||||
address2: 'test',
|
||||
address3: 'test',
|
||||
postcode: 'test',
|
||||
telephone: 'test',
|
||||
fax: 'test',
|
||||
email: 'test'
|
||||
},
|
||||
id: 'hruser',
|
||||
email: 'test',
|
||||
isAdmin: () => false
|
||||
} as EcmUserModel,
|
||||
isSelected: false
|
||||
} as CommentModel)
|
||||
};
|
126
lib/core/src/lib/comments/mocks/comments.service.stories.mock.ts
Normal file
126
lib/core/src/lib/comments/mocks/comments.service.stories.mock.ts
Normal file
@ -0,0 +1,126 @@
|
||||
/*!
|
||||
* @license
|
||||
* Copyright 2019 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 { CommentModel, EcmUserModel } from '../../models';
|
||||
import { Observable, of } from 'rxjs';
|
||||
import { CommentsService } from '../interfaces';
|
||||
import { testUser } from './comments.stories.mock';
|
||||
|
||||
export class CommentsServiceStoriesMock implements CommentsService {
|
||||
|
||||
constructor() {}
|
||||
|
||||
get(_id: string): Observable<CommentModel[]> {
|
||||
return commentsResponseMock.getComments();
|
||||
}
|
||||
add(_id: string, message = 'test comment'): Observable<CommentModel> {
|
||||
return commentsResponseMock.addComment(message);
|
||||
}
|
||||
}
|
||||
|
||||
export const commentsResponseMock = {
|
||||
getComments: () => of([
|
||||
{
|
||||
id: 1,
|
||||
message: 'Test Comment',
|
||||
created: new Date(),
|
||||
createdBy: {
|
||||
enabled: true,
|
||||
firstName: 'hruser',
|
||||
displayName: 'hruser',
|
||||
quota: -1,
|
||||
quotaUsed: 12,
|
||||
emailNotificationsEnabled: true,
|
||||
company: {
|
||||
organization: 'test',
|
||||
address1: 'test',
|
||||
address2: 'test',
|
||||
address3: 'test',
|
||||
postcode: 'test',
|
||||
telephone: 'test',
|
||||
fax: 'test',
|
||||
email: 'test'
|
||||
},
|
||||
id: 'hruser',
|
||||
email: 'test',
|
||||
isAdmin: () => false
|
||||
} as EcmUserModel,
|
||||
isSelected: false
|
||||
} as CommentModel,
|
||||
{
|
||||
id: 2,
|
||||
message: 'Test Comment',
|
||||
created: new Date(),
|
||||
createdBy: {
|
||||
enabled: true,
|
||||
firstName: 'hruser',
|
||||
displayName: 'hruser',
|
||||
quota: -1,
|
||||
quotaUsed: 12,
|
||||
emailNotificationsEnabled: true,
|
||||
company: {
|
||||
organization: 'test',
|
||||
address1: 'test',
|
||||
address2: 'test',
|
||||
address3: 'test',
|
||||
postcode: 'test',
|
||||
telephone: 'test',
|
||||
fax: 'test',
|
||||
email: 'test'
|
||||
},
|
||||
id: 'hruser',
|
||||
email: 'test',
|
||||
isAdmin: () => false
|
||||
} as EcmUserModel,
|
||||
isSelected: false
|
||||
} as CommentModel,
|
||||
{
|
||||
id: 3,
|
||||
message: 'Test Comment',
|
||||
created: new Date(),
|
||||
createdBy: {
|
||||
enabled: true,
|
||||
firstName: 'hruser',
|
||||
displayName: 'hruser',
|
||||
quota: -1,
|
||||
quotaUsed: 12,
|
||||
emailNotificationsEnabled: true,
|
||||
company: {
|
||||
organization: 'test',
|
||||
address1: 'test',
|
||||
address2: 'test',
|
||||
address3: 'test',
|
||||
postcode: 'test',
|
||||
telephone: 'test',
|
||||
fax: 'test',
|
||||
email: 'test'
|
||||
},
|
||||
id: 'hruser',
|
||||
email: 'test',
|
||||
isAdmin: () => false
|
||||
} as EcmUserModel,
|
||||
isSelected: false
|
||||
} as CommentModel
|
||||
]),
|
||||
addComment: (message: string) => of({
|
||||
id: 1,
|
||||
message,
|
||||
created: new Date(),
|
||||
createdBy: testUser,
|
||||
isSelected: false
|
||||
} as CommentModel)
|
||||
};
|
105
lib/core/src/lib/comments/mocks/comments.stories.mock.ts
Normal file
105
lib/core/src/lib/comments/mocks/comments.stories.mock.ts
Normal file
@ -0,0 +1,105 @@
|
||||
/*!
|
||||
* @license
|
||||
* Copyright 2019 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 { CommentModel, EcmCompanyModel, EcmUserModel } from '../../models';
|
||||
|
||||
const fakeCompany: EcmCompanyModel = {
|
||||
organization: '',
|
||||
address1: '',
|
||||
address2: '',
|
||||
address3: '',
|
||||
postcode: '',
|
||||
telephone: '',
|
||||
fax: '',
|
||||
email: ''
|
||||
};
|
||||
|
||||
export const getDateXMinutesAgo = (minutes: number) => new Date(new Date().getTime() - minutes * 60000);
|
||||
|
||||
const johnDoe: EcmUserModel = {
|
||||
id: '1',
|
||||
email: 'john.doe@alfresco.com',
|
||||
firstName: 'John',
|
||||
lastName: 'Doe',
|
||||
company: fakeCompany,
|
||||
enabled: true,
|
||||
isAdmin: undefined,
|
||||
avatarId: '001'
|
||||
};
|
||||
|
||||
const janeEod: EcmUserModel = {
|
||||
id: '2',
|
||||
email: 'jane.eod@alfresco.com',
|
||||
firstName: 'Jane',
|
||||
lastName: 'Eod',
|
||||
company: fakeCompany,
|
||||
enabled: true,
|
||||
isAdmin: undefined
|
||||
};
|
||||
|
||||
const robertSmith: EcmUserModel = {
|
||||
id: '3',
|
||||
email: 'robert.smith@alfresco.com',
|
||||
firstName: 'Robert',
|
||||
lastName: 'Smith',
|
||||
company: fakeCompany,
|
||||
enabled: true,
|
||||
isAdmin: undefined
|
||||
};
|
||||
|
||||
export const testUser: EcmUserModel = {
|
||||
id: '44',
|
||||
email: 'test.user@hyland.com',
|
||||
firstName: 'Test',
|
||||
lastName: 'User',
|
||||
company: fakeCompany,
|
||||
enabled: true,
|
||||
isAdmin: undefined,
|
||||
avatarId: '044'
|
||||
};
|
||||
|
||||
|
||||
export const commentsStoriesData: CommentModel[] = [
|
||||
{
|
||||
id: 1,
|
||||
message: `I've done this task, what's next?`,
|
||||
created: getDateXMinutesAgo(30),
|
||||
createdBy: johnDoe,
|
||||
isSelected: false
|
||||
},
|
||||
{
|
||||
id: 2,
|
||||
message: `I've assigned you another one 🤠`,
|
||||
created: getDateXMinutesAgo(15),
|
||||
createdBy: janeEod,
|
||||
isSelected: false
|
||||
},
|
||||
{
|
||||
id: 3,
|
||||
message: '+1',
|
||||
created: getDateXMinutesAgo(12),
|
||||
createdBy: robertSmith,
|
||||
isSelected: false
|
||||
},
|
||||
{
|
||||
id: 4,
|
||||
message: 'Cheers',
|
||||
created: new Date(),
|
||||
createdBy: johnDoe,
|
||||
isSelected: false
|
||||
}
|
||||
];
|
@ -18,4 +18,6 @@
|
||||
export * from './comment-list.component';
|
||||
export * from './comments.component';
|
||||
|
||||
export * from './interfaces/index';
|
||||
|
||||
export * from './comments.module';
|
||||
|
@ -38,3 +38,4 @@ export * from './node-metadata.model';
|
||||
export * from './application-access.model';
|
||||
export * from './user-access.model';
|
||||
export * from './general-user.model';
|
||||
export * from './comment.model';
|
||||
|
@ -31,6 +31,7 @@ import { PeopleModule } from './people/people.module';
|
||||
import { FormModule } from './form/form.module';
|
||||
import { ProcessFormRenderingService } from './form/process-form-rendering.service';
|
||||
import { ProcessServicesPipeModule } from './pipes/process-services-pipe.module';
|
||||
import { TaskCommentsModule } from './task-comments/task-comments.module';
|
||||
|
||||
@NgModule({
|
||||
imports: [
|
||||
@ -42,6 +43,7 @@ import { ProcessServicesPipeModule } from './pipes/process-services-pipe.module'
|
||||
MaterialModule,
|
||||
ProcessListModule,
|
||||
TaskListModule,
|
||||
TaskCommentsModule,
|
||||
AppsListModule,
|
||||
AttachmentModule,
|
||||
PeopleModule,
|
||||
@ -65,6 +67,7 @@ import { ProcessServicesPipeModule } from './pipes/process-services-pipe.module'
|
||||
ReactiveFormsModule,
|
||||
ProcessListModule,
|
||||
TaskListModule,
|
||||
TaskCommentsModule,
|
||||
AppsListModule,
|
||||
AttachmentModule,
|
||||
PeopleModule,
|
||||
|
18
lib/process-services/src/lib/task-comments/index.ts
Normal file
18
lib/process-services/src/lib/task-comments/index.ts
Normal file
@ -0,0 +1,18 @@
|
||||
/*!
|
||||
* @license
|
||||
* Copyright 2019 Alfresco Software, Ltd.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
export * from './public-api';
|
@ -0,0 +1,32 @@
|
||||
/*!
|
||||
* @license
|
||||
* Copyright 2019 Alfresco Software, Ltd.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
export const fakeUser1 = { id: 1, email: 'fake-email@dom.com', firstName: 'firstName', lastName: 'lastName' };
|
||||
|
||||
export const fakeUser2 = { id: 1001, email: 'some-one@somegroup.com', firstName: 'some', lastName: 'one' };
|
||||
|
||||
export const fakeTasksComment = {
|
||||
size: 2, total: 2, start: 0,
|
||||
data: [
|
||||
{
|
||||
id: 1, message: 'fake-message-1', created: '', createdBy: fakeUser1
|
||||
},
|
||||
{
|
||||
id: 2, message: 'fake-message-2', created: '', createdBy: fakeUser1
|
||||
}
|
||||
]
|
||||
};
|
22
lib/process-services/src/lib/task-comments/public-api.ts
Normal file
22
lib/process-services/src/lib/task-comments/public-api.ts
Normal file
@ -0,0 +1,22 @@
|
||||
/*!
|
||||
* @license
|
||||
* Copyright 2019 Alfresco Software, Ltd.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
export * from './task-comments.component';
|
||||
|
||||
export * from './services/task-comments.service';
|
||||
|
||||
export * from './task-comments.module';
|
@ -0,0 +1,94 @@
|
||||
/*!
|
||||
* @license
|
||||
* Copyright 2019 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 { TestBed } from '@angular/core/testing';
|
||||
import { CommentModel, setupTestBed, CoreTestingModule } from '@alfresco/adf-core';
|
||||
import { fakeTasksComment, fakeUser1 } from '../mocks/task-comments.mock';
|
||||
import { TranslateModule } from '@ngx-translate/core';
|
||||
import { TaskCommentsService } from './task-comments.service';
|
||||
|
||||
declare let jasmine: any;
|
||||
|
||||
describe('TaskCommentsService', () => {
|
||||
|
||||
let service: TaskCommentsService;
|
||||
|
||||
setupTestBed({
|
||||
imports: [
|
||||
TranslateModule.forRoot(),
|
||||
CoreTestingModule
|
||||
]
|
||||
});
|
||||
|
||||
beforeEach(() => {
|
||||
service = TestBed.inject(TaskCommentsService);
|
||||
});
|
||||
|
||||
beforeEach(() => {
|
||||
jasmine.Ajax.install();
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
jasmine.Ajax.uninstall();
|
||||
});
|
||||
|
||||
describe('Task comments', () => {
|
||||
|
||||
it('should add a comment task ', (done) => {
|
||||
service.add('999', 'fake-comment-message').subscribe(
|
||||
(res: CommentModel) => {
|
||||
expect(res).toBeDefined();
|
||||
expect(res.id).not.toEqual(null);
|
||||
expect(res.message).toEqual('fake-comment-message');
|
||||
expect(res.created).not.toEqual(null);
|
||||
expect(res.createdBy.email).toEqual('fake-email@dom.com');
|
||||
expect(res.createdBy.firstName).toEqual('firstName');
|
||||
expect(res.createdBy.lastName).toEqual('lastName');
|
||||
done();
|
||||
}
|
||||
);
|
||||
|
||||
jasmine.Ajax.requests.mostRecent().respondWith({
|
||||
status: 200,
|
||||
contentType: 'application/json',
|
||||
responseText: JSON.stringify({
|
||||
id: '111', message: 'fake-comment-message',
|
||||
createdBy: fakeUser1,
|
||||
created: '2016-07-15T11:19:17.440+0000'
|
||||
})
|
||||
});
|
||||
});
|
||||
|
||||
it('should return the tasks comments ', (done) => {
|
||||
service.get('999').subscribe(
|
||||
(res: CommentModel[]) => {
|
||||
expect(res).toBeDefined();
|
||||
expect(res.length).toEqual(2);
|
||||
expect(res[0].message).toEqual('fake-message-1');
|
||||
expect(res[1].message).toEqual('fake-message-2');
|
||||
done();
|
||||
}
|
||||
);
|
||||
|
||||
jasmine.Ajax.requests.mostRecent().respondWith({
|
||||
status: 200,
|
||||
contentType: 'application/json',
|
||||
responseText: JSON.stringify(fakeTasksComment)
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
@ -0,0 +1,107 @@
|
||||
/*!
|
||||
* @license
|
||||
* Copyright 2019 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 { AlfrescoApiService, CommentModel, CommentsService, UserProcessModel } from '@alfresco/adf-core';
|
||||
import { ActivitiCommentsApi, CommentRepresentation } from '@alfresco/js-api';
|
||||
import { Injectable } from '@angular/core';
|
||||
import { from, Observable, throwError } from 'rxjs';
|
||||
import { catchError, map } from 'rxjs/operators';
|
||||
|
||||
@Injectable({
|
||||
providedIn: 'root'
|
||||
})
|
||||
export class TaskCommentsService implements CommentsService {
|
||||
|
||||
private _commentsApi: ActivitiCommentsApi;
|
||||
get commentsApi(): ActivitiCommentsApi {
|
||||
this._commentsApi = this._commentsApi ?? new ActivitiCommentsApi(this.apiService.getInstance());
|
||||
return this._commentsApi;
|
||||
}
|
||||
|
||||
constructor(
|
||||
private apiService: AlfrescoApiService
|
||||
) {}
|
||||
|
||||
/**
|
||||
* Gets all comments that have been added to a task.
|
||||
*
|
||||
* @param id ID of the target task
|
||||
* @returns Details for each comment
|
||||
*/
|
||||
get(id: string): Observable<CommentModel[]> {
|
||||
return from(this.commentsApi.getTaskComments(id))
|
||||
.pipe(
|
||||
map((response) => {
|
||||
const comments: CommentModel[] = [];
|
||||
|
||||
response.data.forEach((comment: CommentRepresentation) => {
|
||||
this.addToComments(comments, comment);
|
||||
});
|
||||
|
||||
return comments;
|
||||
}),
|
||||
catchError(
|
||||
(err: any) => this.handleError(err)
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a comment to a task.
|
||||
*
|
||||
* @param id ID of the target task
|
||||
* @param message Text for the comment
|
||||
* @returns Details about the comment
|
||||
*/
|
||||
add(id: string, message: string): Observable<CommentModel> {
|
||||
return from(this.commentsApi.addTaskComment({ message }, id))
|
||||
.pipe(
|
||||
map(
|
||||
(response: CommentRepresentation) => this.newCommentModel(response)
|
||||
),
|
||||
catchError(
|
||||
(err: any) => this.handleError(err)
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
private addToComments(comments: CommentModel[], comment: CommentRepresentation): void {
|
||||
const user = new UserProcessModel(comment.createdBy);
|
||||
|
||||
const newComment: CommentRepresentation = {
|
||||
id: comment.id,
|
||||
message: comment.message,
|
||||
created: comment.created,
|
||||
createdBy: user
|
||||
};
|
||||
|
||||
comments.push(this.newCommentModel(newComment));
|
||||
}
|
||||
|
||||
private newCommentModel(representation: CommentRepresentation): CommentModel {
|
||||
return new CommentModel({
|
||||
id: representation.id,
|
||||
message: representation.message,
|
||||
created: representation.created,
|
||||
createdBy: representation.createdBy
|
||||
});
|
||||
}
|
||||
|
||||
private handleError(error: any) {
|
||||
return throwError(error || 'Server error');
|
||||
}
|
||||
}
|
@ -0,0 +1,5 @@
|
||||
<adf-comments
|
||||
[readOnly]="readOnly"
|
||||
[id]="taskId"
|
||||
>
|
||||
</adf-comments>
|
@ -0,0 +1,31 @@
|
||||
/*!
|
||||
* @license
|
||||
* Copyright 2019 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, ViewEncapsulation } from '@angular/core';
|
||||
|
||||
@Component({
|
||||
selector: 'adf-task-comments',
|
||||
templateUrl: './task-comments.component.html',
|
||||
encapsulation: ViewEncapsulation.None
|
||||
})
|
||||
export class TaskCommentsComponent {
|
||||
@Input()
|
||||
taskId: string;
|
||||
|
||||
@Input()
|
||||
readOnly: boolean;
|
||||
}
|
@ -0,0 +1,38 @@
|
||||
/*!
|
||||
* @license
|
||||
* Copyright 2019 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 { NgModule } from '@angular/core';
|
||||
import { CommonModule } from '@angular/common';
|
||||
import { TaskCommentsComponent } from './task-comments.component';
|
||||
import { TaskCommentsService } from './services/task-comments.service';
|
||||
import { ADF_COMMENTS_SERVICE, CoreModule } from '@alfresco/adf-core';
|
||||
|
||||
@NgModule({
|
||||
imports: [
|
||||
CommonModule,
|
||||
CoreModule
|
||||
],
|
||||
declarations: [TaskCommentsComponent],
|
||||
exports: [TaskCommentsComponent],
|
||||
providers: [
|
||||
{
|
||||
provide: ADF_COMMENTS_SERVICE,
|
||||
useClass: TaskCommentsService
|
||||
}
|
||||
]
|
||||
})
|
||||
export class TaskCommentsModule {}
|
@ -82,10 +82,12 @@
|
||||
<adf-info-drawer-tab label="ADF_TASK_LIST.DETAILS.LABELS.INFO_DRAWER_TAB_ACTIVITY_TITLE">
|
||||
<mat-card *ngIf="showComments">
|
||||
<mat-card-content>
|
||||
<adf-comments #activitiComments
|
||||
[readOnly]="isReadOnlyComment()"
|
||||
[taskId]="taskDetails.id">
|
||||
</adf-comments>
|
||||
<adf-task-comments
|
||||
#activitiComments
|
||||
[readOnly]="isReadOnlyComment()"
|
||||
[taskId]="taskDetails.id"
|
||||
>
|
||||
</adf-task-comments>
|
||||
</mat-card-content>
|
||||
</mat-card>
|
||||
</adf-info-drawer-tab>
|
||||
|
@ -40,6 +40,7 @@ import { AttachFormComponent } from './components/attach-form.component';
|
||||
import { FormModule } from '../form/form.module';
|
||||
import { ClaimTaskDirective } from './components/task-form/claim-task.directive';
|
||||
import { UnclaimTaskDirective } from './components/task-form/unclaim-task.directive';
|
||||
import { TaskCommentsModule } from '../task-comments/task-comments.module';
|
||||
|
||||
@NgModule({
|
||||
imports: [
|
||||
@ -52,7 +53,8 @@ import { UnclaimTaskDirective } from './components/task-form/unclaim-task.direct
|
||||
CoreModule,
|
||||
PeopleModule,
|
||||
ProcessCommentsModule,
|
||||
ContentWidgetModule
|
||||
ContentWidgetModule,
|
||||
TaskCommentsModule
|
||||
],
|
||||
declarations: [
|
||||
NoTaskDetailsTemplateDirective,
|
||||
|
@ -23,6 +23,7 @@ export * from './lib/process-comments/index';
|
||||
export * from './lib/people/index';
|
||||
export * from './lib/content-widget/index';
|
||||
export * from './lib/form/index';
|
||||
export * from './lib/task-comments/index';
|
||||
export * from './lib/pipes/process-name.pipe';
|
||||
export * from './lib/pipes/process-services-pipe.module';
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user