2023-01-15 13:14:48 +02:00
|
|
|
///
|
2024-01-09 10:46:16 +02:00
|
|
|
/// Copyright © 2016-2024 The Thingsboard Authors
|
2023-01-15 13:14:48 +02:00
|
|
|
///
|
|
|
|
|
/// Licensed under the Apache License, Version 2.0 (the "License");
|
|
|
|
|
/// you may not use this file except in compliance with the License.
|
|
|
|
|
/// You may obtain a copy of the License at
|
|
|
|
|
///
|
|
|
|
|
/// http://www.apache.org/licenses/LICENSE-2.0
|
|
|
|
|
///
|
|
|
|
|
/// Unless required by applicable law or agreed to in writing, software
|
|
|
|
|
/// distributed under the License is distributed on an "AS IS" BASIS,
|
|
|
|
|
/// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
|
|
|
/// See the License for the specific language governing permissions and
|
|
|
|
|
/// limitations under the License.
|
|
|
|
|
///
|
|
|
|
|
|
|
|
|
|
import { Component, Input, OnInit } from '@angular/core';
|
|
|
|
|
import { select, Store } from '@ngrx/store';
|
|
|
|
|
import { AppState } from '@core/core.state';
|
|
|
|
|
import { TranslateService } from '@ngx-translate/core';
|
|
|
|
|
import { AlarmCommentService } from '@core/http/alarm-comment.service';
|
|
|
|
|
import { AbstractControl, FormBuilder, FormGroup } from '@angular/forms';
|
|
|
|
|
import { DialogService } from '@core/services/dialog.service';
|
|
|
|
|
import { AuthUser, User } from '@shared/models/user.model';
|
|
|
|
|
import { getCurrentAuthUser, selectUserDetails } from '@core/auth/auth.selectors';
|
|
|
|
|
import { Direction, SortOrder } from '@shared/models/page/sort-order';
|
|
|
|
|
import { MAX_SAFE_PAGE_SIZE, PageLink } from '@shared/models/page/page-link';
|
|
|
|
|
import { DateAgoPipe } from '@shared/pipe/date-ago.pipe';
|
|
|
|
|
import { map } from 'rxjs/operators';
|
|
|
|
|
import { AlarmComment, AlarmCommentInfo, AlarmCommentType } from '@shared/models/alarm.models';
|
|
|
|
|
import { UtilsService } from '@core/services/utils.service';
|
|
|
|
|
import { EntityType } from '@shared/models/entity-type.models';
|
2023-03-31 15:35:25 +03:00
|
|
|
import { DatePipe } from '@angular/common';
|
2023-11-28 11:30:46 +02:00
|
|
|
import { ImportExportService } from '@shared/import-export/import-export.service';
|
2023-01-15 13:14:48 +02:00
|
|
|
|
|
|
|
|
interface AlarmCommentsDisplayData {
|
|
|
|
|
commentId?: string,
|
|
|
|
|
displayName?: string,
|
2023-03-31 15:35:25 +03:00
|
|
|
createdTime: string,
|
2023-01-15 13:14:48 +02:00
|
|
|
createdDateAgo?: string,
|
|
|
|
|
edit?: boolean,
|
|
|
|
|
isEdited?: boolean,
|
2023-03-31 15:35:25 +03:00
|
|
|
editedTime?: string;
|
2023-01-15 13:14:48 +02:00
|
|
|
editedDateAgo?: string,
|
|
|
|
|
showActions?: boolean,
|
|
|
|
|
commentText?: string,
|
|
|
|
|
isSystemComment?: boolean,
|
|
|
|
|
avatarBgColor?: string
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@Component({
|
|
|
|
|
selector: 'tb-alarm-comment',
|
|
|
|
|
templateUrl: './alarm-comment.component.html',
|
|
|
|
|
styleUrls: ['./alarm-comment.component.scss']
|
|
|
|
|
})
|
|
|
|
|
export class AlarmCommentComponent implements OnInit {
|
|
|
|
|
@Input()
|
|
|
|
|
alarmId: string;
|
|
|
|
|
|
|
|
|
|
@Input()
|
2023-03-29 12:15:46 +03:00
|
|
|
alarmActivityOnly: boolean = false;
|
2023-01-15 13:14:48 +02:00
|
|
|
|
|
|
|
|
authUser: AuthUser;
|
|
|
|
|
|
|
|
|
|
alarmCommentFormGroup: FormGroup;
|
|
|
|
|
|
|
|
|
|
alarmComments: Array<AlarmComment>;
|
|
|
|
|
|
|
|
|
|
displayData: Array<AlarmCommentsDisplayData> = new Array<AlarmCommentsDisplayData>();
|
|
|
|
|
|
|
|
|
|
alarmCommentSortOrder: SortOrder = {
|
|
|
|
|
property: 'createdTime',
|
2023-02-10 16:17:12 +02:00
|
|
|
direction: Direction.DESC
|
2023-01-15 13:14:48 +02:00
|
|
|
};
|
|
|
|
|
|
|
|
|
|
editMode: boolean = false;
|
|
|
|
|
|
|
|
|
|
userDisplayName$ = this.store.pipe(
|
|
|
|
|
select(selectUserDetails),
|
|
|
|
|
map((user) => this.getUserDisplayName(user))
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
currentUserDisplayName: string;
|
|
|
|
|
currentUserAvatarColor: string;
|
|
|
|
|
|
|
|
|
|
constructor(protected store: Store<AppState>,
|
|
|
|
|
private translate: TranslateService,
|
|
|
|
|
private alarmCommentService: AlarmCommentService,
|
|
|
|
|
public fb: FormBuilder,
|
|
|
|
|
private dialogService: DialogService,
|
|
|
|
|
public dateAgoPipe: DateAgoPipe,
|
2023-03-31 15:35:25 +03:00
|
|
|
private utilsService: UtilsService,
|
|
|
|
|
private datePipe: DatePipe,
|
|
|
|
|
private importExportService: ImportExportService) {
|
2023-01-15 13:14:48 +02:00
|
|
|
|
|
|
|
|
this.authUser = getCurrentAuthUser(store);
|
|
|
|
|
|
|
|
|
|
this.alarmCommentFormGroup = this.fb.group(
|
|
|
|
|
{
|
|
|
|
|
alarmCommentEdit: [''],
|
|
|
|
|
alarmComment: ['']
|
|
|
|
|
}
|
|
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
ngOnInit() {
|
|
|
|
|
this.loadAlarmComments();
|
|
|
|
|
this.currentUserAvatarColor = this.utilsService.stringToHslColor(this.currentUserDisplayName,
|
|
|
|
|
60, 40);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
loadAlarmComments(): void {
|
|
|
|
|
this.alarmCommentService.getAlarmComments(this.alarmId, new PageLink(MAX_SAFE_PAGE_SIZE, 0, null,
|
2023-02-28 15:04:03 +02:00
|
|
|
this.alarmCommentSortOrder), {ignoreLoading: true}).subscribe(
|
2023-01-15 13:14:48 +02:00
|
|
|
(pagedData) => {
|
|
|
|
|
this.alarmComments = pagedData.data;
|
|
|
|
|
this.displayData.length = 0;
|
|
|
|
|
for (let alarmComment of pagedData.data) {
|
2023-03-29 12:15:46 +03:00
|
|
|
let displayDataElement = {} as AlarmCommentsDisplayData;
|
2023-03-31 15:35:25 +03:00
|
|
|
displayDataElement.createdTime = this.datePipe.transform(alarmComment.createdTime, 'yyyy-MM-dd HH:mm:ss');
|
2023-01-15 13:14:48 +02:00
|
|
|
displayDataElement.createdDateAgo = this.dateAgoPipe.transform(alarmComment.createdTime);
|
|
|
|
|
displayDataElement.commentText = alarmComment.comment.text;
|
|
|
|
|
displayDataElement.isSystemComment = alarmComment.type === AlarmCommentType.SYSTEM;
|
|
|
|
|
if (alarmComment.type === AlarmCommentType.OTHER) {
|
|
|
|
|
displayDataElement.commentId = alarmComment.id.id;
|
|
|
|
|
displayDataElement.displayName = this.getUserDisplayName(alarmComment);
|
|
|
|
|
displayDataElement.edit = false;
|
|
|
|
|
displayDataElement.isEdited = alarmComment.comment.edited;
|
2023-03-31 15:35:25 +03:00
|
|
|
displayDataElement.editedTime = this.datePipe.transform(alarmComment.comment.editedOn, 'yyyy-MM-dd HH:mm:ss');
|
2023-03-30 12:07:14 +03:00
|
|
|
displayDataElement.editedDateAgo = this.dateAgoPipe.transform(alarmComment.comment.editedOn) + '\n';
|
2023-01-15 13:14:48 +02:00
|
|
|
displayDataElement.showActions = false;
|
|
|
|
|
displayDataElement.isSystemComment = false;
|
|
|
|
|
displayDataElement.avatarBgColor = this.utilsService.stringToHslColor(displayDataElement.displayName,
|
|
|
|
|
40, 60);
|
|
|
|
|
}
|
|
|
|
|
this.displayData.push(displayDataElement);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
)
|
|
|
|
|
}
|
|
|
|
|
|
2023-02-10 16:17:12 +02:00
|
|
|
changeSortDirection() {
|
|
|
|
|
let currentDirection = this.alarmCommentSortOrder.direction;
|
|
|
|
|
this.alarmCommentSortOrder.direction = currentDirection === Direction.DESC ? Direction.ASC : Direction.DESC;
|
|
|
|
|
this.loadAlarmComments();
|
|
|
|
|
}
|
|
|
|
|
|
2023-03-31 15:35:25 +03:00
|
|
|
exportAlarmActivity() {
|
|
|
|
|
let fileName = this.translate.instant('alarm.alarm') + '_' + this.translate.instant('alarm-activity.activity');
|
|
|
|
|
this.importExportService.exportCsv(this.getDataForExport(), fileName.toLowerCase());
|
|
|
|
|
}
|
|
|
|
|
|
2023-01-15 13:14:48 +02:00
|
|
|
saveComment(): void {
|
|
|
|
|
const commentInputValue: string = this.getAlarmCommentFormControl().value;
|
|
|
|
|
if (commentInputValue) {
|
|
|
|
|
const comment: AlarmComment = {
|
|
|
|
|
alarmId: {
|
|
|
|
|
id: this.alarmId,
|
|
|
|
|
entityType: EntityType.ALARM
|
|
|
|
|
},
|
|
|
|
|
type: AlarmCommentType.OTHER,
|
|
|
|
|
comment: {
|
|
|
|
|
text: commentInputValue
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
this.doSave(comment);
|
|
|
|
|
this.clearCommentInput();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
saveEditedComment(commentId: string): void {
|
|
|
|
|
const commentEditInputValue: string = this.getAlarmCommentEditFormControl().value;
|
|
|
|
|
if (commentEditInputValue) {
|
|
|
|
|
const editedComment: AlarmComment = this.getAlarmCommentById(commentId);
|
|
|
|
|
editedComment.comment.text = commentEditInputValue;
|
|
|
|
|
this.doSave(editedComment);
|
|
|
|
|
this.clearCommentEditInput();
|
|
|
|
|
this.editMode = false;
|
|
|
|
|
this.getAlarmCommentFormControl().enable({emitEvent: false});
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private doSave(comment: AlarmComment): void {
|
2023-02-28 15:04:03 +02:00
|
|
|
this.alarmCommentService.saveAlarmComment(this.alarmId, comment, {ignoreLoading: true}).subscribe(
|
2023-01-15 13:14:48 +02:00
|
|
|
() => {
|
|
|
|
|
this.loadAlarmComments();
|
|
|
|
|
}
|
|
|
|
|
)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
editComment(commentId: string): void {
|
|
|
|
|
const commentDisplayData = this.getDataElementByCommentId(commentId);
|
|
|
|
|
commentDisplayData.edit = true;
|
|
|
|
|
this.editMode = true;
|
|
|
|
|
this.getAlarmCommentEditFormControl().patchValue(commentDisplayData.commentText);
|
|
|
|
|
this.getAlarmCommentFormControl().disable({emitEvent: false});
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
cancelEdit(commentId: string): void {
|
|
|
|
|
const commentDisplayData = this.getDataElementByCommentId(commentId);
|
|
|
|
|
commentDisplayData.edit = false;
|
|
|
|
|
this.editMode = false;
|
|
|
|
|
this.getAlarmCommentFormControl().enable({emitEvent: false});
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
deleteComment(commentId: string): void {
|
|
|
|
|
const alarmCommentInfo: AlarmComment = this.getAlarmCommentById(commentId);
|
|
|
|
|
const commentText: string = alarmCommentInfo.comment.text;
|
|
|
|
|
this.dialogService.confirm(
|
2023-03-29 12:15:46 +03:00
|
|
|
this.translate.instant('alarm-activity.delete-alarm-comment'),
|
2023-01-15 13:14:48 +02:00
|
|
|
commentText,
|
|
|
|
|
this.translate.instant('action.cancel'),
|
|
|
|
|
this.translate.instant('action.delete')).subscribe(
|
|
|
|
|
(result) => {
|
|
|
|
|
if (result) {
|
2023-02-28 15:04:03 +02:00
|
|
|
this.alarmCommentService.deleteAlarmComments(this.alarmId, commentId, {ignoreLoading: true})
|
|
|
|
|
.subscribe(() => {
|
|
|
|
|
this.loadAlarmComments();
|
|
|
|
|
}
|
2023-01-15 13:14:48 +02:00
|
|
|
)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
)
|
|
|
|
|
}
|
|
|
|
|
|
2023-02-10 16:17:12 +02:00
|
|
|
getSortDirectionIcon() {
|
2023-03-29 12:15:46 +03:00
|
|
|
return this.alarmCommentSortOrder.direction === Direction.DESC ? 'mdi:sort-descending' : 'mdi:sort-ascending'
|
2023-02-10 16:17:12 +02:00
|
|
|
}
|
|
|
|
|
|
2023-03-29 12:15:46 +03:00
|
|
|
getSortDirectionTooltipText() {
|
|
|
|
|
let text = this.alarmCommentSortOrder.direction === Direction.DESC ? 'alarm-activity.newest-first' :
|
|
|
|
|
'alarm-activity.oldest-first';
|
|
|
|
|
return this.translate.instant(text);
|
2023-02-10 16:17:12 +02:00
|
|
|
}
|
|
|
|
|
|
2023-03-29 12:15:46 +03:00
|
|
|
isDirectionAscending() {
|
|
|
|
|
return this.alarmCommentSortOrder.direction === Direction.ASC;
|
2023-02-10 16:17:12 +02:00
|
|
|
}
|
|
|
|
|
|
2023-01-15 13:14:48 +02:00
|
|
|
onCommentMouseEnter(commentId: string, displayDataIndex: number): void {
|
|
|
|
|
if (!this.editMode) {
|
|
|
|
|
const alarmUserId = this.getAlarmCommentById(commentId).userId.id;
|
|
|
|
|
if (this.authUser.userId === alarmUserId) {
|
|
|
|
|
this.displayData[displayDataIndex].showActions = true;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
onCommentMouseLeave(displayDataIndex: number): void {
|
|
|
|
|
this.displayData[displayDataIndex].showActions = false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
getUserInitials(userName: string): string {
|
|
|
|
|
let initials = '';
|
|
|
|
|
const userNameSplit = userName.split(' ');
|
|
|
|
|
initials += userNameSplit[0].charAt(0).toUpperCase();
|
|
|
|
|
if (userNameSplit.length > 1) {
|
|
|
|
|
initials += userNameSplit[userNameSplit.length - 1].charAt(0).toUpperCase();
|
|
|
|
|
}
|
|
|
|
|
return initials;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
getCurrentUserBgColor(userDisplayName: string) {
|
|
|
|
|
return this.utilsService.stringToHslColor(userDisplayName, 40, 60);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private getUserDisplayName(alarmCommentInfo: AlarmCommentInfo | User): string {
|
|
|
|
|
let name = '';
|
|
|
|
|
if ((alarmCommentInfo.firstName && alarmCommentInfo.firstName.length > 0) ||
|
|
|
|
|
(alarmCommentInfo.lastName && alarmCommentInfo.lastName.length > 0)) {
|
|
|
|
|
if (alarmCommentInfo.firstName) {
|
|
|
|
|
name += alarmCommentInfo.firstName;
|
|
|
|
|
}
|
|
|
|
|
if (alarmCommentInfo.lastName) {
|
|
|
|
|
if (name.length > 0) {
|
|
|
|
|
name += ' ';
|
|
|
|
|
}
|
|
|
|
|
name += alarmCommentInfo.lastName;
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
name = alarmCommentInfo.email;
|
|
|
|
|
}
|
|
|
|
|
return name;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
getAlarmCommentFormControl(): AbstractControl {
|
|
|
|
|
return this.alarmCommentFormGroup.get('alarmComment');
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
getAlarmCommentEditFormControl(): AbstractControl {
|
|
|
|
|
return this.alarmCommentFormGroup.get('alarmCommentEdit');
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private clearCommentInput(): void {
|
|
|
|
|
this.getAlarmCommentFormControl().patchValue('');
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private clearCommentEditInput(): void {
|
|
|
|
|
this.getAlarmCommentEditFormControl().patchValue('');
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private getAlarmCommentById(id: string): AlarmComment {
|
|
|
|
|
return this.alarmComments.find(comment => comment.id.id === id);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private getDataElementByCommentId(commentId: string): AlarmCommentsDisplayData {
|
|
|
|
|
return this.displayData.find(commentDisplayData => commentDisplayData.commentId === commentId);
|
|
|
|
|
}
|
|
|
|
|
|
2023-03-31 15:35:25 +03:00
|
|
|
private getDataForExport() {
|
|
|
|
|
let dataToExport = [];
|
|
|
|
|
for (let row of this.displayData) {
|
|
|
|
|
let exportRow = {
|
|
|
|
|
[this.translate.instant('alarm-activity.author')]: row.isSystemComment ?
|
|
|
|
|
this.translate.instant('alarm-activity.system') : row.displayName,
|
|
|
|
|
[this.translate.instant('alarm-activity.created-date')]: row.createdTime,
|
|
|
|
|
[this.translate.instant('alarm-activity.edited-date')]: row.editedTime,
|
|
|
|
|
[this.translate.instant('alarm-activity.text')]: row.commentText
|
|
|
|
|
}
|
|
|
|
|
dataToExport.push(exportRow)
|
|
|
|
|
}
|
|
|
|
|
return dataToExport;
|
|
|
|
|
}
|
|
|
|
|
|
2023-01-15 13:14:48 +02:00
|
|
|
}
|