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 45 import org.thingsboard.server.common.data.UpdateMessage;
46 46 import org.thingsboard.server.common.data.User;
47 47 import org.thingsboard.server.common.data.alarm.Alarm;
48   -import org.thingsboard.server.common.data.id.AlarmId;
49 48 import org.thingsboard.server.common.data.alarm.AlarmInfo;
50 49 import org.thingsboard.server.common.data.alarm.AlarmSearchStatus;
51 50 import org.thingsboard.server.common.data.alarm.AlarmSeverity;
... ... @@ -56,6 +55,7 @@ import org.thingsboard.server.common.data.audit.ActionType;
56 55 import org.thingsboard.server.common.data.audit.AuditLog;
57 56 import org.thingsboard.server.common.data.device.DeviceSearchQuery;
58 57 import org.thingsboard.server.common.data.entityview.EntityViewSearchQuery;
  58 +import org.thingsboard.server.common.data.id.AlarmId;
59 59 import org.thingsboard.server.common.data.id.AssetId;
60 60 import org.thingsboard.server.common.data.id.CustomerId;
61 61 import org.thingsboard.server.common.data.id.DashboardId;
... ... @@ -73,6 +73,7 @@ import org.thingsboard.server.common.data.kv.AttributeKvEntry;
73 73 import org.thingsboard.server.common.data.kv.TsKvEntry;
74 74 import org.thingsboard.server.common.data.page.PageData;
75 75 import org.thingsboard.server.common.data.page.PageLink;
  76 +import org.thingsboard.server.common.data.page.SortOrder;
76 77 import org.thingsboard.server.common.data.page.TimePageLink;
77 78 import org.thingsboard.server.common.data.plugin.ComponentDescriptor;
78 79 import org.thingsboard.server.common.data.plugin.ComponentType;
... ... @@ -890,7 +891,7 @@ public class RestClient implements ClientHttpRequestInterceptor, Closeable {
890 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 895 Map<String, String> params = new HashMap<>();
895 896 params.put("customerId", customerId.getId().toString());
896 897 addPageLinkToParam(params, pageLink);
... ... @@ -1629,22 +1630,42 @@ public class RestClient implements ClientHttpRequestInterceptor, Closeable {
1629 1630 return RestJsonConverter.toTimeseries(timeseries);
1630 1631 }
1631 1632
  1633 + @Deprecated
1632 1634 public List<TsKvEntry> getTimeseries(EntityId entityId, List<String> keys, Long interval, Aggregation agg, TimePageLink pageLink) {
1633 1635 return getTimeseries(entityId, keys, interval, agg, pageLink, true);
1634 1636 }
1635 1637
  1638 + @Deprecated
1636 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 1645 Map<String, String> params = new HashMap<>();
1638 1646 params.put("entityType", entityId.getEntityType().name());
1639 1647 params.put("entityId", entityId.getId().toString());
1640 1648 params.put("keys", listToString(keys));
1641 1649 params.put("interval", interval == null ? "0" : interval.toString());
1642 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 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 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 1669 HttpMethod.GET,
1649 1670 HttpEntity.EMPTY,
1650 1671 new ParameterizedTypeReference<Map<String, List<JsonNode>>>() {
... ... @@ -1996,23 +2017,12 @@ public class RestClient implements ClientHttpRequestInterceptor, Closeable {
1996 2017 }
1997 2018
1998 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 2020 String urlParams = "limit={limit}&ascOrder={ascOrder}";
2011 2021 if (pageLink.getStartTime() != null) {
2012   - urlParams += "&" + startTime + "={startTime}";
  2022 + urlParams += "&startTime={startTime}";
2013 2023 }
2014 2024 if (pageLink.getEndTime() != null) {
2015   - urlParams += "&" + endTime + "={endTime}";
  2025 + urlParams += "&endTime={endTime}";
2016 2026 }
2017 2027 return urlParams;
2018 2028 }
... ...
... ... @@ -65,7 +65,7 @@
65 65 "moment": "^2.27.0",
66 66 "ngx-clipboard": "^13.0.1",
67 67 "ngx-color-picker": "^10.0.1",
68   - "ngx-daterangepicker-material": "^3.0.4",
  68 + "ngx-daterangepicker-material": "^4.0.1",
69 69 "ngx-flowchart": "git://github.com/thingsboard/ngx-flowchart.git#master",
70 70 "ngx-hm-carousel": "^2.0.0-rc.1",
71 71 "ngx-sharebuttons": "^8.0.1",
... ... @@ -105,10 +105,9 @@
105 105 "@types/jquery": "^3.5.1",
106 106 "@types/js-beautify": "^1.11.0",
107 107 "@types/jstree": "^3.3.40",
108   - "@types/jszip": "^3.4.1",
109 108 "@types/leaflet": "^1.5.17",
110   - "@types/leaflet-markercluster": "^1.0.3",
111 109 "@types/leaflet-polylinedecorator": "^1.6.0",
  110 + "@types/leaflet.markercluster": "^1.4.2",
112 111 "@types/lodash": "^4.14.159",
113 112 "@types/raphael": "^2.3.0",
114 113 "@types/react": "^16.9.46",
... ...
... ... @@ -47,7 +47,7 @@ import {
47 47 import { forkJoin, Observable, of, ReplaySubject, Subject, throwError } from 'rxjs';
48 48 import { CancelAnimationFrame } from '@core/services/raf.service';
49 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 51 import { EntityId } from '@app/shared/models/id/entity-id';
52 52 import * as moment_ from 'moment';
53 53 import { emptyPageData, PageData } from '@shared/models/page/page-data';
... ... @@ -1332,7 +1332,7 @@ export class WidgetSubscription implements IWidgetSubscription {
1332 1332
1333 1333 private updateLegend(dataIndex: number, data: DataSet, detectChanges: boolean) {
1334 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 1336 const units = dataKey.units && dataKey.units.length ? dataKey.units : this.units;
1337 1337 const legendKeyData = this.legendData.data[dataIndex];
1338 1338 if (this.legendConfig.showMin) {
... ...
... ... @@ -421,7 +421,7 @@ export class ImportExportService {
421 421 }
422 422
423 423 public exportJSZip(data: object, filename: string) {
424   - const jsZip: JSZip = new JSZip();
  424 + const jsZip = new JSZip();
425 425 for (const keyName in data) {
426 426 if (data.hasOwnProperty(keyName)) {
427 427 const valueData = data[keyName];
... ...
... ... @@ -61,7 +61,7 @@
61 61 </div>
62 62 </mat-toolbar>
63 63 <div fxFlex class="table-container">
64   - <table mat-table [dataSource]="alarmsDatasource"
  64 + <table mat-table [dataSource]="alarmsDatasource" [trackBy]="trackByRowIndex"
65 65 matSort [matSortActive]="sortOrderProperty" [matSortDirection]="pageLinkSortDirection()" matSortDisableClear>
66 66 <ng-container matColumnDef="select" sticky>
67 67 <mat-header-cell *matHeaderCellDef style="width: 30px;">
... ...
... ... @@ -247,11 +247,8 @@ export class AlarmsTableWidgetComponent extends PageComponent implements OnInit,
247 247 }
248 248
249 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 254 public pageLinkSortDirection(): SortDirection {
... ... @@ -565,6 +562,10 @@ export class AlarmsTableWidgetComponent extends PageComponent implements OnInit,
565 562 return column.def;
566 563 }
567 564
  565 + public trackByRowIndex(index: number) {
  566 + return index;
  567 + }
  568 +
568 569 public headerStyle(key: EntityColumn): any {
569 570 const columnWidth = this.columnWidth[key.def];
570 571 return widthStyle(columnWidth);
... ... @@ -606,7 +607,19 @@ export class AlarmsTableWidgetComponent extends PageComponent implements OnInit,
606 607 } else {
607 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 623 } else {
611 624 return '';
612 625 }
... ... @@ -804,7 +817,7 @@ export class AlarmsTableWidgetComponent extends PageComponent implements OnInit,
804 817 const alarmField = alarmFields[key.name];
805 818 if (alarmField) {
806 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 821 } else if (alarmField.value === alarmFields.severity.value) {
809 822 return this.translate.instant(alarmSeverityTranslations.get(value));
810 823 } else if (alarmField.value === alarmFields.status.value) {
... ...
... ... @@ -1002,7 +1002,8 @@ export abstract class TbAnalogueGauge<S extends AnalogueGaugeSettings, O extends
1002 1002 // animations
1003 1003 animation: settings.animation !== false && !this.ctx.isMobile,
1004 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 1007 } as O;
1007 1008
1008 1009 this.prepareGaugeOptions(settings, gaugeData);
... ...
... ... @@ -38,7 +38,7 @@
38 38 </div>
39 39 </mat-toolbar>
40 40 <div fxFlex class="table-container">
41   - <table mat-table [dataSource]="entityDatasource"
  41 + <table mat-table [dataSource]="entityDatasource" [trackBy]="trackByRowIndex"
42 42 matSort [matSortActive]="sortOrderProperty" [matSortDirection]="pageLinkSortDirection()" matSortDisableClear>
43 43 <ng-container [matColumnDef]="column.def" *ngFor="let column of columns; trackBy: trackByColumnDef;">
44 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 206 }
207 207
208 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 213 public pageLinkSortDirection(): SortDirection {
... ... @@ -488,6 +485,10 @@ export class EntitiesTableWidgetComponent extends PageComponent implements OnIni
488 485 return column.def;
489 486 }
490 487
  488 + public trackByRowIndex(index: number) {
  489 + return index;
  490 + }
  491 +
491 492 public headerStyle(key: EntityColumn): any {
492 493 const columnWidth = this.columnWidth[key.def];
493 494 return widthStyle(columnWidth);
... ... @@ -529,7 +530,19 @@ export class EntitiesTableWidgetComponent extends PageComponent implements OnIni
529 530 } else {
530 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 546 } else {
534 547 return '';
535 548 }
... ...
... ... @@ -380,7 +380,7 @@ export class TbFlot {
380 380 const yaxesMap: {[units: string]: TbFlotAxisOptions} = {};
381 381 const predefinedThresholds: TbFlotThresholdMarking[] = [];
382 382 const thresholdsDatasources: Datasource[] = [];
383   - if (this.settings.customLegendEnabled) {
  383 + if (this.settings.customLegendEnabled && this.settings.dataKeysListForLabels?.length) {
384 384 this.labelPatternsSourcesData = [];
385 385 const labelPatternsDatasources: Datasource[] = [];
386 386 this.settings.dataKeysListForLabels.forEach((item) => {
... ...
... ... @@ -67,6 +67,7 @@ export class KnobComponent extends PageComponent implements OnInit, OnDestroy {
67 67 title = '';
68 68 minValue: number;
69 69 maxValue: number;
  70 + newValue = 0;
70 71
71 72 private startDeg = -1;
72 73 private currentDeg = 0;
... ... @@ -175,16 +176,15 @@ export class KnobComponent extends PageComponent implements OnInit, OnDestroy {
175 176
176 177 const offset = this.knob.offset();
177 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 183 const t: Touch = ((e.originalEvent as any).touches) ? (e.originalEvent as any).touches[0] : e;
183   -
184 184 const a = center.y - t.pageY;
185 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 188 deg = 360 + deg;
189 189 }
190 190 if (deg > this.maxDeg) {
... ... @@ -196,13 +196,17 @@ export class KnobComponent extends PageComponent implements OnInit, OnDestroy {
196 196 }
197 197 this.currentDeg = deg;
198 198 this.lastDeg = deg;
199   - this.knobTopPointerContainer.css('transform','rotate('+(this.currentDeg)+'deg)');
  199 + this.knobTopPointerContainer.css('transform', 'rotate(' + (this.currentDeg) + 'deg)');
200 200 this.turn(this.degreeToRatio(this.currentDeg));
201 201 this.rotation = this.currentDeg;
202 202 this.startDeg = -1;
  203 + this.rpcUpdateValue(this.newValue);
203 204 });
204 205
  206 +
  207 +
205 208 this.knob.on('mousedown touchstart', (e) => {
  209 + this.moving = false;
206 210 e.preventDefault();
207 211 const offset = this.knob.offset();
208 212 const center = {
... ... @@ -211,7 +215,7 @@ export class KnobComponent extends PageComponent implements OnInit, OnDestroy {
211 215 };
212 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 219 this.moving = true;
216 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 266 });
263 267
264 268 $(document).on('mouseup.rem touchend.rem',() => {
  269 + if(this.newValue !== this.rpcValue && this.moving) {
  270 + this.rpcUpdateValue(this.newValue);
  271 + }
265 272 this.knob.off('.rem');
266 273 $(document).off('.rem');
267 274 this.rotation = this.currentDeg;
... ... @@ -308,12 +315,12 @@ export class KnobComponent extends PageComponent implements OnInit, OnDestroy {
308 315 }
309 316
310 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 322 this.updateColor(this.canvasBar.getValueColor());
316   - this.onValue(value);
  323 + this.onValue(this.newValue);
317 324 }
318 325
319 326 private resize() {
... ... @@ -379,7 +386,6 @@ export class KnobComponent extends PageComponent implements OnInit, OnDestroy {
379 386 private onValue(value: number) {
380 387 this.value = this.formatValue(value);
381 388 this.checkValueSize();
382   - this.rpcUpdateValue(value);
383 389 this.ctx.detectChanges();
384 390 }
385 391
... ...
... ... @@ -112,6 +112,9 @@ $error-height: 14px !default;
112 112 height: 90%;
113 113 }
114 114
  115 + .mat-slide-toggle-label{
  116 + height: 100%;
  117 + }
115 118 .mat-slide-toggle-thumb {
116 119 top: 0;
117 120 left: 0;
... ...
... ... @@ -40,7 +40,7 @@ import {
40 40 } from '@shared/models/widget.models';
41 41 import { UtilsService } from '@core/services/utils.service';
42 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 44 import cssjs from '@core/css/css';
45 45 import { PageLink } from '@shared/models/page/page-link';
46 46 import { Direction, SortOrder, sortOrderFromString } from '@shared/models/page/sort-order';
... ... @@ -197,11 +197,8 @@ export class TimeseriesTableWidgetComponent extends PageComponent implements OnI
197 197 }
198 198
199 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 407 const units = contentInfo.units || this.ctx.widgetConfig.units;
411 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 523 row[d + 1] = cellData[1];
516 524 });
517 525 }
  526 +
518 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 532 } else {
531   - rows.push(rowsMap[t]);
  533 + rows.push(value);
532 534 }
533 535 }
  536 +
534 537 return rows;
535 538 }
536 539
537   -
538 540 isEmpty(): Observable<boolean> {
539 541 return this.rowsSubject.pipe(
540 542 map((rows) => !rows.length)
... ...
... ... @@ -96,8 +96,9 @@ export class DashboardFormComponent extends EntityComponent<Dashboard> {
96 96 }
97 97
98 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 104 onPublicLinkCopied($event) {
... ...
... ... @@ -29,7 +29,8 @@
29 29 <mat-form-field fxFlex class="mat-block">
30 30 <mat-label translate>rulenode.name</mat-label>
31 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 34 {{ 'rulenode.name-required' | translate }}
34 35 </mat-error>
35 36 </mat-form-field>
... ...
... ... @@ -72,8 +72,9 @@ export class RuleNodeDetailsComponent extends PageComponent implements OnInit, O
72 72 }
73 73 if (this.ruleNode) {
74 74 if (this.ruleNode.component.type !== RuleNodeType.RULE_CHAIN) {
  75 +
75 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 78 debugMode: [this.ruleNode.debugMode, []],
78 79 configuration: [this.ruleNode.configuration, [Validators.required]],
79 80 additionalInfo: this.fb.group(
... ... @@ -102,6 +103,7 @@ export class RuleNodeDetailsComponent extends PageComponent implements OnInit, O
102 103
103 104 private updateRuleNode() {
104 105 const formValue = this.ruleNodeFormGroup.value || {};
  106 +
105 107 if (this.ruleNode.component.type === RuleNodeType.RULE_CHAIN) {
106 108 const targetRuleChainId: string = formValue.targetRuleChainId;
107 109 if (this.ruleNode.targetRuleChainId !== targetRuleChainId && targetRuleChainId) {
... ... @@ -115,6 +117,7 @@ export class RuleNodeDetailsComponent extends PageComponent implements OnInit, O
115 117 Object.assign(this.ruleNode, formValue);
116 118 }
117 119 } else {
  120 + formValue.name = formValue.name.trim();
118 121 Object.assign(this.ruleNode, formValue);
119 122 }
120 123 }
... ...
... ... @@ -1550,6 +1550,7 @@ export class AddRuleNodeDialogComponent extends DialogComponent<AddRuleNodeDialo
1550 1550
1551 1551 add(): void {
1552 1552 this.submitted = true;
  1553 +
1553 1554 this.ruleNodeDetailsComponent.validate();
1554 1555 if (this.ruleNodeDetailsComponent.ruleNodeFormGroup.valid) {
1555 1556 this.dialogRef.close(this.ruleNode);
... ...
1 1 {
2 2 "access": {
3   - "unauthorized": "권한 없음.",
4   - "unauthorized-access": "허가되지 않은 접근",
  3 + "unauthorized": "승인되지 않음",
  4 + "unauthorized-access": "승인되지 않은 접근",
5 5 "unauthorized-access-text": "이 리소스에 접근하려면 로그인해야 합니다!",
6 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 13 "action": {
12 14 "activate": "활설화",
... ... @@ -22,11 +24,11 @@
22 24 "update": "업데이트",
23 25 "remove": "제거",
24 26 "search": "검색",
25   - "clear-search": "Clear search",
  27 + "clear-search": "검색 초기화",
26 28 "assign": "할당",
27 29 "unassign": "비할당",
28 30 "share": "Share",
29   - "make-private": "Make private",
  31 + "make-private": "비공개로 설정",
30 32 "apply": "적용",
31 33 "apply-changes": "변경사항 적용",
32 34 "edit-mode": "수정 모드",
... ... @@ -44,8 +46,8 @@
44 46 "undo": "취소",
45 47 "copy": "복사",
46 48 "paste": "붙여넣기",
47   - "copy-reference": "Copy reference",
48   - "paste-reference": "Paste reference",
  49 + "copy-reference": "참조 복사",
  50 + "paste-reference": "참조 붙여넣기",
49 51 "import": "가져오기",
50 52 "export": "내보내기",
51 53 "share-via": "Share via {{provider}}"
... ... @@ -79,26 +81,26 @@
79 81 "smtp-port": "SMTP 포트",
80 82 "smtp-port-required": "SMTP 포트를 입력해야 합니다.",
81 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 87 "enable-tls": "TLS 사용",
86 88 "tls-version" : "TLS 버전",
87 89 "send-test-mail": "테스트 메일 보내기"
88 90 },
89 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 98 "search-status": {
97 99 "ANY": "Any",
98   - "ACTIVE": "Active",
  100 + "ACTIVE": "활성",
99 101 "CLEARED": "Cleared",
100   - "ACK": "Acknowledged",
101   - "UNACK": "Unacknowledged"
  102 + "ACK": "수용",
  103 + "UNACK": "불수용"
102 104 },
103 105 "display-status": {
104 106 "ACTIVE_UNACK": "Active Unacknowledged",
... ... @@ -107,28 +109,28 @@
107 109 "CLEARED_ACK": "Cleared Acknowledged"
108 110 },
109 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 119 "alarm-details": "Alarm details",
118   - "start-time": "Start time",
119   - "end-time": "End time",
  120 + "start-time": "시작 시각",
  121 + "end-time": "마지막 시각",
120 122 "ack-time": "Acknowledged time",
121 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 134 "polling-interval": "Alarms polling interval (sec)",
133 135 "polling-interval-required": "Alarms polling interval is required.",
134 136 "min-polling-interval-message": "At least 1 sec polling interval is allowed.",
... ... @@ -178,46 +180,46 @@
178 180 "any-relation": "any"
179 181 },
180 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 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 223 "delete-asset-title": "Are you sure you want to delete the asset '{{assetName}}'?",
222 224 "delete-asset-text": "Be careful, after the confirmation the asset and all related data will become unrecoverable.",
223 225 "delete-assets-title": "Are you sure you want to delete { count, plural, 1 {1 asset} other {# assets} }?",
... ... @@ -248,10 +250,11 @@
248 250 "scope-server": "서버 속성",
249 251 "scope-shared": "공유 속성",
250 252 "add": "속성 추가",
251   - "key": "Key",
252   - "key-required": "속성 key를 입력하세요.",
  253 + "key": "키",
  254 + "last-update-time": "마지막 수정된 시간",
  255 + "key-required": "속성 키를 입력하세요.",
253 256 "value": "Value",
254   - "value-required": "속성 value를 입력하세요.",
  257 + "value-required": "속성 값을 입력하세요.",
255 258 "delete-attributes-title": "{ count, plural, 1 {속성} other {여러 속성들을} } 삭제하시겠습니까??",
256 259 "delete-attributes-text": "모든 선택된 속성들이 제거 될 것이므로 주의하십시오.",
257 260 "delete-attributes": "속성 삭제",
... ... @@ -264,38 +267,40 @@
264 267 "add-widget-to-dashboard": "대시보드에 위젯 추가",
265 268 "selected-attributes": "{ count, plural, 1 {속성 1개} other {속성 #개} } 선택됨",
266 269 "selected-telemetry": "{ count, plural, 1 {최근 데이터 1개} other {최근 데이터 #개} } 선택됨"
  270 + "no-attributes-text": "아무 속성도 찾을 수 없습니다",
  271 + "no-telemetry-text": "아무 텔레메트리도 찾을 수 없습니다."
267 272 },
268 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 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 305 "confirm-on-exit": {
301 306 "message": "변경 사항을 저장하지 않았습니다. 이 페이지를 나가시겠습니까?",
... ... @@ -323,8 +328,8 @@
323 328 },
324 329 "content-type": {
325 330 "json": "Json",
326   - "text": "Text",
327   - "binary": "Binary (Base64)"
  331 + "text": "텍스트",
  332 + "binary": "바이너리 (Base64)"
328 333 },
329 334 "customer": {
330 335 "customers": "커스터머",
... ... @@ -337,10 +342,10 @@
337 342 "manage-customer-users": "커스터머 사용자 관리",
338 343 "manage-customer-devices": "커스터머 디바이스 관리",
339 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 349 "add-customer-text": "커스터머 추가",
345 350 "no-customers-text": "커스터머가 없습니다.",
346 351 "customer-details": "커스터머 상세정보",
... ... @@ -355,16 +360,16 @@
355 360 "title": "타이틀",
356 361 "title-required": "타이틀을 입력하세요.",
357 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 374 "datetime": {
370 375 "date-from": "시작 날짜",
... ... @@ -522,8 +527,8 @@
522 527 "assign-to-customer-text": "디바이스를 할당할 커스터머를 선택하세요.",
523 528 "device-details": "디바이스 상세정보",
524 529 "add-device-text": "디바이스 추가",
525   - "credentials": "크리덴셜",
526   - "manage-credentials": "크리덴셜 관리",
  530 + "credentials": "자격 증명",
  531 + "manage-credentials": "자격 증명 관리",
527 532 "delete": "디바이스 삭제",
528 533 "assign-devices": "디바이스 할당",
529 534 "assign-devices-text": "{ count, plural, 1 {디바이스 1개} other {디바이스 #개} }를 커서터머에 할당",
... ... @@ -575,8 +580,8 @@
575 580 "unknown-error": "알 수 없는 오류"
576 581 },
577 582 "entity": {
578   - "entity": "Entity",
579   - "entities": "Entities",
  583 + "entity": "개체",
  584 + "entities": "개체",
580 585 "aliases": "Entity aliases",
581 586 "entity-alias": "Entity alias",
582 587 "unable-delete-entity-alias-title": "Unable to delete entity alias",
... ... @@ -588,70 +593,70 @@
588 593 "alias-required": "Entity alias is required.",
589 594 "remove-alias": "Remove entity alias",
590 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 602 "no-entities-matching": "No entities matching '{{entity}}' were found.",
598 603 "no-entity-types-matching": "No entity types matching '{{entityType}}' were found.",
599   - "name-starts-with": "Name starts with",
  604 + "name-starts-with": "다음으로 시작하는 이름",
600 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 608 "entity-name-filter-required": "Entity name filter is required.",
604 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 612 "no-aliases-found": "No aliases found.",
608 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 624 "list-of-devices": "{ count, plural, 1 {One device} other {List of # devices} }",
620 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 628 "list-of-assets": "{ count, plural, 1 {One asset} other {List of # assets} }",
624 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 632 "list-of-rules": "{ count, plural, 1 {One rule} other {List of # rules} }",
628 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 636 "list-of-plugins": "{ count, plural, 1 {One plugin} other {List of # plugins} }",
632 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 640 "list-of-tenants": "{ count, plural, 1 {One tenant} other {List of # tenants} }",
636 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 644 "list-of-customers": "{ count, plural, 1 {One customer} other {List of # customers} }",
640 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 648 "list-of-users": "{ count, plural, 1 {One user} other {List of # users} }",
644 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 652 "list-of-dashboards": "{ count, plural, 1 {One dashboard} other {List of # dashboards} }",
648 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 656 "list-of-alarms": "{ count, plural, 1 {One alarms} other {List of # alarms} }",
652 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 660 "list-of-rulechains": "{ count, plural, 1 {One rule chain} other {List of # rule chains} }",
656 661 "rulechain-name-starts-with": "Rule chains whose names start with '{{prefix}}'",
657 662 "type-current-customer": "Current Customer",
... ... @@ -667,23 +672,23 @@
667 672 "type-error": "에러",
668 673 "type-lc-event": "주기적 이벤트",
669 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 677 "no-events-prompt": "이벤트 없음",
673 678 "error": "에러",
674 679 "alarm": "알람",
675 680 "event-time": "이벤트 발생 시간",
676 681 "server": "서버",
677 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 692 "event": "이벤트",
688 693 "status": "상태",
689 694 "success": "성공",
... ... @@ -692,11 +697,11 @@
692 697 "errors-occurred": "오류가 발생했습니다"
693 698 },
694 699 "extension": {
695   - "extensions": "Extensions",
  700 + "extensions": "확장",
696 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 705 "id": "Id",
701 706 "extension-id": "Extension id",
702 707 "extension-type": "Extension type",
... ... @@ -992,14 +997,14 @@
992 997 "invalid-additional-info": "Unable to parse additional info json."
993 998 },
994 999 "rulechain": {
995   - "rulechain": "Rule chain",
996   - "rulechains": "Rule chains",
  1000 + "rulechain": "규칙 사슬",
  1001 + "rulechains": "규칙 사슬",
997 1002 "root": "Root",
998 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 1008 "set-root": "Make rule chain root",
1004 1009 "set-root-rulechain-title": "Are you sure you want to make the rule chain '{{ruleChainName}}' root?",
1005 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 1013 "delete-rulechains-title": "Are you sure you want to delete { count, plural, 1 {1 rule chain} other {# rule chains} }?",
1009 1014 "delete-rulechains-action-title": "Delete { count, plural, 1 {1 rule chain} other {# rule chains} }",
1010 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 1024 "export-failed-error": "Unable to export rule chain: {{error}}",
1020 1025 "create-new-rulechain": "Create new rule chain",
1021 1026 "rulechain-file": "Rule chain file",
... ... @@ -1029,70 +1034,70 @@
1029 1034 "debug-mode": "Debug mode"
1030 1035 },
1031 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 1065 "type-filter-details": "Filter incoming messages with configured conditions",
1061 1066 "type-enrichment": "Enrichment",
1062 1067 "type-enrichment-details": "Add additional information into Message Metadata",
1063 1068 "type-transformation": "Transformation",
1064 1069 "type-transformation-details": "Change Message payload and Metadata",
1065   - "type-action": "Action",
  1070 + "type-action": "",
1066 1071 "type-action-details": "Perform special action",
1067   - "type-external": "External",
  1072 + "type-external": "외부",
1068 1073 "type-external-details": "Interacts with external system",
1069 1074 "type-rule-chain": "Rule Chain",
1070 1075 "type-rule-chain-details": "Forwards incoming messages to specified Rule Chain",
1071   - "type-input": "Input",
  1076 + "type-input": "입력",
1072 1077 "type-input-details": "Logical input of Rule Chain, forwards incoming messages to next related Rule Node",
1073 1078 "directive-is-not-loaded": "Defined configuration directive '{{directiveName}}' is not available.",
1074 1079 "ui-resources-load-error": "Failed to load configuration ui resources.",
1075 1080 "invalid-target-rulechain": "Unable to resolve target rule chain!",
1076 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 1091 "tenant": {
1087 1092 "tenants": "테넌트",
1088 1093 "management": "테넌트 관리",
1089 1094 "add": "테넌트 추가",
1090   - "admins": "Admins",
  1095 + "admins": "관리자",
1091 1096 "manage-tenant-admins": "테넌트 관리자 관리",
1092 1097 "delete": "테넌트 삭제",
1093 1098 "add-tenant-text": "테넌트 추가",
1094 1099 "no-tenants-text": "테넌트가 없습니다.",
1095   - "tenant-details": "테넌트 상세정보",
  1100 + "tenant-details": "테넌트 상세 정보",
1096 1101 "delete-tenant-title": "'{{tenantTitle}}' 테넌트를 삭제하시겠습니까?",
1097 1102 "delete-tenant-text": "테넌트와 관련된 모든 정보를 복구할 수 없으므로 주의하십시오.",
1098 1103 "delete-tenants-title": "{ count, plural, 1 {테넌트 1개} other {테넌트 #개} }를 삭제하시겠습니까?",
... ... @@ -1101,23 +1106,23 @@
1101 1106 "title": "타이틀",
1102 1107 "title-required": "타이틀을 입력하세요.",
1103 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 1114 "no-tenants-matching": "No tenants matching '{{entity}}' were found.",
1110   - "tenant-required": "Tenant is required"
  1115 + "tenant-required": "테넌트가 필요합니다."
1111 1116 },
1112 1117 "timeinterval": {
1113 1118 "seconds-interval": "{ seconds, plural, 1 {1 second} other {# seconds} }",
1114 1119 "minutes-interval": "{ minutes, plural, 1 {1 minute} other {# minutes} }",
1115 1120 "hours-interval": "{ hours, plural, 1 {1 hour} other {# hours} }",
1116 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 1126 "advanced": "고급"
1122 1127 },
1123 1128 "timewindow": {
... ... @@ -1125,13 +1130,13 @@
1125 1130 "hours": "{ hours, plural, 0 { hour } 1 {1 hour } other {# hours } }",
1126 1131 "minutes": "{ minutes, plural, 0 { minute } 1 {1 minute } other {# minutes } }",
1127 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 1137 "edit": "타임윈도우 편집",
1133 1138 "date-range": "날짜 범위",
1134   - "last": "Last",
  1139 + "last": "과거",
1135 1140 "time-period": "기간"
1136 1141 },
1137 1142 "user": {
... ... @@ -1146,7 +1151,7 @@
1146 1151 "delete": "사용자 삭제",
1147 1152 "add-user-text": "새로운 사용자 추가",
1148 1153 "no-users-text": "사용자가 없습니다.",
1149   - "user-details": "사용자 상세정보",
  1154 + "user-details": "사용자 상세 정보",
1150 1155 "delete-user-title": "'{{userEmail}}' 사용자를 삭제하시겠습니까?",
1151 1156 "delete-user-text": "사용자와 관련된 모든 데이터를 복구할 수 없으므로 주의하십시오.",
1152 1157 "delete-users-title": "{ count, plural, 1 {사용자 1명} other {사용자 #명} }을 삭제하시겠니까?",
... ... @@ -1242,10 +1247,10 @@
1242 1247 "update-dashboard-state": "Update current dashboard state",
1243 1248 "open-dashboard": "Navigate to other dashboard",
1244 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 1254 "open-right-layout": "Open right dashboard layout (mobile view)"
1250 1255 },
1251 1256 "widgets-bundle": {
... ... @@ -1253,13 +1258,13 @@
1253 1258 "widgets-bundles": "위젯 번들",
1254 1259 "add": "위젯 번들 추가",
1255 1260 "delete": "위젯 번들 삭제",
1256   - "title": "타이틀",
1257   - "title-required": "타이틀을 입력하세요.",
  1261 + "title": "제목",
  1262 + "title-required": "제목을 입력하세요.",
1258 1263 "add-widgets-bundle-text": "위젯 번들 추가",
1259 1264 "no-widgets-bundles-text": "위젯 번들이 없습니다.",
1260 1265 "empty": "위젯 번들이 비어있습니다.",
1261 1266 "details": "상세",
1262   - "widgets-bundle-details": "위젯 번들 상세정보",
  1267 + "widgets-bundle-details": "위젯 번들 상세 정보",
1263 1268 "delete-widgets-bundle-title": "'{{widgetsBundleTitle}}' 위젯 번들을 삭제하시겠습니까?",
1264 1269 "delete-widgets-bundle-text": "위젯 번들과 관련된 모든 데이터를 복구할 수 없으므로 주의하십시오.",
1265 1270 "delete-widgets-bundles-title": "{ count, plural, 1 {위젯 번들 1개} other {위젯 번들 #개} }를 삭제하시겠습니까?",
... ... @@ -1279,15 +1284,15 @@
1279 1284 "data": "데이터",
1280 1285 "settings": "설정",
1281 1286 "advanced": "고급",
1282   - "title": "타이틀",
  1287 + "title": "제목",
1283 1288 "general-settings": "일반 설정",
1284   - "display-title": "타이틀 표시",
  1289 + "display-title": "제목 표시",
1285 1290 "drop-shadow": "그림자",
1286 1291 "enable-fullscreen": "전체화면 사용 ",
1287 1292 "background-color": "배경 색",
1288 1293 "text-color": "글자 색",
1289 1294 "padding": "패딩",
1290   - "title-style": "타이틀 스타일",
  1295 + "title-style": "제목 스타일",
1291 1296 "mobile-mode-settings": "모바일 모드 설정",
1292 1297 "order": "순서",
1293 1298 "height": "높이",
... ... @@ -1333,18 +1338,18 @@
1333 1338 "Oct": "10월",
1334 1339 "Nov": "11월",
1335 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 1353 "Date Range Template": "기간 템플릿",
1349 1354 "Today": "오늘",
1350 1355 "Yesterday": "어제",
... ... @@ -1359,22 +1364,22 @@
1359 1364 "Hour": "시간",
1360 1365 "Day": "일",
1361 1366 "Week": "주",
1362   - "2 weeks": "주",
  1367 + "2 weeks": "2 주",
1363 1368 "Month": "달",
1364 1369 "3 months": "3 개월",
1365 1370 "6 months": "6 개월",
1366 1371 "Custom interval": "사용자 지정 간격",
1367 1372 "Interval": "간격",
1368 1373 "Step size": "단계 크기",
1369   - "Ok": "Ok"
  1374 + "Ok": "확인"
1370 1375 }
1371 1376 }
1372 1377 },
1373 1378 "icon": {
1374   - "icon": "Icon",
1375   - "select-icon": "Select icon",
  1379 + "icon": "아이콘",
  1380 + "select-icon": "선택된 아이콘",
1376 1381 "material-icons": "Material icons",
1377   - "show-all": "Show all icons"
  1382 + "show-all": "모든 아이콘 보기"
1378 1383 },
1379 1384 "custom": {
1380 1385 "widget-action": {
... ...
... ... @@ -3,7 +3,7 @@
3 3 "compilerOptions": {
4 4 "outDir": "../out-tsc/app",
5 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 8 "angularCompilerOptions": {
9 9 "fullTemplateTypeCheck": true
... ...
... ... @@ -1397,20 +1397,6 @@
1397 1397 dependencies:
1398 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 1400 "@types/leaflet-polylinedecorator@^1.6.0":
1415 1401 version "1.6.0"
1416 1402 resolved "https://registry.yarnpkg.com/@types/leaflet-polylinedecorator/-/leaflet-polylinedecorator-1.6.0.tgz#1572131ffedb3154c6e18e682d2fb700e203af19"
... ... @@ -1418,6 +1404,13 @@
1418 1404 dependencies:
1419 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 1414 "@types/leaflet@*", "@types/leaflet@^1.5.17":
1422 1415 version "1.5.17"
1423 1416 resolved "https://registry.yarnpkg.com/@types/leaflet/-/leaflet-1.5.17.tgz#b2153dc12c344e6896a93ffc6b61ac79da251e5b"
... ... @@ -5632,7 +5625,7 @@ jstree@^3.3.10:
5632 5625 dependencies:
5633 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 5629 version "3.5.0"
5637 5630 resolved "https://registry.yarnpkg.com/jszip/-/jszip-3.5.0.tgz#b4fd1f368245346658e781fec9675802489e15f6"
5638 5631 integrity sha512-WRtu7TPCmYePR1nazfrtuF216cIVon/3GWOvHS9QR5bIwSbnxtdpma6un3jyGGNhHsKCSzn5Ypk+EkDRvTGiFA==
... ... @@ -6421,10 +6414,12 @@ ngx-color-picker@^10.0.1:
6421 6414 dependencies:
6422 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 6424 "ngx-flowchart@git://github.com/thingsboard/ngx-flowchart.git#master":
6430 6425 version "0.0.0"
... ...