[AAE-12179] Remove process-services and content-services dependencies… (#8161)

* [AAE-12179] Remove process-services and content-services dependencies from core comment-list component

* [AAE-12179] Remove comment-list injection token

* [AAE-12179] remove token injection in task module and node module
This commit is contained in:
Diogo Bastos 2023-01-31 15:21:01 +00:00 committed by GitHub
parent 11c3a02acc
commit 0ab39e28fd
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
28 changed files with 304 additions and 262 deletions

View File

@ -0,0 +1,23 @@
---
Title: Content Comment List Service
Added: v6.0.0
Status: Active
Last reviewed: 2023-01-17
---
# [Content Comment List service](../../../lib/content-services/src/lib/node-comments/services/content-comment-list.service.ts "Defined in content-comment-list.service.ts")
Gets user image for comments in Content Services.
## Class members
### Methods
- **getUserImage**(user: `string`): `string`<br/>
Gets user image
- _user:_ `string` - The user id;
- **Returns** `string` - The user image path
## See also
- [Node comments component](../../../lib/content-services/src/lib/node-comments/node-comments.component.ts)

View File

@ -2,10 +2,10 @@
Title: Comment list component Title: Comment list component
Added: v2.0.0 Added: v2.0.0
Status: Active Status: Active
Last reviewed: 2018-11-14 Last reviewed: 2023-01-10
--- ---
# [Comment list component](../../../lib/core/src/lib/comments/comment-list.component.ts "Defined in comment-list.component.ts") # [Comment list component](../../../lib/core/src/lib/comments/comment-list/comment-list.component.ts "Defined in comment-list.component.ts")
Shows a list of comments. Shows a list of comments.

View File

@ -21,10 +21,7 @@ import { NodeCommentsComponent } from './node-comments.component';
import { CoreModule } from '@alfresco/adf-core'; import { CoreModule } from '@alfresco/adf-core';
@NgModule({ @NgModule({
imports: [ imports: [CommonModule, CoreModule],
CommonModule,
CoreModule
],
declarations: [NodeCommentsComponent], declarations: [NodeCommentsComponent],
exports: [NodeCommentsComponent] exports: [NodeCommentsComponent]
}) })

View File

@ -15,7 +15,7 @@
* limitations under the License. * limitations under the License.
*/ */
import { AlfrescoApiService, LogService, CommentModel } from '@alfresco/adf-core'; import { AlfrescoApiService, LogService, CommentModel, CommentsService, PeopleContentService } from '@alfresco/adf-core';
import { CommentEntry, CommentsApi, Comment } from '@alfresco/js-api'; import { CommentEntry, CommentsApi, Comment } from '@alfresco/js-api';
import { Injectable } from '@angular/core'; import { Injectable } from '@angular/core';
import { Observable, from, throwError } from 'rxjs'; import { Observable, from, throwError } from 'rxjs';
@ -24,7 +24,7 @@ import { map, catchError } from 'rxjs/operators';
@Injectable({ @Injectable({
providedIn: 'root' providedIn: 'root'
}) })
export class NodeCommentsService { export class NodeCommentsService implements CommentsService {
private _commentsApi: CommentsApi; private _commentsApi: CommentsApi;
get commentsApi(): CommentsApi { get commentsApi(): CommentsApi {
@ -34,7 +34,8 @@ export class NodeCommentsService {
constructor( constructor(
private apiService: AlfrescoApiService, private apiService: AlfrescoApiService,
private logService: LogService private logService: LogService,
private peopleContentService: PeopleContentService
) {} ) {}
/** /**
@ -99,4 +100,8 @@ export class NodeCommentsService {
this.logService.error(error); this.logService.error(error);
return throwError(error || 'Server error'); return throwError(error || 'Server error');
} }
getUserImage(user: string): string {
return this.peopleContentService.getUserProfileImage(user);
}
} }

View File

@ -17,117 +17,46 @@
import { CUSTOM_ELEMENTS_SCHEMA } from '@angular/core'; import { CUSTOM_ELEMENTS_SCHEMA } from '@angular/core';
import { ComponentFixture, fakeAsync, TestBed } from '@angular/core/testing'; import { ComponentFixture, fakeAsync, TestBed } from '@angular/core/testing';
import { CommentModel, UserProcessModel } from '../models'; import { CommentModel } from '../../models/comment.model';
import { CommentListComponent } from './comment-list.component'; import { CommentListComponent } from './comment-list.component';
import { By } from '@angular/platform-browser'; import { By } from '@angular/platform-browser';
import { EcmUserService } from '../services/ecm-user.service'; import { setupTestBed } from '../../testing/setup-test-bed';
import { PeopleProcessService } from '../services/people-process.service'; import { CoreTestingModule } from '../../testing/core.testing.module';
import { setupTestBed } from '../testing/setup-test-bed';
import { CoreTestingModule } from '../testing/core.testing.module';
import { TranslateModule } from '@ngx-translate/core'; import { TranslateModule } from '@ngx-translate/core';
import {
const testUser = new UserProcessModel({ commentUserNoPictureDefined,
id: '1', commentUserPictureDefined,
firstName: 'Test', mockCommentOne,
lastName: 'User', mockCommentTwo,
email: 'tu@domain.com' testUser
}); } from './mocks/comment-list.mock';
import { CommentListServiceMock } from './mocks/comment-list.service.mock';
const processCommentOne = new CommentModel({ import { ADF_COMMENTS_SERVICE } from '../interfaces/comments.token';
id: 1,
message: 'Test Comment',
created: new Date(),
createdBy: testUser
});
const processCommentTwo = new CommentModel({
id: 2,
message: '2nd Test Comment',
created: new Date(),
createdBy: testUser
});
const contentCommentUserPictureDefined = new CommentModel({
id: 2,
message: '2nd Test Comment',
created: new Date(),
createdBy: {
enabled: true,
firstName: 'some',
lastName: 'one',
email: 'some-one@somegroup.com',
emailNotificationsEnabled: true,
company: {},
id: 'fake-email@dom.com',
avatarId: '001-001-001'
}
});
const processCommentUserPictureDefined = new CommentModel({
id: 2,
message: '2nd Test Comment',
created: new Date(),
createdBy: {
id: '1',
firstName: 'Test',
lastName: 'User',
email: 'tu@domain.com',
pictureId: '001-001-001'
}
});
const contentCommentUserNoPictureDefined = new CommentModel({
id: 2,
message: '2nd Test Comment',
created: new Date(),
createdBy: {
enabled: true,
firstName: 'some',
lastName: 'one',
email: 'some-one@somegroup.com',
emailNotificationsEnabled: true,
company: {},
id: 'fake-email@dom.com'
}
});
const processCommentUserNoPictureDefined = new CommentModel({
id: 2,
message: '2nd Test Comment',
created: new Date(),
createdBy: {
id: '1',
firstName: 'Test',
lastName: 'User',
email: 'tu@domain.com'
}
});
describe('CommentListComponent', () => { describe('CommentListComponent', () => {
let commentList: CommentListComponent; let commentList: CommentListComponent;
let fixture: ComponentFixture<CommentListComponent>; let fixture: ComponentFixture<CommentListComponent>;
let element: HTMLElement; let element: HTMLElement;
let ecmUserService: EcmUserService;
let peopleProcessService: PeopleProcessService;
setupTestBed({ setupTestBed({
imports: [ imports: [
TranslateModule.forRoot(), TranslateModule.forRoot(),
CoreTestingModule CoreTestingModule
], ],
schemas: [CUSTOM_ELEMENTS_SCHEMA] schemas: [CUSTOM_ELEMENTS_SCHEMA],
providers: [
{
provide: ADF_COMMENTS_SERVICE,
useClass: CommentListServiceMock
}
]
}); });
beforeEach(() => { beforeEach(() => {
ecmUserService = TestBed.inject(EcmUserService);
spyOn(ecmUserService, 'getUserProfileImage').and.returnValue('alfresco-logo.svg');
peopleProcessService = TestBed.inject(PeopleProcessService);
spyOn(peopleProcessService, 'getUserImage').and.returnValue('alfresco-logo.svg');
fixture = TestBed.createComponent(CommentListComponent); fixture = TestBed.createComponent(CommentListComponent);
commentList = fixture.componentInstance; commentList = fixture.componentInstance;
element = fixture.nativeElement; element = fixture.nativeElement;
fixture.detectChanges(); fixture.detectChanges();
}); });
@ -137,7 +66,7 @@ describe('CommentListComponent', () => {
}); });
it('should emit row click event', fakeAsync(() => { it('should emit row click event', fakeAsync(() => {
commentList.comments = [Object.assign({}, processCommentOne)]; commentList.comments = [Object.assign({}, mockCommentOne)];
commentList.clickRow.subscribe((selectedComment: CommentModel) => { commentList.clickRow.subscribe((selectedComment: CommentModel) => {
expect(selectedComment.id).toEqual(1); expect(selectedComment.id).toEqual(1);
@ -154,9 +83,9 @@ describe('CommentListComponent', () => {
})); }));
it('should deselect the previous selected comment when a new one is clicked', fakeAsync(() => { it('should deselect the previous selected comment when a new one is clicked', fakeAsync(() => {
processCommentOne.isSelected = true; mockCommentOne.isSelected = true;
const commentOne = Object.assign({}, processCommentOne); const commentOne = Object.assign({}, mockCommentOne);
const commentTwo = Object.assign({}, processCommentTwo); const commentTwo = Object.assign({}, mockCommentTwo);
commentList.selectedComment = commentOne; commentList.selectedComment = commentOne;
commentList.comments = [commentOne, commentTwo]; commentList.comments = [commentOne, commentTwo];
@ -182,31 +111,31 @@ describe('CommentListComponent', () => {
}); });
it('should show comment message when input is given', async () => { it('should show comment message when input is given', async () => {
commentList.comments = [Object.assign({}, processCommentOne)]; commentList.comments = [Object.assign({}, mockCommentOne)];
fixture.detectChanges(); fixture.detectChanges();
await fixture.whenStable(); await fixture.whenStable();
const elements = fixture.nativeElement.querySelectorAll('.adf-comment-message'); const elements = fixture.nativeElement.querySelectorAll('.adf-comment-message');
expect(elements.length).toBe(1); expect(elements.length).toBe(1);
expect(elements[0].innerText).toBe(processCommentOne.message); expect(elements[0].innerText).toBe(mockCommentOne.message);
expect(fixture.nativeElement.querySelector('.adf-comment-message:empty')).toBeNull(); expect(fixture.nativeElement.querySelector('.adf-comment-message:empty')).toBeNull();
}); });
it('should show comment user when input is given', async () => { it('should show comment user when input is given', async () => {
commentList.comments = [Object.assign({}, processCommentOne)]; commentList.comments = [Object.assign({}, mockCommentOne)];
fixture.detectChanges(); fixture.detectChanges();
await fixture.whenStable(); await fixture.whenStable();
const elements = fixture.nativeElement.querySelectorAll('.adf-comment-user-name'); const elements = fixture.nativeElement.querySelectorAll('.adf-comment-user-name');
expect(elements.length).toBe(1); expect(elements.length).toBe(1);
expect(elements[0].innerText).toBe(processCommentOne.createdBy.firstName + ' ' + processCommentOne.createdBy.lastName); expect(elements[0].innerText).toBe(mockCommentOne.createdBy.firstName + ' ' + mockCommentOne.createdBy.lastName);
expect(fixture.nativeElement.querySelector('.adf-comment-user-name:empty')).toBeNull(); expect(fixture.nativeElement.querySelector('.adf-comment-user-name:empty')).toBeNull();
}); });
it('comment date time should start with few seconds ago when comment date is few seconds ago', async () => { it('comment date time should start with few seconds ago when comment date is few seconds ago', async () => {
const commentFewSecond = Object.assign({}, processCommentOne); const commentFewSecond = Object.assign({}, mockCommentOne);
commentFewSecond.created = new Date(); commentFewSecond.created = new Date();
commentList.comments = [commentFewSecond]; commentList.comments = [commentFewSecond];
@ -219,7 +148,7 @@ describe('CommentListComponent', () => {
}); });
it('comment date time should start with Yesterday when comment date is yesterday', async () => { it('comment date time should start with Yesterday when comment date is yesterday', async () => {
const commentOld = Object.assign({}, processCommentOne); const commentOld = Object.assign({}, mockCommentOne);
commentOld.created = new Date((Date.now() - 24 * 3600 * 1000)); commentOld.created = new Date((Date.now() - 24 * 3600 * 1000));
commentList.comments = [commentOld]; commentList.comments = [commentOld];
@ -231,7 +160,7 @@ describe('CommentListComponent', () => {
}); });
it('comment date time should not start with Today/Yesterday when comment date is before yesterday', async () => { it('comment date time should not start with Today/Yesterday when comment date is before yesterday', async () => {
const commentOld = Object.assign({}, processCommentOne); const commentOld = Object.assign({}, mockCommentOne);
commentOld.created = new Date((Date.now() - 24 * 3600 * 1000 * 2)); commentOld.created = new Date((Date.now() - 24 * 3600 * 1000 * 2));
commentList.comments = [commentOld]; commentList.comments = [commentOld];
@ -244,51 +173,29 @@ describe('CommentListComponent', () => {
}); });
it('should show user icon when input is given', async () => { it('should show user icon when input is given', async () => {
commentList.comments = [Object.assign({}, processCommentOne)]; commentList.comments = [Object.assign({}, mockCommentOne)];
fixture.detectChanges(); fixture.detectChanges();
await fixture.whenStable(); await fixture.whenStable();
const elements = fixture.nativeElement.querySelectorAll('.adf-comment-img-container'); const elements = fixture.nativeElement.querySelectorAll('.adf-comment-img-container');
expect(elements.length).toBe(1); expect(elements.length).toBe(1);
expect(elements[0].innerText).toContain(commentList.getUserShortName(processCommentOne.createdBy)); expect(elements[0].innerText).toContain(commentList.getUserShortName(mockCommentOne.createdBy));
expect(fixture.nativeElement.querySelector('.adf-comment-img-container:empty')).toBeNull(); expect(fixture.nativeElement.querySelector('.adf-comment-img-container:empty')).toBeNull();
}); });
it('should return content picture when is a content user with a picture', async () => { it('should return picture when is a user with a picture', async () => {
commentList.comments = [contentCommentUserPictureDefined]; commentList.comments = [commentUserPictureDefined];
fixture.detectChanges(); fixture.detectChanges();
await fixture.whenStable(); await fixture.whenStable();
const elements = fixture.nativeElement.querySelectorAll('.adf-people-img'); const elements = fixture.nativeElement.querySelectorAll('.adf-people-img');
expect(elements.length).toBe(1); expect(elements.length).toBe(1);
expect(fixture.nativeElement.getElementsByClassName('adf-people-img')[0].src).toContain('alfresco-logo.svg');
}); });
it('should return process picture when is a process user with a picture', async () => { it('should return short name when is a user without a picture', async () => {
commentList.comments = [processCommentUserPictureDefined]; commentList.comments = [commentUserNoPictureDefined];
fixture.detectChanges();
await fixture.whenStable();
const elements = fixture.nativeElement.querySelectorAll('.adf-people-img');
expect(elements.length).toBe(1);
expect(fixture.nativeElement.getElementsByClassName('adf-people-img')[0].src).toContain('alfresco-logo.svg');
});
it('should return content short name when is a content user without a picture', async () => {
commentList.comments = [contentCommentUserNoPictureDefined];
fixture.detectChanges();
await fixture.whenStable();
const elements = fixture.nativeElement.querySelectorAll('.adf-comment-user-icon');
expect(elements.length).toBe(1);
});
it('should return process short name when is a process user without a picture', async () => {
commentList.comments = [processCommentUserNoPictureDefined];
fixture.detectChanges(); fixture.detectChanges();
await fixture.whenStable(); await fixture.whenStable();

View File

@ -16,11 +16,11 @@
*/ */
import { Meta, moduleMetadata, Story } from '@storybook/angular'; import { Meta, moduleMetadata, Story } from '@storybook/angular';
import { CoreStoryModule } from '../testing/core.story.module'; import { CoreStoryModule } from '../../testing/core.story.module';
import { CommentListComponent } from './comment-list.component'; import { CommentListComponent } from './comment-list.component';
import { CommentsModule } from './comments.module'; import { CommentsModule } from '../comments.module';
import { commentsTaskData, commentsNodeData } from './mocks/comments.stories.mock'; import { commentsTaskData, commentsNodeData } from '../mocks/comments.stories.mock';
import { EcmUserService } from '../services'; import { EcmUserService } from '../../services';
export default { export default {
component: CommentListComponent, component: CommentListComponent,

View File

@ -15,13 +15,13 @@
* limitations under the License. * limitations under the License.
*/ */
import { Component, EventEmitter, Input, Output, ViewEncapsulation, OnInit, OnDestroy } from '@angular/core'; import { Component, EventEmitter, Input, Output, ViewEncapsulation, OnInit, OnDestroy, Inject } from '@angular/core';
import { CommentModel } from '../models/comment.model'; import { CommentModel } from '../../models/comment.model';
import { EcmUserService } from '../services/ecm-user.service'; import { UserPreferencesService, UserPreferenceValues } from '../../common/services/user-preferences.service';
import { PeopleProcessService } from '../services/people-process.service';
import { UserPreferencesService, UserPreferenceValues } from '../common/services/user-preferences.service';
import { Subject } from 'rxjs'; import { Subject } from 'rxjs';
import { takeUntil } from 'rxjs/operators'; import { takeUntil } from 'rxjs/operators';
import { CommentsService } from '../interfaces/comments-service.interface';
import { ADF_COMMENTS_SERVICE } from '../interfaces/comments.token';
@Component({ @Component({
selector: 'adf-comment-list', selector: 'adf-comment-list',
@ -44,9 +44,10 @@ export class CommentListComponent implements OnInit, OnDestroy {
currentLocale; currentLocale;
private onDestroy$ = new Subject<boolean>(); private onDestroy$ = new Subject<boolean>();
constructor(public peopleProcessService: PeopleProcessService, constructor(
public ecmUserService: EcmUserService, @Inject(ADF_COMMENTS_SERVICE) private commentsService: Partial<CommentsService>,
public userPreferenceService: UserPreferencesService) { public userPreferenceService: UserPreferencesService
) {
} }
ngOnInit() { ngOnInit() {
@ -88,14 +89,6 @@ export class CommentListComponent implements OnInit, OnDestroy {
} }
getUserImage(user: any): string { getUserImage(user: any): string {
if (this.isAContentUsers(user)) { return this.commentsService.getUserImage(user);
return this.ecmUserService.getUserProfileImage(user.avatarId);
} else {
return this.peopleProcessService.getUserImage(user);
}
}
private isAContentUsers(user: any): boolean {
return user.avatarId;
} }
} }

View File

@ -0,0 +1,51 @@
/*!
* @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 { CommonModule } from '@angular/common';
import { NgModule } from '@angular/core';
import { TranslateModule } from '@ngx-translate/core';
import { MatButtonModule } from '@angular/material/button';
import { MatFormFieldModule } from '@angular/material/form-field';
import { MatInputModule } from '@angular/material/input';
import { MatListModule } from '@angular/material/list';
import { MatLineModule } from '@angular/material/core';
import { FormsModule } from '@angular/forms';
import { PipeModule } from '../../pipes/pipe.module';
import { CommentListComponent } from './comment-list.component';
@NgModule({
imports: [
PipeModule,
FormsModule,
CommonModule,
TranslateModule,
MatButtonModule,
MatFormFieldModule,
MatInputModule,
MatListModule,
MatLineModule
],
declarations: [
CommentListComponent
],
exports: [
CommentListComponent
]
})
export class CommentListModule {
}

View 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';

View File

@ -0,0 +1,71 @@
/*!
* @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 } from '../../../models/comment.model';
import { UserProcessModel } from '../../../models/user-process.model';
export const testUser = new UserProcessModel({
id: '1',
firstName: 'Test',
lastName: 'User',
email: 'tu@domain.com'
});
export const mockCommentOne = new CommentModel({
id: 1,
message: 'Test Comment',
created: new Date(),
createdBy: testUser
});
export const mockCommentTwo = new CommentModel({
id: 2,
message: '2nd Test Comment',
created: new Date(),
createdBy: testUser
});
export const commentUserPictureDefined = new CommentModel({
id: 2,
message: '2nd Test Comment',
created: new Date(),
createdBy: {
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 commentUserNoPictureDefined = new CommentModel({
id: 2,
message: '2nd Test Comment',
created: new Date(),
createdBy: {
enabled: true,
firstName: 'some',
lastName: 'one',
email: 'some-one@somegroup.com',
emailNotificationsEnabled: true,
company: {},
id: 'fake-email@dom.com'
}
});

View File

@ -15,12 +15,13 @@
* limitations under the License. * limitations under the License.
*/ */
import { Observable } from 'rxjs'; import { CommentsService } from '../../interfaces/comments-service.interface';
import { CommentModel } from '@alfresco/adf-core';
export interface CommentProcessServiceInterface { export class CommentListServiceMock implements Partial<CommentsService> {
addTaskComment(taskId: string, message: string): Observable<CommentModel>;
getTaskComments(taskId: string): Observable<CommentModel[]>; constructor() {}
getProcessInstanceComments(processInstanceId: string): Observable<CommentModel[]>;
addProcessInstanceComment(processInstanceId: string, message: string): Observable<CommentModel>; getUserImage(_user: any): string {
return 'mock-user-image-path';
}
} }

View 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.
*/
export * from './comment-list.component';
export * from './comment-list.module';

View File

@ -25,8 +25,8 @@ import { MatListModule } from '@angular/material/list';
import { MatLineModule } from '@angular/material/core'; import { MatLineModule } from '@angular/material/core';
import { FormsModule } from '@angular/forms'; import { FormsModule } from '@angular/forms';
import { PipeModule } from '../pipes/pipe.module'; import { PipeModule } from '../pipes/pipe.module';
import { CommentListModule } from './comment-list/comment-list.module';
import { CommentListComponent } from './comment-list.component';
import { CommentsComponent } from './comments.component'; import { CommentsComponent } from './comments.component';
@NgModule({ @NgModule({
@ -39,14 +39,13 @@ import { CommentsComponent } from './comments.component';
MatFormFieldModule, MatFormFieldModule,
MatInputModule, MatInputModule,
MatListModule, MatListModule,
MatLineModule MatLineModule,
CommentListModule
], ],
declarations: [ declarations: [
CommentListComponent,
CommentsComponent CommentsComponent
], ],
exports: [ exports: [
CommentListComponent,
CommentsComponent CommentsComponent
] ]
}) })

View File

@ -21,4 +21,5 @@ import { CommentModel } from '../../models/comment.model';
export interface CommentsService { export interface CommentsService {
get(id: string): Observable<CommentModel[]>; get(id: string): Observable<CommentModel[]>;
add(id: string, message: string): Observable<CommentModel>; add(id: string, message: string): Observable<CommentModel>;
getUserImage(user: any): string;
} }

View File

@ -19,7 +19,7 @@ import { CommentModel, EcmUserModel } from '../../models';
import { Observable, of } from 'rxjs'; import { Observable, of } from 'rxjs';
import { CommentsService } from '../interfaces'; import { CommentsService } from '../interfaces';
export class CommentsServiceMock implements CommentsService { export class CommentsServiceMock implements Partial<CommentsService> {
constructor() {} constructor() {}

View File

@ -20,7 +20,7 @@ import { Observable, of } from 'rxjs';
import { CommentsService } from '../interfaces'; import { CommentsService } from '../interfaces';
import { testUser } from './comments.stories.mock'; import { testUser } from './comments.stories.mock';
export class CommentsServiceStoriesMock implements CommentsService { export class CommentsServiceStoriesMock implements Partial<CommentsService> {
constructor() {} constructor() {}

View File

@ -15,9 +15,10 @@
* limitations under the License. * limitations under the License.
*/ */
export * from './comment-list.component';
export * from './comments.component'; export * from './comments.component';
export * from './interfaces/index'; export * from './interfaces/index';
export * from './comments.module'; export * from './comments.module';
export * from './comment-list/index';

View File

@ -36,6 +36,7 @@ import { ViewerModule } from './viewer/viewer.module';
import { FormBaseModule } from './form/form-base.module'; import { FormBaseModule } from './form/form-base.module';
import { SidenavLayoutModule } from './layout/layout.module'; import { SidenavLayoutModule } from './layout/layout.module';
import { CommentsModule } from './comments/comments.module'; import { CommentsModule } from './comments/comments.module';
import { CommentListModule } from './comments/comment-list/comment-list.module';
import { ButtonsMenuModule } from './buttons-menu/buttons-menu.module'; import { ButtonsMenuModule } from './buttons-menu/buttons-menu.module';
import { TemplateModule } from './templates/template.module'; import { TemplateModule } from './templates/template.module';
import { ClipboardModule } from './clipboard/clipboard.module'; import { ClipboardModule } from './clipboard/clipboard.module';
@ -85,6 +86,7 @@ import { MAT_SNACK_BAR_DEFAULT_OPTIONS } from '@angular/material/snack-bar';
CardViewModule, CardViewModule,
FormBaseModule, FormBaseModule,
CommentsModule, CommentsModule,
CommentListModule,
LoginModule, LoginModule,
LanguageMenuModule, LanguageMenuModule,
InfoDrawerModule, InfoDrawerModule,
@ -124,6 +126,7 @@ import { MAT_SNACK_BAR_DEFAULT_OPTIONS } from '@angular/material/snack-bar';
CardViewModule, CardViewModule,
FormBaseModule, FormBaseModule,
CommentsModule, CommentsModule,
CommentListModule,
LoginModule, LoginModule,
LanguageMenuModule, LanguageMenuModule,
InfoDrawerModule, InfoDrawerModule,

View File

@ -18,32 +18,14 @@
import { Injectable } from '@angular/core'; import { Injectable } from '@angular/core';
import { Observable, from, of } from 'rxjs'; import { Observable, from, of } from 'rxjs';
import { map } from 'rxjs/operators'; import { map } from 'rxjs/operators';
import { CommentModel, UserProcessModel } from '@alfresco/adf-core'; import { CommentModel, UserProcessModel, CommentsService } from '@alfresco/adf-core';
import { CommentProcessServiceInterface } from '../interfaces/comment-process.service.interface'; import { fakeUser1 } from '../mock/comment-process.mock';
import { testUser, fakeUser1 } from '../mock/comment-process.mock';
@Injectable() @Injectable()
export class CommentProcessServiceMock implements CommentProcessServiceInterface { export class CommentProcessServiceMock implements Partial<CommentsService> {
private comments: CommentModel [] = []; private comments: CommentModel [] = [];
addTaskComment(taskId: string, message: string): Observable<CommentModel> { get(_id: string): Observable<CommentModel[]> {
const comment = new CommentModel({
id: taskId,
message: message,
created: new Date(),
createdBy: testUser,
isSelected: false
});
this.comments.push(comment);
return of(comment);
}
getTaskComments(_taskId: string): Observable<CommentModel[]> {
return of(this.comments);
}
getProcessInstanceComments(_processInstanceId: string): Observable<CommentModel[]> {
const user = new UserProcessModel(fakeUser1); const user = new UserProcessModel(fakeUser1);
this.comments.push(new CommentModel({ this.comments.push(new CommentModel({
@ -56,7 +38,7 @@ export class CommentProcessServiceMock implements CommentProcessServiceInterface
return of(this.comments); return of(this.comments);
} }
addProcessInstanceComment(_processInstanceId: string, _message: string): Observable<CommentModel> { add(_id: string, _message: string): Observable<CommentModel> {
return from(this.comments).pipe( return from(this.comments).pipe(
map((response) => new CommentModel({ map((response) => new CommentModel({
id: response.id, id: response.id,

View File

@ -47,7 +47,7 @@ describe('ProcessCommentsComponent', () => {
component = fixture.componentInstance; component = fixture.componentInstance;
commentProcessService = TestBed.inject(CommentProcessService); commentProcessService = TestBed.inject(CommentProcessService);
getCommentsSpy = spyOn(commentProcessService, 'getProcessInstanceComments').and.returnValue(of(mockProcessInstanceComments)); getCommentsSpy = spyOn(commentProcessService, 'get').and.returnValue(of(mockProcessInstanceComments));
}); });
it('should load comments when processInstanceId specified', () => { it('should load comments when processInstanceId specified', () => {

View File

@ -76,7 +76,7 @@ export class ProcessCommentsComponent implements OnChanges, OnDestroy {
add(): void { add(): void {
if (this.message && this.message.trim() && !this.beingAdded) { if (this.message && this.message.trim() && !this.beingAdded) {
this.beingAdded = true; this.beingAdded = true;
this.commentProcessService.addProcessInstanceComment(this.processInstanceId, this.message) this.commentProcessService.add(this.processInstanceId, this.message)
.subscribe( .subscribe(
(res: CommentModel) => { (res: CommentModel) => {
this.comments.unshift(res); this.comments.unshift(res);
@ -107,7 +107,7 @@ export class ProcessCommentsComponent implements OnChanges, OnDestroy {
private getProcessInstanceComments(processInstanceId: string): void { private getProcessInstanceComments(processInstanceId: string): void {
this.resetComments(); this.resetComments();
if (processInstanceId) { if (processInstanceId) {
this.commentProcessService.getProcessInstanceComments(processInstanceId).subscribe( this.commentProcessService.get(processInstanceId).subscribe(
(res: CommentModel[]) => { (res: CommentModel[]) => {
res = res.sort((comment1: CommentModel, comment2: CommentModel) => { res = res.sort((comment1: CommentModel, comment2: CommentModel) => {
const date1 = new Date(comment1.created); const date1 = new Date(comment1.created);

View File

@ -19,9 +19,10 @@ import { CommonModule } from '@angular/common';
import { NgModule } from '@angular/core'; import { NgModule } from '@angular/core';
import { MaterialModule } from '../material.module'; import { MaterialModule } from '../material.module';
import { FormsModule, ReactiveFormsModule } from '@angular/forms'; import { FormsModule, ReactiveFormsModule } from '@angular/forms';
import { CoreModule } from '@alfresco/adf-core'; import { ADF_COMMENTS_SERVICE, CoreModule } from '@alfresco/adf-core';
import { ProcessCommentsComponent } from './process-comments.component'; import { ProcessCommentsComponent } from './process-comments.component';
import { CommentProcessService } from './services/comment-process.service';
@NgModule({ @NgModule({
imports: [ imports: [
@ -36,6 +37,12 @@ import { ProcessCommentsComponent } from './process-comments.component';
], ],
exports: [ exports: [
ProcessCommentsComponent ProcessCommentsComponent
],
providers: [
{
provide: ADF_COMMENTS_SERVICE,
useClass: CommentProcessService
}
] ]
}) })
export class ProcessCommentsModule { export class ProcessCommentsModule {

View File

@ -17,15 +17,14 @@
import { Injectable } from '@angular/core'; import { Injectable } from '@angular/core';
import { Observable, from, throwError } from 'rxjs'; import { Observable, from, throwError } from 'rxjs';
import { CommentModel, UserProcessModel, AlfrescoApiService, LogService } from '@alfresco/adf-core'; import { CommentModel, UserProcessModel, AlfrescoApiService, LogService, CommentsService, PeopleProcessService } from '@alfresco/adf-core';
import { map, catchError } from 'rxjs/operators'; import { map, catchError } from 'rxjs/operators';
import { ActivitiCommentsApi } from '@alfresco/js-api'; import { ActivitiCommentsApi } from '@alfresco/js-api';
import { CommentProcessServiceInterface } from '../interfaces/comment-process.service.interface';
@Injectable({ @Injectable({
providedIn: 'root' providedIn: 'root'
}) })
export class CommentProcessService implements CommentProcessServiceInterface { export class CommentProcessService implements CommentsService {
private _commentsApi: ActivitiCommentsApi; private _commentsApi: ActivitiCommentsApi;
get commentsApi(): ActivitiCommentsApi { get commentsApi(): ActivitiCommentsApi {
@ -34,53 +33,9 @@ export class CommentProcessService implements CommentProcessServiceInterface {
} }
constructor(private apiService: AlfrescoApiService, constructor(private apiService: AlfrescoApiService,
private logService: LogService) { private logService: LogService,
} private peopleProcessService: PeopleProcessService
) {
/**
* Adds a comment to a task.
*
* @param taskId ID of the target task
* @param message Text for the comment
* @returns Details about the comment
*/
addTaskComment(taskId: string, message: string): Observable<CommentModel> {
return from(this.commentsApi.addTaskComment({ message }, taskId))
.pipe(
map((response) => new CommentModel({
id: response.id,
message: response.message,
created: response.created,
createdBy: response.createdBy
})),
catchError((err: any) => this.handleError(err))
);
}
/**
* Gets all comments that have been added to a task.
*
* @param taskId ID of the target task
* @returns Details for each comment
*/
getTaskComments(taskId: string): Observable<CommentModel[]> {
return from(this.commentsApi.getTaskComments(taskId))
.pipe(
map((response) => {
const comments: CommentModel[] = [];
response.data.forEach((comment) => {
const user = new UserProcessModel(comment.createdBy);
comments.push(new CommentModel({
id: comment.id,
message: comment.message,
created: comment.created,
createdBy: user
}));
});
return comments;
}),
catchError((err: any) => this.handleError(err))
);
} }
/** /**
@ -89,8 +44,8 @@ export class CommentProcessService implements CommentProcessServiceInterface {
* @param processInstanceId ID of the target process instance * @param processInstanceId ID of the target process instance
* @returns Details for each comment * @returns Details for each comment
*/ */
getProcessInstanceComments(processInstanceId: string): Observable<CommentModel[]> { get(id: string): Observable<CommentModel[]> {
return from(this.commentsApi.getProcessInstanceComments(processInstanceId)) return from(this.commentsApi.getProcessInstanceComments(id))
.pipe( .pipe(
map((response) => { map((response) => {
const comments: CommentModel[] = []; const comments: CommentModel[] = [];
@ -116,9 +71,9 @@ export class CommentProcessService implements CommentProcessServiceInterface {
* @param message Text for the comment * @param message Text for the comment
* @returns Details of the comment added * @returns Details of the comment added
*/ */
addProcessInstanceComment(processInstanceId: string, message: string): Observable<CommentModel> { add(id: string, message: string): Observable<CommentModel> {
return from( return from(
this.commentsApi.addProcessInstanceComment({ message }, processInstanceId) this.commentsApi.addProcessInstanceComment({ message }, id)
).pipe( ).pipe(
map((response) => new CommentModel({ map((response) => new CommentModel({
id: response.id, id: response.id,
@ -135,4 +90,7 @@ export class CommentProcessService implements CommentProcessServiceInterface {
return throwError(error || 'Server error'); return throwError(error || 'Server error');
} }
getUserImage(user: any): string {
return this.peopleProcessService.getUserImage(user);
}
} }

View File

@ -57,7 +57,7 @@ describe('ProcessInstanceDetailsComponent', () => {
const commentService = fixture.debugElement.injector.get(CommentProcessService); const commentService = fixture.debugElement.injector.get(CommentProcessService);
getProcessSpy = spyOn(service, 'getProcess').and.returnValue(of(exampleProcess)); getProcessSpy = spyOn(service, 'getProcess').and.returnValue(of(exampleProcess));
spyOn(commentService, 'getProcessInstanceComments').and.returnValue(of(mockProcessInstanceComments)); spyOn(commentService, 'get').and.returnValue(of(mockProcessInstanceComments));
}); });
afterEach(() => { afterEach(() => {

View File

@ -15,7 +15,7 @@
* limitations under the License. * limitations under the License.
*/ */
import { AlfrescoApiService, CommentModel, CommentsService, UserProcessModel } from '@alfresco/adf-core'; import { AlfrescoApiService, CommentModel, CommentsService, PeopleProcessService, UserProcessModel } from '@alfresco/adf-core';
import { ActivitiCommentsApi, CommentRepresentation } from '@alfresco/js-api'; import { ActivitiCommentsApi, CommentRepresentation } from '@alfresco/js-api';
import { Injectable } from '@angular/core'; import { Injectable } from '@angular/core';
import { from, Observable, throwError } from 'rxjs'; import { from, Observable, throwError } from 'rxjs';
@ -33,7 +33,8 @@ export class TaskCommentsService implements CommentsService {
} }
constructor( constructor(
private apiService: AlfrescoApiService private apiService: AlfrescoApiService,
private peopleProcessService: PeopleProcessService
) {} ) {}
/** /**
@ -104,4 +105,8 @@ export class TaskCommentsService implements CommentsService {
private handleError(error: any) { private handleError(error: any) {
return throwError(error || 'Server error'); return throwError(error || 'Server error');
} }
getUserImage(user: UserProcessModel): string {
return this.peopleProcessService.getUserImage(user);
}
} }

View File

@ -30,7 +30,6 @@ import {
PeopleProcessService, PeopleProcessService,
CommentModel CommentModel
} from '@alfresco/adf-core'; } from '@alfresco/adf-core';
import { CommentProcessService } from '../../process-comments/services/comment-process.service';
import { TaskDetailsModel } from '../models/task-details.model'; import { TaskDetailsModel } from '../models/task-details.model';
import { import {
noDataMock, noDataMock,
@ -45,6 +44,7 @@ import { ProcessTestingModule } from '../../testing/process.testing.module';
import { TranslateModule } from '@ngx-translate/core'; import { TranslateModule } from '@ngx-translate/core';
import { TaskService } from '../../form/services/task.service'; import { TaskService } from '../../form/services/task.service';
import { TaskFormService } from '../../form/services/task-form.service'; import { TaskFormService } from '../../form/services/task-form.service';
import { TaskCommentsService } from '../../task-comments/services/task-comments.service';
const fakeUser = new UserProcessModel({ const fakeUser = new UserProcessModel({
id: 'fake-id', id: 'fake-id',
@ -71,7 +71,7 @@ describe('TaskDetailsComponent', () => {
let getTasksSpy: jasmine.Spy; let getTasksSpy: jasmine.Spy;
let assignTaskSpy: jasmine.Spy; let assignTaskSpy: jasmine.Spy;
let logService: LogService; let logService: LogService;
let commentProcessService: CommentProcessService; let taskCommentsService: TaskCommentsService;
let peopleProcessService: PeopleProcessService; let peopleProcessService: PeopleProcessService;
let bpmUserService: BpmUserService; let bpmUserService: BpmUserService;
@ -102,9 +102,9 @@ describe('TaskDetailsComponent', () => {
getTasksSpy = spyOn(taskListService, 'getTasks').and.returnValue(of(tasksMock)); getTasksSpy = spyOn(taskListService, 'getTasks').and.returnValue(of(tasksMock));
assignTaskSpy = spyOn(taskListService, 'assignTask').and.returnValue(of(fakeTaskAssignResponse)); assignTaskSpy = spyOn(taskListService, 'assignTask').and.returnValue(of(fakeTaskAssignResponse));
commentProcessService = TestBed.inject(CommentProcessService); taskCommentsService = TestBed.inject(TaskCommentsService);
spyOn(commentProcessService, 'getTaskComments').and.returnValue(of([ spyOn(taskCommentsService, 'get').and.returnValue(of([
new CommentModel({ message: 'Test1', created: Date.now(), createdBy: { firstName: 'Admin', lastName: 'User' } }), 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: 'Test2', created: Date.now(), createdBy: { firstName: 'Admin', lastName: 'User' } }),
new CommentModel({ message: 'Test3', created: Date.now(), createdBy: { firstName: 'Admin', lastName: 'User' } }) new CommentModel({ message: 'Test3', created: Date.now(), createdBy: { firstName: 'Admin', lastName: 'User' } })