Browse Source

Merge pull request #14943 from thingsboard/rc

Merge rc to master
pull/14945/head
Vladyslav Prykhodko 8 months ago
committed by GitHub
parent
commit
0e6e5ab921
No known key found for this signature in database GPG Key ID: B5690EEEBB952194
  1. 9
      ui-ngx/src/app/core/http/image.service.ts
  2. 2
      ui-ngx/src/app/modules/home/components/alarm-rules/alarm-rule-dialog.component.ts
  3. 2
      ui-ngx/src/app/modules/home/components/alarm-rules/cf-alarm-rule-condition-dialog.component.html
  4. 5
      ui-ngx/src/app/modules/home/components/alarm-rules/cf-alarm-rule-condition-dialog.component.ts
  5. 3
      ui-ngx/src/app/modules/home/components/alarm-rules/cf-alarm-rule-condition.component.ts
  6. 4
      ui-ngx/src/app/modules/home/components/widget/lib/chart/bar-chart-with-labels-widget.component.scss
  7. 4
      ui-ngx/src/app/modules/home/components/widget/lib/chart/range-chart-widget.component.scss
  8. 13
      ui-ngx/src/app/modules/home/components/widget/lib/rpc/power-button-widget.models.ts
  9. 2
      ui-ngx/src/app/modules/home/components/widget/lib/settings/cards/api-usage-settings.component.models.ts
  10. 2
      ui-ngx/src/app/shared/components/entity/entity-select.component.html
  11. 7
      ui-ngx/src/app/shared/components/image/gallery-image-input.component.ts
  12. 24
      ui-ngx/src/app/shared/models/alarm.models.ts
  13. 2
      ui-ngx/src/app/shared/pipe/image.pipe.ts
  14. 727
      ui-ngx/src/assets/locale/locale.constant-el_GR.json
  15. 8
      ui-ngx/src/assets/locale/locale.constant-en_US.json
  16. 778
      ui-ngx/src/assets/locale/locale.constant-es_ES.json
  17. 713
      ui-ngx/src/assets/locale/locale.constant-hi_IN.json
  18. 2
      ui-ngx/src/assets/locale/locale.constant-nl_NL.json
  19. 1152
      ui-ngx/src/assets/locale/locale.constant-no_NO.json

9
ui-ngx/src/app/core/http/image.service.ts

@ -31,7 +31,7 @@ import {
removeTbImagePrefix,
ResourceSubType
} from '@shared/models/resource.models';
import { catchError, map, switchMap } from 'rxjs/operators';
import { catchError, finalize, map, switchMap } from 'rxjs/operators';
import { DomSanitizer, SafeUrl } from '@angular/platform-browser';
import { blobToBase64, blobToText } from '@core/utils';
import { ResourcesService } from '@core/services/resources.service';
@ -116,16 +116,15 @@ export class ImageService {
request = new ReplaySubject<Blob>(1);
this.imagesLoading[imageLink] = request;
const options = defaultHttpOptionsFromConfig({ignoreLoading: true, ignoreErrors: true});
this.http.get(imageLink, {...options, ...{ responseType: 'blob' } }).subscribe({
this.http.get(imageLink, {...options, ...{ responseType: 'blob' } }).pipe(
finalize(()=> delete this.imagesLoading[imageLink])
).subscribe({
next: (value) => {
request.next(value);
request.complete();
},
error: err => {
request.error(err);
},
complete: () => {
delete this.imagesLoading[imageLink];
}
});
}

2
ui-ngx/src/app/modules/home/components/alarm-rules/alarm-rule-dialog.component.ts

@ -180,7 +180,7 @@ export class AlarmRuleDialogComponent extends DialogComponent<AlarmRuleDialogCom
});
} else {
this.fieldFormGroup.get('name').markAsTouched();
this.entitySelect.entityAutocompleteMarkAsTouched();
this.entitySelect?.entityAutocompleteMarkAsTouched();
}
}

2
ui-ngx/src/app/modules/home/components/alarm-rules/cf-alarm-rule-condition-dialog.component.html

@ -125,7 +125,7 @@
<section class="tb-form-panel stroked">
<div class="flex flex-row items-center justify-between">
<div class="tb-form-panel-title">{{ 'alarm-rule.type' | translate }}</div>
<tb-toggle-select formControlName="type" selectMediaBreakpoint="xs" [disabled]="isNoData">
<tb-toggle-select formControlName="type" selectMediaBreakpoint="xs">
<tb-toggle-option *ngFor="let alarmConditionType of alarmConditionTypes" [value]="alarmConditionType">
{{ alarmConditionTypeTranslation.get(alarmConditionType) | translate }}
</tb-toggle-option>

5
ui-ngx/src/app/modules/home/components/alarm-rules/cf-alarm-rule-condition-dialog.component.ts

@ -228,6 +228,11 @@ export class CfAlarmRuleConditionDialogComponent extends DialogComponent<CfAlarm
if (this.isNoData && this.conditionFormGroup.get('type').value !== AlarmRuleConditionType.SIMPLE) {
this.conditionFormGroup.get('type').patchValue(AlarmRuleConditionType.SIMPLE);
}
if (this.isNoData) {
this.conditionFormGroup.get('type').disable({emitEvent: false});
} else {
this.conditionFormGroup.get('type').enable({emitEvent: false});
}
}
private hasNoData(data: Array<AlarmRuleFilter>) {

3
ui-ngx/src/app/modules/home/components/alarm-rules/cf-alarm-rule-condition.component.ts

@ -295,6 +295,9 @@ export class CfAlarmRuleConditionComponent implements ControlValueAccessor, Vali
}
}).afterClosed().subscribe((result) => {
if (result) {
if (!this.modelValue) {
this.modelValue = {} as AlarmRuleCondition;
}
this.modelValue.schedule = result;
this.updateModel();
}

4
ui-ngx/src/app/modules/home/components/widget/lib/chart/bar-chart-with-labels-widget.component.scss

@ -20,9 +20,7 @@
display: flex;
flex-direction: column;
gap: 8px;
&.overlay {
padding: 20px 24px 24px 24px;
}
padding: 20px 24px 24px 24px;
> div:not(.tb-bar-chart-overlay) {
z-index: 1;
}

4
ui-ngx/src/app/modules/home/components/widget/lib/chart/range-chart-widget.component.scss

@ -20,9 +20,7 @@
display: flex;
flex-direction: column;
gap: 8px;
&.overlay {
padding: 20px 24px 24px 24px;
}
padding: 20px 24px 24px 24px;
> div:not(.tb-range-chart-overlay) {
z-index: 1;
}

13
ui-ngx/src/app/modules/home/components/widget/lib/rpc/power-button-widget.models.ts

@ -28,7 +28,7 @@ import { Circle, Effect, Element, G, Gradient, Path, Runner, Svg, Text, Timeline
import '@svgdotjs/svg.filter.js';
import tinycolor from 'tinycolor2';
import { WidgetContext } from '@home/models/widget-component.models';
import { Observable, of } from 'rxjs';
import { Observable, of, shareReplay } from 'rxjs';
import { isSvgIcon, splitIconName } from '@shared/models/icon.models';
import { catchError, map, take } from 'rxjs/operators';
import { MatIconRegistry } from '@angular/material/icon';
@ -336,6 +336,8 @@ export abstract class PowerButtonShape {
protected onPowerSymbolCircle: Path;
protected onPowerSymbolLine: Path;
private onIcon$: Observable<Element>;
protected constructor(protected widgetContext: WidgetContext,
protected svgShape: Svg,
protected iconRegistry: MatIconRegistry,
@ -428,7 +430,10 @@ export abstract class PowerButtonShape {
public drawOnShape(onCenterGroup?: G, label?: boolean, labelWeight?: string, circleStroke?: boolean, mask?: Circle) {
if (this.icons.onButtonIcon.showIcon) {
this.createIconElement(this.icons.onButtonIcon.icon, this.icons.onButtonIcon.iconSize).subscribe(icon => {
this.onIcon$ = this.createIconElement(this.icons.onButtonIcon.icon, this.icons.onButtonIcon.iconSize)
.pipe(shareReplay(1));
this.onIcon$.subscribe(icon => {
this.onPowerSymbolIcon = icon.center(cx, cy);
if (isDefinedAndNotNull(onCenterGroup)) {
this.onPowerSymbolIcon.addTo(onCenterGroup);
@ -462,7 +467,9 @@ export abstract class PowerButtonShape {
public onCenterTimeLine(timeline: Timeline, label: boolean) {
if (this.icons.onButtonIcon.showIcon) {
this.onPowerSymbolIcon.timeline(timeline);
if (this.onIcon$) {
this.onIcon$.subscribe(icon => icon.timeline(timeline))
}
} else {
if (label) {
this.onLabelShape.timeline(timeline);

2
ui-ngx/src/app/modules/home/components/widget/lib/settings/cards/api-usage-settings.component.models.ts

@ -89,7 +89,7 @@ export const apiUsageDefaultSettings: ApiUsageWidgetSettings = {
generateDataKey('{i18n:api-usage.data-points-storage-days}', 'dbApiState', 'storageDataPointsLimit', 'storageDataPointsCount'),
generateDataKey('{i18n:api-usage.alarms-created}', 'alarmApiState', 'createdAlarmsLimit', 'createdAlarmsCount'),
generateDataKey('{i18n:api-usage.emails}', 'emailApiState', 'emailLimit', 'emailCount'),
generateDataKey('{i18n:api-usage.sms}', 'notificationApiState', 'smsLimit', 'smsCount'),
generateDataKey('{i18n:api-usage.sms}', 'smsApiState', 'smsLimit', 'smsCount'),
],
targetDashboardState: 'default',
background: {

2
ui-ngx/src/app/shared/components/entity/entity-select.component.html

@ -34,7 +34,7 @@
*ngIf="modelValue.entityType && !entityTypeNullUUID.has(modelValue.entityType)"
class="flex-1"
[appearance]="appearance"
[required]="required"
[required]="required && modelValue.entityType !== AliasEntityType.CURRENT_CUSTOMER"
[entityType]="modelValue.entityType"
[useEntityDisplayName]="useEntityDisplayName"
(entityChanged)="changeEntity($event)"

7
ui-ngx/src/app/shared/components/image/gallery-image-input.component.ts

@ -171,9 +171,9 @@ export class GalleryImageInputComponent extends PageComponent implements OnInit,
}
}
private updateModel(value: string) {
private updateModel(value: string, forcedToUpdate = false): void {
this.cd.markForCheck();
if (this.imageUrl !== value) {
if (this.imageUrl !== value || forcedToUpdate) {
this.imageUrl = value;
this.propagateChange(prependTbImagePrefix(this.imageUrl));
}
@ -211,9 +211,10 @@ export class GalleryImageInputComponent extends PageComponent implements OnInit,
}
}).afterClosed().subscribe((image) => {
if (image) {
const forcedToUpdate = this.imageUrl === image.link && this.imageResource?.descriptor?.etag !== image.descriptor.etag;
this.linkType = ImageLinkType.resource;
this.imageResource = image;
this.updateModel(image.link);
this.updateModel(image.link, forcedToUpdate);
}
});
}

24
ui-ngx/src/app/shared/models/alarm.models.ts

@ -27,7 +27,7 @@ import { AlarmCommentId } from '@shared/models/id/alarm-comment-id';
import { UserId } from '@shared/models/id/user-id';
import { AlarmFilter } from '@shared/models/query/query.models';
import { HasTenantId } from '@shared/models/entity.models';
import { isNotEmptyStr } from '@core/utils';
import { isDefinedAndNotNull, isNotEmptyStr } from '@core/utils';
export enum AlarmsMode {
ALL,
@ -391,18 +391,20 @@ export class AlarmQueryV2 {
export const 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 += ' ';
if (isDefinedAndNotNull(alarmAssignee)) {
if (isNotEmptyStr(alarmAssignee.firstName) || isNotEmptyStr(alarmAssignee.lastName)) {
if (alarmAssignee.firstName) {
displayName += alarmAssignee.firstName;
}
if (alarmAssignee.lastName) {
if (displayName.length > 0) {
displayName += ' ';
}
displayName += alarmAssignee.lastName;
}
displayName += alarmAssignee.lastName;
} else {
displayName = alarmAssignee.email;
}
} else {
displayName = alarmAssignee.email;
}
return displayName;
};

2
ui-ngx/src/app/shared/pipe/image.pipe.ts

@ -38,7 +38,7 @@ export class ImagePipe implements PipeTransform {
private sanitizer: DomSanitizer,
private zone: NgZone) { }
transform(urlData: string | UrlHolder, args?: any): Observable<SafeUrl | string> {
transform(urlData: string | UrlHolder, args?: any, triggerUpdate?: number): Observable<SafeUrl | string> {
const ignoreLoadingImage = !!args?.ignoreLoadingImage;
const asString = !!args?.asString;
const emptyUrl = args?.emptyUrl || NO_IMAGE_DATA_URI;

727
ui-ngx/src/assets/locale/locale.constant-el_GR.json

File diff suppressed because it is too large

8
ui-ngx/src/assets/locale/locale.constant-en_US.json

@ -810,7 +810,7 @@
"no-assets-matching": "No assets matching '{{entity}}' were found.",
"asset-required": "Asset is required.",
"name-starts-with": "Asset name expression",
"help-text": "Use '%' according to need: '%asset_name_contains%', '%asset_name_ends', 'asset_starts_with'.",
"help-text": "Use '%' according to need: '%asset_name_contains%', '%asset_name_ends', 'asset_starts_with%'.",
"import": "Import assets",
"asset-file": "Asset file",
"label": "Label",
@ -2131,7 +2131,7 @@
"remove-alias": "Remove device alias",
"add-alias": "Add device alias",
"name-starts-with": "Device name expression",
"help-text": "Use '%' according to need: '%device_name_contains%', '%device_name_ends', 'device_starts_with'.",
"help-text": "Use '%' according to need: '%device_name_contains%', '%device_name_ends', 'device_starts_with%'.",
"device-list": "Device list",
"use-device-name-filter": "Use filter",
"device-list-empty": "No devices selected.",
@ -3048,7 +3048,7 @@
"no-entities-text": "No entities found",
"no-entity-types-matching": "No entity types matching '{{entityType}}' were found.",
"name-starts-with": "Name expression",
"help-text": "Use '%' according to need: '%entity_name_contains%', '%entity_name_ends', 'entity_starts_with'.",
"help-text": "Use '%' according to need: '%entity_name_contains%', '%entity_name_ends', 'entity_starts_with%'.",
"use-entity-name-filter": "Use filter",
"entity-list-empty": "No entities selected.",
"entity-type-list-required": "At least one entity type should be selected.",
@ -3251,7 +3251,7 @@
"remove-alias": "Remove entity view alias",
"add-alias": "Add entity view alias",
"name-starts-with": "Entity View name expression",
"help-text": "Use '%' according to need: '%entity-view_name_contains%', '%entity-view_name_ends', 'entity-view_starts_with'.",
"help-text": "Use '%' according to need: '%entity-view_name_contains%', '%entity-view_name_ends', 'entity-view_starts_with%'.",
"entity-view-list": "Entity View list",
"use-entity-view-name-filter": "Use filter",
"entity-view-list-empty": "No entity views selected.",

778
ui-ngx/src/assets/locale/locale.constant-es_ES.json

File diff suppressed because it is too large

713
ui-ngx/src/assets/locale/locale.constant-hi_IN.json

File diff suppressed because it is too large

2
ui-ngx/src/assets/locale/locale.constant-nl_NL.json

@ -936,6 +936,8 @@
"transport-data-points-hourly-activity": "Transportdatapunten: uurlijkse activiteit",
"transport-data-points-daily-activity": "Transportdatapunten: dagelijkse activiteit",
"transport-data-points-monthly-activity": "Transportdatapunten: maandelijkse activiteit",
"view-details": "Details bekijken",
"view-statistics": "Statistieken bekijken",
"transport-messages": "Transportberichten",
"transport-messages-hourly-activity": "Transportberichten: uurlijkse activiteit",
"transport-data-point-hourly-activity": "Transportdatapunt: uurlijkse activiteit",

1152
ui-ngx/src/assets/locale/locale.constant-no_NO.json

File diff suppressed because it is too large
Loading…
Cancel
Save