UI: fixed alarm tables and alarm details breaking if deleted user was assigned or left comments
This commit is contained in:
parent
9039607780
commit
7df466d0db
@ -31,6 +31,7 @@ import {
|
||||
hashCode,
|
||||
isDefined,
|
||||
isDefinedAndNotNull,
|
||||
isNotEmptyStr,
|
||||
isString,
|
||||
isUndefined,
|
||||
objToBase64,
|
||||
@ -41,7 +42,13 @@ import { TranslateService } from '@ngx-translate/core';
|
||||
import { customTranslationsPrefix, i18nPrefix } from '@app/shared/models/constants';
|
||||
import { DataKey, Datasource, DatasourceType, KeyInfo } from '@shared/models/widget.models';
|
||||
import { DataKeyType } from '@app/shared/models/telemetry/telemetry.models';
|
||||
import { alarmFields, alarmSeverityTranslations, alarmStatusTranslations } from '@shared/models/alarm.models';
|
||||
import {
|
||||
AlarmAssignee,
|
||||
AlarmCommentInfo,
|
||||
alarmFields,
|
||||
alarmSeverityTranslations,
|
||||
alarmStatusTranslations
|
||||
} from '@shared/models/alarm.models';
|
||||
import { materialColors } from '@app/shared/models/material.models';
|
||||
import { WidgetInfo } from '@home/models/widget-component.models';
|
||||
import jsonSchemaDefaults from 'json-schema-defaults';
|
||||
@ -374,6 +381,39 @@ export class UtilsService {
|
||||
});
|
||||
}
|
||||
|
||||
public getUserDisplayName(alarmAssignee: AlarmAssignee | AlarmCommentInfo) {
|
||||
let displayName = '';
|
||||
if (isNotEmptyStr(alarmAssignee.firstName) || isNotEmptyStr(alarmAssignee.lastName)) {
|
||||
if (alarmAssignee.firstName) {
|
||||
displayName += alarmAssignee.firstName;
|
||||
}
|
||||
if (alarmAssignee.lastName) {
|
||||
if (displayName.length > 0) {
|
||||
displayName += ' ';
|
||||
}
|
||||
displayName += alarmAssignee.lastName;
|
||||
}
|
||||
} else {
|
||||
displayName = alarmAssignee.email;
|
||||
}
|
||||
return displayName;
|
||||
}
|
||||
|
||||
getUserInitials(alarmAssignee: AlarmAssignee): string {
|
||||
let initials = '';
|
||||
if (isNotEmptyStr(alarmAssignee.firstName) || isNotEmptyStr(alarmAssignee.lastName)) {
|
||||
if (alarmAssignee.firstName) {
|
||||
initials += alarmAssignee.firstName.charAt(0);
|
||||
}
|
||||
if (alarmAssignee.lastName) {
|
||||
initials += alarmAssignee.lastName.charAt(0);
|
||||
}
|
||||
} else {
|
||||
initials += alarmAssignee.email.charAt(0);
|
||||
}
|
||||
return initials.toUpperCase();
|
||||
}
|
||||
|
||||
public stringToHslColor(str: string, saturationPercentage: number, lightnessPercentage: number): string {
|
||||
if (str && str.length) {
|
||||
const hue = hashCode(str) % 360;
|
||||
|
||||
@ -110,9 +110,7 @@ export class AlarmAssigneePanelComponent implements OnInit, AfterViewInit, OnDe
|
||||
this.filteredUsers = this.selectUserFormGroup.get('user').valueChanges
|
||||
.pipe(
|
||||
debounceTime(150),
|
||||
map(value => {
|
||||
return value ? (typeof value === 'string' ? value : '') : ''
|
||||
}),
|
||||
map(value => value ? (typeof value === 'string' ? value : '') : ''),
|
||||
distinctUntilChanged(),
|
||||
switchMap(name => this.fetchUsers(name)),
|
||||
share(),
|
||||
@ -123,7 +121,7 @@ export class AlarmAssigneePanelComponent implements OnInit, AfterViewInit, OnDe
|
||||
ngAfterViewInit() {
|
||||
setTimeout(() => {
|
||||
this.userInput.nativeElement.focus();
|
||||
}, 0)
|
||||
}, 0);
|
||||
}
|
||||
|
||||
ngOnDestroy() {
|
||||
@ -149,7 +147,7 @@ export class AlarmAssigneePanelComponent implements OnInit, AfterViewInit, OnDe
|
||||
this.alarmService.assignAlarm(this.alarmId, user.id.id, {ignoreLoading: true}).subscribe(
|
||||
() => {
|
||||
this.reassigned = true;
|
||||
this.overlayRef.dispose()
|
||||
this.overlayRef.dispose();
|
||||
});
|
||||
}
|
||||
|
||||
@ -157,7 +155,7 @@ export class AlarmAssigneePanelComponent implements OnInit, AfterViewInit, OnDe
|
||||
this.alarmService.unassignAlarm(this.alarmId, {ignoreLoading: true}).subscribe(
|
||||
() => {
|
||||
this.reassigned = true;
|
||||
this.overlayRef.dispose()
|
||||
this.overlayRef.dispose();
|
||||
});
|
||||
}
|
||||
|
||||
@ -170,9 +168,7 @@ export class AlarmAssigneePanelComponent implements OnInit, AfterViewInit, OnDe
|
||||
return this.userService.getUsersForAssign(this.alarmId, pageLink, {ignoreLoading: true})
|
||||
.pipe(
|
||||
catchError(() => of(emptyPageData<UserEmailInfo>())),
|
||||
map(pageData => {
|
||||
return pageData.data;
|
||||
})
|
||||
map(pageData => pageData.data)
|
||||
);
|
||||
}
|
||||
|
||||
@ -191,42 +187,11 @@ export class AlarmAssigneePanelComponent implements OnInit, AfterViewInit, OnDe
|
||||
}, 0);
|
||||
}
|
||||
|
||||
getUserDisplayName(entity: User) {
|
||||
let displayName = '';
|
||||
if ((entity.firstName && entity.firstName.length > 0) ||
|
||||
(entity.lastName && entity.lastName.length > 0)) {
|
||||
if (entity.firstName) {
|
||||
displayName += entity.firstName;
|
||||
}
|
||||
if (entity.lastName) {
|
||||
if (displayName.length > 0) {
|
||||
displayName += ' ';
|
||||
}
|
||||
displayName += entity.lastName;
|
||||
}
|
||||
} else {
|
||||
displayName = entity.email;
|
||||
}
|
||||
return displayName;
|
||||
getUserInitials(entity: UserEmailInfo): string {
|
||||
return this.utilsService.getUserInitials(entity);
|
||||
}
|
||||
|
||||
getUserInitials(entity: User): string {
|
||||
let initials = '';
|
||||
if (entity.firstName && entity.firstName.length ||
|
||||
entity.lastName && entity.lastName.length) {
|
||||
if (entity.firstName) {
|
||||
initials += entity.firstName.charAt(0);
|
||||
}
|
||||
if (entity.lastName) {
|
||||
initials += entity.lastName.charAt(0);
|
||||
}
|
||||
} else {
|
||||
initials += entity.email.charAt(0);
|
||||
}
|
||||
return initials.toUpperCase();
|
||||
}
|
||||
|
||||
getFullName(entity: User): string {
|
||||
getFullName(entity: UserEmailInfo): string {
|
||||
let fullName = '';
|
||||
if ((entity.firstName && entity.firstName.length > 0) ||
|
||||
(entity.lastName && entity.lastName.length > 0)) {
|
||||
@ -243,8 +208,8 @@ export class AlarmAssigneePanelComponent implements OnInit, AfterViewInit, OnDe
|
||||
return fullName;
|
||||
}
|
||||
|
||||
getAvatarBgColor(entity: User) {
|
||||
return this.utilsService.stringToHslColor(this.getUserDisplayName(entity), 40, 60);
|
||||
getAvatarBgColor(entity: UserEmailInfo) {
|
||||
return this.utilsService.stringToHslColor(this.utilsService.getUserDisplayName(entity), 40, 60);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@ -165,39 +165,8 @@ export class AlarmAssigneeSelectPanelComponent implements OnInit, AfterViewInit
|
||||
}, 0);
|
||||
}
|
||||
|
||||
getUserDisplayName(entity: UserEmailInfo) {
|
||||
let displayName = '';
|
||||
if ((entity.firstName && entity.firstName.length > 0) ||
|
||||
(entity.lastName && entity.lastName.length > 0)) {
|
||||
if (entity.firstName) {
|
||||
displayName += entity.firstName;
|
||||
}
|
||||
if (entity.lastName) {
|
||||
if (displayName.length > 0) {
|
||||
displayName += ' ';
|
||||
}
|
||||
displayName += entity.lastName;
|
||||
}
|
||||
} else {
|
||||
displayName = entity.email;
|
||||
}
|
||||
return displayName;
|
||||
}
|
||||
|
||||
getUserInitials(entity: UserEmailInfo): string {
|
||||
let initials = '';
|
||||
if (entity.firstName && entity.firstName.length ||
|
||||
entity.lastName && entity.lastName.length) {
|
||||
if (entity.firstName) {
|
||||
initials += entity.firstName.charAt(0);
|
||||
}
|
||||
if (entity.lastName) {
|
||||
initials += entity.lastName.charAt(0);
|
||||
}
|
||||
} else {
|
||||
initials += entity.email.charAt(0);
|
||||
}
|
||||
return initials.toUpperCase();
|
||||
return this.utilsService.getUserInitials(entity);
|
||||
}
|
||||
|
||||
getFullName(entity: UserEmailInfo): string {
|
||||
@ -218,7 +187,7 @@ export class AlarmAssigneeSelectPanelComponent implements OnInit, AfterViewInit
|
||||
}
|
||||
|
||||
getAvatarBgColor(entity: UserEmailInfo) {
|
||||
return this.utilsService.stringToHslColor(this.getUserDisplayName(entity), 40, 60);
|
||||
return this.utilsService.stringToHslColor(this.utilsService.getUserDisplayName(entity), 40, 60);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@ -20,10 +20,12 @@
|
||||
subscriptSizing="dynamic">
|
||||
<mat-label translate>alarm.assignee</mat-label>
|
||||
<input matInput readonly [value]="getAssignee()">
|
||||
<span *ngIf="alarm?.assigneeId" matPrefix class="user-avatar"
|
||||
[style.backgroundColor]="getAvatarBgColor(alarm.assignee)">
|
||||
<span *ngIf="userAssigned; else unassigned" matPrefix class="user-avatar"
|
||||
[style.background-color]="getAvatarBgColor(alarm.assignee)">
|
||||
{{ getUserInitials(alarm.assignee) }}
|
||||
</span>
|
||||
<mat-icon *ngIf="!alarm?.assigneeId" matPrefix class="unassigned-icon">account_circle</mat-icon>
|
||||
<ng-template #unassigned>
|
||||
<mat-icon matPrefix class="material-icons unassigned-icon">{{ alarm?.assigneeId ? 'no_accounts' : 'account_circle' }}</mat-icon>
|
||||
</ng-template>
|
||||
<mat-icon matSuffix>arrow_drop_down</mat-icon>
|
||||
</mat-form-field>
|
||||
|
||||
@ -25,6 +25,7 @@ import {
|
||||
import { ConnectedPosition, Overlay, OverlayConfig, OverlayRef } from '@angular/cdk/overlay';
|
||||
import { ComponentPortal } from '@angular/cdk/portal';
|
||||
import { TranslateService } from '@ngx-translate/core';
|
||||
import { isNotEmptyStr } from '@core/utils';
|
||||
|
||||
@Component({
|
||||
selector: 'tb-alarm-assignee',
|
||||
@ -41,6 +42,8 @@ export class AlarmAssigneeComponent {
|
||||
@Output()
|
||||
alarmReassigned = new EventEmitter<boolean>();
|
||||
|
||||
userAssigned: boolean;
|
||||
|
||||
constructor(private utilsService: UtilsService,
|
||||
private overlay: Overlay,
|
||||
private viewContainerRef: ViewContainerRef,
|
||||
@ -49,68 +52,22 @@ export class AlarmAssigneeComponent {
|
||||
|
||||
getAssignee() {
|
||||
if (this.alarm) {
|
||||
if (this.alarm.assignee) {
|
||||
return this.getUserDisplayName(this.alarm.assignee);
|
||||
this.userAssigned = this.alarm.assigneeId && ((isNotEmptyStr(this.alarm.assignee?.firstName) ||
|
||||
isNotEmptyStr(this.alarm.assignee?.lastName)) || isNotEmptyStr(this.alarm.assignee?.email));
|
||||
if (this.userAssigned) {
|
||||
return this.utilsService.getUserDisplayName(this.alarm.assignee);
|
||||
} else {
|
||||
return this.translateService.instant('alarm.unassigned');
|
||||
return this.translateService.instant(this.alarm.assigneeId ? 'alarm.user-deleted' : 'alarm.unassigned');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
getUserDisplayName(entity: AlarmAssignee) {
|
||||
let displayName = '';
|
||||
if ((entity.firstName && entity.firstName.length > 0) ||
|
||||
(entity.lastName && entity.lastName.length > 0)) {
|
||||
if (entity.firstName) {
|
||||
displayName += entity.firstName;
|
||||
}
|
||||
if (entity.lastName) {
|
||||
if (displayName.length > 0) {
|
||||
displayName += ' ';
|
||||
}
|
||||
displayName += entity.lastName;
|
||||
}
|
||||
} else {
|
||||
displayName = entity.email;
|
||||
}
|
||||
return displayName;
|
||||
}
|
||||
|
||||
getUserInitials(entity: AlarmAssignee): string {
|
||||
let initials = '';
|
||||
if (entity.firstName && entity.firstName.length ||
|
||||
entity.lastName && entity.lastName.length) {
|
||||
if (entity.firstName) {
|
||||
initials += entity.firstName.charAt(0);
|
||||
}
|
||||
if (entity.lastName) {
|
||||
initials += entity.lastName.charAt(0);
|
||||
}
|
||||
} else {
|
||||
initials += entity.email.charAt(0);
|
||||
}
|
||||
return initials.toUpperCase();
|
||||
}
|
||||
|
||||
getFullName(entity: AlarmAssignee): string {
|
||||
let fullName = '';
|
||||
if ((entity.firstName && entity.firstName.length > 0) ||
|
||||
(entity.lastName && entity.lastName.length > 0)) {
|
||||
if (entity.firstName) {
|
||||
fullName += entity.firstName;
|
||||
}
|
||||
if (entity.lastName) {
|
||||
if (fullName.length > 0) {
|
||||
fullName += ' ';
|
||||
}
|
||||
fullName += entity.lastName;
|
||||
}
|
||||
}
|
||||
return fullName;
|
||||
getUserInitials(alarmAssignee: AlarmAssignee): string {
|
||||
return this.utilsService.getUserInitials(alarmAssignee);
|
||||
}
|
||||
|
||||
getAvatarBgColor(entity: AlarmAssignee) {
|
||||
return this.utilsService.stringToHslColor(this.getUserDisplayName(entity), 40, 60);
|
||||
return this.utilsService.stringToHslColor(this.utilsService.getUserDisplayName(entity), 40, 60);
|
||||
}
|
||||
|
||||
openAlarmAssigneePanel($event: Event, alarm: AlarmInfo) {
|
||||
|
||||
@ -69,10 +69,14 @@
|
||||
*ngIf="!displayDataElement.edit; else commentEditing"
|
||||
(mouseenter)="onCommentMouseEnter(displayDataElement.commentId, i)"
|
||||
(mouseleave)="onCommentMouseLeave(i)">
|
||||
<div class="user-avatar" fxLayout="row" fxLayoutAlign="center center" fxFlexAlign="start" fxHide.xs
|
||||
<div *ngIf="displayDataElement.userExists; else userDeleted" class="user-avatar"
|
||||
fxLayout="row" fxLayoutAlign="center center" fxFlexAlign="start" fxHide.xs
|
||||
[style.background-color]="displayDataElement.avatarBgColor">
|
||||
{{ getUserInitials(displayDataElement.displayName) }}
|
||||
</div>
|
||||
<ng-template #userDeleted>
|
||||
<mat-icon matPrefix class="mat-icon tb-mat-30" fxHide.xs>no_accounts</mat-icon>
|
||||
</ng-template>
|
||||
<div fxFlex fxLayout="column" fxLayoutGap="5px">
|
||||
<div fxLayout="row" fxLayoutGap="8px" fxLayoutAlign="start center">
|
||||
<span class="user-name">{{ displayDataElement.displayName }}</span>
|
||||
|
||||
@ -86,7 +86,7 @@ $border: 1px solid mat.get-color-from-palette($tb-primary);
|
||||
background-color: $primary-color;
|
||||
border: $border;
|
||||
border-bottom: none;
|
||||
border-radius: 8px 8px 0px 0px;
|
||||
border-radius: 8px 8px 0 0;
|
||||
|
||||
&.activity-only {
|
||||
border: none;
|
||||
@ -94,7 +94,7 @@ $border: 1px solid mat.get-color-from-palette($tb-primary);
|
||||
|
||||
&.asc {
|
||||
border-bottom: $border;
|
||||
box-shadow: 0px 4px 10px rgba(23, 33, 90, 0.08);
|
||||
box-shadow: 0 4px 10px rgba(23, 33, 90, 0.08);
|
||||
|
||||
&.activity-only {
|
||||
border: none;
|
||||
@ -116,7 +116,7 @@ $border: 1px solid mat.get-color-from-palette($tb-primary);
|
||||
.comments-container {
|
||||
border: $border;
|
||||
border-top: none;
|
||||
border-radius: 0px 0px 8px 8px;
|
||||
border-radius: 0 0 8px 8px;
|
||||
|
||||
&.activity-only {
|
||||
border: none;
|
||||
@ -134,6 +134,11 @@ $border: 1px solid mat.get-color-from-palette($tb-primary);
|
||||
&:hover {
|
||||
background-color: $primary-color;
|
||||
}
|
||||
|
||||
.mat-icon {
|
||||
align-self: start;
|
||||
color: rgba(0, 0, 0, 0.38);
|
||||
}
|
||||
}
|
||||
|
||||
.user-avatar {
|
||||
|
||||
@ -21,31 +21,33 @@ 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 { AuthUser } 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 { AlarmComment, AlarmCommentType } from '@shared/models/alarm.models';
|
||||
import { UtilsService } from '@core/services/utils.service';
|
||||
import { EntityType } from '@shared/models/entity-type.models';
|
||||
import { DatePipe } from '@angular/common';
|
||||
import { ImportExportService } from '@shared/import-export/import-export.service';
|
||||
import { isNotEmptyStr } from '@core/utils';
|
||||
|
||||
interface AlarmCommentsDisplayData {
|
||||
commentId?: string,
|
||||
displayName?: string,
|
||||
createdTime: string,
|
||||
createdDateAgo?: string,
|
||||
edit?: boolean,
|
||||
isEdited?: boolean,
|
||||
commentId?: string;
|
||||
displayName?: string;
|
||||
createdTime: string;
|
||||
createdDateAgo?: string;
|
||||
edit?: boolean;
|
||||
isEdited?: boolean;
|
||||
editedTime?: string;
|
||||
editedDateAgo?: string,
|
||||
showActions?: boolean,
|
||||
commentText?: string,
|
||||
isSystemComment?: boolean,
|
||||
avatarBgColor?: string
|
||||
editedDateAgo?: string;
|
||||
showActions?: boolean;
|
||||
commentText?: string;
|
||||
isSystemComment?: boolean;
|
||||
avatarBgColor?: string;
|
||||
userExists?: boolean;
|
||||
}
|
||||
|
||||
@Component({
|
||||
@ -58,7 +60,7 @@ export class AlarmCommentComponent implements OnInit {
|
||||
alarmId: string;
|
||||
|
||||
@Input()
|
||||
alarmActivityOnly: boolean = false;
|
||||
alarmActivityOnly = false;
|
||||
|
||||
authUser: AuthUser;
|
||||
|
||||
@ -73,11 +75,11 @@ export class AlarmCommentComponent implements OnInit {
|
||||
direction: Direction.DESC
|
||||
};
|
||||
|
||||
editMode: boolean = false;
|
||||
editMode = false;
|
||||
|
||||
userDisplayName$ = this.store.pipe(
|
||||
select(selectUserDetails),
|
||||
map((user) => this.getUserDisplayName(user))
|
||||
map((user) => this.utilsService.getUserDisplayName(user))
|
||||
);
|
||||
|
||||
currentUserDisplayName: string;
|
||||
@ -115,15 +117,18 @@ export class AlarmCommentComponent implements OnInit {
|
||||
(pagedData) => {
|
||||
this.alarmComments = pagedData.data;
|
||||
this.displayData.length = 0;
|
||||
for (let alarmComment of pagedData.data) {
|
||||
let displayDataElement = {} as AlarmCommentsDisplayData;
|
||||
for (const alarmComment of pagedData.data) {
|
||||
const displayDataElement = {} as AlarmCommentsDisplayData;
|
||||
displayDataElement.createdTime = this.datePipe.transform(alarmComment.createdTime, 'yyyy-MM-dd HH:mm:ss');
|
||||
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.userExists = isNotEmptyStr(alarmComment.firstName) || isNotEmptyStr(alarmComment.lastName) ||
|
||||
isNotEmptyStr(alarmComment.email);
|
||||
displayDataElement.displayName = displayDataElement.userExists ? this.utilsService.getUserDisplayName(alarmComment) :
|
||||
this.translate.instant('alarm.user-deleted');
|
||||
displayDataElement.edit = false;
|
||||
displayDataElement.isEdited = alarmComment.comment.edited;
|
||||
displayDataElement.editedTime = this.datePipe.transform(alarmComment.comment.editedOn, 'yyyy-MM-dd HH:mm:ss');
|
||||
@ -136,17 +141,17 @@ export class AlarmCommentComponent implements OnInit {
|
||||
this.displayData.push(displayDataElement);
|
||||
}
|
||||
}
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
changeSortDirection() {
|
||||
let currentDirection = this.alarmCommentSortOrder.direction;
|
||||
const currentDirection = this.alarmCommentSortOrder.direction;
|
||||
this.alarmCommentSortOrder.direction = currentDirection === Direction.DESC ? Direction.ASC : Direction.DESC;
|
||||
this.loadAlarmComments();
|
||||
}
|
||||
|
||||
exportAlarmActivity() {
|
||||
let fileName = this.translate.instant('alarm.alarm') + '_' + this.translate.instant('alarm-activity.activity');
|
||||
const fileName = this.translate.instant('alarm.alarm') + '_' + this.translate.instant('alarm-activity.activity');
|
||||
this.importExportService.exportCsv(this.getDataForExport(), fileName.toLowerCase());
|
||||
}
|
||||
|
||||
@ -162,7 +167,7 @@ export class AlarmCommentComponent implements OnInit {
|
||||
comment: {
|
||||
text: commentInputValue
|
||||
}
|
||||
}
|
||||
};
|
||||
this.doSave(comment);
|
||||
this.clearCommentInput();
|
||||
}
|
||||
@ -185,7 +190,7 @@ export class AlarmCommentComponent implements OnInit {
|
||||
() => {
|
||||
this.loadAlarmComments();
|
||||
}
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
editComment(commentId: string): void {
|
||||
@ -217,18 +222,18 @@ export class AlarmCommentComponent implements OnInit {
|
||||
.subscribe(() => {
|
||||
this.loadAlarmComments();
|
||||
}
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
getSortDirectionIcon() {
|
||||
return this.alarmCommentSortOrder.direction === Direction.DESC ? 'mdi:sort-descending' : 'mdi:sort-ascending'
|
||||
return this.alarmCommentSortOrder.direction === Direction.DESC ? 'mdi:sort-descending' : 'mdi:sort-ascending';
|
||||
}
|
||||
|
||||
getSortDirectionTooltipText() {
|
||||
let text = this.alarmCommentSortOrder.direction === Direction.DESC ? 'alarm-activity.newest-first' :
|
||||
const text = this.alarmCommentSortOrder.direction === Direction.DESC ? 'alarm-activity.newest-first' :
|
||||
'alarm-activity.oldest-first';
|
||||
return this.translate.instant(text);
|
||||
}
|
||||
@ -264,25 +269,6 @@ export class AlarmCommentComponent implements OnInit {
|
||||
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');
|
||||
}
|
||||
@ -308,16 +294,16 @@ export class AlarmCommentComponent implements OnInit {
|
||||
}
|
||||
|
||||
private getDataForExport() {
|
||||
let dataToExport = [];
|
||||
for (let row of this.displayData) {
|
||||
let exportRow = {
|
||||
const dataToExport = [];
|
||||
for (const row of this.displayData) {
|
||||
const 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)
|
||||
};
|
||||
dataToExport.push(exportRow);
|
||||
}
|
||||
return dataToExport;
|
||||
}
|
||||
|
||||
@ -31,13 +31,13 @@ import { forkJoin, Observable } from 'rxjs';
|
||||
import { PageData } from '@shared/models/page/page-data';
|
||||
import { EntityId } from '@shared/models/id/entity-id';
|
||||
import {
|
||||
AlarmAssignee,
|
||||
AlarmInfo,
|
||||
AlarmQueryV2,
|
||||
AlarmSearchStatus,
|
||||
alarmSeverityColors,
|
||||
alarmSeverityTranslations,
|
||||
AlarmsMode,
|
||||
AlarmStatus,
|
||||
alarmStatusTranslations
|
||||
} from '@app/shared/models/alarm.models';
|
||||
import { AlarmService } from '@app/core/http/alarm.service';
|
||||
@ -60,7 +60,7 @@ import {
|
||||
AlarmAssigneePanelData
|
||||
} from '@home/components/alarm/alarm-assignee-panel.component';
|
||||
import { ComponentPortal } from '@angular/cdk/portal';
|
||||
import { getEntityDetailsPageURL, isDefinedAndNotNull } from '@core/utils';
|
||||
import { getEntityDetailsPageURL, isDefinedAndNotNull, isNotEmptyStr } from '@core/utils';
|
||||
import { UtilsService } from '@core/services/utils.service';
|
||||
import { AlarmFilterConfig } from '@shared/models/query/query.models';
|
||||
import { EntityService } from '@core/http/entity.service';
|
||||
@ -129,22 +129,15 @@ export class AlarmTableConfig extends EntityTableConfig<AlarmInfo, TimePageLink>
|
||||
})));
|
||||
this.columns.push(
|
||||
new EntityTableColumn<AlarmInfo>('assignee', 'alarm.assignee', '240px',
|
||||
(entity) => {
|
||||
return this.getAssigneeTemplate(entity)
|
||||
},
|
||||
() => ({}),
|
||||
false,
|
||||
() => ({}),
|
||||
(entity) => undefined,
|
||||
false,
|
||||
(entity) => this.getAssigneeTemplate(entity), () => ({}), false, () => ({}), () => undefined, false,
|
||||
{
|
||||
icon: 'keyboard_arrow_down',
|
||||
type: CellActionDescriptorType.DEFAULT,
|
||||
isEnabled: (entity) => true,
|
||||
isEnabled: () => true,
|
||||
name: this.translate.instant('alarm.assign'),
|
||||
onAction: ($event, entity) => this.openAlarmAssigneePanel($event, entity)
|
||||
})
|
||||
)
|
||||
);
|
||||
this.columns.push(
|
||||
new EntityTableColumn<AlarmInfo>('status', 'alarm.status', '25%',
|
||||
(entity) => this.translate.instant(alarmStatusTranslations.get(entity.status))));
|
||||
@ -177,7 +170,7 @@ export class AlarmTableConfig extends EntityTableConfig<AlarmInfo, TimePageLink>
|
||||
isEnabled: true,
|
||||
onAction: ($event, entities) => this.deleteAlarms($event, entities)
|
||||
}
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
fetchAlarms(pageLink: TimePageLink): Observable<PageData<AlarmInfo>> {
|
||||
@ -216,61 +209,32 @@ export class AlarmTableConfig extends EntityTableConfig<AlarmInfo, TimePageLink>
|
||||
}
|
||||
|
||||
getAssigneeTemplate(entity: AlarmInfo): string {
|
||||
return `
|
||||
<span class="assignee-cell">
|
||||
${isDefinedAndNotNull(entity.assigneeId) ?
|
||||
`<span class="assigned-container">
|
||||
<span class="user-avatar" style="background-color: ${this.getAvatarBgColor(entity)}">
|
||||
${this.getUserInitials(entity)}
|
||||
const hasAssigneeId = isDefinedAndNotNull(entity.assigneeId);
|
||||
let templateContent: string;
|
||||
|
||||
if (hasAssigneeId && ((isNotEmptyStr(entity.assignee?.firstName) || isNotEmptyStr(entity.assignee?.lastName)) ||
|
||||
isNotEmptyStr(entity.assignee?.email))) {
|
||||
templateContent = `
|
||||
<span class="assigned-container">
|
||||
<span class="user-avatar" style="background-color: ${this.getAvatarBgColor(entity.assignee)}">
|
||||
${this.utilsService.getUserInitials(entity.assignee)}
|
||||
</span>
|
||||
<span class="user-display-name">${this.getUserDisplayName(entity)}</span>
|
||||
</span>`
|
||||
:
|
||||
`<span class="unassigned-container">
|
||||
<mat-icon class="material-icons unassigned-icon">account_circle</mat-icon>
|
||||
<span>${this.translate.instant('alarm.unassigned')}</span>
|
||||
</span>`
|
||||
}
|
||||
</span>`
|
||||
}
|
||||
|
||||
getUserDisplayName(entity: AlarmInfo) {
|
||||
let displayName = '';
|
||||
if ((entity.assignee.firstName && entity.assignee.firstName.length > 0) ||
|
||||
(entity.assignee.lastName && entity.assignee.lastName.length > 0)) {
|
||||
if (entity.assignee.firstName) {
|
||||
displayName += entity.assignee.firstName;
|
||||
}
|
||||
if (entity.assignee.lastName) {
|
||||
if (displayName.length > 0) {
|
||||
displayName += ' ';
|
||||
}
|
||||
displayName += entity.assignee.lastName;
|
||||
}
|
||||
<span class="user-display-name">${this.utilsService.getUserDisplayName(entity.assignee)}</span>
|
||||
</span>`;
|
||||
} else {
|
||||
displayName = entity.assignee.email;
|
||||
templateContent = `
|
||||
<span class="unassigned-container">
|
||||
<mat-icon class="material-icons unassigned-icon">
|
||||
${hasAssigneeId ? 'no_accounts' : 'account_circle'}
|
||||
</mat-icon>
|
||||
<span>${this.translate.instant(hasAssigneeId ? 'alarm.user-deleted' : 'alarm.unassigned')}</span>
|
||||
</span>`;
|
||||
}
|
||||
return displayName;
|
||||
return `<span class="assignee-cell">${templateContent}</span>`;
|
||||
}
|
||||
|
||||
getUserInitials(entity: AlarmInfo): string {
|
||||
let initials = '';
|
||||
if (entity.assignee.firstName && entity.assignee.firstName.length ||
|
||||
entity.assignee.lastName && entity.assignee.lastName.length) {
|
||||
if (entity.assignee.firstName) {
|
||||
initials += entity.assignee.firstName.charAt(0);
|
||||
}
|
||||
if (entity.assignee.lastName) {
|
||||
initials += entity.assignee.lastName.charAt(0);
|
||||
}
|
||||
} else {
|
||||
initials += entity.assignee.email.charAt(0);
|
||||
}
|
||||
return initials.toUpperCase();
|
||||
}
|
||||
|
||||
getAvatarBgColor(entity: AlarmInfo) {
|
||||
return this.utilsService.stringToHslColor(this.getUserDisplayName(entity), 40, 60);
|
||||
getAvatarBgColor(alarmAssignee: AlarmAssignee) {
|
||||
return this.utilsService.stringToHslColor(this.utilsService.getUserDisplayName(alarmAssignee), 40, 60);
|
||||
}
|
||||
|
||||
openAlarmAssigneePanel($event: Event, entity: AlarmInfo) {
|
||||
@ -312,7 +276,7 @@ export class AlarmTableConfig extends EntityTableConfig<AlarmInfo, TimePageLink>
|
||||
this.viewContainerRef, injector));
|
||||
componentRef.onDestroy(() => {
|
||||
if (componentRef.instance.reassigned) {
|
||||
this.updateData()
|
||||
this.updateData();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@ -88,24 +88,24 @@
|
||||
<span [innerHTML]="cellContent(alarm, column, row)"></span>
|
||||
<ng-container *ngIf="column.entityKey.key === 'assignee'">
|
||||
<span class="assignee-cell" fxLayout="row" fxLayoutAlign="start center">
|
||||
<span *ngIf="alarm.assigneeId" class="assigned-container">
|
||||
<span class="user-avatar" [style.backgroundColor]="getAvatarBgColor(alarm)">
|
||||
{{ getUserInitials(alarm) }}
|
||||
<span *ngIf="alarm.assigneeId && checkAssigneeHasName(alarm.assignee); else unassigned"
|
||||
class="assigned-container">
|
||||
<span class="user-avatar" [style.backgroundColor]="getAvatarBgColor(alarm.assignee)">
|
||||
{{ getUserInitials(alarm.assignee) }}
|
||||
</span>
|
||||
<span [matTooltip]="getUserDisplayName(alarm)"
|
||||
matTooltipPosition="above">
|
||||
{{ getUserDisplayName(alarm) }}
|
||||
<span [matTooltip]="getUserDisplayName(alarm.assignee)" matTooltipPosition="above">
|
||||
{{ getUserDisplayName(alarm.assignee) }}
|
||||
</span>
|
||||
</span>
|
||||
<span *ngIf="!alarm.assigneeId" class="unassigned-container">
|
||||
<mat-icon class="material-icons unassigned-icon">account_circle</mat-icon>
|
||||
<span matTooltip="{{ 'alarm.unassigned' | translate }}"
|
||||
matTooltipPosition="above"
|
||||
style="vertical-align: middle"
|
||||
translate>
|
||||
alarm.unassigned
|
||||
<ng-template #unassigned>
|
||||
<span class="unassigned-container">
|
||||
<mat-icon class="material-icons unassigned-icon">{{ alarm.assigneeId ? 'no_accounts' : 'account_circle' }}</mat-icon>
|
||||
<span matTooltip="{{ (alarm.assigneeId ? 'alarm.user-deleted' : 'alarm.unassigned') | translate }}"
|
||||
matTooltipPosition="above" style="vertical-align: middle">
|
||||
{{ (alarm.assigneeId ? 'alarm.user-deleted' : 'alarm.unassigned') | translate }}
|
||||
</span>
|
||||
</span>
|
||||
</ng-template>
|
||||
<button *ngIf="allowAssign"
|
||||
mat-icon-button [disabled]="isLoading$ | async"
|
||||
matTooltip="{{ 'alarm.assign' | translate }}"
|
||||
|
||||
@ -37,7 +37,16 @@ import { DataKey, WidgetActionDescriptor, WidgetConfig } from '@shared/models/wi
|
||||
import { IWidgetSubscription } from '@core/api/widget-api.models';
|
||||
import { UtilsService } from '@core/services/utils.service';
|
||||
import { TranslateService } from '@ngx-translate/core';
|
||||
import { deepClone, hashCode, isDefined, isDefinedAndNotNull, isNumber, isObject, isUndefined } from '@core/utils';
|
||||
import {
|
||||
deepClone,
|
||||
hashCode,
|
||||
isDefined,
|
||||
isDefinedAndNotNull,
|
||||
isNotEmptyStr,
|
||||
isNumber,
|
||||
isObject,
|
||||
isUndefined
|
||||
} from '@core/utils';
|
||||
import cssjs from '@core/css/css';
|
||||
import { sortItems } from '@shared/models/page/page-link';
|
||||
import { Direction } from '@shared/models/page/sort-order';
|
||||
@ -83,7 +92,14 @@ import {
|
||||
DisplayColumnsPanelComponent,
|
||||
DisplayColumnsPanelData
|
||||
} from '@home/components/widget/lib/display-columns-panel.component';
|
||||
import { AlarmDataInfo, alarmFields, AlarmInfo, alarmSeverityColors, AlarmStatus } from '@shared/models/alarm.models';
|
||||
import {
|
||||
AlarmAssignee,
|
||||
AlarmDataInfo,
|
||||
alarmFields,
|
||||
AlarmInfo,
|
||||
alarmSeverityColors,
|
||||
AlarmStatus
|
||||
} from '@shared/models/alarm.models';
|
||||
import { DatePipe } from '@angular/common';
|
||||
import {
|
||||
AlarmDetailsDialogComponent,
|
||||
@ -1097,43 +1113,21 @@ export class AlarmsTableWidgetComponent extends PageComponent implements OnInit,
|
||||
this.rowStyleCache.length = 0;
|
||||
}
|
||||
|
||||
getUserDisplayName(entity: AlarmInfo) {
|
||||
let displayName = '';
|
||||
if ((entity.assignee.firstName && entity.assignee.firstName.length > 0) ||
|
||||
(entity.assignee.lastName && entity.assignee.lastName.length > 0)) {
|
||||
if (entity.assignee.firstName) {
|
||||
displayName += entity.assignee.firstName;
|
||||
}
|
||||
if (entity.assignee.lastName) {
|
||||
if (displayName.length > 0) {
|
||||
displayName += ' ';
|
||||
}
|
||||
displayName += entity.assignee.lastName;
|
||||
}
|
||||
} else {
|
||||
displayName = entity.assignee.email;
|
||||
}
|
||||
return displayName;
|
||||
checkAssigneeHasName(alarmAssignee: AlarmAssignee): boolean {
|
||||
return (isNotEmptyStr(alarmAssignee?.firstName) || isNotEmptyStr(alarmAssignee?.lastName)) ||
|
||||
isNotEmptyStr(alarmAssignee?.email);
|
||||
}
|
||||
|
||||
getUserInitials(entity: AlarmInfo): string {
|
||||
let initials = '';
|
||||
if (entity.assignee.firstName && entity.assignee.firstName.length ||
|
||||
entity.assignee.lastName && entity.assignee.lastName.length) {
|
||||
if (entity.assignee.firstName) {
|
||||
initials += entity.assignee.firstName.charAt(0);
|
||||
}
|
||||
if (entity.assignee.lastName) {
|
||||
initials += entity.assignee.lastName.charAt(0);
|
||||
}
|
||||
} else {
|
||||
initials += entity.assignee.email.charAt(0);
|
||||
}
|
||||
return initials.toUpperCase();
|
||||
getUserDisplayName(alarmAssignee: AlarmAssignee) {
|
||||
return this.utils.getUserDisplayName(alarmAssignee);
|
||||
}
|
||||
|
||||
getAvatarBgColor(entity: AlarmInfo) {
|
||||
return this.utils.stringToHslColor(this.getUserDisplayName(entity), 40, 60);
|
||||
getUserInitials(alarmAssignee: AlarmAssignee): string {
|
||||
return this.utils.getUserInitials(alarmAssignee);
|
||||
}
|
||||
|
||||
getAvatarBgColor(alarmAssignee: AlarmAssignee) {
|
||||
return this.utils.stringToHslColor(this.getUserDisplayName(alarmAssignee), 40, 60);
|
||||
}
|
||||
|
||||
openAlarmAssigneePanel($event: Event, entity: AlarmInfo) {
|
||||
|
||||
@ -127,7 +127,7 @@ export interface AlarmComment extends BaseData<AlarmCommentId> {
|
||||
text: string;
|
||||
edited?: boolean;
|
||||
editedOn?: number;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
export interface AlarmCommentInfo extends AlarmComment {
|
||||
@ -173,9 +173,9 @@ export const simulatedAlarm: AlarmInfo = {
|
||||
originatorName: 'Simulated',
|
||||
originatorLabel: 'Simulated',
|
||||
assignee: {
|
||||
firstName: "",
|
||||
lastName: "",
|
||||
email: "test@example.com",
|
||||
firstName: '',
|
||||
lastName: '',
|
||||
email: 'test@example.com',
|
||||
},
|
||||
originator: {
|
||||
entityType: EntityType.DEVICE,
|
||||
|
||||
@ -594,6 +594,7 @@
|
||||
"assignee-last-name": "Assignee last name",
|
||||
"assignee-email": "Assignee email",
|
||||
"unassigned": "Unassigned",
|
||||
"user-deleted": "User deleted",
|
||||
"assignee-not-set": "All",
|
||||
"status": "Status",
|
||||
"alarm-details": "Alarm details",
|
||||
|
||||
@ -912,6 +912,9 @@ mat-icon {
|
||||
&.tb-mat-28 {
|
||||
@include tb-mat-icon-size(28);
|
||||
}
|
||||
&.tb-mat-30 {
|
||||
@include tb-mat-icon-size(30);
|
||||
}
|
||||
&.tb-mat-32 {
|
||||
@include tb-mat-icon-size(32);
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user