Commit 10cea37abe9249459a4e43e6a4e42edcba06f774

Authored by Vladyslav_Prykhodko
Committed by Vladyslav Prykhodko
1 parent d520415d

UI: Add new setting for subscription reloadOnlyOnDataUpdated

@@ -47,7 +47,7 @@ @@ -47,7 +47,7 @@
47 "resources": [], 47 "resources": [],
48 "templateHtml": "<tb-timeseries-table-widget \n [ctx]=\"ctx\">\n</tb-timeseries-table-widget>", 48 "templateHtml": "<tb-timeseries-table-widget \n [ctx]=\"ctx\">\n</tb-timeseries-table-widget>",
49 "templateCss": "", 49 "templateCss": "",
50 - "controllerScript": "self.onInit = function() {\n}\n\nself.onDataUpdated = function() {\n self.ctx.$scope.timeseriesTableWidget.onDataUpdated();\n}\n\nself.actionSources = function() {\n return {\n 'actionCellButton': {\n name: 'widget-action.action-cell-button',\n multiple: true\n },\n 'rowClick': {\n name: 'widget-action.row-click',\n multiple: false\n }\n };\n}\n\nself.onDestroy = function() {\n}", 50 + "controllerScript": "self.onInit = function() {\n}\n\nself.onDataUpdated = function() {\n self.ctx.$scope.timeseriesTableWidget.onDataUpdated();\n}\n\nself.typeParameters = function() {\n return {\n reloadOnlyOnDataUpdated: true\n };\n}\n\nself.actionSources = function() {\n return {\n 'actionCellButton': {\n name: 'widget-action.action-cell-button',\n multiple: true\n },\n 'rowClick': {\n name: 'widget-action.row-click',\n multiple: false\n }\n };\n}\n\nself.onDestroy = function() {\n}",
51 "settingsSchema": "{\n \"schema\": {\n \"type\": \"object\",\n \"title\": \"TimeseriesTableSettings\",\n \"properties\": {\n \"showTimestamp\": {\n \"title\": \"Display timestamp column\",\n \"type\": \"boolean\",\n \"default\": true\n },\n \"showMilliseconds\": {\n \"title\": \"Display timestamp milliseconds\",\n \"type\": \"boolean\",\n \"default\": false\n },\n \"displayPagination\": {\n \"title\": \"Display pagination\",\n \"type\": \"boolean\",\n \"default\": true\n }, \n \"defaultPageSize\": {\n \"title\": \"Default page size\",\n \"type\": \"number\",\n \"default\": 10\n },\n \"hideEmptyLines\": {\n \"title\": \"Hide empty lines\",\n \"type\": \"boolean\",\n \"default\": false\n }\n },\n \"required\": []\n },\n \"form\": [\n \"showTimestamp\",\n \"showMilliseconds\",\n \"displayPagination\",\n \"defaultPageSize\",\n \"hideEmptyLines\"\n ]\n}", 51 "settingsSchema": "{\n \"schema\": {\n \"type\": \"object\",\n \"title\": \"TimeseriesTableSettings\",\n \"properties\": {\n \"showTimestamp\": {\n \"title\": \"Display timestamp column\",\n \"type\": \"boolean\",\n \"default\": true\n },\n \"showMilliseconds\": {\n \"title\": \"Display timestamp milliseconds\",\n \"type\": \"boolean\",\n \"default\": false\n },\n \"displayPagination\": {\n \"title\": \"Display pagination\",\n \"type\": \"boolean\",\n \"default\": true\n }, \n \"defaultPageSize\": {\n \"title\": \"Default page size\",\n \"type\": \"number\",\n \"default\": 10\n },\n \"hideEmptyLines\": {\n \"title\": \"Hide empty lines\",\n \"type\": \"boolean\",\n \"default\": false\n }\n },\n \"required\": []\n },\n \"form\": [\n \"showTimestamp\",\n \"showMilliseconds\",\n \"displayPagination\",\n \"defaultPageSize\",\n \"hideEmptyLines\"\n ]\n}",
52 "dataKeySettingsSchema": "{\n \"schema\": {\n \"type\": \"object\",\n \"title\": \"DataKeySettings\",\n \"properties\": {\n \"useCellStyleFunction\": {\n \"title\": \"Use cell style function\",\n \"type\": \"boolean\",\n \"default\": false\n },\n \"cellStyleFunction\": {\n \"title\": \"Cell style function: f(value)\",\n \"type\": \"string\",\n \"default\": \"\"\n },\n \"useCellContentFunction\": {\n \"title\": \"Use cell content function\",\n \"type\": \"boolean\",\n \"default\": false\n },\n \"cellContentFunction\": {\n \"title\": \"Cell content function: f(value, rowData, ctx)\",\n \"type\": \"string\",\n \"default\": \"\"\n }\n },\n \"required\": []\n },\n \"form\": [\n \"useCellStyleFunction\",\n {\n \"key\": \"cellStyleFunction\",\n \"type\": \"javascript\"\n },\n \"useCellContentFunction\",\n {\n \"key\": \"cellContentFunction\",\n \"type\": \"javascript\"\n }\n ]\n}", 52 "dataKeySettingsSchema": "{\n \"schema\": {\n \"type\": \"object\",\n \"title\": \"DataKeySettings\",\n \"properties\": {\n \"useCellStyleFunction\": {\n \"title\": \"Use cell style function\",\n \"type\": \"boolean\",\n \"default\": false\n },\n \"cellStyleFunction\": {\n \"title\": \"Cell style function: f(value)\",\n \"type\": \"string\",\n \"default\": \"\"\n },\n \"useCellContentFunction\": {\n \"title\": \"Use cell content function\",\n \"type\": \"boolean\",\n \"default\": false\n },\n \"cellContentFunction\": {\n \"title\": \"Cell content function: f(value, rowData, ctx)\",\n \"type\": \"string\",\n \"default\": \"\"\n }\n },\n \"required\": []\n },\n \"form\": [\n \"useCellStyleFunction\",\n {\n \"key\": \"cellStyleFunction\",\n \"type\": \"javascript\"\n },\n \"useCellContentFunction\",\n {\n \"key\": \"cellContentFunction\",\n \"type\": \"javascript\"\n }\n ]\n}",
53 "defaultConfig": "{\"datasources\":[{\"type\":\"function\",\"name\":\"function\",\"dataKeys\":[{\"name\":\"f(x)\",\"type\":\"function\",\"label\":\"Temperature °C\",\"color\":\"#2196f3\",\"settings\":{\"useCellStyleFunction\":true,\"cellStyleFunction\":\"if (value) {\\n var percent = (value + 60)/120 * 100;\\n var color = tinycolor.mix('blue', 'red', amount = percent);\\n color.setAlpha(.5);\\n return {\\n paddingLeft: '20px',\\n color: '#ffffff',\\n background: color.toRgbString(),\\n fontSize: '18px'\\n };\\n} else {\\n return {};\\n}\"},\"_hash\":0.8587686344902596,\"funcBody\":\"var value = prevValue + Math.random() * 40 - 20;\\nvar multiplier = Math.pow(10, 1 || 0);\\nvar value = Math.round(value * multiplier) / multiplier;\\nif (value < -60) {\\n\\tvalue = -60;\\n} else if (value > 60) {\\n\\tvalue = 60;\\n}\\nreturn value;\"},{\"name\":\"f(x)\",\"type\":\"function\",\"label\":\"Humidity, %\",\"color\":\"#ffc107\",\"settings\":{\"useCellStyleFunction\":true,\"cellStyleFunction\":\"if (value) {\\n var percent = value;\\n var backgroundColor = tinycolor('blue');\\n backgroundColor.setAlpha(value/100);\\n var color = 'blue';\\n if (value > 50) {\\n color = 'white';\\n }\\n \\n return {\\n paddingLeft: '20px',\\n color: color,\\n background: backgroundColor.toRgbString(),\\n fontSize: '18px'\\n };\\n} else {\\n return {};\\n}\",\"useCellContentFunction\":false},\"_hash\":0.12775350966079668,\"funcBody\":\"var value = prevValue + Math.random() * 20 - 10;\\nvar multiplier = Math.pow(10, 1 || 0);\\nvar value = Math.round(value * multiplier) / multiplier;\\nif (value < 5) {\\n\\tvalue = 5;\\n} else if (value > 100) {\\n\\tvalue = 100;\\n}\\nreturn value;\"}]}],\"timewindow\":{\"realtime\":{\"interval\":1000,\"timewindowMs\":60000},\"aggregation\":{\"type\":\"NONE\",\"limit\":200}},\"showTitle\":true,\"backgroundColor\":\"rgb(255, 255, 255)\",\"color\":\"rgba(0, 0, 0, 0.87)\",\"padding\":\"8px\",\"settings\":{\"showTimestamp\":true,\"displayPagination\":true,\"defaultPageSize\":10},\"title\":\"Timeseries table\",\"dropShadow\":true,\"enableFullscreen\":true,\"titleStyle\":{\"fontSize\":\"16px\",\"fontWeight\":400,\"padding\":\"5px 10px 5px 10px\"},\"useDashboardTimewindow\":false,\"showLegend\":false,\"widgetStyle\":{},\"actions\":{},\"showTitleIcon\":false,\"iconColor\":\"rgba(0, 0, 0, 0.87)\",\"iconSize\":\"24px\"}" 53 "defaultConfig": "{\"datasources\":[{\"type\":\"function\",\"name\":\"function\",\"dataKeys\":[{\"name\":\"f(x)\",\"type\":\"function\",\"label\":\"Temperature °C\",\"color\":\"#2196f3\",\"settings\":{\"useCellStyleFunction\":true,\"cellStyleFunction\":\"if (value) {\\n var percent = (value + 60)/120 * 100;\\n var color = tinycolor.mix('blue', 'red', amount = percent);\\n color.setAlpha(.5);\\n return {\\n paddingLeft: '20px',\\n color: '#ffffff',\\n background: color.toRgbString(),\\n fontSize: '18px'\\n };\\n} else {\\n return {};\\n}\"},\"_hash\":0.8587686344902596,\"funcBody\":\"var value = prevValue + Math.random() * 40 - 20;\\nvar multiplier = Math.pow(10, 1 || 0);\\nvar value = Math.round(value * multiplier) / multiplier;\\nif (value < -60) {\\n\\tvalue = -60;\\n} else if (value > 60) {\\n\\tvalue = 60;\\n}\\nreturn value;\"},{\"name\":\"f(x)\",\"type\":\"function\",\"label\":\"Humidity, %\",\"color\":\"#ffc107\",\"settings\":{\"useCellStyleFunction\":true,\"cellStyleFunction\":\"if (value) {\\n var percent = value;\\n var backgroundColor = tinycolor('blue');\\n backgroundColor.setAlpha(value/100);\\n var color = 'blue';\\n if (value > 50) {\\n color = 'white';\\n }\\n \\n return {\\n paddingLeft: '20px',\\n color: color,\\n background: backgroundColor.toRgbString(),\\n fontSize: '18px'\\n };\\n} else {\\n return {};\\n}\",\"useCellContentFunction\":false},\"_hash\":0.12775350966079668,\"funcBody\":\"var value = prevValue + Math.random() * 20 - 10;\\nvar multiplier = Math.pow(10, 1 || 0);\\nvar value = Math.round(value * multiplier) / multiplier;\\nif (value < 5) {\\n\\tvalue = 5;\\n} else if (value > 100) {\\n\\tvalue = 100;\\n}\\nreturn value;\"}]}],\"timewindow\":{\"realtime\":{\"interval\":1000,\"timewindowMs\":60000},\"aggregation\":{\"type\":\"NONE\",\"limit\":200}},\"showTitle\":true,\"backgroundColor\":\"rgb(255, 255, 255)\",\"color\":\"rgba(0, 0, 0, 0.87)\",\"padding\":\"8px\",\"settings\":{\"showTimestamp\":true,\"displayPagination\":true,\"defaultPageSize\":10},\"title\":\"Timeseries table\",\"dropShadow\":true,\"enableFullscreen\":true,\"titleStyle\":{\"fontSize\":\"16px\",\"fontWeight\":400,\"padding\":\"5px 10px 5px 10px\"},\"useDashboardTimewindow\":false,\"showLegend\":false,\"widgetStyle\":{},\"actions\":{},\"showTitleIcon\":false,\"iconColor\":\"rgba(0, 0, 0, 0.87)\",\"iconSize\":\"24px\"}"
@@ -134,4 +134,4 @@ @@ -134,4 +134,4 @@
134 } 134 }
135 } 135 }
136 ] 136 ]
137 -}  
  137 +}
@@ -71,6 +71,7 @@ export class DataAggregator { @@ -71,6 +71,7 @@ export class DataAggregator {
71 71
72 private dataReceived = false; 72 private dataReceived = false;
73 private resetPending = false; 73 private resetPending = false;
  74 + private updatedData = false;
74 75
75 private noAggregation = this.aggregationType === AggregationType.NONE; 76 private noAggregation = this.aggregationType === AggregationType.NONE;
76 private aggregationTimeout = Math.max(this.interval, 1000); 77 private aggregationTimeout = Math.max(this.interval, 1000);
@@ -90,7 +91,8 @@ export class DataAggregator { @@ -90,7 +91,8 @@ export class DataAggregator {
90 private timeWindow: number, 91 private timeWindow: number,
91 private interval: number, 92 private interval: number,
92 private stateData: boolean, 93 private stateData: boolean,
93 - private utils: UtilsService) { 94 + private utils: UtilsService,
  95 + private isReloadOnlyOnDataUpdated: boolean) {
94 this.tsKeyNames.forEach((key) => { 96 this.tsKeyNames.forEach((key) => {
95 this.dataBuffer[key] = []; 97 this.dataBuffer[key] = [];
96 }); 98 });
@@ -140,6 +142,7 @@ export class DataAggregator { @@ -140,6 +142,7 @@ export class DataAggregator {
140 this.elapsed = 0; 142 this.elapsed = 0;
141 this.aggregationTimeout = Math.max(this.interval, 1000); 143 this.aggregationTimeout = Math.max(this.interval, 1000);
142 this.resetPending = true; 144 this.resetPending = true;
  145 + this.updatedData = false;
143 this.intervalTimeoutHandle = setTimeout(this.onInterval.bind(this), this.aggregationTimeout); 146 this.intervalTimeoutHandle = setTimeout(this.onInterval.bind(this), this.aggregationTimeout);
144 } 147 }
145 148
@@ -180,6 +183,7 @@ export class DataAggregator { @@ -180,6 +183,7 @@ export class DataAggregator {
180 this.onInterval(history, detectChanges); 183 this.onInterval(history, detectChanges);
181 } 184 }
182 } 185 }
  186 + this.updatedData = true;
183 } 187 }
184 188
185 private onInterval(history?: boolean, detectChanges?: boolean) { 189 private onInterval(history?: boolean, detectChanges?: boolean) {
@@ -201,8 +205,9 @@ export class DataAggregator { @@ -201,8 +205,9 @@ export class DataAggregator {
201 } else { 205 } else {
202 this.data = this.updateData(); 206 this.data = this.updateData();
203 } 207 }
204 - if (this.onDataCb) { 208 + if (this.onDataCb && (!this.isReloadOnlyOnDataUpdated || this.updatedData)) {
205 this.onDataCb(this.data, detectChanges); 209 this.onDataCb(this.data, detectChanges);
  210 + this.updatedData = false;
206 } 211 }
207 if (!history) { 212 if (!history) {
208 this.intervalTimeoutHandle = setTimeout(this.onInterval.bind(this), this.aggregationTimeout); 213 this.intervalTimeoutHandle = setTimeout(this.onInterval.bind(this), this.aggregationTimeout);
@@ -223,6 +228,7 @@ export class DataAggregator { @@ -223,6 +228,7 @@ export class DataAggregator {
223 this.lastPrevKvPairData[key] = [aggTimestamp, aggData.aggValue]; 228 this.lastPrevKvPairData[key] = [aggTimestamp, aggData.aggValue];
224 } 229 }
225 aggKeyData.delete(aggTimestamp); 230 aggKeyData.delete(aggTimestamp);
  231 + this.updatedData = true;
226 } else if (aggTimestamp <= this.endTs) { 232 } else if (aggTimestamp <= this.endTs) {
227 const kvPair: [number, any] = [aggTimestamp, aggData.aggValue]; 233 const kvPair: [number, any] = [aggTimestamp, aggData.aggValue];
228 keyData.push(kvPair); 234 keyData.push(kvPair);
@@ -66,6 +66,7 @@ export interface EntityDataSubscriptionOptions { @@ -66,6 +66,7 @@ export interface EntityDataSubscriptionOptions {
66 type: widgetType; 66 type: widgetType;
67 entityFilter?: EntityFilter; 67 entityFilter?: EntityFilter;
68 isPaginatedDataSubscription?: boolean; 68 isPaginatedDataSubscription?: boolean;
  69 + isReloadOnlyOnDataUpdated?: boolean;
69 pageLink?: EntityDataPageLink; 70 pageLink?: EntityDataPageLink;
70 keyFilters?: Array<KeyFilter>; 71 keyFilters?: Array<KeyFilter>;
71 additionalKeyFilters?: Array<KeyFilter>; 72 additionalKeyFilters?: Array<KeyFilter>;
@@ -671,7 +672,8 @@ export class EntityDataSubscription { @@ -671,7 +672,8 @@ export class EntityDataSubscription {
671 subsTw.aggregation.timeWindow, 672 subsTw.aggregation.timeWindow,
672 subsTw.aggregation.interval, 673 subsTw.aggregation.interval,
673 subsTw.aggregation.stateData, 674 subsTw.aggregation.stateData,
674 - this.utils 675 + this.utils,
  676 + this.entityDataSubscriptionOptions.isReloadOnlyOnDataUpdated
675 ); 677 );
676 } 678 }
677 679
@@ -60,7 +60,8 @@ export class EntityDataService { @@ -60,7 +60,8 @@ export class EntityDataService {
60 constructor(private telemetryService: TelemetryWebsocketService, 60 constructor(private telemetryService: TelemetryWebsocketService,
61 private utils: UtilsService) {} 61 private utils: UtilsService) {}
62 62
63 - public prepareSubscription(listener: EntityDataListener): Observable<EntityDataLoadResult> { 63 + public prepareSubscription(listener: EntityDataListener,
  64 + isReloadOnlyOnDataUpdated = false): Observable<EntityDataLoadResult> {
64 const datasource = listener.configDatasource; 65 const datasource = listener.configDatasource;
65 listener.subscriptionOptions = this.createSubscriptionOptions( 66 listener.subscriptionOptions = this.createSubscriptionOptions(
66 datasource, 67 datasource,
@@ -68,7 +69,8 @@ export class EntityDataService { @@ -68,7 +69,8 @@ export class EntityDataService {
68 datasource.pageLink, 69 datasource.pageLink,
69 datasource.keyFilters, 70 datasource.keyFilters,
70 null, 71 null,
71 - false); 72 + false,
  73 + isReloadOnlyOnDataUpdated);
72 if (datasource.type === DatasourceType.entity && (!datasource.entityFilter || !datasource.pageLink)) { 74 if (datasource.type === DatasourceType.entity && (!datasource.entityFilter || !datasource.pageLink)) {
73 return of(null); 75 return of(null);
74 } 76 }
@@ -87,7 +89,8 @@ export class EntityDataService { @@ -87,7 +89,8 @@ export class EntityDataService {
87 89
88 public subscribeForPaginatedData(listener: EntityDataListener, 90 public subscribeForPaginatedData(listener: EntityDataListener,
89 pageLink: EntityDataPageLink, 91 pageLink: EntityDataPageLink,
90 - keyFilters: KeyFilter[]): Observable<EntityDataLoadResult> { 92 + keyFilters: KeyFilter[],
  93 + isReloadOnlyOnDataUpdated = false): Observable<EntityDataLoadResult> {
91 const datasource = listener.configDatasource; 94 const datasource = listener.configDatasource;
92 listener.subscriptionOptions = this.createSubscriptionOptions( 95 listener.subscriptionOptions = this.createSubscriptionOptions(
93 datasource, 96 datasource,
@@ -95,7 +98,8 @@ export class EntityDataService { @@ -95,7 +98,8 @@ export class EntityDataService {
95 pageLink, 98 pageLink,
96 datasource.keyFilters, 99 datasource.keyFilters,
97 keyFilters, 100 keyFilters,
98 - true); 101 + true,
  102 + isReloadOnlyOnDataUpdated);
99 if (datasource.type === DatasourceType.entity && (!datasource.entityFilter || !pageLink)) { 103 if (datasource.type === DatasourceType.entity && (!datasource.entityFilter || !pageLink)) {
100 listener.dataLoaded(emptyPageData<EntityData>(), [], 104 listener.dataLoaded(emptyPageData<EntityData>(), [],
101 listener.configDatasourceIndex, listener.subscriptionOptions.pageLink); 105 listener.configDatasourceIndex, listener.subscriptionOptions.pageLink);
@@ -119,7 +123,8 @@ export class EntityDataService { @@ -119,7 +123,8 @@ export class EntityDataService {
119 pageLink: EntityDataPageLink, 123 pageLink: EntityDataPageLink,
120 keyFilters: KeyFilter[], 124 keyFilters: KeyFilter[],
121 additionalKeyFilters: KeyFilter[], 125 additionalKeyFilters: KeyFilter[],
122 - isPaginatedDataSubscription: boolean): EntityDataSubscriptionOptions { 126 + isPaginatedDataSubscription: boolean,
  127 + isReloadOnlyOnDataUpdated: boolean): EntityDataSubscriptionOptions {
123 const subscriptionDataKeys: Array<SubscriptionDataKey> = []; 128 const subscriptionDataKeys: Array<SubscriptionDataKey> = [];
124 datasource.dataKeys.forEach((dataKey) => { 129 datasource.dataKeys.forEach((dataKey) => {
125 const subscriptionDataKey: SubscriptionDataKey = { 130 const subscriptionDataKey: SubscriptionDataKey = {
@@ -142,6 +147,7 @@ export class EntityDataService { @@ -142,6 +147,7 @@ export class EntityDataService {
142 entityDataSubscriptionOptions.additionalKeyFilters = additionalKeyFilters; 147 entityDataSubscriptionOptions.additionalKeyFilters = additionalKeyFilters;
143 } 148 }
144 entityDataSubscriptionOptions.isPaginatedDataSubscription = isPaginatedDataSubscription; 149 entityDataSubscriptionOptions.isPaginatedDataSubscription = isPaginatedDataSubscription;
  150 + entityDataSubscriptionOptions.isReloadOnlyOnDataUpdated = isReloadOnlyOnDataUpdated;
145 return entityDataSubscriptionOptions; 151 return entityDataSubscriptionOptions;
146 } 152 }
147 } 153 }
@@ -226,6 +226,7 @@ export interface WidgetSubscriptionOptions { @@ -226,6 +226,7 @@ export interface WidgetSubscriptionOptions {
226 hasDataPageLink?: boolean; 226 hasDataPageLink?: boolean;
227 singleEntity?: boolean; 227 singleEntity?: boolean;
228 warnOnPageDataOverflow?: boolean; 228 warnOnPageDataOverflow?: boolean;
  229 + reloadOnlyOnDataUpdated?: boolean;
229 targetDeviceAliasIds?: Array<string>; 230 targetDeviceAliasIds?: Array<string>;
230 targetDeviceIds?: Array<string>; 231 targetDeviceIds?: Array<string>;
231 useDashboardTimewindow?: boolean; 232 useDashboardTimewindow?: boolean;
@@ -83,6 +83,7 @@ export class WidgetSubscription implements IWidgetSubscription { @@ -83,6 +83,7 @@ export class WidgetSubscription implements IWidgetSubscription {
83 hasDataPageLink: boolean; 83 hasDataPageLink: boolean;
84 singleEntity: boolean; 84 singleEntity: boolean;
85 warnOnPageDataOverflow: boolean; 85 warnOnPageDataOverflow: boolean;
  86 + reloadOnlyOnDataUpdated: boolean;
86 87
87 datasourcePages: PageData<Datasource>[]; 88 datasourcePages: PageData<Datasource>[];
88 dataPages: PageData<Array<DatasourceData>>[]; 89 dataPages: PageData<Array<DatasourceData>>[];
@@ -200,6 +201,7 @@ export class WidgetSubscription implements IWidgetSubscription { @@ -200,6 +201,7 @@ export class WidgetSubscription implements IWidgetSubscription {
200 this.hasDataPageLink = options.hasDataPageLink; 201 this.hasDataPageLink = options.hasDataPageLink;
201 this.singleEntity = options.singleEntity; 202 this.singleEntity = options.singleEntity;
202 this.warnOnPageDataOverflow = options.warnOnPageDataOverflow; 203 this.warnOnPageDataOverflow = options.warnOnPageDataOverflow;
  204 + this.reloadOnlyOnDataUpdated = options.reloadOnlyOnDataUpdated;
203 this.datasourcePages = []; 205 this.datasourcePages = [];
204 this.datasources = []; 206 this.datasources = [];
205 this.dataPages = []; 207 this.dataPages = [];
@@ -423,7 +425,7 @@ export class WidgetSubscription implements IWidgetSubscription { @@ -423,7 +425,7 @@ export class WidgetSubscription implements IWidgetSubscription {
423 } 425 }
424 }; 426 };
425 this.entityDataListeners.push(listener); 427 this.entityDataListeners.push(listener);
426 - return this.ctx.entityDataService.prepareSubscription(listener); 428 + return this.ctx.entityDataService.prepareSubscription(listener, this.reloadOnlyOnDataUpdated);
427 }); 429 });
428 return forkJoin(resolveResultObservables).pipe( 430 return forkJoin(resolveResultObservables).pipe(
429 map((resolveResults) => { 431 map((resolveResults) => {
@@ -815,7 +817,7 @@ export class WidgetSubscription implements IWidgetSubscription { @@ -815,7 +817,7 @@ export class WidgetSubscription implements IWidgetSubscription {
815 } 817 }
816 }; 818 };
817 this.entityDataListeners[datasourceIndex] = entityDataListener; 819 this.entityDataListeners[datasourceIndex] = entityDataListener;
818 - return this.ctx.entityDataService.subscribeForPaginatedData(entityDataListener, pageLink, keyFilters); 820 + return this.ctx.entityDataService.subscribeForPaginatedData(entityDataListener, pageLink, keyFilters, this.reloadOnlyOnDataUpdated);
819 } else { 821 } else {
820 return of(null); 822 return of(null);
821 } 823 }
@@ -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, isEqual, isNumber } from '@core/utils'; 43 +import { hashCode, isDefined, 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';
@@ -578,8 +578,7 @@ class TimeseriesDatasource implements DataSource<TimeseriesRow> { @@ -578,8 +578,7 @@ class TimeseriesDatasource implements DataSource<TimeseriesRow> {
578 578
579 private fetchRows(pageLink: PageLink): Observable<PageData<TimeseriesRow>> { 579 private fetchRows(pageLink: PageLink): Observable<PageData<TimeseriesRow>> {
580 return this.allRows$.pipe( 580 return this.allRows$.pipe(
581 - map((data) => pageLink.filterData(data)),  
582 - distinctUntilChanged((prev, curr) => isEqual(prev, curr)) 581 + map((data) => pageLink.filterData(data))
583 ); 582 );
584 } 583 }
585 } 584 }
@@ -485,6 +485,9 @@ export class WidgetComponentService { @@ -485,6 +485,9 @@ export class WidgetComponentService {
485 if (isUndefined(result.typeParameters.warnOnPageDataOverflow)) { 485 if (isUndefined(result.typeParameters.warnOnPageDataOverflow)) {
486 result.typeParameters.warnOnPageDataOverflow = true; 486 result.typeParameters.warnOnPageDataOverflow = true;
487 } 487 }
  488 + if (isUndefined(result.typeParameters.reloadOnlyOnDataUpdated)) {
  489 + result.typeParameters.reloadOnlyOnDataUpdated = false;
  490 + }
488 if (isUndefined(result.typeParameters.dataKeysOptional)) { 491 if (isUndefined(result.typeParameters.dataKeysOptional)) {
489 result.typeParameters.dataKeysOptional = false; 492 result.typeParameters.dataKeysOptional = false;
490 } 493 }
@@ -895,6 +895,7 @@ export class WidgetComponent extends PageComponent implements OnInit, AfterViewI @@ -895,6 +895,7 @@ export class WidgetComponent extends PageComponent implements OnInit, AfterViewI
895 hasDataPageLink: this.typeParameters.hasDataPageLink, 895 hasDataPageLink: this.typeParameters.hasDataPageLink,
896 singleEntity: this.typeParameters.singleEntity, 896 singleEntity: this.typeParameters.singleEntity,
897 warnOnPageDataOverflow: this.typeParameters.warnOnPageDataOverflow, 897 warnOnPageDataOverflow: this.typeParameters.warnOnPageDataOverflow,
  898 + reloadOnlyOnDataUpdated: this.typeParameters.reloadOnlyOnDataUpdated,
898 comparisonEnabled: comparisonSettings.comparisonEnabled, 899 comparisonEnabled: comparisonSettings.comparisonEnabled,
899 timeForComparison: comparisonSettings.timeForComparison 900 timeForComparison: comparisonSettings.timeForComparison
900 }; 901 };
@@ -154,6 +154,7 @@ export interface WidgetTypeParameters { @@ -154,6 +154,7 @@ export interface WidgetTypeParameters {
154 hasDataPageLink?: boolean; 154 hasDataPageLink?: boolean;
155 singleEntity?: boolean; 155 singleEntity?: boolean;
156 warnOnPageDataOverflow?: boolean; 156 warnOnPageDataOverflow?: boolean;
  157 + reloadOnlyOnDataUpdated?: boolean;
157 } 158 }
158 159
159 export interface WidgetControllerDescriptor { 160 export interface WidgetControllerDescriptor {