@openremote/or-attribute-card 1.8.0-snapshot.20250725070921 → 1.8.0-snapshot.20250725120000

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.
package/lib/index.js CHANGED
@@ -1,209 +1,865 @@
1
- var __decorate=this&&this.__decorate||function(t,e,i,a){var s,r=arguments.length,o=r<3?e:null===a?a=Object.getOwnPropertyDescriptor(e,i):a;if("object"==typeof Reflect&&"function"==typeof Reflect.decorate)o=Reflect.decorate(t,e,i,a);else for(var n=t.length-1;n>=0;n--)(s=t[n])&&(o=(r<3?s(o):r>3?s(e,i,o):s(e,i))||o);return r>3&&o&&Object.defineProperty(e,i,o),o},__awaiter=this&&this.__awaiter||function(t,e,i,a){return new(i||(i=Promise))(function(s,r){function o(t){try{l(a.next(t))}catch(t){r(t)}}function n(t){try{l(a.throw(t))}catch(t){r(t)}}function l(t){var e;t.done?s(t.value):((e=t.value)instanceof i?e:new i(function(t){t(e)})).then(o,n)}l((a=a.apply(t,e||[])).next())})};import{css as t,html as e,LitElement as i,unsafeCSS as a}from"lit";import{customElement as s,property as r,state as o,query as n}from"lit/decorators.js";import l from"i18next";import{AssetModelUtil as d}from"@openremote/model";import{DefaultColor3 as h,DefaultColor4 as u,manager as p,Util as c}from"@openremote/core";import{isAxiosError as m}from"@openremote/rest";import{Chart as v,LineController as f,LineElement as b,PointElement as g,LinearScale as w,TimeSeriesScale as y,Title as _}from"chart.js";import"chartjs-adapter-moment";import{InputType as x}from"@openremote/or-mwc-components/or-mwc-input";import{getAssetDescriptorIconTemplate as A}from"@openremote/or-icon";import"@openremote/or-mwc-components/or-mwc-dialog";import"@openremote/or-attribute-picker";import C from"moment";import{OrAssetTreeSelectionEvent as O}from"@openremote/or-asset-tree";import{OrMwcDialog as V,showDialog as S}from"@openremote/or-mwc-components/or-mwc-dialog";import{OrAssetAttributePicker as D,OrAssetAttributePickerPickedEvent as $}from"@openremote/or-attribute-picker";import{getContentWithMenuTemplate as T}from"@openremote/or-mwc-components/or-mwc-menu";import{when as z}from"lit/directives/when.js";import{debounce as M}from"lodash";v.register(f,b,g,w,_,y);let style=t`
2
-
3
- :host {
4
- --internal-or-attribute-history-graph-line-color: var(--or-attribute-history-graph-line-color, var(--or-app-color4, ${a(u)}));
5
- width: 100%;
6
- }
7
-
8
- :host([hidden]) {
9
- display: none;
10
- }
11
-
12
- .panel {
13
- position: relative;
14
- height: 100%;
15
- }
16
- .panel.panel-empty {
17
- display: flex;
18
- }
19
- .panel.panel-empty .panel-content-wrapper {
20
- align-items: center;
21
- width: 100%;
22
- }
23
- .panel.panel-empty .panel-content {
24
- align-items: center;
25
- justify-content: center;
26
- flex-direction: column;
27
- }
28
-
29
- .panel-content-wrapper {
30
- height: 100%;
31
- display: flex;
32
- flex-direction: column;
33
- }
34
-
35
- .panel-title {
36
- display: flex;
37
- align-items: center;
38
- /*margin: -15px -15px 0 0;*/ /* compensate for the click-space of the plusminus button */
39
- font-weight: bolder;
40
- line-height: 1em;
41
- color: var(--internal-or-asset-viewer-title-text-color);
42
- flex: 0 0 auto;
43
- }
44
-
45
- .panel-title-text {
46
- flex: 1;
47
- text-transform: uppercase;
48
- white-space: nowrap;
49
- text-overflow: ellipsis;
50
- overflow: hidden;
51
- }
52
-
53
- .panel-content {
54
- display: flex;
55
- flex-direction: column;
56
- width: 100%;
57
- flex: 1;
58
- }
59
-
60
- .mainvalue-wrapper {
61
- width: 100%;
62
- display: flex;
63
- flex: 0 0 60px;
64
- align-items: center;
65
- justify-content: center;
66
- }
67
-
68
- .graph-wrapper {
69
- width: 100%;
70
- display: flex;
71
- flex: 1;
72
- align-items: center;
73
- }
74
-
75
- .main-number {
76
- color: var(--internal-or-asset-viewer-title-text-color);
77
- font-size: 42px;
78
- }
79
-
80
- .main-number-icon {
81
- font-size: 24px;
82
- margin-right: 10px;
83
- display: flex;
84
- }
85
-
86
- .main-number-unit {
87
- font-size: 42px;
88
- color: var(--internal-or-asset-viewer-title-text-color);
89
- font-weight: 200;
90
- margin-left: 5px;
91
- }
92
-
93
- .main-number.xs, .main-number-unit.xs {
94
- font-size: 18px;
95
- }
96
- .main-number.s, .main-number-unit.s {
97
- font-size: 24px;
98
- }
99
- .main-number.m, .main-number-unit.m {
100
- font-size: 30px;
101
- }
102
- .main-number.l, .main-number-unit.l {
103
- font-size: 36px;
104
- }
105
- .main-number.xl, .main-number-unit.xl {
106
- font-size: 42px;
107
- }
108
-
109
- .chart-wrapper {
110
- flex: 1 1 auto;
111
- width: 65%;
112
- height: 75%;
113
- }
114
- .controls-wrapper {
115
- flex: 0 0 80px;
116
- height: 100%;
117
- display: flex;
118
- flex-direction: column;
119
- align-items: end;
120
- place-content: space-between;
121
- }
122
-
123
- .delta-wrapper {
124
- /*flex: 0 0 50px;*/
125
- text-align: right;
126
-
127
- /*position: absolute;*/
128
- /*right: var(--internal-or-asset-viewer-panel-padding);*/
129
- }
130
-
131
- .date-range-wrapper {
132
- flex: 1;
133
- display: flex;
134
- justify-content: space-between;
135
- }
136
-
137
- .period-selector {
138
-
139
- }
140
-
141
- .delta {
142
- color: var(--or-app-color3, ${a(h)});
143
- font-weight: bold;
144
- }
145
- `,OrAttributeCard=class extends i{static get styles(){return[style]}constructor(){super(),this.assets=[],this.assetAttributes=[],this.data=void 0,this.mainValueDecimals=2,this.mainValueSize="m",this.delta=void 0,this.deltaPlus="",this.deltaFormat="absolute",this.showControls=!0,this.hideAttributePicker=!1,this.showTitle=!0,this._loading=!1,this.period="day"}connectedCallback(){super.connectedCallback(),this._style=window.getComputedStyle(this)}disconnectedCallback(){super.disconnectedCallback(),this._cleanup()}firstUpdated(){this.loadSettings()}updated(t){t.has("realm")&&void 0!=t.get("realm")&&(this.assets=[],this.loadSettings()),(t.has("period")||t.has("compareTimestamp")||t.has("timestamp")||t.has("assetAttributes")||t.has("realm"))&&(this.data=void 0,this._chart&&(this._chart.destroy(),this._chart=void 0),this.loadData()),this.data&&0!==this.data.length&&(this._chart?t.has("data")&&(this._chart.data.datasets[0].data=this.data.filter(t=>null!=t.y),this._chart.update(),this.delta=this.getFormattedDelta(this.getFirstKnownMeasurement(this.data),this.getLastKnownMeasurement(this.data))):this._chart=new v(this._chartElem.getContext("2d"),{type:"line",data:{datasets:[{data:this.data.filter(t=>null!=t.y),tension:.1,spanGaps:!0,backgroundColor:"transparent",borderColor:this._style.getPropertyValue("--internal-or-attribute-history-graph-line-color"),pointBorderColor:"transparent"}]},options:{responsive:!0,maintainAspectRatio:!1,plugins:{legend:{display:!1},tooltip:{displayColors:!1,callbacks:{title:t=>"",footer:()=>""}}},scales:{y:{display:!1},x:{type:"time",min:this._startOfPeriod,max:this._endOfPeriod,display:!1}}}}),(t.has("mainValue")||t.has("mainValueDecimals"))&&(this.formattedMainValue=this.getFormattedValue(this.mainValue)),t.has("delta")&&(this.deltaPlus=this.delta&&this.delta.val>0?"+":""))}shouldHideAttributePicker(){return this.hideAttributePicker&&"true"==this.hideAttributePicker.toString()}shouldShowControls(){return this.showControls&&"true"==this.showControls.toString()}shouldShowTitle(){return this.showTitle&&"true"==this.showTitle.toString()}render(){return this._error||this.assets&&this.assetAttributes&&0!==this.assetAttributes.length?(this.updateComplete.then(()=>{this.resizeObserver=new ResizeObserver(M(t=>{let e=t[0].devicePixelContentBoxSize[0].inlineSize;this.setLabelSizeByWidth(e)},200)),this.resizeObserver.observe(this.shadowRoot.querySelector(".graph-wrapper"))}),e`
146
- <div class="panel" id="attribute-card">
147
- <div class="panel-content-wrapper">
148
- <div class="panel-title">
149
- ${this.shouldShowTitle()?e`<span class="panel-title-text">${this.assets[0].name+" - "+l.t(this.assetAttributes[0][1].name)}</span>`:void 0}
150
- ${this.shouldShowTitle()?T(e`
151
- <or-mwc-input icon="dots-vertical" type="button"></or-mwc-input>
152
- `,[{text:l.t("editAttribute"),value:"editAttribute"},{text:l.t("editDelta"),value:"editDelta"},{text:l.t("editCurrentValue"),value:"editCurrentValue"},{text:l.t("delete"),value:"delete"}],void 0,t=>this.handleMenuSelect(t)):void 0}
153
- </div>
154
- <div class="panel-content">
155
- <div class="mainvalue-wrapper">
156
- ${z(!this._loading,()=>e`
157
- <span class="main-number-icon">${this.assets&&1===this.assets.length?A(d.getAssetDescriptor(this.assets[0].type)):""}</span>
158
- <span class="main-number ${this.mainValueSize}">${this.formattedMainValue?this.formattedMainValue.value:""}</span>
159
- <span class="main-number-unit ${this.mainValueSize}">${this.formattedMainValue?this.formattedMainValue.unit:""}</span>
160
- `)}
161
- </div>
162
- <div class="graph-wrapper">
163
-
164
- ${z(this._error,()=>e`
165
- <div style="flex: 0 0 80px;"></div>
166
- <or-translate .value="${this._error}" style="flex: 1; text-align: center;"></or-translate>
167
- `,()=>e`
168
- <div class="chart-wrapper">
169
- ${z(this._loading,()=>e`
170
- <or-loading-indicator></or-loading-indicator>
171
- `,()=>e`
172
- <canvas id="chart"></canvas>
173
- `)}
174
- </div>
175
- `)}
176
-
177
- <div class="controls-wrapper">
178
- <div class="delta-wrapper">
179
- <span class="delta">${this.delta?this.deltaPlus+(void 0!==this.delta.val&&null!==this.delta.val?this.delta.val:"")+(this.delta.unit||""):""}</span>
180
- </div>
181
- ${this.shouldShowControls()?e`
182
- <div class="period-selector-wrapper">
183
- ${T(e`<or-mwc-input class="period-selector" .type="${x.BUTTON}" label="${this.period?this.period:"-"}"></or-mwc-input>`,[{value:"hour",text:"hour"},{value:"day",text:"day"},{value:"week",text:"week"},{value:"month",text:"month"},{value:"year",text:"year"}].map(t=>(t.text=l.t(t.value),t)),this.period,t=>this._setPeriodOption(t),void 0,!1,!0,!1,!1,"kpi-menu-id",!0)}
184
- </div>
185
- `:e`
186
- <or-mwc-input class="period-selector" .type="${x.BUTTON}" disabled .label="${l.t(this.period?this.period:"-")}"></or-mwc-input>
187
- `}
188
- </div>
189
- </div>
190
- </div>
191
- </div>
192
- </div>
193
- `):e`
194
- <div class="panel panel-empty">
195
- <div class="panel-content-wrapper">
196
- <div class="panel-content">
197
- ${!this.shouldHideAttributePicker()?e`
198
- <or-mwc-input class="button" .type="${x.BUTTON}" label="selectAttribute" icon="plus" @or-mwc-input-changed="${()=>this._openDialog("editAttribute")}"></or-mwc-input>
199
- `:e`
200
- <span style="text-align: center;">${l.t("noAttributeConnected")}</span>
201
- `}
202
- </div>
203
- </div>
204
- </div>
205
- `}_openDialog(t){let i;switch(t){case"editDelta":case"editCurrentValue":(i=new V().setHeading(l.t(t)).setDismissAction(null).setContent("editDelta"===t?e`
206
- <or-mwc-input id="delta-mode-picker" value="${this.deltaFormat}" @or-mwc-input-changed="${t=>{this.deltaFormat=t.detail.value,this.saveSettings()}}" .type="${x.LIST}" .options="${[["percentage","Percentage"],["absolute","Absolute"]]}"></or-mwc-input>
207
- `:e`
208
- <or-mwc-input id="current-value-decimals" .label="${l.t("decimals")}" value="${this.mainValueDecimals}" .type="${x.TEXT}"></or-mwc-input>
209
- `).setActions([{actionName:"cancel",content:e`<or-mwc-input class="button" .type="${x.BUTTON}" label="cancel"></or-mwc-input>`,action:()=>{}},{actionName:"yes",default:!0,content:e`<or-mwc-input class="button" .type="${x.BUTTON}" label="ok" data-mdc-dialog-action="yes"></or-mwc-input>`,action:()=>{if("editDelta"===t)this.delta=this.data?this.getFormattedDelta(this.getFirstKnownMeasurement(this.data),this.getLastKnownMeasurement(this.data)):void 0;else if(i&&i.shadowRoot&&i.shadowRoot.getElementById("current-value-decimals")){let t=parseInt(i.shadowRoot.getElementById("current-value-decimals").value,10);t<0?this.mainValueDecimals=0:t>10?this.mainValueDecimals=10:this.mainValueDecimals=t,this.formattedMainValue=this.getFormattedValue(this.mainValue),this.saveSettings()}}}])).addEventListener(O.NAME,t=>__awaiter(this,void 0,void 0,function*(){let e=t.detail&&t.detail.newNodes.length>0?t.detail.newNodes[0]:void 0;if(e){let t=yield p.events.sendEventWithReply({eventType:"read-asset",assetId:e.asset.id});this.asset=t.asset}else this.asset=void 0}));break;default:(i=new D().setHeading(l.t("selectAttribute"))).addEventListener($.NAME,t=>__awaiter(this,void 0,void 0,function*(){let e=t.detail[0];try{let t=yield p.rest.api.AssetResource.get(e.id);this.asset=t.data,this._setAttribute(e.name)}catch(t){console.error("Failed to get assets requested in settings",t)}}))}i&&S(i)}_setAttribute(t){if(this.asset&&t){let e=this.asset.attributes?this.asset.attributes[t]:void 0;this.assets=[this.asset],this.assetAttributes=e?[[0,e]]:[],this.saveSettings()}}_cleanup(){this._chart&&(this._chart.destroy(),this._chart=void 0)}loadSettings(){return __awaiter(this,arguments,void 0,function*(t=!1){this.assetAttributes=[],(!this.period||t)&&(this.period="day"),(!this.deltaFormat||t)&&(this.deltaFormat="absolute"),(!this.mainValueDecimals||t)&&(this.mainValueDecimals=0),this.realm||(this.realm=p.getRealm());let e=(yield p.console.retrieveData("OrChartConfig"))||[];if(Array.isArray(e)||(e=[e]),0===e.length||!this.panelName)return;let i=window.location.hash,a=e.find(t=>t.realm===this.realm),s=a&&a.views&&a.views[i]?a.views[i][this.panelName]:void 0;if(!s)return;if(!s.attributeRefs){delete a.views[i][this.panelName];let t=[...e.filter(t=>t.realm!==this.realm),a];p.console.storeData("OrChartConfig",t);return}let r=s.attributeRefs.map(t=>t.id);if(0!==r.length&&(this._loading=!0,!r.every(t=>!!this.assets.find(e=>e.id===t)))){try{let t=(yield p.rest.api.AssetResource.queryAssets({ids:r})).data||[];s.attributeRefs=s.attributeRefs.filter(e=>!!t.find(t=>t.id===e.id&&t.attributes&&t.attributes.hasOwnProperty(e.name))),e=[...e.filter(t=>t.realm!==this.realm),a],p.console.storeData("OrChartConfig",e),this.assets=t.filter(t=>s.attributeRefs.find(e=>e.id===t.id))}catch(t){console.error("Failed to get assets requested in settings",t)}this._loading=!1,this.assets&&this.assets.length>0&&(this.assetAttributes=s.attributeRefs.map(t=>{let e=this.assets.findIndex(e=>e.id===t.id),i=e>=0?this.assets[e]:void 0;return i&&i.attributes?[e,i.attributes[t.name]]:void 0}).filter(t=>!!t),this.period=s.period||"day",this.mainValueDecimals=s.decimals||0,this.deltaFormat=s.deltaFormat||"absolute")}})}saveSettings(){return __awaiter(this,void 0,void 0,function*(){if(!this.panelName)return;let t=window.location.hash,e=(yield p.console.retrieveData("OrChartConfig"))||[],i=e.find(t=>t.realm===this.realm);i||(i={realm:this.realm,views:{}}),i.views[t]||(i.views[t]={}),this.assets&&this.assetAttributes&&0!==this.assets.length&&0!==this.assetAttributes.length?(i.realm=this.realm,i.views[t][this.panelName]={attributeRefs:this.assetAttributes.map(([t,e])=>{let i=this.assets[t];return i?{id:i.id,name:e.name}:void 0}).filter(t=>!!t),period:this.period,deltaFormat:this.deltaFormat,decimals:this.mainValueDecimals}):delete i.views[t][this.panelName],e=[...e.filter(t=>t.realm!==this.realm),i],p.console.storeData("OrChartConfig",e)})}loadData(){return __awaiter(this,void 0,void 0,function*(){var t;if(this.data||!this.assetAttributes||!this.assets||0===this.assets.length||0===this.assetAttributes.length||!this.period)return;this._dataAbortController&&(this._dataAbortController.abort("Data request overridden"),delete this._dataAbortController),this._loading=!0;let e="HOUR";switch(this.period){case"hour":e="MINUTE";break;case"day":case"week":e="HOUR";break;case"month":e="DAY";break;case"year":e="MONTH"}e.toLowerCase(),this._startOfPeriod=C().subtract(1,this.period).toDate().getTime(),this._endOfPeriod=C().toDate().getTime();let i=this.assets[0].id,a=this.assetAttributes[0][1].name;this._dataAbortController=new AbortController;try{let t=yield p.rest.api.AssetDatapointResource.getDatapoints(i,a,{type:"lttb",fromTimestamp:this._startOfPeriod,toTimestamp:this._endOfPeriod,amountOfPoints:20},{signal:this._dataAbortController.signal});this._loading=!1,200===t.status&&(this.data=t.data,this.delta=this.getFormattedDelta(this.getFirstKnownMeasurement(this.data),this.getLastKnownMeasurement(this.data)),this.deltaPlus=this.delta&&this.delta.val>0?"+":"",this._error=void 0)}catch(e){if(console.error(e),(null==e?void 0:e.message)==="canceled")return;if(this._loading=!1,m(e)){if(e.message.includes("timeout")){this._error="noAttributeDataTimeout";return}else if((null==(t=e.response)?void 0:t.status)===413){this._error="datapointRequestTooLarge";return}}this._error="couldNotRetrieveAttribute"}finally{this.mainValue=void 0,this.formattedMainValue=void 0;let t=yield p.events.sendEventWithReply({eventType:"read-asset-attribute",ref:{id:i,name:a}});this.mainValue=t.value,this.formattedMainValue=this.getFormattedValue(this.mainValue)}})}getTotalValue(t){return t.reduce((t,e)=>e.y?t+Math.round(e.y):t,0)}getHighestValue(t){return Math.max.apply(Math,t.map(t=>t.y||!1))}getFormattedValue(t){if(void 0===t||!this.assets||!this.assetAttributes||0===this.assets.length||0===this.assetAttributes.length)return;let e=this.assetAttributes[0][1],i=+(null==t?void 0:t.toFixed(this.mainValueDecimals)),a=d.getAttributeDescriptor(e.name,this.assets[0].type),s=c.resolveUnits(c.getAttributeUnits(e,a,this.assets[0].type));return(this.setLabelSizeByLength(i.toString()),s)?{value:i,unit:s}:{value:i,unit:""}}getFirstKnownMeasurement(t){for(let e=0;e<=t.length;e++)if(t[e]&&void 0!==t[e].y)return t[e].y;return 0}getLastKnownMeasurement(t){for(let e=t.length-1;e>=0;e--)if(t[e]&&void 0!==t[e].y)return t[e].y;return 0}getFormattedDelta(t,e){if("percentage"===this.deltaFormat)if(!t||!e)return{val:0,unit:"%"};else if(0===e&&0===t)return{val:0,unit:"%"};else return 0===e&&0!==t?{val:100,unit:"%"}:{val:Math.round((e-t)/t*100),unit:"%"};return{val:Math.round(e-t),unit:""}}handleMenuSelect(t){"delete"===t?(this.assets=[],this.assetAttributes=[],this.saveSettings()):this._openDialog(t)}setLabelSizeByLength(t){t.length>=20&&(this.mainValueSize="xs"),t.length<20&&(this.mainValueSize="s"),t.length<15&&(this.mainValueSize="m"),t.length<10&&(this.mainValueSize="l"),t.length<5&&(this.mainValueSize="xl")}setLabelSizeByWidth(t){t<60?this.mainValueSize="s":t<100?this.mainValueSize="m":t<200?this.mainValueSize="l":this.mainValueSize="xl"}_setPeriodOption(t){this.period=t,this.saveSettings()}};__decorate([r()],OrAttributeCard.prototype,"panelName",void 0),__decorate([r({type:Object})],OrAttributeCard.prototype,"assets",void 0),__decorate([r({type:Object})],OrAttributeCard.prototype,"assetAttributes",void 0),__decorate([r()],OrAttributeCard.prototype,"data",void 0),__decorate([r({type:String})],OrAttributeCard.prototype,"realm",void 0),__decorate([r()],OrAttributeCard.prototype,"mainValue",void 0),__decorate([r()],OrAttributeCard.prototype,"mainValueDecimals",void 0),__decorate([r()],OrAttributeCard.prototype,"mainValueSize",void 0),__decorate([r()],OrAttributeCard.prototype,"delta",void 0),__decorate([r()],OrAttributeCard.prototype,"deltaPlus",void 0),__decorate([r()],OrAttributeCard.prototype,"deltaFormat",void 0),__decorate([r()],OrAttributeCard.prototype,"showControls",void 0),__decorate([r()],OrAttributeCard.prototype,"hideAttributePicker",void 0),__decorate([r()],OrAttributeCard.prototype,"showTitle",void 0),__decorate([r()],OrAttributeCard.prototype,"_loading",void 0),__decorate([r()],OrAttributeCard.prototype,"period",void 0),__decorate([o()],OrAttributeCard.prototype,"_error",void 0),__decorate([n("#chart")],OrAttributeCard.prototype,"_chartElem",void 0),OrAttributeCard=__decorate([s("or-attribute-card")],OrAttributeCard);export{OrAttributeCard};
1
+ var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
2
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
3
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
4
+ else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
5
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
6
+ };
7
+ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
8
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
9
+ return new (P || (P = Promise))(function (resolve, reject) {
10
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
11
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
12
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
13
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
14
+ });
15
+ };
16
+ import { css, html, LitElement, unsafeCSS } from "lit";
17
+ import { customElement, property, state, query } from "lit/decorators.js";
18
+ import i18next from "i18next";
19
+ import { AssetModelUtil } from "@openremote/model";
20
+ import { DefaultColor3, DefaultColor4, manager, Util } from "@openremote/core";
21
+ import { isAxiosError } from "@openremote/rest";
22
+ import { Chart, LineController, LineElement, PointElement, LinearScale, TimeSeriesScale, Title } from "chart.js";
23
+ import "chartjs-adapter-moment";
24
+ import { InputType } from "@openremote/or-mwc-components/or-mwc-input";
25
+ import { getAssetDescriptorIconTemplate } from "@openremote/or-icon";
26
+ import "@openremote/or-mwc-components/or-mwc-dialog";
27
+ import "@openremote/or-attribute-picker";
28
+ import moment from "moment";
29
+ import { OrAssetTreeSelectionEvent } from "@openremote/or-asset-tree";
30
+ import { OrMwcDialog, showDialog } from "@openremote/or-mwc-components/or-mwc-dialog";
31
+ import { OrAssetAttributePicker, OrAssetAttributePickerPickedEvent } from "@openremote/or-attribute-picker";
32
+ import { getContentWithMenuTemplate } from "@openremote/or-mwc-components/or-mwc-menu";
33
+ import { when } from "lit/directives/when.js";
34
+ import { debounce } from "lodash";
35
+ Chart.register(LineController, LineElement, PointElement, LinearScale, Title, TimeSeriesScale);
36
+ // language=CSS
37
+ const style = css `
38
+
39
+ :host {
40
+ --internal-or-attribute-history-graph-line-color: var(--or-attribute-history-graph-line-color, var(--or-app-color4, ${unsafeCSS(DefaultColor4)}));
41
+ width: 100%;
42
+ }
43
+
44
+ :host([hidden]) {
45
+ display: none;
46
+ }
47
+
48
+ .panel {
49
+ position: relative;
50
+ height: 100%;
51
+ }
52
+ .panel.panel-empty {
53
+ display: flex;
54
+ }
55
+ .panel.panel-empty .panel-content-wrapper {
56
+ align-items: center;
57
+ width: 100%;
58
+ }
59
+ .panel.panel-empty .panel-content {
60
+ align-items: center;
61
+ justify-content: center;
62
+ flex-direction: column;
63
+ }
64
+
65
+ .panel-content-wrapper {
66
+ height: 100%;
67
+ display: flex;
68
+ flex-direction: column;
69
+ }
70
+
71
+ .panel-title {
72
+ display: flex;
73
+ align-items: center;
74
+ /*margin: -15px -15px 0 0;*/ /* compensate for the click-space of the plusminus button */
75
+ font-weight: bolder;
76
+ line-height: 1em;
77
+ color: var(--internal-or-asset-viewer-title-text-color);
78
+ flex: 0 0 auto;
79
+ }
80
+
81
+ .panel-title-text {
82
+ flex: 1;
83
+ text-transform: uppercase;
84
+ white-space: nowrap;
85
+ text-overflow: ellipsis;
86
+ overflow: hidden;
87
+ }
88
+
89
+ .panel-content {
90
+ display: flex;
91
+ flex-direction: column;
92
+ width: 100%;
93
+ flex: 1;
94
+ }
95
+
96
+ .mainvalue-wrapper {
97
+ width: 100%;
98
+ display: flex;
99
+ flex: 0 0 60px;
100
+ align-items: center;
101
+ justify-content: center;
102
+ }
103
+
104
+ .graph-wrapper {
105
+ width: 100%;
106
+ display: flex;
107
+ flex: 1;
108
+ align-items: center;
109
+ }
110
+
111
+ .main-number {
112
+ color: var(--internal-or-asset-viewer-title-text-color);
113
+ font-size: 42px;
114
+ }
115
+
116
+ .main-number-icon {
117
+ font-size: 24px;
118
+ margin-right: 10px;
119
+ display: flex;
120
+ }
121
+
122
+ .main-number-unit {
123
+ font-size: 42px;
124
+ color: var(--internal-or-asset-viewer-title-text-color);
125
+ font-weight: 200;
126
+ margin-left: 5px;
127
+ }
128
+
129
+ .main-number.xs, .main-number-unit.xs {
130
+ font-size: 18px;
131
+ }
132
+ .main-number.s, .main-number-unit.s {
133
+ font-size: 24px;
134
+ }
135
+ .main-number.m, .main-number-unit.m {
136
+ font-size: 30px;
137
+ }
138
+ .main-number.l, .main-number-unit.l {
139
+ font-size: 36px;
140
+ }
141
+ .main-number.xl, .main-number-unit.xl {
142
+ font-size: 42px;
143
+ }
144
+
145
+ .chart-wrapper {
146
+ flex: 1 1 auto;
147
+ width: 65%;
148
+ height: 75%;
149
+ }
150
+ .controls-wrapper {
151
+ flex: 0 0 80px;
152
+ height: 100%;
153
+ display: flex;
154
+ flex-direction: column;
155
+ align-items: end;
156
+ place-content: space-between;
157
+ }
158
+
159
+ .delta-wrapper {
160
+ /*flex: 0 0 50px;*/
161
+ text-align: right;
162
+
163
+ /*position: absolute;*/
164
+ /*right: var(--internal-or-asset-viewer-panel-padding);*/
165
+ }
166
+
167
+ .date-range-wrapper {
168
+ flex: 1;
169
+ display: flex;
170
+ justify-content: space-between;
171
+ }
172
+
173
+ .period-selector {
174
+
175
+ }
176
+
177
+ .delta {
178
+ color: var(--or-app-color3, ${unsafeCSS(DefaultColor3)});
179
+ font-weight: bold;
180
+ }
181
+ `;
182
+ let OrAttributeCard = class OrAttributeCard extends LitElement {
183
+ static get styles() {
184
+ return [
185
+ style
186
+ ];
187
+ }
188
+ constructor() {
189
+ super();
190
+ this.assets = [];
191
+ this.assetAttributes = [];
192
+ this.data = undefined;
193
+ this.mainValueDecimals = 2;
194
+ this.mainValueSize = "m";
195
+ this.delta = undefined;
196
+ this.deltaPlus = "";
197
+ this.deltaFormat = "absolute";
198
+ this.showControls = true;
199
+ this.hideAttributePicker = false;
200
+ this.showTitle = true;
201
+ this._loading = false;
202
+ this.period = "day";
203
+ }
204
+ connectedCallback() {
205
+ super.connectedCallback();
206
+ this._style = window.getComputedStyle(this);
207
+ }
208
+ disconnectedCallback() {
209
+ super.disconnectedCallback();
210
+ this._cleanup();
211
+ }
212
+ firstUpdated() {
213
+ this.loadSettings();
214
+ }
215
+ updated(changedProperties) {
216
+ if (changedProperties.has("realm") && changedProperties.get("realm") != undefined) {
217
+ this.assets = [];
218
+ this.loadSettings();
219
+ }
220
+ const reloadData = changedProperties.has("period") || changedProperties.has("compareTimestamp")
221
+ || changedProperties.has("timestamp") || changedProperties.has("assetAttributes") || changedProperties.has("realm");
222
+ if (reloadData) {
223
+ this.data = undefined;
224
+ if (this._chart) {
225
+ this._chart.destroy();
226
+ this._chart = undefined;
227
+ }
228
+ this.loadData();
229
+ }
230
+ if (!this.data || this.data.length === 0) {
231
+ return;
232
+ }
233
+ if (!this._chart) {
234
+ this._chart = new Chart(this._chartElem.getContext("2d"), {
235
+ type: "line",
236
+ data: {
237
+ datasets: [
238
+ {
239
+ data: this.data.filter(value => value.y != null),
240
+ tension: 0.1,
241
+ spanGaps: true,
242
+ backgroundColor: "transparent",
243
+ borderColor: this._style.getPropertyValue("--internal-or-attribute-history-graph-line-color"),
244
+ pointBorderColor: "transparent",
245
+ }
246
+ ]
247
+ },
248
+ options: {
249
+ responsive: true,
250
+ maintainAspectRatio: false,
251
+ plugins: {
252
+ legend: {
253
+ display: false
254
+ },
255
+ tooltip: {
256
+ displayColors: false,
257
+ callbacks: {
258
+ title: (context) => {
259
+ return "";
260
+ },
261
+ // label: (context) => {
262
+ // return context.parsed.y; // Removes the colon before the label
263
+ // },
264
+ footer: () => {
265
+ return ""; // Hack the broken vertical alignment of body with footerFontSize: 0
266
+ }
267
+ }
268
+ }
269
+ },
270
+ scales: {
271
+ y: {
272
+ display: false
273
+ },
274
+ x: {
275
+ type: "time",
276
+ min: this._startOfPeriod,
277
+ max: this._endOfPeriod,
278
+ display: false,
279
+ }
280
+ }
281
+ }
282
+ });
283
+ }
284
+ else {
285
+ if (changedProperties.has("data")) {
286
+ this._chart.data.datasets[0].data = this.data.filter(value => value.y != null);
287
+ this._chart.update();
288
+ this.delta = this.getFormattedDelta(this.getFirstKnownMeasurement(this.data), this.getLastKnownMeasurement(this.data));
289
+ }
290
+ }
291
+ if (changedProperties.has("mainValue") || changedProperties.has("mainValueDecimals")) {
292
+ this.formattedMainValue = this.getFormattedValue(this.mainValue);
293
+ }
294
+ if (changedProperties.has("delta")) {
295
+ this.deltaPlus = this.delta && this.delta.val > 0 ? "+" : "";
296
+ }
297
+ }
298
+ shouldHideAttributePicker() {
299
+ return (this.hideAttributePicker && this.hideAttributePicker.toString() == "true");
300
+ }
301
+ shouldShowControls() {
302
+ return (this.showControls && this.showControls.toString() == "true");
303
+ }
304
+ shouldShowTitle() {
305
+ return (this.showTitle && this.showTitle.toString() == "true");
306
+ }
307
+ render() {
308
+ if (!this._error && (!this.assets || !this.assetAttributes || this.assetAttributes.length === 0)) {
309
+ return html `
310
+ <div class="panel panel-empty">
311
+ <div class="panel-content-wrapper">
312
+ <div class="panel-content">
313
+ ${!this.shouldHideAttributePicker() ? html `
314
+ <or-mwc-input class="button" .type="${InputType.BUTTON}" label="selectAttribute" icon="plus" @or-mwc-input-changed="${() => this._openDialog("editAttribute")}"></or-mwc-input>
315
+ ` : html `
316
+ <span style="text-align: center;">${i18next.t('noAttributeConnected')}</span>
317
+ `}
318
+ </div>
319
+ </div>
320
+ </div>
321
+ `;
322
+ }
323
+ this.updateComplete.then(() => {
324
+ this.resizeObserver = new ResizeObserver(debounce((entries) => {
325
+ const elemSize = entries[0].devicePixelContentBoxSize[0].inlineSize;
326
+ this.setLabelSizeByWidth(elemSize);
327
+ }, 200));
328
+ this.resizeObserver.observe(this.shadowRoot.querySelector(".graph-wrapper"));
329
+ });
330
+ return html `
331
+ <div class="panel" id="attribute-card">
332
+ <div class="panel-content-wrapper">
333
+ <div class="panel-title">
334
+ ${this.shouldShowTitle() ? html `<span class="panel-title-text">${this.assets[0].name + " - " + i18next.t(this.assetAttributes[0][1].name)}</span>` : undefined}
335
+ ${this.shouldShowTitle() ? getContentWithMenuTemplate(html `
336
+ <or-mwc-input icon="dots-vertical" type="button"></or-mwc-input>
337
+ `, [
338
+ {
339
+ text: i18next.t("editAttribute"),
340
+ value: "editAttribute"
341
+ },
342
+ {
343
+ text: i18next.t("editDelta"),
344
+ value: "editDelta"
345
+ },
346
+ {
347
+ text: i18next.t("editCurrentValue"),
348
+ value: "editCurrentValue"
349
+ },
350
+ {
351
+ text: i18next.t("delete"),
352
+ value: "delete"
353
+ }
354
+ ], undefined, (option) => this.handleMenuSelect(option)) : undefined}
355
+ </div>
356
+ <div class="panel-content">
357
+ <div class="mainvalue-wrapper">
358
+ ${when(!this._loading, () => html `
359
+ <span class="main-number-icon">${this.assets && this.assets.length === 1 ? getAssetDescriptorIconTemplate(AssetModelUtil.getAssetDescriptor(this.assets[0].type)) : ""}</span>
360
+ <span class="main-number ${this.mainValueSize}">${this.formattedMainValue ? this.formattedMainValue.value : ""}</span>
361
+ <span class="main-number-unit ${this.mainValueSize}">${this.formattedMainValue ? this.formattedMainValue.unit : ""}</span>
362
+ `)}
363
+ </div>
364
+ <div class="graph-wrapper">
365
+
366
+ ${when(this._error, () => html `
367
+ <div style="flex: 0 0 80px;"></div>
368
+ <or-translate .value="${this._error}" style="flex: 1; text-align: center;"></or-translate>
369
+ `, () => html `
370
+ <div class="chart-wrapper">
371
+ ${when(this._loading, () => html `
372
+ <or-loading-indicator></or-loading-indicator>
373
+ `, () => html `
374
+ <canvas id="chart"></canvas>
375
+ `)}
376
+ </div>
377
+ `)}
378
+
379
+ <div class="controls-wrapper">
380
+ <div class="delta-wrapper">
381
+ <span class="delta">${this.delta ? this.deltaPlus + (this.delta.val !== undefined && this.delta.val !== null ? this.delta.val : "") + (this.delta.unit || "") : ""}</span>
382
+ </div>
383
+ ${this.shouldShowControls() ? html `
384
+ <div class="period-selector-wrapper">
385
+ ${getContentWithMenuTemplate(html `<or-mwc-input class="period-selector" .type="${InputType.BUTTON}" label="${this.period ? this.period : '-'}"></or-mwc-input>`, [{ value: "hour", text: "hour" }, { value: "day", text: "day" }, { value: "week", text: "week" }, { value: "month", text: "month" }, { value: "year", text: "year" }].map((option) => {
386
+ option.text = i18next.t(option.value);
387
+ return option;
388
+ }), this.period, (value) => this._setPeriodOption(value), undefined, // closedCallback
389
+ false, // multiSelect
390
+ true, // translateValues
391
+ false, // midHeight
392
+ false, // fullWidth
393
+ "kpi-menu-id", // Menu Id
394
+ true // fixToHost
395
+ )}
396
+ </div>
397
+ ` : html `
398
+ <or-mwc-input class="period-selector" .type="${InputType.BUTTON}" disabled .label="${i18next.t(this.period ? this.period : "-")}"></or-mwc-input>
399
+ `}
400
+ </div>
401
+ </div>
402
+ </div>
403
+ </div>
404
+ </div>
405
+ `;
406
+ }
407
+ _openDialog(dialogContent) {
408
+ let dialog;
409
+ switch (dialogContent) {
410
+ case "editDelta":
411
+ case "editCurrentValue":
412
+ dialog = new OrMwcDialog()
413
+ .setHeading(i18next.t(dialogContent))
414
+ .setDismissAction(null)
415
+ .setContent(dialogContent === "editDelta"
416
+ ? html `
417
+ <or-mwc-input id="delta-mode-picker" value="${this.deltaFormat}" @or-mwc-input-changed="${(evt) => { this.deltaFormat = evt.detail.value; this.saveSettings(); }}" .type="${InputType.LIST}" .options="${[
418
+ ["percentage", "Percentage"],
419
+ ["absolute", "Absolute"]
420
+ ]}"></or-mwc-input>
421
+ `
422
+ : html `
423
+ <or-mwc-input id="current-value-decimals" .label="${i18next.t("decimals")}" value="${this.mainValueDecimals}" .type="${InputType.TEXT}"></or-mwc-input>
424
+ `)
425
+ .setActions([
426
+ {
427
+ actionName: "cancel",
428
+ content: html `<or-mwc-input class="button" .type="${InputType.BUTTON}" label="cancel"></or-mwc-input>`,
429
+ action: () => {
430
+ // Nothing to do here
431
+ }
432
+ },
433
+ {
434
+ actionName: "yes",
435
+ default: true,
436
+ content: html `<or-mwc-input class="button" .type="${InputType.BUTTON}" label="ok" data-mdc-dialog-action="yes"></or-mwc-input>`,
437
+ action: () => {
438
+ if (dialogContent === "editDelta") {
439
+ this.delta = this.data ? this.getFormattedDelta(this.getFirstKnownMeasurement(this.data), this.getLastKnownMeasurement(this.data)) : undefined;
440
+ }
441
+ else {
442
+ if (dialog && dialog.shadowRoot && dialog.shadowRoot.getElementById("current-value-decimals")) {
443
+ const elm = dialog.shadowRoot.getElementById("current-value-decimals");
444
+ const input = parseInt(elm.value, 10);
445
+ if (input < 0) {
446
+ this.mainValueDecimals = 0;
447
+ }
448
+ else if (input > 10) {
449
+ this.mainValueDecimals = 10;
450
+ }
451
+ else {
452
+ this.mainValueDecimals = input;
453
+ }
454
+ this.formattedMainValue = this.getFormattedValue(this.mainValue);
455
+ this.saveSettings();
456
+ }
457
+ }
458
+ }
459
+ }
460
+ ]);
461
+ dialog.addEventListener(OrAssetTreeSelectionEvent.NAME, (ev) => __awaiter(this, void 0, void 0, function* () {
462
+ const selectedNode = ev.detail && ev.detail.newNodes.length > 0 ? ev.detail.newNodes[0] : undefined;
463
+ if (!selectedNode) {
464
+ this.asset = undefined;
465
+ }
466
+ else {
467
+ // fully load the asset
468
+ const assetEvent = yield manager.events.sendEventWithReply({
469
+ eventType: "read-asset",
470
+ assetId: selectedNode.asset.id
471
+ });
472
+ this.asset = assetEvent.asset;
473
+ }
474
+ }));
475
+ break;
476
+ default:
477
+ dialog = new OrAssetAttributePicker()
478
+ .setHeading(i18next.t("selectAttribute"));
479
+ dialog.addEventListener(OrAssetAttributePickerPickedEvent.NAME, (ev) => __awaiter(this, void 0, void 0, function* () {
480
+ // handle selected attrs
481
+ const attrRef = ev.detail[0];
482
+ try {
483
+ const response = yield manager.rest.api.AssetResource.get(attrRef.id);
484
+ this.asset = response.data;
485
+ this._setAttribute(attrRef.name);
486
+ }
487
+ catch (e) {
488
+ console.error("Failed to get assets requested in settings", e);
489
+ }
490
+ }));
491
+ break;
492
+ }
493
+ if (dialog) {
494
+ showDialog(dialog);
495
+ }
496
+ }
497
+ _setAttribute(attributeName) {
498
+ if (this.asset && attributeName) {
499
+ const attr = this.asset.attributes ? this.asset.attributes[attributeName] : undefined;
500
+ this.assets = [this.asset];
501
+ this.assetAttributes = attr ? [[0, attr]] : [];
502
+ this.saveSettings();
503
+ }
504
+ }
505
+ _cleanup() {
506
+ if (this._chart) {
507
+ this._chart.destroy();
508
+ this._chart = undefined;
509
+ }
510
+ }
511
+ loadSettings() {
512
+ return __awaiter(this, arguments, void 0, function* (reset = false) {
513
+ this.assetAttributes = [];
514
+ if (!this.period || reset) {
515
+ this.period = "day";
516
+ }
517
+ if (!this.deltaFormat || reset) {
518
+ this.deltaFormat = "absolute";
519
+ }
520
+ if (!this.mainValueDecimals || reset) {
521
+ this.mainValueDecimals = 0;
522
+ }
523
+ if (!this.realm) {
524
+ this.realm = manager.getRealm();
525
+ }
526
+ let allConfigs = (yield manager.console.retrieveData("OrChartConfig")) || [];
527
+ if (!Array.isArray(allConfigs)) {
528
+ allConfigs = [allConfigs];
529
+ }
530
+ if (allConfigs.length === 0 || !this.panelName) {
531
+ return;
532
+ }
533
+ const viewSelector = window.location.hash;
534
+ let config = allConfigs.find(e => e.realm === this.realm);
535
+ const view = config && config.views && config.views[viewSelector] ? config.views[viewSelector][this.panelName] : undefined;
536
+ if (!view) {
537
+ return;
538
+ }
539
+ if (!view.attributeRefs) {
540
+ // Old/invalid config format remove it
541
+ delete config.views[viewSelector][this.panelName];
542
+ const cleanData = [...allConfigs.filter(e => e.realm !== this.realm), config];
543
+ manager.console.storeData("OrChartConfig", cleanData);
544
+ return;
545
+ }
546
+ const assetIds = view.attributeRefs.map((attrRef) => attrRef.id);
547
+ if (assetIds.length === 0) {
548
+ return;
549
+ }
550
+ this._loading = true;
551
+ if (!assetIds.every(id => !!this.assets.find(asset => asset.id === id))) {
552
+ const query = {
553
+ ids: assetIds
554
+ };
555
+ try {
556
+ const response = yield manager.rest.api.AssetResource.queryAssets(query);
557
+ const assets = response.data || [];
558
+ view.attributeRefs = view.attributeRefs.filter((attrRef) => !!assets.find((asset) => asset.id === attrRef.id && asset.attributes && asset.attributes.hasOwnProperty(attrRef.name)));
559
+ allConfigs = [...allConfigs.filter(e => e.realm !== this.realm), config];
560
+ manager.console.storeData("OrChartConfig", allConfigs);
561
+ this.assets = assets.filter((asset) => view.attributeRefs.find((attrRef) => attrRef.id === asset.id));
562
+ }
563
+ catch (e) {
564
+ console.error("Failed to get assets requested in settings", e);
565
+ }
566
+ this._loading = false;
567
+ if (this.assets && this.assets.length > 0) {
568
+ this.assetAttributes = view.attributeRefs.map((attrRef) => {
569
+ const assetIndex = this.assets.findIndex((asset) => asset.id === attrRef.id);
570
+ const asset = assetIndex >= 0 ? this.assets[assetIndex] : undefined;
571
+ return asset && asset.attributes ? [assetIndex, asset.attributes[attrRef.name]] : undefined;
572
+ }).filter((indexAndAttr) => !!indexAndAttr);
573
+ this.period = view.period || "day";
574
+ this.mainValueDecimals = view.decimals || 0;
575
+ this.deltaFormat = view.deltaFormat || "absolute";
576
+ }
577
+ }
578
+ });
579
+ }
580
+ saveSettings() {
581
+ return __awaiter(this, void 0, void 0, function* () {
582
+ if (!this.panelName) {
583
+ return;
584
+ }
585
+ const viewSelector = window.location.hash;
586
+ let allConfigs = (yield manager.console.retrieveData("OrChartConfig")) || [];
587
+ let config = allConfigs.find(e => e.realm === this.realm);
588
+ if (!config) {
589
+ config = {
590
+ realm: this.realm,
591
+ views: {}
592
+ };
593
+ }
594
+ if (!config.views[viewSelector]) {
595
+ config.views[viewSelector] = {};
596
+ }
597
+ if (!this.assets || !this.assetAttributes || this.assets.length === 0 || this.assetAttributes.length === 0) {
598
+ delete config.views[viewSelector][this.panelName];
599
+ }
600
+ else {
601
+ config.realm = this.realm;
602
+ config.views[viewSelector][this.panelName] = {
603
+ attributeRefs: this.assetAttributes.map(([index, attr]) => {
604
+ const asset = this.assets[index];
605
+ return !!asset ? { id: asset.id, name: attr.name } : undefined;
606
+ }).filter((attrRef) => !!attrRef),
607
+ period: this.period,
608
+ deltaFormat: this.deltaFormat,
609
+ decimals: this.mainValueDecimals
610
+ };
611
+ }
612
+ allConfigs = [...allConfigs.filter(e => e.realm !== this.realm), config];
613
+ manager.console.storeData("OrChartConfig", allConfigs);
614
+ });
615
+ }
616
+ loadData() {
617
+ return __awaiter(this, void 0, void 0, function* () {
618
+ var _a;
619
+ if (this.data || !this.assetAttributes || !this.assets || this.assets.length === 0 || this.assetAttributes.length === 0 || !this.period) {
620
+ return;
621
+ }
622
+ // If a new requests comes in, we override it with this one using AbortController.
623
+ if (this._dataAbortController) {
624
+ this._dataAbortController.abort("Data request overridden");
625
+ delete this._dataAbortController;
626
+ }
627
+ this._loading = true;
628
+ let interval = "HOUR" /* DatapointInterval.HOUR */;
629
+ let stepSize = 1;
630
+ switch (this.period) {
631
+ case "hour":
632
+ interval = "MINUTE" /* DatapointInterval.MINUTE */;
633
+ stepSize = 5;
634
+ break;
635
+ case "day":
636
+ interval = "HOUR" /* DatapointInterval.HOUR */;
637
+ stepSize = 1;
638
+ break;
639
+ case "week":
640
+ interval = "HOUR" /* DatapointInterval.HOUR */;
641
+ stepSize = 6;
642
+ break;
643
+ case "month":
644
+ interval = "DAY" /* DatapointInterval.DAY */;
645
+ stepSize = 1;
646
+ break;
647
+ case "year":
648
+ interval = "MONTH" /* DatapointInterval.MONTH */;
649
+ stepSize = 1;
650
+ break;
651
+ }
652
+ const lowerCaseInterval = interval.toLowerCase();
653
+ this._startOfPeriod = moment().subtract(1, this.period).toDate().getTime();
654
+ this._endOfPeriod = moment().toDate().getTime();
655
+ const assetId = this.assets[0].id;
656
+ const attributeName = this.assetAttributes[0][1].name;
657
+ this._dataAbortController = new AbortController();
658
+ try {
659
+ const response = yield manager.rest.api.AssetDatapointResource.getDatapoints(assetId, attributeName, { type: "lttb", fromTimestamp: this._startOfPeriod, toTimestamp: this._endOfPeriod, amountOfPoints: 20 }, { signal: this._dataAbortController.signal });
660
+ this._loading = false;
661
+ if (response.status === 200) {
662
+ this.data = response.data;
663
+ this.delta = this.getFormattedDelta(this.getFirstKnownMeasurement(this.data), this.getLastKnownMeasurement(this.data));
664
+ this.deltaPlus = this.delta && this.delta.val > 0 ? "+" : "";
665
+ this._error = undefined;
666
+ }
667
+ }
668
+ catch (ex) {
669
+ console.error(ex);
670
+ if ((ex === null || ex === void 0 ? void 0 : ex.message) === "canceled") {
671
+ return; // If request has been canceled (using AbortController); return, and prevent _loading is set to false.
672
+ }
673
+ this._loading = false;
674
+ if (isAxiosError(ex)) {
675
+ if (ex.message.includes("timeout")) {
676
+ this._error = "noAttributeDataTimeout";
677
+ return;
678
+ }
679
+ else if (((_a = ex.response) === null || _a === void 0 ? void 0 : _a.status) === 413) {
680
+ this._error = "datapointRequestTooLarge";
681
+ return;
682
+ }
683
+ }
684
+ this._error = "couldNotRetrieveAttribute";
685
+ }
686
+ finally {
687
+ // Finally, request the current value through WS request/response
688
+ this.mainValue = undefined;
689
+ this.formattedMainValue = undefined;
690
+ const currentValue = yield manager.events.sendEventWithReply({
691
+ eventType: "read-asset-attribute",
692
+ ref: {
693
+ id: assetId,
694
+ name: attributeName
695
+ }
696
+ });
697
+ this.mainValue = currentValue.value;
698
+ this.formattedMainValue = this.getFormattedValue(this.mainValue);
699
+ }
700
+ });
701
+ }
702
+ getTotalValue(data) {
703
+ return data.reduce((acc, val) => {
704
+ return val.y ? acc + Math.round(val.y) : acc;
705
+ }, 0);
706
+ }
707
+ getHighestValue(data) {
708
+ return Math.max.apply(Math, data.map((e) => e.y || false));
709
+ }
710
+ getFormattedValue(value) {
711
+ if (value === undefined || !this.assets || !this.assetAttributes || this.assets.length === 0 || this.assetAttributes.length === 0) {
712
+ return;
713
+ }
714
+ const attr = this.assetAttributes[0][1];
715
+ const roundedVal = +(value === null || value === void 0 ? void 0 : value.toFixed(this.mainValueDecimals)); // + operator prevents str return
716
+ const attributeDescriptor = AssetModelUtil.getAttributeDescriptor(attr.name, this.assets[0].type);
717
+ const units = Util.resolveUnits(Util.getAttributeUnits(attr, attributeDescriptor, this.assets[0].type));
718
+ this.setLabelSizeByLength(roundedVal.toString());
719
+ if (!units) {
720
+ return { value: roundedVal, unit: "" };
721
+ }
722
+ return {
723
+ value: roundedVal,
724
+ unit: units
725
+ };
726
+ }
727
+ getFirstKnownMeasurement(data) {
728
+ for (let i = 0; i <= data.length; i++) {
729
+ if (data[i] && data[i].y !== undefined)
730
+ return data[i].y;
731
+ }
732
+ return 0;
733
+ }
734
+ getLastKnownMeasurement(data) {
735
+ for (let i = data.length - 1; i >= 0; i--) {
736
+ if (data[i] && data[i].y !== undefined)
737
+ return data[i].y;
738
+ }
739
+ return 0;
740
+ }
741
+ getFormattedDelta(firstVal, lastVal) {
742
+ if (this.deltaFormat === "percentage") {
743
+ if (firstVal && lastVal) {
744
+ if (lastVal === 0 && firstVal === 0) {
745
+ return { val: 0, unit: "%" };
746
+ }
747
+ else if (lastVal === 0 && firstVal !== 0) {
748
+ return { val: 100, unit: "%" };
749
+ }
750
+ else {
751
+ const math = Math.round((lastVal - firstVal) / firstVal * 100);
752
+ return { val: math, unit: "%" };
753
+ }
754
+ }
755
+ else {
756
+ return { val: 0, unit: "%" };
757
+ }
758
+ }
759
+ return { val: Math.round(lastVal - firstVal), unit: "" };
760
+ }
761
+ handleMenuSelect(value) {
762
+ if (value === "delete") {
763
+ this.assets = [];
764
+ this.assetAttributes = [];
765
+ this.saveSettings();
766
+ }
767
+ else {
768
+ this._openDialog(value);
769
+ }
770
+ }
771
+ setLabelSizeByLength(value) {
772
+ if (value.length >= 20) {
773
+ this.mainValueSize = "xs";
774
+ }
775
+ if (value.length < 20) {
776
+ this.mainValueSize = "s";
777
+ }
778
+ if (value.length < 15) {
779
+ this.mainValueSize = "m";
780
+ }
781
+ if (value.length < 10) {
782
+ this.mainValueSize = "l";
783
+ }
784
+ if (value.length < 5) {
785
+ this.mainValueSize = "xl";
786
+ }
787
+ }
788
+ setLabelSizeByWidth(inlineSize) {
789
+ if (inlineSize < 60) {
790
+ this.mainValueSize = "s";
791
+ }
792
+ else if (inlineSize < 100) {
793
+ this.mainValueSize = "m";
794
+ }
795
+ else if (inlineSize < 200) {
796
+ this.mainValueSize = "l";
797
+ }
798
+ else {
799
+ this.mainValueSize = "xl";
800
+ }
801
+ }
802
+ _setPeriodOption(value) {
803
+ this.period = value;
804
+ this.saveSettings();
805
+ }
806
+ };
807
+ __decorate([
808
+ property()
809
+ ], OrAttributeCard.prototype, "panelName", void 0);
810
+ __decorate([
811
+ property({ type: Object })
812
+ ], OrAttributeCard.prototype, "assets", void 0);
813
+ __decorate([
814
+ property({ type: Object })
815
+ ], OrAttributeCard.prototype, "assetAttributes", void 0);
816
+ __decorate([
817
+ property()
818
+ ], OrAttributeCard.prototype, "data", void 0);
819
+ __decorate([
820
+ property({ type: String })
821
+ ], OrAttributeCard.prototype, "realm", void 0);
822
+ __decorate([
823
+ property()
824
+ ], OrAttributeCard.prototype, "mainValue", void 0);
825
+ __decorate([
826
+ property()
827
+ ], OrAttributeCard.prototype, "mainValueDecimals", void 0);
828
+ __decorate([
829
+ property()
830
+ ], OrAttributeCard.prototype, "mainValueSize", void 0);
831
+ __decorate([
832
+ property()
833
+ ], OrAttributeCard.prototype, "delta", void 0);
834
+ __decorate([
835
+ property()
836
+ ], OrAttributeCard.prototype, "deltaPlus", void 0);
837
+ __decorate([
838
+ property()
839
+ ], OrAttributeCard.prototype, "deltaFormat", void 0);
840
+ __decorate([
841
+ property()
842
+ ], OrAttributeCard.prototype, "showControls", void 0);
843
+ __decorate([
844
+ property()
845
+ ], OrAttributeCard.prototype, "hideAttributePicker", void 0);
846
+ __decorate([
847
+ property()
848
+ ], OrAttributeCard.prototype, "showTitle", void 0);
849
+ __decorate([
850
+ property()
851
+ ], OrAttributeCard.prototype, "_loading", void 0);
852
+ __decorate([
853
+ property()
854
+ ], OrAttributeCard.prototype, "period", void 0);
855
+ __decorate([
856
+ state()
857
+ ], OrAttributeCard.prototype, "_error", void 0);
858
+ __decorate([
859
+ query("#chart")
860
+ ], OrAttributeCard.prototype, "_chartElem", void 0);
861
+ OrAttributeCard = __decorate([
862
+ customElement("or-attribute-card")
863
+ ], OrAttributeCard);
864
+ export { OrAttributeCard };
865
+ //# sourceMappingURL=index.js.map