Commit 98227ea665aa0e38622140b9e022ed249ea9cf3e

Authored by Igor Kulikov
2 parents d04a5195 aa82a478

Merge branch 'master' into develop/3.2

@@ -45,7 +45,6 @@ import org.thingsboard.server.common.data.Tenant; @@ -45,7 +45,6 @@ import org.thingsboard.server.common.data.Tenant;
45 import org.thingsboard.server.common.data.UpdateMessage; 45 import org.thingsboard.server.common.data.UpdateMessage;
46 import org.thingsboard.server.common.data.User; 46 import org.thingsboard.server.common.data.User;
47 import org.thingsboard.server.common.data.alarm.Alarm; 47 import org.thingsboard.server.common.data.alarm.Alarm;
48 -import org.thingsboard.server.common.data.id.AlarmId;  
49 import org.thingsboard.server.common.data.alarm.AlarmInfo; 48 import org.thingsboard.server.common.data.alarm.AlarmInfo;
50 import org.thingsboard.server.common.data.alarm.AlarmSearchStatus; 49 import org.thingsboard.server.common.data.alarm.AlarmSearchStatus;
51 import org.thingsboard.server.common.data.alarm.AlarmSeverity; 50 import org.thingsboard.server.common.data.alarm.AlarmSeverity;
@@ -56,6 +55,7 @@ import org.thingsboard.server.common.data.audit.ActionType; @@ -56,6 +55,7 @@ import org.thingsboard.server.common.data.audit.ActionType;
56 import org.thingsboard.server.common.data.audit.AuditLog; 55 import org.thingsboard.server.common.data.audit.AuditLog;
57 import org.thingsboard.server.common.data.device.DeviceSearchQuery; 56 import org.thingsboard.server.common.data.device.DeviceSearchQuery;
58 import org.thingsboard.server.common.data.entityview.EntityViewSearchQuery; 57 import org.thingsboard.server.common.data.entityview.EntityViewSearchQuery;
  58 +import org.thingsboard.server.common.data.id.AlarmId;
59 import org.thingsboard.server.common.data.id.AssetId; 59 import org.thingsboard.server.common.data.id.AssetId;
60 import org.thingsboard.server.common.data.id.CustomerId; 60 import org.thingsboard.server.common.data.id.CustomerId;
61 import org.thingsboard.server.common.data.id.DashboardId; 61 import org.thingsboard.server.common.data.id.DashboardId;
@@ -73,6 +73,7 @@ import org.thingsboard.server.common.data.kv.AttributeKvEntry; @@ -73,6 +73,7 @@ import org.thingsboard.server.common.data.kv.AttributeKvEntry;
73 import org.thingsboard.server.common.data.kv.TsKvEntry; 73 import org.thingsboard.server.common.data.kv.TsKvEntry;
74 import org.thingsboard.server.common.data.page.PageData; 74 import org.thingsboard.server.common.data.page.PageData;
75 import org.thingsboard.server.common.data.page.PageLink; 75 import org.thingsboard.server.common.data.page.PageLink;
  76 +import org.thingsboard.server.common.data.page.SortOrder;
76 import org.thingsboard.server.common.data.page.TimePageLink; 77 import org.thingsboard.server.common.data.page.TimePageLink;
77 import org.thingsboard.server.common.data.plugin.ComponentDescriptor; 78 import org.thingsboard.server.common.data.plugin.ComponentDescriptor;
78 import org.thingsboard.server.common.data.plugin.ComponentType; 79 import org.thingsboard.server.common.data.plugin.ComponentType;
@@ -890,7 +891,7 @@ public class RestClient implements ClientHttpRequestInterceptor, Closeable { @@ -890,7 +891,7 @@ public class RestClient implements ClientHttpRequestInterceptor, Closeable {
890 }, params).getBody(); 891 }, params).getBody();
891 } 892 }
892 893
893 - public PageData<DashboardInfo> getCustomerDashboards(CustomerId customerId, TimePageLink pageLink) { 894 + public PageData<DashboardInfo> getCustomerDashboards(CustomerId customerId, PageLink pageLink) {
894 Map<String, String> params = new HashMap<>(); 895 Map<String, String> params = new HashMap<>();
895 params.put("customerId", customerId.getId().toString()); 896 params.put("customerId", customerId.getId().toString());
896 addPageLinkToParam(params, pageLink); 897 addPageLinkToParam(params, pageLink);
@@ -1629,22 +1630,42 @@ public class RestClient implements ClientHttpRequestInterceptor, Closeable { @@ -1629,22 +1630,42 @@ public class RestClient implements ClientHttpRequestInterceptor, Closeable {
1629 return RestJsonConverter.toTimeseries(timeseries); 1630 return RestJsonConverter.toTimeseries(timeseries);
1630 } 1631 }
1631 1632
  1633 + @Deprecated
1632 public List<TsKvEntry> getTimeseries(EntityId entityId, List<String> keys, Long interval, Aggregation agg, TimePageLink pageLink) { 1634 public List<TsKvEntry> getTimeseries(EntityId entityId, List<String> keys, Long interval, Aggregation agg, TimePageLink pageLink) {
1633 return getTimeseries(entityId, keys, interval, agg, pageLink, true); 1635 return getTimeseries(entityId, keys, interval, agg, pageLink, true);
1634 } 1636 }
1635 1637
  1638 + @Deprecated
1636 public List<TsKvEntry> getTimeseries(EntityId entityId, List<String> keys, Long interval, Aggregation agg, TimePageLink pageLink, boolean useStrictDataTypes) { 1639 public List<TsKvEntry> getTimeseries(EntityId entityId, List<String> keys, Long interval, Aggregation agg, TimePageLink pageLink, boolean useStrictDataTypes) {
  1640 + SortOrder sortOrder = pageLink.getSortOrder();
  1641 + return getTimeseries(entityId, keys, interval, agg, sortOrder != null ? sortOrder.getDirection() : null, pageLink.getStartTime(), pageLink.getEndTime(), 100, useStrictDataTypes);
  1642 + }
  1643 +
  1644 + public List<TsKvEntry> getTimeseries(EntityId entityId, List<String> keys, Long interval, Aggregation agg, SortOrder.Direction sortOrder, Long startTime, Long endTime, Integer limit, boolean useStrictDataTypes) {
1637 Map<String, String> params = new HashMap<>(); 1645 Map<String, String> params = new HashMap<>();
1638 params.put("entityType", entityId.getEntityType().name()); 1646 params.put("entityType", entityId.getEntityType().name());
1639 params.put("entityId", entityId.getId().toString()); 1647 params.put("entityId", entityId.getId().toString());
1640 params.put("keys", listToString(keys)); 1648 params.put("keys", listToString(keys));
1641 params.put("interval", interval == null ? "0" : interval.toString()); 1649 params.put("interval", interval == null ? "0" : interval.toString());
1642 params.put("agg", agg == null ? "NONE" : agg.name()); 1650 params.put("agg", agg == null ? "NONE" : agg.name());
  1651 + params.put("limit", limit != null ? limit.toString() : "100");
  1652 + params.put("orderBy", sortOrder != null ? sortOrder.name() : "DESC");
1643 params.put("useStrictDataTypes", Boolean.toString(useStrictDataTypes)); 1653 params.put("useStrictDataTypes", Boolean.toString(useStrictDataTypes));
1644 - addPageLinkToParam(params, pageLink); 1654 +
  1655 + StringBuilder urlBuilder = new StringBuilder(baseURL);
  1656 + urlBuilder.append("/api/plugins/telemetry/{entityType}/{entityId}/values/timeseries?keys={keys}&interval={interval}&agg={agg}&useStrictDataTypes={useStrictDataTypes}&orderBy={orderBy}");
  1657 +
  1658 + if (startTime != null) {
  1659 + urlBuilder.append("&startTs={startTs}");
  1660 + params.put("startTs", String.valueOf(startTime));
  1661 + }
  1662 + if (endTime != null) {
  1663 + urlBuilder.append("&endTs={endTs}");
  1664 + params.put("endTs", String.valueOf(endTime));
  1665 + }
1645 1666
1646 Map<String, List<JsonNode>> timeseries = restTemplate.exchange( 1667 Map<String, List<JsonNode>> timeseries = restTemplate.exchange(
1647 - baseURL + "/api/plugins/telemetry/{entityType}/{entityId}/values/timeseries?keys={keys}&interval={interval}&agg={agg}&useStrictDataTypes={useStrictDataTypes}&" + getUrlParamsTs(pageLink), 1668 + urlBuilder.toString(),
1648 HttpMethod.GET, 1669 HttpMethod.GET,
1649 HttpEntity.EMPTY, 1670 HttpEntity.EMPTY,
1650 new ParameterizedTypeReference<Map<String, List<JsonNode>>>() { 1671 new ParameterizedTypeReference<Map<String, List<JsonNode>>>() {
@@ -1996,23 +2017,12 @@ public class RestClient implements ClientHttpRequestInterceptor, Closeable { @@ -1996,23 +2017,12 @@ public class RestClient implements ClientHttpRequestInterceptor, Closeable {
1996 } 2017 }
1997 2018
1998 private String getTimeUrlParams(TimePageLink pageLink) { 2019 private String getTimeUrlParams(TimePageLink pageLink) {
1999 - return this.getUrlParams(pageLink);  
2000 - }  
2001 - private String getUrlParams(TimePageLink pageLink) {  
2002 - return getUrlParams(pageLink, "startTime", "endTime");  
2003 - }  
2004 -  
2005 - private String getUrlParamsTs(TimePageLink pageLink) {  
2006 - return getUrlParams(pageLink, "startTs", "endTs");  
2007 - }  
2008 -  
2009 - private String getUrlParams(TimePageLink pageLink, String startTime, String endTime) {  
2010 String urlParams = "limit={limit}&ascOrder={ascOrder}"; 2020 String urlParams = "limit={limit}&ascOrder={ascOrder}";
2011 if (pageLink.getStartTime() != null) { 2021 if (pageLink.getStartTime() != null) {
2012 - urlParams += "&" + startTime + "={startTime}"; 2022 + urlParams += "&startTime={startTime}";
2013 } 2023 }
2014 if (pageLink.getEndTime() != null) { 2024 if (pageLink.getEndTime() != null) {
2015 - urlParams += "&" + endTime + "={endTime}"; 2025 + urlParams += "&endTime={endTime}";
2016 } 2026 }
2017 return urlParams; 2027 return urlParams;
2018 } 2028 }
@@ -65,7 +65,7 @@ @@ -65,7 +65,7 @@
65 "moment": "^2.27.0", 65 "moment": "^2.27.0",
66 "ngx-clipboard": "^13.0.1", 66 "ngx-clipboard": "^13.0.1",
67 "ngx-color-picker": "^10.0.1", 67 "ngx-color-picker": "^10.0.1",
68 - "ngx-daterangepicker-material": "^3.0.4", 68 + "ngx-daterangepicker-material": "^4.0.1",
69 "ngx-flowchart": "git://github.com/thingsboard/ngx-flowchart.git#master", 69 "ngx-flowchart": "git://github.com/thingsboard/ngx-flowchart.git#master",
70 "ngx-hm-carousel": "^2.0.0-rc.1", 70 "ngx-hm-carousel": "^2.0.0-rc.1",
71 "ngx-sharebuttons": "^8.0.1", 71 "ngx-sharebuttons": "^8.0.1",
@@ -105,10 +105,9 @@ @@ -105,10 +105,9 @@
105 "@types/jquery": "^3.5.1", 105 "@types/jquery": "^3.5.1",
106 "@types/js-beautify": "^1.11.0", 106 "@types/js-beautify": "^1.11.0",
107 "@types/jstree": "^3.3.40", 107 "@types/jstree": "^3.3.40",
108 - "@types/jszip": "^3.4.1",  
109 "@types/leaflet": "^1.5.17", 108 "@types/leaflet": "^1.5.17",
110 - "@types/leaflet-markercluster": "^1.0.3",  
111 "@types/leaflet-polylinedecorator": "^1.6.0", 109 "@types/leaflet-polylinedecorator": "^1.6.0",
  110 + "@types/leaflet.markercluster": "^1.4.2",
112 "@types/lodash": "^4.14.159", 111 "@types/lodash": "^4.14.159",
113 "@types/raphael": "^2.3.0", 112 "@types/raphael": "^2.3.0",
114 "@types/react": "^16.9.46", 113 "@types/react": "^16.9.46",
@@ -47,7 +47,7 @@ import { @@ -47,7 +47,7 @@ import {
47 import { forkJoin, Observable, of, ReplaySubject, Subject, throwError } from 'rxjs'; 47 import { forkJoin, Observable, of, ReplaySubject, Subject, throwError } from 'rxjs';
48 import { CancelAnimationFrame } from '@core/services/raf.service'; 48 import { CancelAnimationFrame } from '@core/services/raf.service';
49 import { EntityType } from '@shared/models/entity-type.models'; 49 import { EntityType } from '@shared/models/entity-type.models';
50 -import { createLabelFromDatasource, deepClone, isDefined, isEqual } from '@core/utils'; 50 +import { createLabelFromDatasource, deepClone, isDefined, isDefinedAndNotNull, isEqual } from '@core/utils';
51 import { EntityId } from '@app/shared/models/id/entity-id'; 51 import { EntityId } from '@app/shared/models/id/entity-id';
52 import * as moment_ from 'moment'; 52 import * as moment_ from 'moment';
53 import { emptyPageData, PageData } from '@shared/models/page/page-data'; 53 import { emptyPageData, PageData } from '@shared/models/page/page-data';
@@ -1332,7 +1332,7 @@ export class WidgetSubscription implements IWidgetSubscription { @@ -1332,7 +1332,7 @@ export class WidgetSubscription implements IWidgetSubscription {
1332 1332
1333 private updateLegend(dataIndex: number, data: DataSet, detectChanges: boolean) { 1333 private updateLegend(dataIndex: number, data: DataSet, detectChanges: boolean) {
1334 const dataKey = this.legendData.keys.find(key => key.dataIndex === dataIndex).dataKey; 1334 const dataKey = this.legendData.keys.find(key => key.dataIndex === dataIndex).dataKey;
1335 - const decimals = isDefined(dataKey.decimals) ? dataKey.decimals : this.decimals; 1335 + const decimals = isDefinedAndNotNull(dataKey.decimals) ? dataKey.decimals : this.decimals;
1336 const units = dataKey.units && dataKey.units.length ? dataKey.units : this.units; 1336 const units = dataKey.units && dataKey.units.length ? dataKey.units : this.units;
1337 const legendKeyData = this.legendData.data[dataIndex]; 1337 const legendKeyData = this.legendData.data[dataIndex];
1338 if (this.legendConfig.showMin) { 1338 if (this.legendConfig.showMin) {
@@ -421,7 +421,7 @@ export class ImportExportService { @@ -421,7 +421,7 @@ export class ImportExportService {
421 } 421 }
422 422
423 public exportJSZip(data: object, filename: string) { 423 public exportJSZip(data: object, filename: string) {
424 - const jsZip: JSZip = new JSZip(); 424 + const jsZip = new JSZip();
425 for (const keyName in data) { 425 for (const keyName in data) {
426 if (data.hasOwnProperty(keyName)) { 426 if (data.hasOwnProperty(keyName)) {
427 const valueData = data[keyName]; 427 const valueData = data[keyName];
@@ -61,7 +61,7 @@ @@ -61,7 +61,7 @@
61 </div> 61 </div>
62 </mat-toolbar> 62 </mat-toolbar>
63 <div fxFlex class="table-container"> 63 <div fxFlex class="table-container">
64 - <table mat-table [dataSource]="alarmsDatasource" 64 + <table mat-table [dataSource]="alarmsDatasource" [trackBy]="trackByRowIndex"
65 matSort [matSortActive]="sortOrderProperty" [matSortDirection]="pageLinkSortDirection()" matSortDisableClear> 65 matSort [matSortActive]="sortOrderProperty" [matSortDirection]="pageLinkSortDirection()" matSortDisableClear>
66 <ng-container matColumnDef="select" sticky> 66 <ng-container matColumnDef="select" sticky>
67 <mat-header-cell *matHeaderCellDef style="width: 30px;"> 67 <mat-header-cell *matHeaderCellDef style="width: 30px;">
@@ -247,11 +247,8 @@ export class AlarmsTableWidgetComponent extends PageComponent implements OnInit, @@ -247,11 +247,8 @@ export class AlarmsTableWidgetComponent extends PageComponent implements OnInit,
247 } 247 }
248 248
249 public onDataUpdated() { 249 public onDataUpdated() {
250 - this.ngZone.run(() => {  
251 - this.updateTitle(true);  
252 - this.alarmsDatasource.updateAlarms();  
253 - this.ctx.detectChanges();  
254 - }); 250 + this.updateTitle(true);
  251 + this.alarmsDatasource.updateAlarms();
255 } 252 }
256 253
257 public pageLinkSortDirection(): SortDirection { 254 public pageLinkSortDirection(): SortDirection {
@@ -565,6 +562,10 @@ export class AlarmsTableWidgetComponent extends PageComponent implements OnInit, @@ -565,6 +562,10 @@ export class AlarmsTableWidgetComponent extends PageComponent implements OnInit,
565 return column.def; 562 return column.def;
566 } 563 }
567 564
  565 + public trackByRowIndex(index: number) {
  566 + return index;
  567 + }
  568 +
568 public headerStyle(key: EntityColumn): any { 569 public headerStyle(key: EntityColumn): any {
569 const columnWidth = this.columnWidth[key.def]; 570 const columnWidth = this.columnWidth[key.def];
570 return widthStyle(columnWidth); 571 return widthStyle(columnWidth);
@@ -606,7 +607,19 @@ export class AlarmsTableWidgetComponent extends PageComponent implements OnInit, @@ -606,7 +607,19 @@ export class AlarmsTableWidgetComponent extends PageComponent implements OnInit,
606 } else { 607 } else {
607 content = this.defaultContent(key, contentInfo, value); 608 content = this.defaultContent(key, contentInfo, value);
608 } 609 }
609 - return isDefined(content) ? this.domSanitizer.bypassSecurityTrustHtml(content) : ''; 610 +
  611 + if (!isDefined(content)) {
  612 + return '';
  613 +
  614 + } else {
  615 + switch (typeof content) {
  616 + case 'string':
  617 + return this.domSanitizer.bypassSecurityTrustHtml(content);
  618 + default:
  619 + return content;
  620 + }
  621 + }
  622 +
610 } else { 623 } else {
611 return ''; 624 return '';
612 } 625 }
@@ -804,7 +817,7 @@ export class AlarmsTableWidgetComponent extends PageComponent implements OnInit, @@ -804,7 +817,7 @@ export class AlarmsTableWidgetComponent extends PageComponent implements OnInit,
804 const alarmField = alarmFields[key.name]; 817 const alarmField = alarmFields[key.name];
805 if (alarmField) { 818 if (alarmField) {
806 if (alarmField.time) { 819 if (alarmField.time) {
807 - return this.datePipe.transform(value, 'yyyy-MM-dd HH:mm:ss'); 820 + return value ? this.datePipe.transform(value, 'yyyy-MM-dd HH:mm:ss') : '';
808 } else if (alarmField.value === alarmFields.severity.value) { 821 } else if (alarmField.value === alarmFields.severity.value) {
809 return this.translate.instant(alarmSeverityTranslations.get(value)); 822 return this.translate.instant(alarmSeverityTranslations.get(value));
810 } else if (alarmField.value === alarmFields.status.value) { 823 } else if (alarmField.value === alarmFields.status.value) {
@@ -1002,7 +1002,8 @@ export abstract class TbAnalogueGauge<S extends AnalogueGaugeSettings, O extends @@ -1002,7 +1002,8 @@ export abstract class TbAnalogueGauge<S extends AnalogueGaugeSettings, O extends
1002 // animations 1002 // animations
1003 animation: settings.animation !== false && !this.ctx.isMobile, 1003 animation: settings.animation !== false && !this.ctx.isMobile,
1004 animationDuration: (isDefined(settings.animationDuration) && settings.animationDuration !== null) ? settings.animationDuration : 500, 1004 animationDuration: (isDefined(settings.animationDuration) && settings.animationDuration !== null) ? settings.animationDuration : 500,
1005 - animationRule: settings.animationRule || 'cycle' 1005 + animationRule: settings.animationRule || 'cycle',
  1006 + animatedValue: true
1006 } as O; 1007 } as O;
1007 1008
1008 this.prepareGaugeOptions(settings, gaugeData); 1009 this.prepareGaugeOptions(settings, gaugeData);
@@ -38,7 +38,7 @@ @@ -38,7 +38,7 @@
38 </div> 38 </div>
39 </mat-toolbar> 39 </mat-toolbar>
40 <div fxFlex class="table-container"> 40 <div fxFlex class="table-container">
41 - <table mat-table [dataSource]="entityDatasource" 41 + <table mat-table [dataSource]="entityDatasource" [trackBy]="trackByRowIndex"
42 matSort [matSortActive]="sortOrderProperty" [matSortDirection]="pageLinkSortDirection()" matSortDisableClear> 42 matSort [matSortActive]="sortOrderProperty" [matSortDirection]="pageLinkSortDirection()" matSortDisableClear>
43 <ng-container [matColumnDef]="column.def" *ngFor="let column of columns; trackBy: trackByColumnDef;"> 43 <ng-container [matColumnDef]="column.def" *ngFor="let column of columns; trackBy: trackByColumnDef;">
44 <mat-header-cell [ngStyle]="headerStyle(column)" *matHeaderCellDef mat-sort-header> {{ column.title }} </mat-header-cell> 44 <mat-header-cell [ngStyle]="headerStyle(column)" *matHeaderCellDef mat-sort-header> {{ column.title }} </mat-header-cell>
@@ -206,11 +206,8 @@ export class EntitiesTableWidgetComponent extends PageComponent implements OnIni @@ -206,11 +206,8 @@ export class EntitiesTableWidgetComponent extends PageComponent implements OnIni
206 } 206 }
207 207
208 public onDataUpdated() { 208 public onDataUpdated() {
209 - this.ngZone.run(() => {  
210 - this.updateTitle(true);  
211 - this.entityDatasource.dataUpdated();  
212 - this.ctx.detectChanges();  
213 - }); 209 + this.updateTitle(true);
  210 + this.entityDatasource.dataUpdated();
214 } 211 }
215 212
216 public pageLinkSortDirection(): SortDirection { 213 public pageLinkSortDirection(): SortDirection {
@@ -488,6 +485,10 @@ export class EntitiesTableWidgetComponent extends PageComponent implements OnIni @@ -488,6 +485,10 @@ export class EntitiesTableWidgetComponent extends PageComponent implements OnIni
488 return column.def; 485 return column.def;
489 } 486 }
490 487
  488 + public trackByRowIndex(index: number) {
  489 + return index;
  490 + }
  491 +
491 public headerStyle(key: EntityColumn): any { 492 public headerStyle(key: EntityColumn): any {
492 const columnWidth = this.columnWidth[key.def]; 493 const columnWidth = this.columnWidth[key.def];
493 return widthStyle(columnWidth); 494 return widthStyle(columnWidth);
@@ -529,7 +530,19 @@ export class EntitiesTableWidgetComponent extends PageComponent implements OnIni @@ -529,7 +530,19 @@ export class EntitiesTableWidgetComponent extends PageComponent implements OnIni
529 } else { 530 } else {
530 content = this.defaultContent(key, contentInfo, value); 531 content = this.defaultContent(key, contentInfo, value);
531 } 532 }
532 - return isDefined(content) ? this.domSanitizer.bypassSecurityTrustHtml(content) : ''; 533 +
  534 + if (!isDefined(content)) {
  535 + return '';
  536 +
  537 + } else {
  538 + switch (typeof content) {
  539 + case 'string':
  540 + return this.domSanitizer.bypassSecurityTrustHtml(content);
  541 + default:
  542 + return content;
  543 + }
  544 + }
  545 +
533 } else { 546 } else {
534 return ''; 547 return '';
535 } 548 }
@@ -380,7 +380,7 @@ export class TbFlot { @@ -380,7 +380,7 @@ export class TbFlot {
380 const yaxesMap: {[units: string]: TbFlotAxisOptions} = {}; 380 const yaxesMap: {[units: string]: TbFlotAxisOptions} = {};
381 const predefinedThresholds: TbFlotThresholdMarking[] = []; 381 const predefinedThresholds: TbFlotThresholdMarking[] = [];
382 const thresholdsDatasources: Datasource[] = []; 382 const thresholdsDatasources: Datasource[] = [];
383 - if (this.settings.customLegendEnabled) { 383 + if (this.settings.customLegendEnabled && this.settings.dataKeysListForLabels?.length) {
384 this.labelPatternsSourcesData = []; 384 this.labelPatternsSourcesData = [];
385 const labelPatternsDatasources: Datasource[] = []; 385 const labelPatternsDatasources: Datasource[] = [];
386 this.settings.dataKeysListForLabels.forEach((item) => { 386 this.settings.dataKeysListForLabels.forEach((item) => {
@@ -67,6 +67,7 @@ export class KnobComponent extends PageComponent implements OnInit, OnDestroy { @@ -67,6 +67,7 @@ export class KnobComponent extends PageComponent implements OnInit, OnDestroy {
67 title = ''; 67 title = '';
68 minValue: number; 68 minValue: number;
69 maxValue: number; 69 maxValue: number;
  70 + newValue = 0;
70 71
71 private startDeg = -1; 72 private startDeg = -1;
72 private currentDeg = 0; 73 private currentDeg = 0;
@@ -175,16 +176,15 @@ export class KnobComponent extends PageComponent implements OnInit, OnDestroy { @@ -175,16 +176,15 @@ export class KnobComponent extends PageComponent implements OnInit, OnDestroy {
175 176
176 const offset = this.knob.offset(); 177 const offset = this.knob.offset();
177 const center = { 178 const center = {
178 - y : offset.top + this.knob.height()/2,  
179 - x: offset.left + this.knob.width()/2 179 + y: offset.top + this.knob.height() / 2,
  180 + x: offset.left + this.knob.width() / 2
180 }; 181 };
181 - const rad2deg = 180/Math.PI; 182 + const rad2deg = 180 / Math.PI;
182 const t: Touch = ((e.originalEvent as any).touches) ? (e.originalEvent as any).touches[0] : e; 183 const t: Touch = ((e.originalEvent as any).touches) ? (e.originalEvent as any).touches[0] : e;
183 -  
184 const a = center.y - t.pageY; 184 const a = center.y - t.pageY;
185 const b = center.x - t.pageX; 185 const b = center.x - t.pageX;
186 - let deg = Math.atan2(a,b)*rad2deg;  
187 - if(deg < 0){ 186 + let deg = Math.atan2(a, b) * rad2deg;
  187 + if (deg < 0) {
188 deg = 360 + deg; 188 deg = 360 + deg;
189 } 189 }
190 if (deg > this.maxDeg) { 190 if (deg > this.maxDeg) {
@@ -196,13 +196,17 @@ export class KnobComponent extends PageComponent implements OnInit, OnDestroy { @@ -196,13 +196,17 @@ export class KnobComponent extends PageComponent implements OnInit, OnDestroy {
196 } 196 }
197 this.currentDeg = deg; 197 this.currentDeg = deg;
198 this.lastDeg = deg; 198 this.lastDeg = deg;
199 - this.knobTopPointerContainer.css('transform','rotate('+(this.currentDeg)+'deg)'); 199 + this.knobTopPointerContainer.css('transform', 'rotate(' + (this.currentDeg) + 'deg)');
200 this.turn(this.degreeToRatio(this.currentDeg)); 200 this.turn(this.degreeToRatio(this.currentDeg));
201 this.rotation = this.currentDeg; 201 this.rotation = this.currentDeg;
202 this.startDeg = -1; 202 this.startDeg = -1;
  203 + this.rpcUpdateValue(this.newValue);
203 }); 204 });
204 205
  206 +
  207 +
205 this.knob.on('mousedown touchstart', (e) => { 208 this.knob.on('mousedown touchstart', (e) => {
  209 + this.moving = false;
206 e.preventDefault(); 210 e.preventDefault();
207 const offset = this.knob.offset(); 211 const offset = this.knob.offset();
208 const center = { 212 const center = {
@@ -211,7 +215,7 @@ export class KnobComponent extends PageComponent implements OnInit, OnDestroy { @@ -211,7 +215,7 @@ export class KnobComponent extends PageComponent implements OnInit, OnDestroy {
211 }; 215 };
212 const rad2deg = 180/Math.PI; 216 const rad2deg = 180/Math.PI;
213 217
214 - this.knob.on('mousemove.rem touchmove.rem', (ev) => { 218 + $(document).on('mousemove.rem touchmove.rem', (ev) => {
215 this.moving = true; 219 this.moving = true;
216 const t: Touch = ((ev.originalEvent as any).touches) ? (ev.originalEvent as any).touches[0] : ev; 220 const t: Touch = ((ev.originalEvent as any).touches) ? (ev.originalEvent as any).touches[0] : ev;
217 221
@@ -262,6 +266,9 @@ export class KnobComponent extends PageComponent implements OnInit, OnDestroy { @@ -262,6 +266,9 @@ export class KnobComponent extends PageComponent implements OnInit, OnDestroy {
262 }); 266 });
263 267
264 $(document).on('mouseup.rem touchend.rem',() => { 268 $(document).on('mouseup.rem touchend.rem',() => {
  269 + if(this.newValue !== this.rpcValue && this.moving) {
  270 + this.rpcUpdateValue(this.newValue);
  271 + }
265 this.knob.off('.rem'); 272 this.knob.off('.rem');
266 $(document).off('.rem'); 273 $(document).off('.rem');
267 this.rotation = this.currentDeg; 274 this.rotation = this.currentDeg;
@@ -308,12 +315,12 @@ export class KnobComponent extends PageComponent implements OnInit, OnDestroy { @@ -308,12 +315,12 @@ export class KnobComponent extends PageComponent implements OnInit, OnDestroy {
308 } 315 }
309 316
310 private turn(ratio: number) { 317 private turn(ratio: number) {
311 - const value = Number((this.minValue + (this.maxValue - this.minValue)*ratio).toFixed(this.ctx.decimals));  
312 - if (this.canvasBar.value !== value) {  
313 - this.canvasBar.value = value; 318 + this.newValue = Number((this.minValue + (this.maxValue - this.minValue)*ratio).toFixed(this.ctx.decimals));
  319 + if (this.canvasBar.value !== this.newValue) {
  320 + this.canvasBar.value = this.newValue;
314 } 321 }
315 this.updateColor(this.canvasBar.getValueColor()); 322 this.updateColor(this.canvasBar.getValueColor());
316 - this.onValue(value); 323 + this.onValue(this.newValue);
317 } 324 }
318 325
319 private resize() { 326 private resize() {
@@ -379,7 +386,6 @@ export class KnobComponent extends PageComponent implements OnInit, OnDestroy { @@ -379,7 +386,6 @@ export class KnobComponent extends PageComponent implements OnInit, OnDestroy {
379 private onValue(value: number) { 386 private onValue(value: number) {
380 this.value = this.formatValue(value); 387 this.value = this.formatValue(value);
381 this.checkValueSize(); 388 this.checkValueSize();
382 - this.rpcUpdateValue(value);  
383 this.ctx.detectChanges(); 389 this.ctx.detectChanges();
384 } 390 }
385 391
@@ -112,6 +112,9 @@ $error-height: 14px !default; @@ -112,6 +112,9 @@ $error-height: 14px !default;
112 height: 90%; 112 height: 90%;
113 } 113 }
114 114
  115 + .mat-slide-toggle-label{
  116 + height: 100%;
  117 + }
115 .mat-slide-toggle-thumb { 118 .mat-slide-toggle-thumb {
116 top: 0; 119 top: 0;
117 left: 0; 120 left: 0;
@@ -40,7 +40,7 @@ import { @@ -40,7 +40,7 @@ import {
40 } from '@shared/models/widget.models'; 40 } from '@shared/models/widget.models';
41 import { UtilsService } from '@core/services/utils.service'; 41 import { UtilsService } from '@core/services/utils.service';
42 import { TranslateService } from '@ngx-translate/core'; 42 import { TranslateService } from '@ngx-translate/core';
43 -import { hashCode, isDefined, isNumber } from '@core/utils'; 43 +import {hashCode, isDefined, isDefinedAndNotNull, isNumber} from '@core/utils';
44 import cssjs from '@core/css/css'; 44 import cssjs from '@core/css/css';
45 import { PageLink } from '@shared/models/page/page-link'; 45 import { PageLink } from '@shared/models/page/page-link';
46 import { Direction, SortOrder, sortOrderFromString } from '@shared/models/page/sort-order'; 46 import { Direction, SortOrder, sortOrderFromString } from '@shared/models/page/sort-order';
@@ -197,11 +197,8 @@ export class TimeseriesTableWidgetComponent extends PageComponent implements OnI @@ -197,11 +197,8 @@ export class TimeseriesTableWidgetComponent extends PageComponent implements OnI
197 } 197 }
198 198
199 public onDataUpdated() { 199 public onDataUpdated() {
200 - this.ngZone.run(() => {  
201 - this.sources.forEach((source) => {  
202 - source.timeseriesDatasource.dataUpdated(this.data);  
203 - });  
204 - this.ctx.detectChanges(); 200 + this.sources.forEach((source) => {
  201 + source.timeseriesDatasource.dataUpdated(this.data);
205 }); 202 });
206 } 203 }
207 204
@@ -410,7 +407,18 @@ export class TimeseriesTableWidgetComponent extends PageComponent implements OnI @@ -410,7 +407,18 @@ export class TimeseriesTableWidgetComponent extends PageComponent implements OnI
410 const units = contentInfo.units || this.ctx.widgetConfig.units; 407 const units = contentInfo.units || this.ctx.widgetConfig.units;
411 content = this.ctx.utils.formatValue(value, decimals, units, true); 408 content = this.ctx.utils.formatValue(value, decimals, units, true);
412 } 409 }
413 - return isDefined(content) ? this.domSanitizer.bypassSecurityTrustHtml(content) : ''; 410 +
  411 + if (!isDefined(content)) {
  412 + return '';
  413 +
  414 + } else {
  415 + switch (typeof content) {
  416 + case 'string':
  417 + return this.domSanitizer.bypassSecurityTrustHtml(content);
  418 + default:
  419 + return content;
  420 + }
  421 + }
414 } 422 }
415 } 423 }
416 424
@@ -515,26 +523,20 @@ class TimeseriesDatasource implements DataSource<TimeseriesRow> { @@ -515,26 +523,20 @@ class TimeseriesDatasource implements DataSource<TimeseriesRow> {
515 row[d + 1] = cellData[1]; 523 row[d + 1] = cellData[1];
516 }); 524 });
517 } 525 }
  526 +
518 const rows: TimeseriesRow[] = []; 527 const rows: TimeseriesRow[] = [];
519 - for (const t of Object.keys(rowsMap)) {  
520 - if (this.hideEmptyLines) {  
521 - let hideLine = true;  
522 - for (let c = 0; (c < data.length) && hideLine; c++) {  
523 - if (rowsMap[t][c + 1]) {  
524 - hideLine = false;  
525 - }  
526 - }  
527 - if (!hideLine) {  
528 - rows.push(rowsMap[t]);  
529 - } 528 +
  529 + for (const value of Object.values(rowsMap)) {
  530 + if (this.hideEmptyLines && isDefinedAndNotNull(value[1])) {
  531 + rows.push(value);
530 } else { 532 } else {
531 - rows.push(rowsMap[t]); 533 + rows.push(value);
532 } 534 }
533 } 535 }
  536 +
534 return rows; 537 return rows;
535 } 538 }
536 539
537 -  
538 isEmpty(): Observable<boolean> { 540 isEmpty(): Observable<boolean> {
539 return this.rowsSubject.pipe( 541 return this.rowsSubject.pipe(
540 map((rows) => !rows.length) 542 map((rows) => !rows.length)
@@ -96,8 +96,9 @@ export class DashboardFormComponent extends EntityComponent<Dashboard> { @@ -96,8 +96,9 @@ export class DashboardFormComponent extends EntityComponent<Dashboard> {
96 } 96 }
97 97
98 prepareFormValue(formValue: any): any { 98 prepareFormValue(formValue: any): any {
99 - formValue.configuration = {...(this.entity.configuration || {}), ...(formValue.configuration || {})};  
100 - return formValue; 99 + const preparedValue = super.prepareFormValue(formValue);
  100 + preparedValue.configuration = {...(this.entity.configuration || {}), ...(preparedValue.configuration || {})};
  101 + return preparedValue;
101 } 102 }
102 103
103 onPublicLinkCopied($event) { 104 onPublicLinkCopied($event) {
@@ -29,7 +29,8 @@ @@ -29,7 +29,8 @@
29 <mat-form-field fxFlex class="mat-block"> 29 <mat-form-field fxFlex class="mat-block">
30 <mat-label translate>rulenode.name</mat-label> 30 <mat-label translate>rulenode.name</mat-label>
31 <input matInput formControlName="name" required> 31 <input matInput formControlName="name" required>
32 - <mat-error *ngIf="ruleNodeFormGroup.get('name').hasError('required')"> 32 + <mat-error *ngIf="ruleNodeFormGroup.get('name').hasError('required')
  33 + || ruleNodeFormGroup.get('name').hasError('pattern')">
33 {{ 'rulenode.name-required' | translate }} 34 {{ 'rulenode.name-required' | translate }}
34 </mat-error> 35 </mat-error>
35 </mat-form-field> 36 </mat-form-field>
@@ -72,8 +72,9 @@ export class RuleNodeDetailsComponent extends PageComponent implements OnInit, O @@ -72,8 +72,9 @@ export class RuleNodeDetailsComponent extends PageComponent implements OnInit, O
72 } 72 }
73 if (this.ruleNode) { 73 if (this.ruleNode) {
74 if (this.ruleNode.component.type !== RuleNodeType.RULE_CHAIN) { 74 if (this.ruleNode.component.type !== RuleNodeType.RULE_CHAIN) {
  75 +
75 this.ruleNodeFormGroup = this.fb.group({ 76 this.ruleNodeFormGroup = this.fb.group({
76 - name: [this.ruleNode.name, [Validators.required]], 77 + name: [this.ruleNode.name, [Validators.required, Validators.pattern('(.|\\s)*\\S(.|\\s)*')]],
77 debugMode: [this.ruleNode.debugMode, []], 78 debugMode: [this.ruleNode.debugMode, []],
78 configuration: [this.ruleNode.configuration, [Validators.required]], 79 configuration: [this.ruleNode.configuration, [Validators.required]],
79 additionalInfo: this.fb.group( 80 additionalInfo: this.fb.group(
@@ -102,6 +103,7 @@ export class RuleNodeDetailsComponent extends PageComponent implements OnInit, O @@ -102,6 +103,7 @@ export class RuleNodeDetailsComponent extends PageComponent implements OnInit, O
102 103
103 private updateRuleNode() { 104 private updateRuleNode() {
104 const formValue = this.ruleNodeFormGroup.value || {}; 105 const formValue = this.ruleNodeFormGroup.value || {};
  106 +
105 if (this.ruleNode.component.type === RuleNodeType.RULE_CHAIN) { 107 if (this.ruleNode.component.type === RuleNodeType.RULE_CHAIN) {
106 const targetRuleChainId: string = formValue.targetRuleChainId; 108 const targetRuleChainId: string = formValue.targetRuleChainId;
107 if (this.ruleNode.targetRuleChainId !== targetRuleChainId && targetRuleChainId) { 109 if (this.ruleNode.targetRuleChainId !== targetRuleChainId && targetRuleChainId) {
@@ -115,6 +117,7 @@ export class RuleNodeDetailsComponent extends PageComponent implements OnInit, O @@ -115,6 +117,7 @@ export class RuleNodeDetailsComponent extends PageComponent implements OnInit, O
115 Object.assign(this.ruleNode, formValue); 117 Object.assign(this.ruleNode, formValue);
116 } 118 }
117 } else { 119 } else {
  120 + formValue.name = formValue.name.trim();
118 Object.assign(this.ruleNode, formValue); 121 Object.assign(this.ruleNode, formValue);
119 } 122 }
120 } 123 }
@@ -1550,6 +1550,7 @@ export class AddRuleNodeDialogComponent extends DialogComponent<AddRuleNodeDialo @@ -1550,6 +1550,7 @@ export class AddRuleNodeDialogComponent extends DialogComponent<AddRuleNodeDialo
1550 1550
1551 add(): void { 1551 add(): void {
1552 this.submitted = true; 1552 this.submitted = true;
  1553 +
1553 this.ruleNodeDetailsComponent.validate(); 1554 this.ruleNodeDetailsComponent.validate();
1554 if (this.ruleNodeDetailsComponent.ruleNodeFormGroup.valid) { 1555 if (this.ruleNodeDetailsComponent.ruleNodeFormGroup.valid) {
1555 this.dialogRef.close(this.ruleNode); 1556 this.dialogRef.close(this.ruleNode);
1 { 1 {
2 "access": { 2 "access": {
3 - "unauthorized": "권한 없음.",  
4 - "unauthorized-access": "허가되지 않은 접근", 3 + "unauthorized": "승인되지 않음",
  4 + "unauthorized-access": "승인되지 않은 접근",
5 "unauthorized-access-text": "이 리소스에 접근하려면 로그인해야 합니다!", 5 "unauthorized-access-text": "이 리소스에 접근하려면 로그인해야 합니다!",
6 "access-forbidden": "접근 금지", 6 "access-forbidden": "접근 금지",
7 - "access-forbidden-text": "접근 권한이 없습니다.!<br> 만일 이 페이지에 계속 접근하려면 다른 사용자로 로그인 하세요.",  
8 - "refresh-token-expired": "세션이 만료되었습니다.",  
9 - "refresh-token-failed": "세션을 새로 고칠 수 없습니다." 7 + "access-forbidden-text": "접근 권한이 없습니다!<br> 만일 이 페이지에 계속 접근하려면 다른 사용자로 로그인 하세요.",
  8 + "refresh-token-expired": "세션이 만료되었습니다",
  9 + "refresh-token-failed": "세션을 새로 고칠 수 없습니다.",
  10 + "permission-denied": "권한이 없습니다",
  11 + "permission-denied-text": "이 작업을 수행할 권한이 없습니다!"
10 }, 12 },
11 "action": { 13 "action": {
12 "activate": "활설화", 14 "activate": "활설화",
@@ -22,11 +24,11 @@ @@ -22,11 +24,11 @@
22 "update": "업데이트", 24 "update": "업데이트",
23 "remove": "제거", 25 "remove": "제거",
24 "search": "검색", 26 "search": "검색",
25 - "clear-search": "Clear search", 27 + "clear-search": "검색 초기화",
26 "assign": "할당", 28 "assign": "할당",
27 "unassign": "비할당", 29 "unassign": "비할당",
28 "share": "Share", 30 "share": "Share",
29 - "make-private": "Make private", 31 + "make-private": "비공개로 설정",
30 "apply": "적용", 32 "apply": "적용",
31 "apply-changes": "변경사항 적용", 33 "apply-changes": "변경사항 적용",
32 "edit-mode": "수정 모드", 34 "edit-mode": "수정 모드",
@@ -44,8 +46,8 @@ @@ -44,8 +46,8 @@
44 "undo": "취소", 46 "undo": "취소",
45 "copy": "복사", 47 "copy": "복사",
46 "paste": "붙여넣기", 48 "paste": "붙여넣기",
47 - "copy-reference": "Copy reference",  
48 - "paste-reference": "Paste reference", 49 + "copy-reference": "참조 복사",
  50 + "paste-reference": "참조 붙여넣기",
49 "import": "가져오기", 51 "import": "가져오기",
50 "export": "내보내기", 52 "export": "내보내기",
51 "share-via": "Share via {{provider}}" 53 "share-via": "Share via {{provider}}"
@@ -79,26 +81,26 @@ @@ -79,26 +81,26 @@
79 "smtp-port": "SMTP 포트", 81 "smtp-port": "SMTP 포트",
80 "smtp-port-required": "SMTP 포트를 입력해야 합니다.", 82 "smtp-port-required": "SMTP 포트를 입력해야 합니다.",
81 "smtp-port-invalid": "올바른 SMTP 포트가 아닙니다.", 83 "smtp-port-invalid": "올바른 SMTP 포트가 아닙니다.",
82 - "timeout-msec": "제한시간 (msec)",  
83 - "timeout-required": "제한시간을 입력해야 합니다.",  
84 - "timeout-invalid": "올바른 제한시간이 아닙니다.", 84 + "timeout-msec": "제한시간 (ms)",
  85 + "timeout-required": "제한시이 입력되지 않았습니다.",
  86 + "timeout-invalid": "제한시간이 올바르게 입력되지 않았습니다.",
85 "enable-tls": "TLS 사용", 87 "enable-tls": "TLS 사용",
86 "tls-version" : "TLS 버전", 88 "tls-version" : "TLS 버전",
87 "send-test-mail": "테스트 메일 보내기" 89 "send-test-mail": "테스트 메일 보내기"
88 }, 90 },
89 "alarm": { 91 "alarm": {
90 - "alarm": "Alarm",  
91 - "alarms": "Alarms",  
92 - "select-alarm": "Select alarm",  
93 - "no-alarms-matching": "No alarms matching '{{entity}}' were found.",  
94 - "alarm-required": "Alarm is required",  
95 - "alarm-status": "Alarm status", 92 + "alarm": "알람",
  93 + "alarms": "알람",
  94 + "select-alarm": "알람 선택",
  95 + "no-alarms-matching": "'{{entity}}'에 대한 알람이 존재하지 않습니다.",
  96 + "alarm-required": "알람이 필요합니다",
  97 + "alarm-status": "알람 상태",
96 "search-status": { 98 "search-status": {
97 "ANY": "Any", 99 "ANY": "Any",
98 - "ACTIVE": "Active", 100 + "ACTIVE": "활성",
99 "CLEARED": "Cleared", 101 "CLEARED": "Cleared",
100 - "ACK": "Acknowledged",  
101 - "UNACK": "Unacknowledged" 102 + "ACK": "수용",
  103 + "UNACK": "불수용"
102 }, 104 },
103 "display-status": { 105 "display-status": {
104 "ACTIVE_UNACK": "Active Unacknowledged", 106 "ACTIVE_UNACK": "Active Unacknowledged",
@@ -107,28 +109,28 @@ @@ -107,28 +109,28 @@
107 "CLEARED_ACK": "Cleared Acknowledged" 109 "CLEARED_ACK": "Cleared Acknowledged"
108 }, 110 },
109 "no-alarms-prompt": "No alarms found", 111 "no-alarms-prompt": "No alarms found",
110 - "created-time": "Created time",  
111 - "type": "Type",  
112 - "severity": "Severity",  
113 - "originator": "Originator",  
114 - "originator-type": "Originator type",  
115 - "details": "Details",  
116 - "status": "Status", 112 + "created-time": "생성된 시간",
  113 + "type": "종류",
  114 + "severity": "심각도",
  115 + "originator": "창시자",
  116 + "originator-type": "창시자 종류",
  117 + "details": "자세히",
  118 + "status": "상태",
117 "alarm-details": "Alarm details", 119 "alarm-details": "Alarm details",
118 - "start-time": "Start time",  
119 - "end-time": "End time", 120 + "start-time": "시작 시각",
  121 + "end-time": "마지막 시각",
120 "ack-time": "Acknowledged time", 122 "ack-time": "Acknowledged time",
121 "clear-time": "Cleared time", 123 "clear-time": "Cleared time",
122 - "severity-critical": "Critical",  
123 - "severity-major": "Major",  
124 - "severity-minor": "Minor",  
125 - "severity-warning": "Warning",  
126 - "severity-indeterminate": "Indeterminate",  
127 - "acknowledge": "Acknowledge",  
128 - "clear": "Clear",  
129 - "search": "Search alarms",  
130 - "selected-alarms": "{ count, plural, 1 {1 alarm} other {# alarms} } selected",  
131 - "no-data": "No data to display", 124 + "severity-critical": "심각한",
  125 + "severity-major": "주요한",
  126 + "severity-minor": "작은",
  127 + "severity-warning": "경고",
  128 + "severity-indeterminate": "중간",
  129 + "acknowledge": "수용",
  130 + "clear": "지우기",
  131 + "search": "알람 검색",
  132 + "selected-alarms": "{ count, plural, 1 {1 alarm} other {# alarms} } 선택됨",
  133 + "no-data": "표시할 데이터가 없습니다",
132 "polling-interval": "Alarms polling interval (sec)", 134 "polling-interval": "Alarms polling interval (sec)",
133 "polling-interval-required": "Alarms polling interval is required.", 135 "polling-interval-required": "Alarms polling interval is required.",
134 "min-polling-interval-message": "At least 1 sec polling interval is allowed.", 136 "min-polling-interval-message": "At least 1 sec polling interval is allowed.",
@@ -178,46 +180,46 @@ @@ -178,46 +180,46 @@
178 "any-relation": "any" 180 "any-relation": "any"
179 }, 181 },
180 "asset": { 182 "asset": {
181 - "asset": "Asset",  
182 - "assets": "Assets",  
183 - "management": "Asset management",  
184 - "view-assets": "View Assets",  
185 - "add": "Add Asset",  
186 - "assign-to-customer": "Assign to customer",  
187 - "assign-asset-to-customer": "Assign Asset(s) To Customer",  
188 - "assign-asset-to-customer-text": "Please select the assets to assign to the customer",  
189 - "no-assets-text": "No assets found",  
190 - "assign-to-customer-text": "Please select the customer to assign the asset(s)",  
191 - "public": "Public",  
192 - "assignedToCustomer": "Assigned to customer",  
193 - "make-public": "Make asset public",  
194 - "make-private": "Make asset private",  
195 - "unassign-from-customer": "Unassign from customer",  
196 - "delete": "Delete asset",  
197 - "asset-public": "Asset is public",  
198 - "asset-type": "Asset type",  
199 - "asset-type-required": "Asset type is required.",  
200 - "select-asset-type": "Select asset type",  
201 - "enter-asset-type": "Enter asset type",  
202 - "any-asset": "Any asset",  
203 - "no-asset-types-matching": "No asset types matching '{{entitySubtype}}' were found.",  
204 - "asset-type-list-empty": "No asset types selected.",  
205 - "asset-types": "Asset types",  
206 - "name": "Name",  
207 - "name-required": "Name is required.",  
208 - "description": "Description",  
209 - "type": "Type",  
210 - "type-required": "Type is required.",  
211 - "details": "Details",  
212 - "events": "Events",  
213 - "add-asset-text": "Add new asset",  
214 - "asset-details": "Asset details",  
215 - "assign-assets": "Assign assets",  
216 - "assign-assets-text": "Assign { count, plural, 1 {1 asset} other {# assets} } to customer",  
217 - "delete-assets": "Delete assets",  
218 - "unassign-assets": "Unassign assets", 183 + "asset": "자산",
  184 + "assets": "자산",
  185 + "management": "자산 관리",
  186 + "view-assets": "자산 보기",
  187 + "add": "자산 추가",
  188 + "assign-to-customer": "고객에게 자산 지정",
  189 + "assign-asset-to-customer": "자산을 고객에게 지정",
  190 + "assign-asset-to-customer-text": "고객에게 지정할 자산을 선택하세요",
  191 + "no-assets-text": "아무 자산도 없습니다",
  192 + "assign-to-customer-text": "자산에 지정될 고객을 선택하세요",
  193 + "public": "공개",
  194 + "assignedToCustomer": "지정된 고객",
  195 + "make-public": "자산을 공개로 설정",
  196 + "make-private": "자산을 비공개로 설정",
  197 + "unassign-from-customer": "고객 지정 해제",
  198 + "delete": "자산 삭제",
  199 + "asset-public": "공개된 자산",
  200 + "asset-type": "자산 종류",
  201 + "asset-type-required": "자산 종류를 선택하세요.",
  202 + "select-asset-type": "자산 종류 선택",
  203 + "enter-asset-type": "자산 종류 입력",
  204 + "any-asset": "모든 자산",
  205 + "no-asset-types-matching": "'{{entitySubtype}}'과 일치하는 자산 종류가 없습니다.",
  206 + "asset-type-list-empty": "아무 자산 종류도 선택되지 않았습니다.",
  207 + "asset-types": "자산 종류",
  208 + "name": "이름",
  209 + "name-required": "이름을 입력하세요.",
  210 + "description": "설명",
  211 + "type": "종류",
  212 + "type-required": "종류를 입력하세요.",
  213 + "details": "자세히",
  214 + "events": "이벤트",
  215 + "add-asset-text": "새로운 자산 추가",
  216 + "asset-details": "자산 자세히",
  217 + "assign-assets": "자산 지정",
  218 + "assign-assets-text": "자산 { count, plural, 1 {1 asset} other {# assets} }을 고객에게 지정",
  219 + "delete-assets": "자산 삭제",
  220 + "unassign-assets": "자산 지정 해제",
219 "unassign-assets-action-title": "Unassign { count, plural, 1 {1 asset} other {# assets} } from customer", 221 "unassign-assets-action-title": "Unassign { count, plural, 1 {1 asset} other {# assets} } from customer",
220 - "assign-new-asset": "Assign new asset", 222 + "assign-new-asset": "새로운 자산 지정",
221 "delete-asset-title": "Are you sure you want to delete the asset '{{assetName}}'?", 223 "delete-asset-title": "Are you sure you want to delete the asset '{{assetName}}'?",
222 "delete-asset-text": "Be careful, after the confirmation the asset and all related data will become unrecoverable.", 224 "delete-asset-text": "Be careful, after the confirmation the asset and all related data will become unrecoverable.",
223 "delete-assets-title": "Are you sure you want to delete { count, plural, 1 {1 asset} other {# assets} }?", 225 "delete-assets-title": "Are you sure you want to delete { count, plural, 1 {1 asset} other {# assets} }?",
@@ -248,10 +250,11 @@ @@ -248,10 +250,11 @@
248 "scope-server": "서버 속성", 250 "scope-server": "서버 속성",
249 "scope-shared": "공유 속성", 251 "scope-shared": "공유 속성",
250 "add": "속성 추가", 252 "add": "속성 추가",
251 - "key": "Key",  
252 - "key-required": "속성 key를 입력하세요.", 253 + "key": "키",
  254 + "last-update-time": "마지막 수정된 시간",
  255 + "key-required": "속성 키를 입력하세요.",
253 "value": "Value", 256 "value": "Value",
254 - "value-required": "속성 value를 입력하세요.", 257 + "value-required": "속성 값을 입력하세요.",
255 "delete-attributes-title": "{ count, plural, 1 {속성} other {여러 속성들을} } 삭제하시겠습니까??", 258 "delete-attributes-title": "{ count, plural, 1 {속성} other {여러 속성들을} } 삭제하시겠습니까??",
256 "delete-attributes-text": "모든 선택된 속성들이 제거 될 것이므로 주의하십시오.", 259 "delete-attributes-text": "모든 선택된 속성들이 제거 될 것이므로 주의하십시오.",
257 "delete-attributes": "속성 삭제", 260 "delete-attributes": "속성 삭제",
@@ -264,38 +267,40 @@ @@ -264,38 +267,40 @@
264 "add-widget-to-dashboard": "대시보드에 위젯 추가", 267 "add-widget-to-dashboard": "대시보드에 위젯 추가",
265 "selected-attributes": "{ count, plural, 1 {속성 1개} other {속성 #개} } 선택됨", 268 "selected-attributes": "{ count, plural, 1 {속성 1개} other {속성 #개} } 선택됨",
266 "selected-telemetry": "{ count, plural, 1 {최근 데이터 1개} other {최근 데이터 #개} } 선택됨" 269 "selected-telemetry": "{ count, plural, 1 {최근 데이터 1개} other {최근 데이터 #개} } 선택됨"
  270 + "no-attributes-text": "아무 속성도 찾을 수 없습니다",
  271 + "no-telemetry-text": "아무 텔레메트리도 찾을 수 없습니다."
267 }, 272 },
268 "audit-log": { 273 "audit-log": {
269 - "audit": "Audit",  
270 - "audit-logs": "Audit Logs",  
271 - "timestamp": "Timestamp",  
272 - "entity-type": "Entity Type",  
273 - "entity-name": "Entity Name",  
274 - "user": "User",  
275 - "type": "Type",  
276 - "status": "Status",  
277 - "details": "Details",  
278 - "type-added": "Added",  
279 - "type-deleted": "Deleted",  
280 - "type-updated": "Updated",  
281 - "type-attributes-updated": "Attributes updated",  
282 - "type-attributes-deleted": "Attributes deleted", 274 + "audit": "감사",
  275 + "audit-logs": "감사 로그",
  276 + "timestamp": "타임스탬프",
  277 + "entity-type": "기체 종류",
  278 + "entity-name": "개체 이름",
  279 + "user": "사용자",
  280 + "type": "종류",
  281 + "status": "상태",
  282 + "details": "자세히",
  283 + "type-added": "추가됨",
  284 + "type-deleted": "삭제됨",
  285 + "type-updated": "수정됨",
  286 + "type-attributes-updated": "속성이 수정되었습니다",
  287 + "type-attributes-deleted": "속성이 삭제되었습니다",
283 "type-rpc-call": "RPC call", 288 "type-rpc-call": "RPC call",
284 - "type-credentials-updated": "Credentials updated",  
285 - "type-assigned-to-customer": "Assigned to Customer",  
286 - "type-unassigned-from-customer": "Unassigned from Customer",  
287 - "type-activated": "Activated",  
288 - "type-suspended": "Suspended",  
289 - "type-credentials-read": "Credentials read",  
290 - "type-attributes-read": "Attributes read",  
291 - "status-success": "Success",  
292 - "status-failure": "Failure",  
293 - "audit-log-details": "Audit log details",  
294 - "no-audit-logs-prompt": "No logs found",  
295 - "action-data": "Action data",  
296 - "failure-details": "Failure details",  
297 - "search": "Search audit logs",  
298 - "clear-search": "Clear search" 289 + "type-credentials-updated": "자격 증명이 갱신되었습니다",
  290 + "type-assigned-to-customer": "고객에게 지정",
  291 + "type-unassigned-from-customer": "지정된 고객 해제",
  292 + "type-activated": "활성",
  293 + "type-suspended": "일시 중지",
  294 + "type-credentials-read": "자격 증명 읽기",
  295 + "type-attributes-read": "속성 읽기",
  296 + "status-success": "성공",
  297 + "status-failure": "실패",
  298 + "audit-log-details": "감사 로그 세부 사항",
  299 + "no-audit-logs-prompt": "아무 로그도 없습니다.",
  300 + "action-data": "액션 데이터",
  301 + "failure-details": "실패 세부 사항",
  302 + "search": "감사 로그 검색",
  303 + "clear-search": "검색 초기화"
299 }, 304 },
300 "confirm-on-exit": { 305 "confirm-on-exit": {
301 "message": "변경 사항을 저장하지 않았습니다. 이 페이지를 나가시겠습니까?", 306 "message": "변경 사항을 저장하지 않았습니다. 이 페이지를 나가시겠습니까?",
@@ -323,8 +328,8 @@ @@ -323,8 +328,8 @@
323 }, 328 },
324 "content-type": { 329 "content-type": {
325 "json": "Json", 330 "json": "Json",
326 - "text": "Text",  
327 - "binary": "Binary (Base64)" 331 + "text": "텍스트",
  332 + "binary": "바이너리 (Base64)"
328 }, 333 },
329 "customer": { 334 "customer": {
330 "customers": "커스터머", 335 "customers": "커스터머",
@@ -337,10 +342,10 @@ @@ -337,10 +342,10 @@
337 "manage-customer-users": "커스터머 사용자 관리", 342 "manage-customer-users": "커스터머 사용자 관리",
338 "manage-customer-devices": "커스터머 디바이스 관리", 343 "manage-customer-devices": "커스터머 디바이스 관리",
339 "manage-customer-dashboards": "커스터머 대시보드 관리", 344 "manage-customer-dashboards": "커스터머 대시보드 관리",
340 - "manage-public-devices": "Manage public devices",  
341 - "manage-public-dashboards": "Manage public dashboards",  
342 - "manage-customer-assets": "Manage customer assets",  
343 - "manage-public-assets": "Manage public assets", 345 + "manage-public-devices": "공개된 디바이스 관리",
  346 + "manage-public-dashboards": "공개된 대시보드 관리",
  347 + "manage-customer-assets": "고객 자산 관리",
  348 + "manage-public-assets": "공개된 자산 관리",
344 "add-customer-text": "커스터머 추가", 349 "add-customer-text": "커스터머 추가",
345 "no-customers-text": "커스터머가 없습니다.", 350 "no-customers-text": "커스터머가 없습니다.",
346 "customer-details": "커스터머 상세정보", 351 "customer-details": "커스터머 상세정보",
@@ -355,16 +360,16 @@ @@ -355,16 +360,16 @@
355 "title": "타이틀", 360 "title": "타이틀",
356 "title-required": "타이틀을 입력하세요.", 361 "title-required": "타이틀을 입력하세요.",
357 "description": "설명", 362 "description": "설명",
358 - "details": "Details",  
359 - "events": "Events",  
360 - "copyId": "Copy customer Id",  
361 - "idCopiedMessage": "Customer Id has been copied to clipboard",  
362 - "select-customer": "Select customer",  
363 - "no-customers-matching": "No customers matching '{{entity}}' were found.",  
364 - "customer-required": "Customer is required",  
365 - "select-default-customer": "Select default customer",  
366 - "default-customer": "Default customer",  
367 - "default-customer-required": "Default customer is required in order to debug dashboard on Tenant level" 363 + "details": "자세히",
  364 + "events": "이벤트",
  365 + "copyId": "고객 ID 복사",
  366 + "idCopiedMessage": "고객 ID가 클립 보드에 복사되었습니다.",
  367 + "select-customer": "선택된 고객",
  368 + "no-customers-matching": "'{{entity}}'에 해당하는 고객을 찾을 수 없습니다.",
  369 + "customer-required": "고객을 입력하세요.",
  370 + "select-default-customer": "기본 고객 선택",
  371 + "default-customer": "기본 고객",
  372 + "default-customer-required": "테넌트 수준에서 대시보드를 디버그 하기 위해서는 기본 고객이 필요합니다."
368 }, 373 },
369 "datetime": { 374 "datetime": {
370 "date-from": "시작 날짜", 375 "date-from": "시작 날짜",
@@ -522,8 +527,8 @@ @@ -522,8 +527,8 @@
522 "assign-to-customer-text": "디바이스를 할당할 커스터머를 선택하세요.", 527 "assign-to-customer-text": "디바이스를 할당할 커스터머를 선택하세요.",
523 "device-details": "디바이스 상세정보", 528 "device-details": "디바이스 상세정보",
524 "add-device-text": "디바이스 추가", 529 "add-device-text": "디바이스 추가",
525 - "credentials": "크리덴셜",  
526 - "manage-credentials": "크리덴셜 관리", 530 + "credentials": "자격 증명",
  531 + "manage-credentials": "자격 증명 관리",
527 "delete": "디바이스 삭제", 532 "delete": "디바이스 삭제",
528 "assign-devices": "디바이스 할당", 533 "assign-devices": "디바이스 할당",
529 "assign-devices-text": "{ count, plural, 1 {디바이스 1개} other {디바이스 #개} }를 커서터머에 할당", 534 "assign-devices-text": "{ count, plural, 1 {디바이스 1개} other {디바이스 #개} }를 커서터머에 할당",
@@ -575,8 +580,8 @@ @@ -575,8 +580,8 @@
575 "unknown-error": "알 수 없는 오류" 580 "unknown-error": "알 수 없는 오류"
576 }, 581 },
577 "entity": { 582 "entity": {
578 - "entity": "Entity",  
579 - "entities": "Entities", 583 + "entity": "개체",
  584 + "entities": "개체",
580 "aliases": "Entity aliases", 585 "aliases": "Entity aliases",
581 "entity-alias": "Entity alias", 586 "entity-alias": "Entity alias",
582 "unable-delete-entity-alias-title": "Unable to delete entity alias", 587 "unable-delete-entity-alias-title": "Unable to delete entity alias",
@@ -588,70 +593,70 @@ @@ -588,70 +593,70 @@
588 "alias-required": "Entity alias is required.", 593 "alias-required": "Entity alias is required.",
589 "remove-alias": "Remove entity alias", 594 "remove-alias": "Remove entity alias",
590 "add-alias": "Add entity alias", 595 "add-alias": "Add entity alias",
591 - "entity-list": "Entity list",  
592 - "entity-type": "Entity type",  
593 - "entity-types": "Entity types",  
594 - "entity-type-list": "Entity type list",  
595 - "any-entity": "Any entity",  
596 - "enter-entity-type": "Enter entity type", 596 + "entity-list": "개체 목록",
  597 + "entity-type": "개체 종류",
  598 + "entity-types": "개체 종류",
  599 + "entity-type-list": "개체 종류 목록",
  600 + "any-entity": "모든 개체",
  601 + "enter-entity-type": "개체 종류 입력",
597 "no-entities-matching": "No entities matching '{{entity}}' were found.", 602 "no-entities-matching": "No entities matching '{{entity}}' were found.",
598 "no-entity-types-matching": "No entity types matching '{{entityType}}' were found.", 603 "no-entity-types-matching": "No entity types matching '{{entityType}}' were found.",
599 - "name-starts-with": "Name starts with", 604 + "name-starts-with": "다음으로 시작하는 이름",
600 "use-entity-name-filter": "Use filter", 605 "use-entity-name-filter": "Use filter",
601 - "entity-list-empty": "No entities selected.",  
602 - "entity-type-list-empty": "No entity types selected.", 606 + "entity-list-empty": "아무 개체도 선택되지 않았습니다.",
  607 + "entity-type-list-empty": "개체 종류가 선택되지 않았습니다.",
603 "entity-name-filter-required": "Entity name filter is required.", 608 "entity-name-filter-required": "Entity name filter is required.",
604 "entity-name-filter-no-entity-matched": "No entities starting with '{{entity}}' were found.", 609 "entity-name-filter-no-entity-matched": "No entities starting with '{{entity}}' were found.",
605 - "all-subtypes": "All",  
606 - "select-entities": "Select entities", 610 + "all-subtypes": "모두",
  611 + "select-entities": "선택된 개체",
607 "no-aliases-found": "No aliases found.", 612 "no-aliases-found": "No aliases found.",
608 "no-alias-matching": "'{{alias}}' not found.", 613 "no-alias-matching": "'{{alias}}' not found.",
609 - "create-new-alias": "Create a new one!",  
610 - "key": "Key",  
611 - "key-name": "Key name",  
612 - "no-keys-found": "No keys found.",  
613 - "no-key-matching": "'{{key}}' not found.",  
614 - "create-new-key": "Create a new one!",  
615 - "type": "Type",  
616 - "type-required": "Entity type is required.",  
617 - "type-device": "Device",  
618 - "type-devices": "Devices", 614 + "create-new-alias": "생성 완료!",
  615 + "key": "키",
  616 + "key-name": "키 이름",
  617 + "no-keys-found": "아무 키도 찾을 수 없습니다..",
  618 + "no-key-matching": "'{{key}}'를 찾을 수 없습니다.",
  619 + "create-new-key": "생성 완료!",
  620 + "type": "종류",
  621 + "type-required": "개체의 종류를 입력하세요.",
  622 + "type-device": "장치",
  623 + "type-devices": "장치",
619 "list-of-devices": "{ count, plural, 1 {One device} other {List of # devices} }", 624 "list-of-devices": "{ count, plural, 1 {One device} other {List of # devices} }",
620 "device-name-starts-with": "Devices whose names start with '{{prefix}}'", 625 "device-name-starts-with": "Devices whose names start with '{{prefix}}'",
621 - "type-asset": "Asset",  
622 - "type-assets": "Assets", 626 + "type-asset": "자산",
  627 + "type-assets": "자산",
623 "list-of-assets": "{ count, plural, 1 {One asset} other {List of # assets} }", 628 "list-of-assets": "{ count, plural, 1 {One asset} other {List of # assets} }",
624 "asset-name-starts-with": "Assets whose names start with '{{prefix}}'", 629 "asset-name-starts-with": "Assets whose names start with '{{prefix}}'",
625 - "type-rule": "Rule",  
626 - "type-rules": "Rules", 630 + "type-rule": "규칙",
  631 + "type-rules": "규칙",
627 "list-of-rules": "{ count, plural, 1 {One rule} other {List of # rules} }", 632 "list-of-rules": "{ count, plural, 1 {One rule} other {List of # rules} }",
628 "rule-name-starts-with": "Rules whose names start with '{{prefix}}'", 633 "rule-name-starts-with": "Rules whose names start with '{{prefix}}'",
629 - "type-plugin": "Plugin",  
630 - "type-plugins": "Plugins", 634 + "type-plugin": "플러그인",
  635 + "type-plugins": "플러그인",
631 "list-of-plugins": "{ count, plural, 1 {One plugin} other {List of # plugins} }", 636 "list-of-plugins": "{ count, plural, 1 {One plugin} other {List of # plugins} }",
632 "plugin-name-starts-with": "Plugins whose names start with '{{prefix}}'", 637 "plugin-name-starts-with": "Plugins whose names start with '{{prefix}}'",
633 - "type-tenant": "Tenant",  
634 - "type-tenants": "Tenants", 638 + "type-tenant": "테넌트",
  639 + "type-tenants": "테넌트",
635 "list-of-tenants": "{ count, plural, 1 {One tenant} other {List of # tenants} }", 640 "list-of-tenants": "{ count, plural, 1 {One tenant} other {List of # tenants} }",
636 "tenant-name-starts-with": "Tenants whose names start with '{{prefix}}'", 641 "tenant-name-starts-with": "Tenants whose names start with '{{prefix}}'",
637 - "type-customer": "Customer",  
638 - "type-customers": "Customers", 642 + "type-customer": "고객",
  643 + "type-customers": "고객",
639 "list-of-customers": "{ count, plural, 1 {One customer} other {List of # customers} }", 644 "list-of-customers": "{ count, plural, 1 {One customer} other {List of # customers} }",
640 "customer-name-starts-with": "Customers whose names start with '{{prefix}}'", 645 "customer-name-starts-with": "Customers whose names start with '{{prefix}}'",
641 - "type-user": "User",  
642 - "type-users": "Users", 646 + "type-user": "사용자",
  647 + "type-users": "사용자",
643 "list-of-users": "{ count, plural, 1 {One user} other {List of # users} }", 648 "list-of-users": "{ count, plural, 1 {One user} other {List of # users} }",
644 "user-name-starts-with": "Users whose names start with '{{prefix}}'", 649 "user-name-starts-with": "Users whose names start with '{{prefix}}'",
645 - "type-dashboard": "Dashboard",  
646 - "type-dashboards": "Dashboards", 650 + "type-dashboard": "대시보드",
  651 + "type-dashboards": "대시보드",
647 "list-of-dashboards": "{ count, plural, 1 {One dashboard} other {List of # dashboards} }", 652 "list-of-dashboards": "{ count, plural, 1 {One dashboard} other {List of # dashboards} }",
648 "dashboard-name-starts-with": "Dashboards whose names start with '{{prefix}}'", 653 "dashboard-name-starts-with": "Dashboards whose names start with '{{prefix}}'",
649 - "type-alarm": "Alarm",  
650 - "type-alarms": "Alarms", 654 + "type-alarm": "알람",
  655 + "type-alarms": "알람",
651 "list-of-alarms": "{ count, plural, 1 {One alarms} other {List of # alarms} }", 656 "list-of-alarms": "{ count, plural, 1 {One alarms} other {List of # alarms} }",
652 "alarm-name-starts-with": "Alarms whose names start with '{{prefix}}'", 657 "alarm-name-starts-with": "Alarms whose names start with '{{prefix}}'",
653 - "type-rulechain": "Rule chain",  
654 - "type-rulechains": "Rule chains", 658 + "type-rulechain": "규칙 사슬",
  659 + "type-rulechains": "규칙 사슬",
655 "list-of-rulechains": "{ count, plural, 1 {One rule chain} other {List of # rule chains} }", 660 "list-of-rulechains": "{ count, plural, 1 {One rule chain} other {List of # rule chains} }",
656 "rulechain-name-starts-with": "Rule chains whose names start with '{{prefix}}'", 661 "rulechain-name-starts-with": "Rule chains whose names start with '{{prefix}}'",
657 "type-current-customer": "Current Customer", 662 "type-current-customer": "Current Customer",
@@ -667,23 +672,23 @@ @@ -667,23 +672,23 @@
667 "type-error": "에러", 672 "type-error": "에러",
668 "type-lc-event": "주기적 이벤트", 673 "type-lc-event": "주기적 이벤트",
669 "type-stats": "통계", 674 "type-stats": "통계",
670 - "type-debug-rule-node": "Debug",  
671 - "type-debug-rule-chain": "Debug", 675 + "type-debug-rule-node": "디버그",
  676 + "type-debug-rule-chain": "디버그",
672 "no-events-prompt": "이벤트 없음", 677 "no-events-prompt": "이벤트 없음",
673 "error": "에러", 678 "error": "에러",
674 "alarm": "알람", 679 "alarm": "알람",
675 "event-time": "이벤트 발생 시간", 680 "event-time": "이벤트 발생 시간",
676 "server": "서버", 681 "server": "서버",
677 "body": "Body", 682 "body": "Body",
678 - "method": "Method",  
679 - "type": "Type",  
680 - "entity": "Entity",  
681 - "message-id": "Message Id",  
682 - "message-type": "Message Type",  
683 - "data-type": "Data Type",  
684 - "relation-type": "Relation Type",  
685 - "metadata": "Metadata",  
686 - "data": "Data", 683 + "method": "방법",
  684 + "type": "종류",
  685 + "entity": "개체",
  686 + "message-id": "메시지 ID",
  687 + "message-type": "메시지 종류",
  688 + "data-type": "데이터 종류",
  689 + "relation-type": "관계 종류",
  690 + "metadata": "메타데이터",
  691 + "data": "데이터",
687 "event": "이벤트", 692 "event": "이벤트",
688 "status": "상태", 693 "status": "상태",
689 "success": "성공", 694 "success": "성공",
@@ -692,11 +697,11 @@ @@ -692,11 +697,11 @@
692 "errors-occurred": "오류가 발생했습니다" 697 "errors-occurred": "오류가 발생했습니다"
693 }, 698 },
694 "extension": { 699 "extension": {
695 - "extensions": "Extensions", 700 + "extensions": "확장",
696 "selected-extensions": "{ count, plural, 1 {1 extension} other {# extensions} } selected", 701 "selected-extensions": "{ count, plural, 1 {1 extension} other {# extensions} } selected",
697 - "type": "Type",  
698 - "key": "Key",  
699 - "value": "Value", 702 + "type": "종류",
  703 + "key": "키",
  704 + "value": "값",
700 "id": "Id", 705 "id": "Id",
701 "extension-id": "Extension id", 706 "extension-id": "Extension id",
702 "extension-type": "Extension type", 707 "extension-type": "Extension type",
@@ -992,14 +997,14 @@ @@ -992,14 +997,14 @@
992 "invalid-additional-info": "Unable to parse additional info json." 997 "invalid-additional-info": "Unable to parse additional info json."
993 }, 998 },
994 "rulechain": { 999 "rulechain": {
995 - "rulechain": "Rule chain",  
996 - "rulechains": "Rule chains", 1000 + "rulechain": "규칙 사슬",
  1001 + "rulechains": "규칙 사슬",
997 "root": "Root", 1002 "root": "Root",
998 "delete": "Delete rule chain", 1003 "delete": "Delete rule chain",
999 - "name": "Name",  
1000 - "name-required": "Name is required.",  
1001 - "description": "Description",  
1002 - "add": "Add Rule Chain", 1004 + "name": "이름",
  1005 + "name-required": "이름을 입력하세요.",
  1006 + "description": "설명",
  1007 + "add": "규칙 사슬 추가",
1003 "set-root": "Make rule chain root", 1008 "set-root": "Make rule chain root",
1004 "set-root-rulechain-title": "Are you sure you want to make the rule chain '{{ruleChainName}}' root?", 1009 "set-root-rulechain-title": "Are you sure you want to make the rule chain '{{ruleChainName}}' root?",
1005 "set-root-rulechain-text": "After the confirmation the rule chain will become root and will handle all incoming transport messages.", 1010 "set-root-rulechain-text": "After the confirmation the rule chain will become root and will handle all incoming transport messages.",
@@ -1008,14 +1013,14 @@ @@ -1008,14 +1013,14 @@
1008 "delete-rulechains-title": "Are you sure you want to delete { count, plural, 1 {1 rule chain} other {# rule chains} }?", 1013 "delete-rulechains-title": "Are you sure you want to delete { count, plural, 1 {1 rule chain} other {# rule chains} }?",
1009 "delete-rulechains-action-title": "Delete { count, plural, 1 {1 rule chain} other {# rule chains} }", 1014 "delete-rulechains-action-title": "Delete { count, plural, 1 {1 rule chain} other {# rule chains} }",
1010 "delete-rulechains-text": "Be careful, after the confirmation all selected rule chains will be removed and all related data will become unrecoverable.", 1015 "delete-rulechains-text": "Be careful, after the confirmation all selected rule chains will be removed and all related data will become unrecoverable.",
1011 - "add-rulechain-text": "Add new rule chain",  
1012 - "no-rulechains-text": "No rule chains found",  
1013 - "rulechain-details": "Rule chain details",  
1014 - "details": "Details",  
1015 - "events": "Events",  
1016 - "system": "System",  
1017 - "import": "Import rule chain",  
1018 - "export": "Export rule chain", 1016 + "add-rulechain-text": "새로운 규칙 사슬 추가",
  1017 + "no-rulechains-text": "아무 규칙 사슬도 없습니다.",
  1018 + "rulechain-details": "규칙 사슬 상세 정보",
  1019 + "details": "자세히",
  1020 + "events": "이벤트",
  1021 + "system": "시스템",
  1022 + "import": "규칙 사슬 불러오기",
  1023 + "export": "규칙 사슬 내보내기",
1019 "export-failed-error": "Unable to export rule chain: {{error}}", 1024 "export-failed-error": "Unable to export rule chain: {{error}}",
1020 "create-new-rulechain": "Create new rule chain", 1025 "create-new-rulechain": "Create new rule chain",
1021 "rulechain-file": "Rule chain file", 1026 "rulechain-file": "Rule chain file",
@@ -1029,70 +1034,70 @@ @@ -1029,70 +1034,70 @@
1029 "debug-mode": "Debug mode" 1034 "debug-mode": "Debug mode"
1030 }, 1035 },
1031 "rulenode": { 1036 "rulenode": {
1032 - "details": "Details",  
1033 - "events": "Events",  
1034 - "search": "Search nodes",  
1035 - "open-node-library": "Open node library",  
1036 - "add": "Add rule node",  
1037 - "name": "Name",  
1038 - "name-required": "Name is required.",  
1039 - "type": "Type",  
1040 - "description": "Description",  
1041 - "delete": "Delete rule node",  
1042 - "select-all-objects": "Select all nodes and connections",  
1043 - "deselect-all-objects": "Deselect all nodes and connections",  
1044 - "delete-selected-objects": "Delete selected nodes and connections",  
1045 - "delete-selected": "Delete selected",  
1046 - "select-all": "Select all",  
1047 - "copy-selected": "Copy selected",  
1048 - "deselect-all": "Deselect all",  
1049 - "rulenode-details": "Rule node details",  
1050 - "debug-mode": "Debug mode",  
1051 - "configuration": "Configuration",  
1052 - "link": "Link",  
1053 - "link-details": "Rule node link details",  
1054 - "add-link": "Add link",  
1055 - "link-label": "Link label",  
1056 - "link-label-required": "Link label is required.",  
1057 - "custom-link-label": "Custom link label",  
1058 - "custom-link-label-required": "Custom link label is required.",  
1059 - "type-filter": "Filter", 1037 + "details": "자세히",
  1038 + "events": "이벤트",
  1039 + "search": "노드 검색",
  1040 + "open-node-library": "노드 라이브러리 열기",
  1041 + "add": "규칙 노드 추가",
  1042 + "name": "이름",
  1043 + "name-required": "이름을 입력하세요.",
  1044 + "type": "종류",
  1045 + "description": "설명",
  1046 + "delete": "규칙 노드 삭제",
  1047 + "select-all-objects": "모든 노드와 연결을 선택",
  1048 + "deselect-all-objects": "모든 노드와 연결을 선택 해제",
  1049 + "delete-selected-objects": "선택된 노드와 연결을 삭제",
  1050 + "delete-selected": "선택 삭제",
  1051 + "select-all": "모두 선택",
  1052 + "copy-selected": "선택 복사",
  1053 + "deselect-all": "선택 해제",
  1054 + "rulenode-details": "규칙 노드 상세 정보",
  1055 + "debug-mode": "디버그 모드",
  1056 + "configuration": "설정",
  1057 + "link": "링크",
  1058 + "link-details": "규칙 노드 링크 상세 정보",
  1059 + "add-link": "링크 추가",
  1060 + "link-label": "링크 라벨",
  1061 + "link-label-required": "링크 라벨을 입력하세요.",
  1062 + "custom-link-label": "링크 라벨 사용자 정의",
  1063 + "custom-link-label-required": "링크 라벨 사용자 정의를 입력하세요.",
  1064 + "type-filter": "필터",
1060 "type-filter-details": "Filter incoming messages with configured conditions", 1065 "type-filter-details": "Filter incoming messages with configured conditions",
1061 "type-enrichment": "Enrichment", 1066 "type-enrichment": "Enrichment",
1062 "type-enrichment-details": "Add additional information into Message Metadata", 1067 "type-enrichment-details": "Add additional information into Message Metadata",
1063 "type-transformation": "Transformation", 1068 "type-transformation": "Transformation",
1064 "type-transformation-details": "Change Message payload and Metadata", 1069 "type-transformation-details": "Change Message payload and Metadata",
1065 - "type-action": "Action", 1070 + "type-action": "",
1066 "type-action-details": "Perform special action", 1071 "type-action-details": "Perform special action",
1067 - "type-external": "External", 1072 + "type-external": "외부",
1068 "type-external-details": "Interacts with external system", 1073 "type-external-details": "Interacts with external system",
1069 "type-rule-chain": "Rule Chain", 1074 "type-rule-chain": "Rule Chain",
1070 "type-rule-chain-details": "Forwards incoming messages to specified Rule Chain", 1075 "type-rule-chain-details": "Forwards incoming messages to specified Rule Chain",
1071 - "type-input": "Input", 1076 + "type-input": "입력",
1072 "type-input-details": "Logical input of Rule Chain, forwards incoming messages to next related Rule Node", 1077 "type-input-details": "Logical input of Rule Chain, forwards incoming messages to next related Rule Node",
1073 "directive-is-not-loaded": "Defined configuration directive '{{directiveName}}' is not available.", 1078 "directive-is-not-loaded": "Defined configuration directive '{{directiveName}}' is not available.",
1074 "ui-resources-load-error": "Failed to load configuration ui resources.", 1079 "ui-resources-load-error": "Failed to load configuration ui resources.",
1075 "invalid-target-rulechain": "Unable to resolve target rule chain!", 1080 "invalid-target-rulechain": "Unable to resolve target rule chain!",
1076 "test-script-function": "Test script function", 1081 "test-script-function": "Test script function",
1077 - "message": "Message",  
1078 - "message-type": "Message type",  
1079 - "message-type-required": "Message type is required",  
1080 - "metadata": "Metadata",  
1081 - "metadata-required": "Metadata entries can't be empty.",  
1082 - "output": "Output",  
1083 - "test": "Test",  
1084 - "help": "Help" 1082 + "message": "메시지",
  1083 + "message-type": "메시지 종류",
  1084 + "message-type-required": "메시지 종류를 입력하세요.",
  1085 + "metadata": "메타데이터",
  1086 + "metadata-required": "메타데이터 엔트리를 입력하세요.",
  1087 + "output": "출력",
  1088 + "test": "테스트",
  1089 + "help": "도움말"
1085 }, 1090 },
1086 "tenant": { 1091 "tenant": {
1087 "tenants": "테넌트", 1092 "tenants": "테넌트",
1088 "management": "테넌트 관리", 1093 "management": "테넌트 관리",
1089 "add": "테넌트 추가", 1094 "add": "테넌트 추가",
1090 - "admins": "Admins", 1095 + "admins": "관리자",
1091 "manage-tenant-admins": "테넌트 관리자 관리", 1096 "manage-tenant-admins": "테넌트 관리자 관리",
1092 "delete": "테넌트 삭제", 1097 "delete": "테넌트 삭제",
1093 "add-tenant-text": "테넌트 추가", 1098 "add-tenant-text": "테넌트 추가",
1094 "no-tenants-text": "테넌트가 없습니다.", 1099 "no-tenants-text": "테넌트가 없습니다.",
1095 - "tenant-details": "테넌트 상세정보", 1100 + "tenant-details": "테넌트 상세 정보",
1096 "delete-tenant-title": "'{{tenantTitle}}' 테넌트를 삭제하시겠습니까?", 1101 "delete-tenant-title": "'{{tenantTitle}}' 테넌트를 삭제하시겠습니까?",
1097 "delete-tenant-text": "테넌트와 관련된 모든 정보를 복구할 수 없으므로 주의하십시오.", 1102 "delete-tenant-text": "테넌트와 관련된 모든 정보를 복구할 수 없으므로 주의하십시오.",
1098 "delete-tenants-title": "{ count, plural, 1 {테넌트 1개} other {테넌트 #개} }를 삭제하시겠습니까?", 1103 "delete-tenants-title": "{ count, plural, 1 {테넌트 1개} other {테넌트 #개} }를 삭제하시겠습니까?",
@@ -1101,23 +1106,23 @@ @@ -1101,23 +1106,23 @@
1101 "title": "타이틀", 1106 "title": "타이틀",
1102 "title-required": "타이틀을 입력하세요.", 1107 "title-required": "타이틀을 입력하세요.",
1103 "description": "설명", 1108 "description": "설명",
1104 - "details": "Details",  
1105 - "events": "Events",  
1106 - "copyId": "Copy tenant Id",  
1107 - "idCopiedMessage": "Tenant Id has been copied to clipboard",  
1108 - "select-tenant": "Select tenant", 1109 + "details": "자세히",
  1110 + "events": "이벤트",
  1111 + "copyId": "테넌트 ID 복사",
  1112 + "idCopiedMessage": "테넌트 ID를 클립보드로 복사",
  1113 + "select-tenant": "테넌트 선택",
1109 "no-tenants-matching": "No tenants matching '{{entity}}' were found.", 1114 "no-tenants-matching": "No tenants matching '{{entity}}' were found.",
1110 - "tenant-required": "Tenant is required" 1115 + "tenant-required": "테넌트가 필요합니다."
1111 }, 1116 },
1112 "timeinterval": { 1117 "timeinterval": {
1113 "seconds-interval": "{ seconds, plural, 1 {1 second} other {# seconds} }", 1118 "seconds-interval": "{ seconds, plural, 1 {1 second} other {# seconds} }",
1114 "minutes-interval": "{ minutes, plural, 1 {1 minute} other {# minutes} }", 1119 "minutes-interval": "{ minutes, plural, 1 {1 minute} other {# minutes} }",
1115 "hours-interval": "{ hours, plural, 1 {1 hour} other {# hours} }", 1120 "hours-interval": "{ hours, plural, 1 {1 hour} other {# hours} }",
1116 "days-interval": "{ days, plural, 1 {1 day} other {# days} }", 1121 "days-interval": "{ days, plural, 1 {1 day} other {# days} }",
1117 - "days": "Days",  
1118 - "hours": "Hours",  
1119 - "minutes": "Minutes",  
1120 - "seconds": "Seconds", 1122 + "days": "일",
  1123 + "hours": "시간",
  1124 + "minutes": "분",
  1125 + "seconds": "초",
1121 "advanced": "고급" 1126 "advanced": "고급"
1122 }, 1127 },
1123 "timewindow": { 1128 "timewindow": {
@@ -1125,13 +1130,13 @@ @@ -1125,13 +1130,13 @@
1125 "hours": "{ hours, plural, 0 { hour } 1 {1 hour } other {# hours } }", 1130 "hours": "{ hours, plural, 0 { hour } 1 {1 hour } other {# hours } }",
1126 "minutes": "{ minutes, plural, 0 { minute } 1 {1 minute } other {# minutes } }", 1131 "minutes": "{ minutes, plural, 0 { minute } 1 {1 minute } other {# minutes } }",
1127 "seconds": "{ seconds, plural, 0 { second } 1 {1 second } other {# seconds } }", 1132 "seconds": "{ seconds, plural, 0 { second } 1 {1 second } other {# seconds } }",
1128 - "realtime": "Realtime",  
1129 - "history": "History",  
1130 - "last-prefix": "last",  
1131 - "period": "from {{ startTime }} to {{ endTime }}", 1133 + "realtime": "실시간",
  1134 + "history": "기록",
  1135 + "last-prefix": "과거",
  1136 + "period": "{{ startTime }}부터 {{ endTime }}까지",
1132 "edit": "타임윈도우 편집", 1137 "edit": "타임윈도우 편집",
1133 "date-range": "날짜 범위", 1138 "date-range": "날짜 범위",
1134 - "last": "Last", 1139 + "last": "과거",
1135 "time-period": "기간" 1140 "time-period": "기간"
1136 }, 1141 },
1137 "user": { 1142 "user": {
@@ -1146,7 +1151,7 @@ @@ -1146,7 +1151,7 @@
1146 "delete": "사용자 삭제", 1151 "delete": "사용자 삭제",
1147 "add-user-text": "새로운 사용자 추가", 1152 "add-user-text": "새로운 사용자 추가",
1148 "no-users-text": "사용자가 없습니다.", 1153 "no-users-text": "사용자가 없습니다.",
1149 - "user-details": "사용자 상세정보", 1154 + "user-details": "사용자 상세 정보",
1150 "delete-user-title": "'{{userEmail}}' 사용자를 삭제하시겠습니까?", 1155 "delete-user-title": "'{{userEmail}}' 사용자를 삭제하시겠습니까?",
1151 "delete-user-text": "사용자와 관련된 모든 데이터를 복구할 수 없으므로 주의하십시오.", 1156 "delete-user-text": "사용자와 관련된 모든 데이터를 복구할 수 없으므로 주의하십시오.",
1152 "delete-users-title": "{ count, plural, 1 {사용자 1명} other {사용자 #명} }을 삭제하시겠니까?", 1157 "delete-users-title": "{ count, plural, 1 {사용자 1명} other {사용자 #명} }을 삭제하시겠니까?",
@@ -1242,10 +1247,10 @@ @@ -1242,10 +1247,10 @@
1242 "update-dashboard-state": "Update current dashboard state", 1247 "update-dashboard-state": "Update current dashboard state",
1243 "open-dashboard": "Navigate to other dashboard", 1248 "open-dashboard": "Navigate to other dashboard",
1244 "custom": "Custom action", 1249 "custom": "Custom action",
1245 - "target-dashboard-state": "Target dashboard state",  
1246 - "target-dashboard-state-required": "Target dashboard state is required",  
1247 - "set-entity-from-widget": "Set entity from widget",  
1248 - "target-dashboard": "Target dashboard", 1250 + "target-dashboard-state": "대상 대시보드 상태",
  1251 + "target-dashboard-state-required": "대상 대시보드 상태가 필요합니다.",
  1252 + "set-entity-from-widget": "위젯으로 부터 객체 설정",
  1253 + "target-dashboard": "대상 대시보드",
1249 "open-right-layout": "Open right dashboard layout (mobile view)" 1254 "open-right-layout": "Open right dashboard layout (mobile view)"
1250 }, 1255 },
1251 "widgets-bundle": { 1256 "widgets-bundle": {
@@ -1253,13 +1258,13 @@ @@ -1253,13 +1258,13 @@
1253 "widgets-bundles": "위젯 번들", 1258 "widgets-bundles": "위젯 번들",
1254 "add": "위젯 번들 추가", 1259 "add": "위젯 번들 추가",
1255 "delete": "위젯 번들 삭제", 1260 "delete": "위젯 번들 삭제",
1256 - "title": "타이틀",  
1257 - "title-required": "타이틀을 입력하세요.", 1261 + "title": "제목",
  1262 + "title-required": "제목을 입력하세요.",
1258 "add-widgets-bundle-text": "위젯 번들 추가", 1263 "add-widgets-bundle-text": "위젯 번들 추가",
1259 "no-widgets-bundles-text": "위젯 번들이 없습니다.", 1264 "no-widgets-bundles-text": "위젯 번들이 없습니다.",
1260 "empty": "위젯 번들이 비어있습니다.", 1265 "empty": "위젯 번들이 비어있습니다.",
1261 "details": "상세", 1266 "details": "상세",
1262 - "widgets-bundle-details": "위젯 번들 상세정보", 1267 + "widgets-bundle-details": "위젯 번들 상세 정보",
1263 "delete-widgets-bundle-title": "'{{widgetsBundleTitle}}' 위젯 번들을 삭제하시겠습니까?", 1268 "delete-widgets-bundle-title": "'{{widgetsBundleTitle}}' 위젯 번들을 삭제하시겠습니까?",
1264 "delete-widgets-bundle-text": "위젯 번들과 관련된 모든 데이터를 복구할 수 없으므로 주의하십시오.", 1269 "delete-widgets-bundle-text": "위젯 번들과 관련된 모든 데이터를 복구할 수 없으므로 주의하십시오.",
1265 "delete-widgets-bundles-title": "{ count, plural, 1 {위젯 번들 1개} other {위젯 번들 #개} }를 삭제하시겠습니까?", 1270 "delete-widgets-bundles-title": "{ count, plural, 1 {위젯 번들 1개} other {위젯 번들 #개} }를 삭제하시겠습니까?",
@@ -1279,15 +1284,15 @@ @@ -1279,15 +1284,15 @@
1279 "data": "데이터", 1284 "data": "데이터",
1280 "settings": "설정", 1285 "settings": "설정",
1281 "advanced": "고급", 1286 "advanced": "고급",
1282 - "title": "타이틀", 1287 + "title": "제목",
1283 "general-settings": "일반 설정", 1288 "general-settings": "일반 설정",
1284 - "display-title": "타이틀 표시", 1289 + "display-title": "제목 표시",
1285 "drop-shadow": "그림자", 1290 "drop-shadow": "그림자",
1286 "enable-fullscreen": "전체화면 사용 ", 1291 "enable-fullscreen": "전체화면 사용 ",
1287 "background-color": "배경 색", 1292 "background-color": "배경 색",
1288 "text-color": "글자 색", 1293 "text-color": "글자 색",
1289 "padding": "패딩", 1294 "padding": "패딩",
1290 - "title-style": "타이틀 스타일", 1295 + "title-style": "제목 스타일",
1291 "mobile-mode-settings": "모바일 모드 설정", 1296 "mobile-mode-settings": "모바일 모드 설정",
1292 "order": "순서", 1297 "order": "순서",
1293 "height": "높이", 1298 "height": "높이",
@@ -1333,18 +1338,18 @@ @@ -1333,18 +1338,18 @@
1333 "Oct": "10월", 1338 "Oct": "10월",
1334 "Nov": "11월", 1339 "Nov": "11월",
1335 "Dec": "12월", 1340 "Dec": "12월",
1336 - "January": "일월",  
1337 - "February": "이월",  
1338 - "March": "행진",  
1339 - "April": "4 월",  
1340 - "June": "유월",  
1341 - "July": "칠월",  
1342 - "August": "팔월",  
1343 - "September": "구월",  
1344 - "October": "십월",  
1345 - "November": "십일월",  
1346 - "December": "12 월",  
1347 - "Custom Date Range": "맞춤 기간", 1341 + "January": "1월",
  1342 + "February": "2월",
  1343 + "March": "3월",
  1344 + "April": "4월",
  1345 + "June": "6월",
  1346 + "July": "7월",
  1347 + "August": "8월",
  1348 + "September": "9월",
  1349 + "October": "10월",
  1350 + "November": "11월",
  1351 + "December": "12월",
  1352 + "Custom Date Range": "임의 기간 범위",
1348 "Date Range Template": "기간 템플릿", 1353 "Date Range Template": "기간 템플릿",
1349 "Today": "오늘", 1354 "Today": "오늘",
1350 "Yesterday": "어제", 1355 "Yesterday": "어제",
@@ -1359,22 +1364,22 @@ @@ -1359,22 +1364,22 @@
1359 "Hour": "시간", 1364 "Hour": "시간",
1360 "Day": "일", 1365 "Day": "일",
1361 "Week": "주", 1366 "Week": "주",
1362 - "2 weeks": "주", 1367 + "2 weeks": "2 주",
1363 "Month": "달", 1368 "Month": "달",
1364 "3 months": "3 개월", 1369 "3 months": "3 개월",
1365 "6 months": "6 개월", 1370 "6 months": "6 개월",
1366 "Custom interval": "사용자 지정 간격", 1371 "Custom interval": "사용자 지정 간격",
1367 "Interval": "간격", 1372 "Interval": "간격",
1368 "Step size": "단계 크기", 1373 "Step size": "단계 크기",
1369 - "Ok": "Ok" 1374 + "Ok": "확인"
1370 } 1375 }
1371 } 1376 }
1372 }, 1377 },
1373 "icon": { 1378 "icon": {
1374 - "icon": "Icon",  
1375 - "select-icon": "Select icon", 1379 + "icon": "아이콘",
  1380 + "select-icon": "선택된 아이콘",
1376 "material-icons": "Material icons", 1381 "material-icons": "Material icons",
1377 - "show-all": "Show all icons" 1382 + "show-all": "모든 아이콘 보기"
1378 }, 1383 },
1379 "custom": { 1384 "custom": {
1380 "widget-action": { 1385 "widget-action": {
@@ -3,7 +3,7 @@ @@ -3,7 +3,7 @@
3 "compilerOptions": { 3 "compilerOptions": {
4 "outDir": "../out-tsc/app", 4 "outDir": "../out-tsc/app",
5 "types": ["node", "jquery", "flot", "tooltipster", "tinycolor2", "js-beautify", 5 "types": ["node", "jquery", "flot", "tooltipster", "tinycolor2", "js-beautify",
6 - "react", "react-dom", "jstree", "raphael", "canvas-gauges", "leaflet", "leaflet-markercluster"] 6 + "react", "react-dom", "jstree", "raphael", "canvas-gauges", "leaflet", "leaflet.markercluster"]
7 }, 7 },
8 "angularCompilerOptions": { 8 "angularCompilerOptions": {
9 "fullTemplateTypeCheck": true 9 "fullTemplateTypeCheck": true
@@ -1397,20 +1397,6 @@ @@ -1397,20 +1397,6 @@
1397 dependencies: 1397 dependencies:
1398 "@types/jquery" "*" 1398 "@types/jquery" "*"
1399 1399
1400 -"@types/jszip@^3.4.1":  
1401 - version "3.4.1"  
1402 - resolved "https://registry.yarnpkg.com/@types/jszip/-/jszip-3.4.1.tgz#e7a4059486e494c949ef750933d009684227846f"  
1403 - integrity sha512-TezXjmf3lj+zQ651r6hPqvSScqBLvyPI9FxdXBqpEwBijNGQ2NXpaFW/7joGzveYkKQUil7iiDHLo6LV71Pc0A==  
1404 - dependencies:  
1405 - jszip "*"  
1406 -  
1407 -"@types/leaflet-markercluster@^1.0.3":  
1408 - version "1.0.3"  
1409 - resolved "https://registry.yarnpkg.com/@types/leaflet-markercluster/-/leaflet-markercluster-1.0.3.tgz#64151be453f6490e8751500482deb961064e782c"  
1410 - integrity sha1-ZBUb5FP2SQ6HUVAEgt65YQZOeCw=  
1411 - dependencies:  
1412 - "@types/leaflet" "*"  
1413 -  
1414 "@types/leaflet-polylinedecorator@^1.6.0": 1400 "@types/leaflet-polylinedecorator@^1.6.0":
1415 version "1.6.0" 1401 version "1.6.0"
1416 resolved "https://registry.yarnpkg.com/@types/leaflet-polylinedecorator/-/leaflet-polylinedecorator-1.6.0.tgz#1572131ffedb3154c6e18e682d2fb700e203af19" 1402 resolved "https://registry.yarnpkg.com/@types/leaflet-polylinedecorator/-/leaflet-polylinedecorator-1.6.0.tgz#1572131ffedb3154c6e18e682d2fb700e203af19"
@@ -1418,6 +1404,13 @@ @@ -1418,6 +1404,13 @@
1418 dependencies: 1404 dependencies:
1419 "@types/leaflet" "*" 1405 "@types/leaflet" "*"
1420 1406
  1407 +"@types/leaflet.markercluster@^1.4.2":
  1408 + version "1.4.2"
  1409 + resolved "https://registry.yarnpkg.com/@types/leaflet.markercluster/-/leaflet.markercluster-1.4.2.tgz#86b8ab7ca2397b48d9ba637757aaf7a6d1cc6f0f"
  1410 + integrity sha512-QQ//hevAxMH2dlRQdRre7V/1G+TbtuDtZnZF/75TNwVIgklrsQVCIcS/cvLsl7UUryfPJ6xmoYHfFzK5iGVgpg==
  1411 + dependencies:
  1412 + "@types/leaflet" "*"
  1413 +
1421 "@types/leaflet@*", "@types/leaflet@^1.5.17": 1414 "@types/leaflet@*", "@types/leaflet@^1.5.17":
1422 version "1.5.17" 1415 version "1.5.17"
1423 resolved "https://registry.yarnpkg.com/@types/leaflet/-/leaflet-1.5.17.tgz#b2153dc12c344e6896a93ffc6b61ac79da251e5b" 1416 resolved "https://registry.yarnpkg.com/@types/leaflet/-/leaflet-1.5.17.tgz#b2153dc12c344e6896a93ffc6b61ac79da251e5b"
@@ -5632,7 +5625,7 @@ jstree@^3.3.10: @@ -5632,7 +5625,7 @@ jstree@^3.3.10:
5632 dependencies: 5625 dependencies:
5633 jquery ">=1.9.1" 5626 jquery ">=1.9.1"
5634 5627
5635 -jszip@*, jszip@^3.1.3, jszip@^3.5.0: 5628 +jszip@^3.1.3, jszip@^3.5.0:
5636 version "3.5.0" 5629 version "3.5.0"
5637 resolved "https://registry.yarnpkg.com/jszip/-/jszip-3.5.0.tgz#b4fd1f368245346658e781fec9675802489e15f6" 5630 resolved "https://registry.yarnpkg.com/jszip/-/jszip-3.5.0.tgz#b4fd1f368245346658e781fec9675802489e15f6"
5638 integrity sha512-WRtu7TPCmYePR1nazfrtuF216cIVon/3GWOvHS9QR5bIwSbnxtdpma6un3jyGGNhHsKCSzn5Ypk+EkDRvTGiFA== 5631 integrity sha512-WRtu7TPCmYePR1nazfrtuF216cIVon/3GWOvHS9QR5bIwSbnxtdpma6un3jyGGNhHsKCSzn5Ypk+EkDRvTGiFA==
@@ -6421,10 +6414,12 @@ ngx-color-picker@^10.0.1: @@ -6421,10 +6414,12 @@ ngx-color-picker@^10.0.1:
6421 dependencies: 6414 dependencies:
6422 tslib "^2.0.0" 6415 tslib "^2.0.0"
6423 6416
6424 -ngx-daterangepicker-material@^3.0.4:  
6425 - version "3.0.4"  
6426 - resolved "https://registry.yarnpkg.com/ngx-daterangepicker-material/-/ngx-daterangepicker-material-3.0.4.tgz#af759e52fd587fcc9bce1fbcfc8cde828df6a471"  
6427 - integrity sha512-pDg8kdXx/h8es8dpjBI+xbsxQbS0dV3uSPgfsx39t9LIw3Dv50h8T1achT5jUWSzSU7855ywTk+NlNBDTgkeNg== 6417 +ngx-daterangepicker-material@^4.0.1:
  6418 + version "4.0.1"
  6419 + resolved "https://registry.yarnpkg.com/ngx-daterangepicker-material/-/ngx-daterangepicker-material-4.0.1.tgz#788c2e32eb4717629d4a0e60a60bf8d6430d8c13"
  6420 + integrity sha512-0gY6DGU+dgYdmoAKrIJSB9xnDqBvj91Yis3II/ZJxxMfZVTG4qMMatck6w8FzdU+CYT64ArCq+Uwa6hJRHX6Nw==
  6421 + dependencies:
  6422 + tslib "^1.10.0"
6428 6423
6429 "ngx-flowchart@git://github.com/thingsboard/ngx-flowchart.git#master": 6424 "ngx-flowchart@git://github.com/thingsboard/ngx-flowchart.git#master":
6430 version "0.0.0" 6425 version "0.0.0"