@openremote/or-dashboard-builder 1.2.0-snapshot.20241015145246 → 1.2.0-snapshot.20241218144812

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1 +1 @@
1
- {"version":3,"file":"gauge-widget.js","sourceRoot":"","sources":["../../src/widgets/gauge-widget.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"gauge-widget.js","sourceRoot":"","sources":["../../src/widgets/gauge-widget.ts"],"names":[],"mappings":"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"}
@@ -1,13 +1,17 @@
1
- var KpiWidget_1,__decorate=this&&this.__decorate||function(t,e,i,s){var o,r=arguments.length,d=r<3?e:null===s?s=Object.getOwnPropertyDescriptor(e,i):s;if("object"==typeof Reflect&&"function"==typeof Reflect.decorate)d=Reflect.decorate(t,e,i,s);else for(var n=t.length-1;n>=0;n--)(o=t[n])&&(d=(r<3?o(d):r>3?o(e,i,d):o(e,i))||d);return r>3&&d&&Object.defineProperty(e,i,d),d};import{customElement,state}from"lit/decorators.js";import{when}from"lit/directives/when.js";import{OrAssetWidget}from"../util/or-asset-widget";import{html}from"lit";import{KpiSettings}from"../settings/kpi-settings";import"@openremote/or-attribute-card";function getDefaultWidgetConfig(){return{attributeRefs:[],period:"day",decimals:0,deltaFormat:"absolute",showTimestampControls:!1}}let KpiWidget=KpiWidget_1=class extends OrAssetWidget{constructor(){super(...arguments),this._loading=!1}static getManifest(){return{displayName:"KPI",displayIcon:"label",minColumnWidth:1,minColumnHeight:1,getContentHtml:t=>new KpiWidget_1(t),getSettingsHtml:t=>new KpiSettings(t),getDefaultConfig:()=>getDefaultWidgetConfig()}}refreshContent(t){this.loadAssets(this.widgetConfig.attributeRefs)}willUpdate(t){if(t.has("widgetConfig")&&this.widgetConfig){const t=this.widgetConfig.attributeRefs,e=null==t?void 0:t.filter((t=>this.isAttributeRefLoaded(t)));(null==e?void 0:e.length)!==(t?t.length:0)&&this.loadAssets(t)}return super.willUpdate(t)}loadAssets(t){this._loading=!0,this.fetchAssets(t).then((e=>{this.loadedAssets=e,this.assetAttributes=null==t?void 0:t.map((t=>{const i=e.findIndex((e=>e.id===t.id)),s=i>=0?e[i]:void 0;return s&&s.attributes?[i,s.attributes[t.name]]:void 0})).filter((t=>!!t))})).finally((()=>{this._loading=!1}))}render(){var t;return html`
1
+ var KpiWidget_1,__decorate=this&&this.__decorate||function(t,e,i,s){var o,r=arguments.length,n=r<3?e:null===s?s=Object.getOwnPropertyDescriptor(e,i):s;if("object"==typeof Reflect&&"function"==typeof Reflect.decorate)n=Reflect.decorate(t,e,i,s);else for(var d=t.length-1;d>=0;d--)(o=t[d])&&(n=(r<3?o(n):r>3?o(e,i,n):o(e,i))||n);return r>3&&n&&Object.defineProperty(e,i,n),n};import{customElement,state}from"lit/decorators.js";import{when}from"lit/directives/when.js";import{OrAssetWidget}from"../util/or-asset-widget";import{html}from"lit";import{KpiSettings}from"../settings/kpi-settings";import"@openremote/or-attribute-card";function getDefaultWidgetConfig(){return{attributeRefs:[],period:"day",decimals:0,deltaFormat:"absolute",showTimestampControls:!1}}let KpiWidget=KpiWidget_1=class extends OrAssetWidget{constructor(){super(...arguments),this._loading=!1}static getManifest(){return{displayName:"KPI",displayIcon:"label",minColumnWidth:1,minColumnHeight:1,getContentHtml:t=>new KpiWidget_1(t),getSettingsHtml:t=>new KpiSettings(t),getDefaultConfig:()=>getDefaultWidgetConfig()}}refreshContent(t){this.loadAssets(this.widgetConfig.attributeRefs)}willUpdate(t){if(t.has("widgetConfig")&&this.widgetConfig){const t=this.widgetConfig.attributeRefs,e=null==t?void 0:t.filter((t=>this.isAttributeRefLoaded(t)));(null==e?void 0:e.length)!==(t?t.length:0)&&this.loadAssets(t)}return super.willUpdate(t)}loadAssets(t){0!==t.length?(this._loading=!0,this._error=void 0,this.fetchAssets(t).then((e=>{this.loadedAssets=e,this.assetAttributes=null==t?void 0:t.map((t=>{const i=e.findIndex((e=>e.id===t.id)),s=i>=0?e[i]:void 0;return s&&s.attributes?[i,s.attributes[t.name]]:void 0})).filter((t=>!!t))})).catch((t=>{this._error=t.message})).finally((()=>{this._loading=!1}))):this._error="noAttributesConnected"}render(){var t;return html`
2
2
  <div style="position: relative; height: 100%; overflow: hidden;">
3
- ${when(this._loading,(()=>html`
4
- <div style="position: absolute; top: -5%; width: 100%; height: 105%; background: white; z-index: 1;">
5
- <or-loading-indicator></or-loading-indicator>
3
+ ${when(this._loading||this._error,(()=>html`
4
+ <div style="position: absolute; top: -5%; width: 100%; height: 105%; background: white; z-index: 1; display: flex; justify-content: center; align-items: center; text-align: center;">
5
+ ${when(this._loading,(()=>html`
6
+ <or-loading-indicator></or-loading-indicator>
7
+ `),(()=>html`
8
+ <or-translate .value="${this._error}"></or-translate>
9
+ `))}
6
10
  </div>
7
11
  `))}
8
12
  <or-attribute-card .assets="${this.loadedAssets}" .assetAttributes="${this.assetAttributes}" .period="${this.widgetConfig.period}"
9
13
  .deltaFormat="${this.widgetConfig.deltaFormat}" .mainValueDecimals="${this.widgetConfig.decimals}"
10
- showControls="${null===(t=this.widgetConfig)||void 0===t?void 0:t.showTimestampControls}" showTitle="${!1}" style="height: 100%;">
14
+ showControls="${null===(t=this.widgetConfig)||void 0===t?void 0:t.showTimestampControls}" showTitle="${!1}" hideAttributePicker="${!0}" style="height: 100%;">
11
15
  </or-attribute-card>
12
16
  </div>
13
17
  `}};__decorate([state()],KpiWidget.prototype,"_loading",void 0),KpiWidget=KpiWidget_1=__decorate([customElement("kpi-widget")],KpiWidget);export{KpiWidget};
@@ -1 +1 @@
1
- {"version":3,"file":"kpi-widget.js","sourceRoot":"","sources":["../../src/widgets/kpi-widget.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"kpi-widget.js","sourceRoot":"","sources":["../../src/widgets/kpi-widget.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@openremote/or-dashboard-builder",
3
- "version": "1.2.0-snapshot.20241015145246",
3
+ "version": "1.2.0-snapshot.20241218144812",
4
4
  "description": "OpenRemote Dashboard Builder",
5
5
  "main": "dist/umd/index.bundle.js",
6
6
  "module": "lib/index.js",
@@ -16,15 +16,15 @@
16
16
  "author": "OpenRemote",
17
17
  "license": "AGPL-3.0-or-later",
18
18
  "dependencies": {
19
- "@openremote/core": "1.2.0-snapshot.20241015145246",
20
- "@openremote/model": "1.2.0-snapshot.20241015145246",
21
- "@openremote/or-chart": "1.2.0-snapshot.20241015145246",
22
- "@openremote/rest": "1.2.0-snapshot.20241015145246",
19
+ "@openremote/core": "1.2.0-snapshot.20241218144812",
20
+ "@openremote/model": "1.2.0-snapshot.20241218144812",
21
+ "@openremote/or-chart": "1.2.0-snapshot.20241218144812",
22
+ "@openremote/rest": "1.2.0-snapshot.20241218144812",
23
23
  "gridstack": "^7.2.0",
24
24
  "lit": "^2.0.2"
25
25
  },
26
26
  "devDependencies": {
27
- "@openremote/util": "1.2.0-snapshot.20241015145246"
27
+ "@openremote/util": "1.2.0-snapshot.20241218144812"
28
28
  },
29
29
  "publishConfig": {
30
30
  "access": "public"
@@ -121,6 +121,13 @@ export class ThresholdsPanel extends LitElement {
121
121
  }
122
122
  }
123
123
 
124
+ private get colorValue() {
125
+ return (color?: string) => {
126
+ if (!color) return "#000000";
127
+ return color.startsWith('#') ? color : '#' + color;
128
+ }
129
+ }
130
+
124
131
  protected render(): TemplateResult {
125
132
  return html`
126
133
  <div id="thresholds-list" class="expanded-panel">
@@ -173,14 +180,12 @@ export class ThresholdsPanel extends LitElement {
173
180
  ` : null}
174
181
 
175
182
  <!-- Thresholds by boolean -->
176
- ${(this.valueType === 'boolean') ? html`
183
+ ${(this.valueType === 'boolean' && this.boolColors) ? html`
177
184
  <div class="threshold-list-item">
178
185
  <div class="threshold-list-item-colour">
179
- <or-mwc-input type="${InputType.COLOUR}" value="${this.boolColors.true}"
180
- @or-mwc-input-changed="${(event: OrInputChangedEvent) => {
181
- this.boolColors.true = event.detail.value;
182
- this.requestUpdate('boolColors');
183
- }}"
186
+ <or-mwc-input type="${InputType.COLOUR}" value="${this.colorValue(this.boolColors?.true)}"
187
+ @or-mwc-input-changed="${(event: OrInputChangedEvent) => {
188
+ this.onBoolColorChange(true, event.detail.value)}}"
184
189
  ></or-mwc-input>
185
190
  </div>
186
191
  <or-mwc-input type="${InputType.TEXT}" comfortable .value="${'True'}" .readonly="${true}"
@@ -188,11 +193,9 @@ export class ThresholdsPanel extends LitElement {
188
193
  </div>
189
194
  <div class="threshold-list-item">
190
195
  <div class="threshold-list-item-colour">
191
- <or-mwc-input type="${InputType.COLOUR}" value="${this.boolColors.false}"
196
+ <or-mwc-input type="${InputType.COLOUR}" value="${this.colorValue(this.boolColors?.false)}"
192
197
  @or-mwc-input-changed="${(event: OrInputChangedEvent) => {
193
- this.boolColors.false = event.detail.value;
194
- this.requestUpdate('boolColors');
195
- }}"
198
+ this.onBoolColorChange(false, event.detail.value)}}"
196
199
  ></or-mwc-input>
197
200
  </div>
198
201
  <or-mwc-input type="${InputType.TEXT}" comfortable .value="${'False'}" .readonly="${true}"
@@ -245,12 +248,30 @@ export class ThresholdsPanel extends LitElement {
245
248
  `
246
249
  }
247
250
 
251
+ protected onBoolColorChange(isTrue: boolean, newColor: string) {
252
+ // in case newColor already has '#' prefix
253
+ const color = newColor.startsWith('#') ? newColor.substring(1) : newColor;
254
+
255
+ if (!this.boolColors) {
256
+ this.boolColors = {
257
+ type: 'boolean',
258
+ true: '4caf50',
259
+ false: 'ef5350'
260
+ };
261
+ }
262
+
263
+ this.boolColors = {
264
+ ...this.boolColors,
265
+ [isTrue ? 'true' : 'false']: color
266
+ };
267
+ }
268
+
248
269
  protected removeThreshold(threshold: [any, string]) {
249
270
  switch (typeof threshold[0]) {
250
271
  case "number":
251
272
  this.thresholds = (this.thresholds as [number, string][]).filter((x) => x !== threshold);
252
273
  break;
253
- default:
274
+ default:
254
275
  this.textColors = (this.textColors as [string, string][]).filter((x) => x !== threshold);
255
276
  break;
256
277
  }
@@ -4,7 +4,7 @@ import {AssetWidgetSettings} from "../util/or-asset-widget";
4
4
  import {i18next} from "@openremote/or-translate";
5
5
  import {InputType, OrInputChangedEvent} from "@openremote/or-mwc-components/or-mwc-input";
6
6
  import {MapWidgetConfig} from "../widgets/map-widget";
7
- import {LngLatLike} from "@openremote/or-map";
7
+ import {AttributeMarkerColours, LngLatLike, MapMarkerColours} from "@openremote/or-map";
8
8
  import "../panels/assettypes-panel";
9
9
  import "../panels/thresholds-panel";
10
10
  import {LngLat} from "maplibre-gl"; // TODO: Replace this import
@@ -12,7 +12,7 @@ import {when} from "lit/directives/when.js";
12
12
  import {AssetTypeSelectEvent, AssetTypesFilterConfig, AttributeNamesSelectEvent} from "../panels/assettypes-panel";
13
13
  import manager from "@openremote/core";
14
14
  import {showSnackbar} from "@openremote/or-mwc-components/or-mwc-snackbar";
15
- import {ThresholdChangeEvent} from "../panels/thresholds-panel";
15
+ import {BoolColorsChangeEvent, ThresholdChangeEvent} from "../panels/thresholds-panel";
16
16
 
17
17
  const styling = css`
18
18
  .switchMwcInputContainer {
@@ -97,9 +97,12 @@ export class MapSettings extends AssetWidgetSettings {
97
97
  <!-- List of customizable thresholds -->
98
98
  ${when(this.widgetConfig.assetIds.length > 0, () => html`
99
99
  <settings-panel displayName="thresholds" expanded="${true}">
100
- <thresholds-panel .thresholds="${this.widgetConfig.thresholds}" .valueType="${this.widgetConfig.valueType}" style="padding-bottom: 12px;"
100
+ <thresholds-panel .thresholds="${this.widgetConfig.thresholds}"
101
+ .boolColors="${this.widgetConfig.boolColors}"
102
+ .valueType="${this.widgetConfig.valueType}" style="padding-bottom: 12px;"
101
103
  .min="${this.widgetConfig.min}" .max="${this.widgetConfig.max}"
102
- @threshold-change="${(ev: ThresholdChangeEvent) => this.onThresholdsChange(ev)}">
104
+ @threshold-change="${(ev: ThresholdChangeEvent) => this.onThresholdsChange(ev)}"
105
+ @bool-colors-change="${(ev: BoolColorsChangeEvent) => this.onBoolColorsChange(ev)}">
103
106
  </thresholds-panel>
104
107
  </settings-panel>
105
108
  `)}
@@ -182,4 +185,9 @@ export class MapSettings extends AssetWidgetSettings {
182
185
  this.notifyConfigUpdate();
183
186
  }
184
187
 
188
+ protected onBoolColorsChange(ev: BoolColorsChangeEvent) {
189
+ this.widgetConfig.boolColors = ev.detail as MapMarkerColours;
190
+ this.notifyConfigUpdate();
191
+ }
192
+
185
193
  }
@@ -3,7 +3,7 @@ import {Asset, AssetQuery, Attribute, AttributeRef} from "@openremote/model";
3
3
  import { state } from "lit/decorators.js";
4
4
  import manager from "@openremote/core";
5
5
  import { showSnackbar } from "@openremote/or-mwc-components/or-mwc-snackbar";
6
- import {WidgetConfig} from "./widget-config";
6
+ import {isAxiosError} from "@openremote/rest";
7
7
  import {WidgetSettings} from "./widget-settings";
8
8
  import { CSSResult } from "lit";
9
9
 
@@ -22,6 +22,9 @@ export abstract class OrAssetWidget extends OrWidget {
22
22
  @state() // cached attribute list; [asset index of the loadedAssets array, attribute]
23
23
  protected assetAttributes: [number, Attribute<any>][] = [];
24
24
 
25
+ @state()
26
+ protected _error?: string;
27
+
25
28
  static get styles(): CSSResult[] {
26
29
  return [...super.styles];
27
30
  }
@@ -83,8 +86,6 @@ export abstract class AssetWidgetSettings extends WidgetSettings {
83
86
 
84
87
  // Simple async function for fetching assets by attributeRefs
85
88
  async function fetchAssetsByAttributeRef(attributeRefs: AttributeRef[] = []) {
86
- const assetIds = attributeRefs.map(ar => ar.id!);
87
- const attributeNames = attributeRefs.map(ar => ar.name!);
88
89
  return fetchAssets({
89
90
  ids: attributeRefs?.map((x: AttributeRef) => x.id) as string[],
90
91
  select: {
@@ -93,14 +94,26 @@ async function fetchAssetsByAttributeRef(attributeRefs: AttributeRef[] = []) {
93
94
  });
94
95
  }
95
96
 
97
+ /**
98
+ * Function that will fetch an array of assets based on {@link assetQuery}.
99
+ * On failure, by default, it will only log to the web browser console.
100
+ * In some cases it will throw a custom error, that holds a custom message.
101
+ */
96
102
  async function fetchAssets(assetQuery: AssetQuery) {
97
103
  let assets: Asset[] = [];
98
104
  assetQuery.realm = { name: manager.displayRealm };
99
105
  await manager.rest.api.AssetResource.queryAssets(assetQuery).then(response => {
100
106
  assets = response.data;
101
- }).catch((reason) => {
102
- console.error(reason);
107
+ }).catch((e) => {
108
+ console.error(e);
103
109
  showSnackbar(undefined, "errorOccurred");
110
+ if(isAxiosError(e)) {
111
+ if(e.message === "Network Error") {
112
+ throw new Error("youAreOffline")
113
+ } else if(e.code === "ECONNABORTED") {
114
+ throw new Error("noAttributeDataTimeout")
115
+ }
116
+ }
104
117
  });
105
118
  return assets;
106
119
  }
@@ -33,6 +33,14 @@ const styling = css`
33
33
  align-items: center;
34
34
  overflow: hidden;
35
35
  }
36
+
37
+ #error-txt {
38
+ height: 100%;
39
+ display: flex;
40
+ justify-content: center;
41
+ align-items: center;
42
+ text-align: center;
43
+ }
36
44
 
37
45
  .attr-input {
38
46
  width: 100%;
@@ -93,7 +101,9 @@ export class AttributeInputWidget extends OrAssetWidget {
93
101
  // If widgetConfig, and the attributeRefs of them have changed...
94
102
  if(changedProps.has("widgetConfig") && this.widgetConfig) {
95
103
  const attributeRefs = this.widgetConfig.attributeRefs;
96
- if(attributeRefs.length > 0 && !this.isAttributeRefLoaded(attributeRefs[0])) {
104
+ if(attributeRefs.length === 0) {
105
+ this._error = "noAttributesConnected";
106
+ } else if(attributeRefs.length > 0 && !this.isAttributeRefLoaded(attributeRefs[0])) {
97
107
  this.loadAssets(attributeRefs);
98
108
  }
99
109
  }
@@ -113,9 +123,16 @@ export class AttributeInputWidget extends OrAssetWidget {
113
123
  }
114
124
 
115
125
  protected loadAssets(attributeRefs: AttributeRef[]) {
126
+ if(attributeRefs.length === 0) {
127
+ this._error = "noAttributesConnected";
128
+ return;
129
+ }
116
130
  this._loading = true;
131
+ this._error = undefined;
117
132
  this.fetchAssets(attributeRefs).then((assets) => {
118
133
  this.loadedAssets = assets;
134
+ }).catch(e => {
135
+ this._error = e.message;
119
136
  }).finally(() => {
120
137
  this._loading = false;
121
138
  });
@@ -126,10 +143,13 @@ export class AttributeInputWidget extends OrAssetWidget {
126
143
  const attribute = (config.attributeRefs.length > 0 && this.loadedAssets[0]?.attributes) ? this.loadedAssets[0].attributes[config.attributeRefs[0].name!] : undefined;
127
144
  const readOnlyMetaItem = Util.getMetaValue(WellknownMetaItems.READONLY, attribute);
128
145
  return html`
129
- ${when(this._loading, () => {
130
- return html`
131
- <or-loading-indicator></or-loading-indicator>
132
- `;
146
+
147
+ ${when(this._loading || this._error, () => {
148
+ if(this._loading) {
149
+ return html`<or-loading-indicator></or-loading-indicator>`;
150
+ } else {
151
+ return html`<or-translate id="error-txt" .value="${this._error}"></or-translate>`;
152
+ }
133
153
  }, () => when(config.attributeRefs.length > 0 && attribute && this.loadedAssets && this.loadedAssets.length > 0, () => {
134
154
  return html`
135
155
  <div id="widget-wrapper">
@@ -143,12 +163,6 @@ export class AttributeInputWidget extends OrAssetWidget {
143
163
  ></or-attribute-input>
144
164
  </div>
145
165
  `;
146
- }, () => {
147
- return html`
148
- <div style="height: 100%; display: flex; justify-content: center; align-items: center;">
149
- <span><or-translate value="noAttributesConnected"></or-translate></span>
150
- </div>
151
- `;
152
166
  }))}
153
167
  `;
154
168
  }
@@ -146,17 +146,26 @@ export class ChartWidget extends OrAssetWidget {
146
146
  this.datapointQuery = this.widgetConfig.datapointQuery;
147
147
 
148
148
  const attributeRefs = this.widgetConfig.attributeRefs;
149
- const missingAssets = attributeRefs?.filter((attrRef: AttributeRef) => !this.isAttributeRefLoaded(attrRef));
150
- if (missingAssets.length > 0) {
151
- this.loadAssets(attributeRefs);
149
+ if(attributeRefs.length === 0) {
150
+ this._error = "noAttributesConnected";
151
+ } else {
152
+ const missingAssets = attributeRefs?.filter((attrRef: AttributeRef) => !this.isAttributeRefLoaded(attrRef));
153
+ if (missingAssets.length > 0) {
154
+ this.loadAssets(attributeRefs);
155
+ }
152
156
  }
153
157
  }
154
158
 
155
159
  return super.willUpdate(changedProps);
156
160
  }
157
161
 
158
- protected loadAssets(attributeRefs: AttributeRef[]) {
162
+ protected loadAssets(attributeRefs: AttributeRef[]): void {
163
+ if(attributeRefs.length === 0) {
164
+ this._error = "noAttributesConnected";
165
+ return;
166
+ }
159
167
  this._loading = true;
168
+ this._error = undefined;
160
169
  this.fetchAssets(attributeRefs).then((assets) => {
161
170
  this.loadedAssets = assets;
162
171
  this.assetAttributes = attributeRefs?.map((attrRef: AttributeRef) => {
@@ -164,6 +173,8 @@ export class ChartWidget extends OrAssetWidget {
164
173
  const foundAsset = assetIndex >= 0 ? assets[assetIndex] : undefined;
165
174
  return foundAsset && foundAsset.attributes ? [assetIndex, foundAsset.attributes[attrRef.name!]] : undefined;
166
175
  }).filter((indexAndAttr: any) => !!indexAndAttr) as [number, Attribute<any>][];
176
+ }).catch(e => {
177
+ this._error = e.message;
167
178
  }).finally(() => {
168
179
  this._loading = false;
169
180
  });
@@ -173,7 +184,13 @@ export class ChartWidget extends OrAssetWidget {
173
184
  return html`
174
185
  ${when(this._loading, () => html`
175
186
  <or-loading-indicator></or-loading-indicator>
176
- `, () => when(this.loadedAssets && this.assetAttributes && this.loadedAssets.length > 0 && this.assetAttributes.length > 0, () => {
187
+
188
+ `, () => when(this._error, () => html`
189
+ <div style="height: 100%; display: flex; justify-content: center; align-items: center; text-align: center;">
190
+ <span><or-translate .value="${this._error}"></or-translate></span>
191
+ </div>
192
+
193
+ `, () => {
177
194
  return html`
178
195
  <or-chart .assets="${this.loadedAssets}" .assetAttributes="${this.assetAttributes}" .rightAxisAttributes="${this.widgetConfig.rightAxisAttributes}"
179
196
  .showLegend="${(this.widgetConfig?.showLegend != null) ? this.widgetConfig?.showLegend : true}"
@@ -183,12 +200,6 @@ export class ChartWidget extends OrAssetWidget {
183
200
  style="height: 100%"
184
201
  ></or-chart>
185
202
  `;
186
- }, () => {
187
- return html`
188
- <div style="height: 100%; display: flex; justify-content: center; align-items: center;">
189
- <span><or-translate value="noAttributesConnected"></or-translate></span>
190
- </div>
191
- `;
192
203
  }))}
193
204
  `;
194
205
  }
@@ -10,6 +10,7 @@ import manager from "@openremote/core";
10
10
  import {when} from "lit/directives/when.js";
11
11
  import {i18next} from "@openremote/or-translate";
12
12
  import {showSnackbar} from "@openremote/or-mwc-components/or-mwc-snackbar";
13
+ import moment from "moment";
13
14
 
14
15
  const styling = css`
15
16
  #gateway-widget-wrapper {
@@ -59,6 +60,8 @@ export class GatewayWidget extends OrWidget {
59
60
 
60
61
  protected _startedByUser = false;
61
62
 
63
+ protected _refreshTimer?: number = undefined;
64
+
62
65
  static getManifest(): WidgetManifest {
63
66
  return {
64
67
  displayName: "Gateway",
@@ -95,6 +98,11 @@ export class GatewayWidget extends OrWidget {
95
98
  console.warn("Keeping the active tunnel open, as it is not started through the widget.")
96
99
  }
97
100
  }
101
+
102
+ if (this._refreshTimer) {
103
+ clearTimeout(this._refreshTimer);
104
+ }
105
+
98
106
  super.disconnectedCallback();
99
107
  }
100
108
 
@@ -132,7 +140,7 @@ export class GatewayWidget extends OrWidget {
132
140
  `, () => {
133
141
  if (this._activeTunnel) {
134
142
  return html`
135
-
143
+ <div>
136
144
  <or-mwc-input .type="${InputType.BUTTON}" icon="stop" label="${i18next.t('gatewayTunnels.stop')}" .disabled="${disabled}"
137
145
  @or-mwc-input-changed="${(ev: OrInputChangedEvent) => this._onStopTunnelClick(ev)}"
138
146
  ></or-mwc-input>
@@ -146,7 +154,10 @@ export class GatewayWidget extends OrWidget {
146
154
  @or-mwc-input-changed="${(ev: OrInputChangedEvent) => this._onTunnelNavigateClick(ev)}"
147
155
  ></or-mwc-input>
148
156
  `)}
149
-
157
+ </div>
158
+ ${when(this._activeTunnel?.autoCloseTime, () => html`
159
+ <div><or-translate value="gatewayTunnels.closesAt"></or-translate>: ${moment(this._activeTunnel?.autoCloseTime).format("lll")}</div>
160
+ `)}
150
161
  `;
151
162
  } else {
152
163
  return html`
@@ -213,6 +224,26 @@ export class GatewayWidget extends OrWidget {
213
224
  */
214
225
  protected _setActiveTunnel(tunnelInfo?: GatewayTunnelInfo, silent = false) {
215
226
  this._activeTunnel = tunnelInfo;
227
+
228
+ if (this._refreshTimer) {
229
+ clearTimeout(this._refreshTimer);
230
+ }
231
+
232
+ if (tunnelInfo?.autoCloseTime) {
233
+ const timeout = tunnelInfo?.autoCloseTime - Date.now();
234
+ if (timeout > 0) {
235
+ this._refreshTimer = window.setTimeout(() => {
236
+ this._getActiveTunnel(this._getTunnelInfoByConfig(this.widgetConfig)).then(info => {
237
+ if (info) {
238
+ this._setActiveTunnel(info, true)
239
+ } else {
240
+ this._setActiveTunnel(undefined);
241
+ }
242
+ });
243
+ }, timeout);
244
+ }
245
+ }
246
+
216
247
  if(tunnelInfo && !silent) {
217
248
  this._navigateToTunnel(tunnelInfo);
218
249
  }
@@ -1,4 +1,4 @@
1
- import {html, TemplateResult} from "lit";
1
+ import {html, css, TemplateResult} from "lit";
2
2
  import {customElement, state} from "lit/decorators.js";
3
3
  import {OrAssetWidget} from "../util/or-asset-widget";
4
4
  import {WidgetConfig} from "../util/widget-config";
@@ -29,6 +29,16 @@ function getDefaultWidgetConfig(): GaugeWidgetConfig {
29
29
  };
30
30
  }
31
31
 
32
+ const styling = css`
33
+ #error-txt {
34
+ height: 100%;
35
+ display: flex;
36
+ justify-content: center;
37
+ align-items: center;
38
+ text-align: center;
39
+ }
40
+ `;
41
+
32
42
  @customElement("gauge-widget")
33
43
  export class GaugeWidget extends OrAssetWidget {
34
44
 
@@ -60,6 +70,10 @@ export class GaugeWidget extends OrAssetWidget {
60
70
  this.loadAssets(this.widgetConfig.attributeRefs);
61
71
  }
62
72
 
73
+ static get styles() {
74
+ return [...super.styles, styling];
75
+ }
76
+
63
77
  // WebComponent lifecycle method, that occurs DURING every state update
64
78
  protected willUpdate(changedProps: Map<string, any>) {
65
79
 
@@ -80,7 +94,12 @@ export class GaugeWidget extends OrAssetWidget {
80
94
  }
81
95
 
82
96
  protected loadAssets(attributeRefs: AttributeRef[]) {
97
+ if(attributeRefs.length === 0) {
98
+ this._error = "noAttributesConnected";
99
+ return;
100
+ }
83
101
  this._loading = true;
102
+ this._error = undefined;
84
103
  this.fetchAssets(attributeRefs).then((assets) => {
85
104
  this.loadedAssets = assets;
86
105
  this.assetAttributes = attributeRefs?.map((attrRef: AttributeRef) => {
@@ -88,6 +107,8 @@ export class GaugeWidget extends OrAssetWidget {
88
107
  const foundAsset = assetIndex >= 0 ? assets[assetIndex] : undefined;
89
108
  return foundAsset && foundAsset.attributes ? [assetIndex, foundAsset.attributes[attrRef.name!]] : undefined;
90
109
  }).filter((indexAndAttr: any) => !!indexAndAttr) as [number, Attribute<any>][];
110
+ }).catch(e => {
111
+ this._error = e.message;
91
112
  }).finally(() => {
92
113
  this._loading = false;
93
114
  });
@@ -96,10 +117,12 @@ export class GaugeWidget extends OrAssetWidget {
96
117
 
97
118
  protected render(): TemplateResult {
98
119
  return html`
99
- ${when(this._loading, () => {
100
- return html`
101
- <or-loading-indicator></or-loading-indicator>
102
- `;
120
+ ${when(this._loading || this._error, () => {
121
+ if(this._loading) {
122
+ return html`<or-loading-indicator></or-loading-indicator>`;
123
+ } else {
124
+ return html`<or-translate id="error-txt" .value="${this._error}"></or-translate>`;
125
+ }
103
126
  }, () => when(this.loadedAssets && this.assetAttributes && this.loadedAssets.length > 0 && this.assetAttributes.length > 0, () => {
104
127
  return html`
105
128
  <or-gauge .asset="${this.loadedAssets[0]}" .assetAttribute="${this.assetAttributes[0]}" .thresholds="${this.widgetConfig.thresholds}"
@@ -109,7 +132,7 @@ export class GaugeWidget extends OrAssetWidget {
109
132
  `;
110
133
  }, () => {
111
134
  return html`
112
- <div style="height: 100%; display: flex; justify-content: center; align-items: center;">
135
+ <div style="height: 100%; display: flex; justify-content: center; align-items: center; text-align: center;">
113
136
  <span><or-translate value="noAttributeConnected"></or-translate></span>
114
137
  </div>
115
138
  `;
@@ -76,7 +76,12 @@ export class KpiWidget extends OrAssetWidget {
76
76
  }
77
77
 
78
78
  protected loadAssets(attributeRefs: AttributeRef[]) {
79
+ if(attributeRefs.length === 0) {
80
+ this._error = "noAttributesConnected";
81
+ return;
82
+ }
79
83
  this._loading = true;
84
+ this._error = undefined;
80
85
  this.fetchAssets(attributeRefs).then((assets) => {
81
86
  this.loadedAssets = assets;
82
87
  this.assetAttributes = attributeRefs?.map((attrRef: AttributeRef) => {
@@ -84,6 +89,8 @@ export class KpiWidget extends OrAssetWidget {
84
89
  const foundAsset = assetIndex >= 0 ? assets[assetIndex] : undefined;
85
90
  return foundAsset && foundAsset.attributes ? [assetIndex, foundAsset.attributes[attrRef.name!]] : undefined;
86
91
  }).filter((indexAndAttr: any) => !!indexAndAttr) as [number, Attribute<any>][];
92
+ }).catch(e => {
93
+ this._error = e.message;
87
94
  }).finally(() => {
88
95
  this._loading = false;
89
96
  });
@@ -92,17 +99,21 @@ export class KpiWidget extends OrAssetWidget {
92
99
  protected render(): TemplateResult {
93
100
  return html`
94
101
  <div style="position: relative; height: 100%; overflow: hidden;">
95
- ${when(this._loading, () => {
102
+ ${when(this._loading || this._error, () => {
96
103
  // Have to use `position: absolute` with white background due to rendering inconsistencies in or-attribute-card
97
104
  return html`
98
- <div style="position: absolute; top: -5%; width: 100%; height: 105%; background: white; z-index: 1;">
99
- <or-loading-indicator></or-loading-indicator>
105
+ <div style="position: absolute; top: -5%; width: 100%; height: 105%; background: white; z-index: 1; display: flex; justify-content: center; align-items: center; text-align: center;">
106
+ ${when(this._loading, () => html`
107
+ <or-loading-indicator></or-loading-indicator>
108
+ `, () => html`
109
+ <or-translate .value="${this._error}"></or-translate>
110
+ `)}
100
111
  </div>
101
112
  `;
102
113
  })}
103
114
  <or-attribute-card .assets="${this.loadedAssets}" .assetAttributes="${this.assetAttributes}" .period="${this.widgetConfig.period}"
104
115
  .deltaFormat="${this.widgetConfig.deltaFormat}" .mainValueDecimals="${this.widgetConfig.decimals}"
105
- showControls="${this.widgetConfig?.showTimestampControls}" showTitle="${false}" style="height: 100%;">
116
+ showControls="${this.widgetConfig?.showTimestampControls}" showTitle="${false}" hideAttributePicker="${true}" style="height: 100%;">
106
117
  </or-attribute-card>
107
118
  </div>
108
119
  `;