@record-evolution/widget-switch 1.0.5 → 1.1.1

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/package.json CHANGED
@@ -3,7 +3,7 @@
3
3
  "description": "IronFlock Widget widget-switch",
4
4
  "license": "MIT",
5
5
  "author": "Record Evolution GmbH",
6
- "version": "1.0.5",
6
+ "version": "1.1.1",
7
7
  "engines": {
8
8
  "node": "18.18.2",
9
9
  "npm": ">=10.0.2"
@@ -8,19 +8,14 @@
8
8
  "on": ">=1",
9
9
  "off": "<1"
10
10
  },
11
+ "value": 1,
12
+ "actionApp": "machineControlApp",
13
+ "actionDevice": 1,
14
+ "actionTopic": "lamp",
11
15
  "styling": {
12
16
  "labelColor": "#000000",
13
17
  "valueColor": "#00cc66"
14
- },
15
- "data": [
16
- {
17
- "tsp": "2025-07-15T10:00:00.000Z",
18
- "value": 1,
19
- "actionApp": "machineControlApp",
20
- "actionDevice": 1,
21
- "actionTopic": "lamp"
22
- }
23
- ]
18
+ }
24
19
  },
25
20
  {
26
21
  "label": "Cooling",
@@ -28,19 +23,14 @@
28
23
  "on": "COOL_ON,1",
29
24
  "off": "COOL_OFF,0"
30
25
  },
26
+ "value": "COOL_ON",
27
+ "actionApp": "coolingSystemApp",
28
+ "actionDevice": 1,
29
+ "actionTopic": "cooling",
31
30
  "styling": {
32
31
  "labelColor": "#0033cc",
33
32
  "valueColor": "#0099ff"
34
- },
35
- "data": [
36
- {
37
- "tsp": "2025-07-15T10:05:00.000Z",
38
- "value": "COOL_ON",
39
- "actionApp": "coolingSystemApp",
40
- "actionDevice": 1,
41
- "actionTopic": "cooling"
42
- }
43
- ]
33
+ }
44
34
  }
45
35
  ]
46
36
  }
@@ -20,33 +20,21 @@ export type ONValues = string;
20
20
  */
21
21
  export type OFFValues = string;
22
22
  /**
23
- * Is not strictly required, but is strongly recommended to be connected to the backend column that represents the switch state. This keeps the switch state consistent with the backend data.
23
+ * Is not strictly required, but is strongly recommended to be connected to the backend column that represents the switch state. This keeps the switch visual state consistent with its physical state.
24
24
  */
25
25
  export type SwitchState = string;
26
26
  /**
27
- * The action topic that is called when clicking the switch. The arguments will be True for ON and False for OFF. Refer to your chosen apps documentation for available topics to call.
27
+ * The action topic that is called at the selected app at the selected device when clicking the switch. The arguments will be True for 'ON' and False for 'OFF'. Refer to the documentation of the app for available topics to call.
28
28
  */
29
- export type ActionTopic = string;
30
- /**
31
- * You can specify a column in the input data to autogenerate dataseries for each distinct entry in this column. E.g. if you have a table with columns [city, timestamp, temperature] and specify 'city' as split column, then you will get a value field for each city.
32
- */
33
- export type SplitDataBy = string;
34
- /**
35
- * The data for the switch state.
36
- */
37
- export type SwitchStateData = {
38
- value?: SwitchState;
39
- actionApp?: ActionApp;
40
- actionDevice?: ActionDeviceTarget;
41
- actionTopic?: ActionTopic;
42
- pivot?: SplitDataBy;
43
- [k: string]: unknown;
44
- }[];
29
+ export type ActionAppTopic = string;
45
30
  export type Switches = {
46
31
  label?: Label;
47
32
  stateMap?: StateMap;
33
+ value?: SwitchState;
34
+ actionDevice?: ActionDeviceTarget;
35
+ actionApp?: ActionApp;
36
+ actionTopic?: ActionAppTopic;
48
37
  styling?: Styling;
49
- data?: SwitchStateData;
50
38
  [k: string]: unknown;
51
39
  }[];
52
40
 
@@ -64,6 +52,18 @@ export interface StateMap {
64
52
  off?: OFFValues;
65
53
  [k: string]: unknown;
66
54
  }
55
+ /**
56
+ * The device that should handle the click on the switch. The 'Device ID' column can be used here when using data driven mode.
57
+ */
58
+ export interface ActionDeviceTarget {
59
+ [k: string]: unknown;
60
+ }
61
+ /**
62
+ * The app that should handle the click on the switch.
63
+ */
64
+ export interface ActionApp {
65
+ [k: string]: unknown;
66
+ }
67
67
  export interface Styling {
68
68
  labelColor?: LabelColor;
69
69
  valueColor?: ValueColor;
@@ -75,15 +75,3 @@ export interface LabelColor {
75
75
  export interface ValueColor {
76
76
  [k: string]: unknown;
77
77
  }
78
- /**
79
- * The app that should handle the click on the switch.
80
- */
81
- export interface ActionApp {
82
- [k: string]: unknown;
83
- }
84
- /**
85
- * The device that should handele the click on the switch. The 'Device ID' column can be used here when using data driven mode.
86
- */
87
- export interface ActionDeviceTarget {
88
- [k: string]: unknown;
89
- }
@@ -15,8 +15,7 @@
15
15
  "dataseries": {
16
16
  "title": "Switches",
17
17
  "type": "array",
18
- "dataDrivenDisabled": true,
19
- "order": 2,
18
+ "order": 3,
20
19
  "items": {
21
20
  "type": "object",
22
21
  "properties": {
@@ -31,7 +30,7 @@
31
30
  "description": "Specify the values for the ON and OFF states. Any value that does not match to either an ON or OFF state will be considered as UNKNOWN.",
32
31
  "type": "object",
33
32
  "required": true,
34
- "order": 3,
33
+ "order": 2,
35
34
  "properties": {
36
35
  "on": {
37
36
  "title": "ON Values",
@@ -47,11 +46,37 @@
47
46
  }
48
47
  }
49
48
  },
49
+ "value": {
50
+ "title": "Switch State",
51
+ "type": "string",
52
+ "description": "Is not strictly required, but is strongly recommended to be connected to the backend column that represents the switch state. This keeps the switch visual state consistent with its physical state.",
53
+ "required": false,
54
+ "order": 3
55
+ },
56
+ "actionDevice": {
57
+ "title": "Action Device Target",
58
+ "description": "The device that should handle the click on the switch. The 'Device ID' column can be used here when using data driven mode.",
59
+ "type": "actionDevice",
60
+ "order": 4
61
+ },
62
+ "actionApp": {
63
+ "title": "Action App",
64
+ "description": "The app that should handle the click on the switch.",
65
+ "dataDrivenDisabled": true,
66
+ "type": "actionApp",
67
+ "order": 5
68
+ },
69
+ "actionTopic": {
70
+ "title": "Action App Topic",
71
+ "description": "The action topic that is called at the selected app at the selected device when clicking the switch. The arguments will be True for 'ON' and False for 'OFF'. Refer to the documentation of the app for available topics to call.",
72
+ "type": "string",
73
+ "order": 6
74
+ },
50
75
  "styling": {
51
76
  "title": "Styling",
52
77
  "description": "",
53
78
  "type": "object",
54
- "order": 6,
79
+ "order": 9,
55
80
  "properties": {
56
81
  "labelColor": {
57
82
  "title": "Label Color",
@@ -66,49 +91,6 @@
66
91
  "order": 5
67
92
  }
68
93
  }
69
- },
70
- "data": {
71
- "title": "Switch State Data",
72
- "description": "The data for the switch state.",
73
- "type": "array",
74
- "order": 4,
75
- "items": {
76
- "type": "object",
77
- "properties": {
78
- "value": {
79
- "title": "Switch State",
80
- "type": "string",
81
- "description": "Is not strictly required, but is strongly recommended to be connected to the backend column that represents the switch state. This keeps the switch state consistent with the backend data.",
82
- "required": false,
83
- "order": 2
84
- },
85
- "actionApp": {
86
- "title": "Action App",
87
- "description": "The app that should handle the click on the switch.",
88
- "dataDrivenDisabled": true,
89
- "type": "actionApp",
90
- "order": 3
91
- },
92
- "actionDevice": {
93
- "title": "Action Device Target",
94
- "description": "The device that should handele the click on the switch. The 'Device ID' column can be used here when using data driven mode.",
95
- "type": "actionDevice",
96
- "order": 4
97
- },
98
- "actionTopic": {
99
- "title": "Action Topic",
100
- "description": "The action topic that is called when clicking the switch. The arguments will be True for ON and False for OFF. Refer to your chosen apps documentation for available topics to call.",
101
- "type": "string",
102
- "order": 5
103
- },
104
- "pivot": {
105
- "title": "Split Data by",
106
- "description": "You can specify a column in the input data to autogenerate dataseries for each distinct entry in this column. E.g. if you have a table with columns [city, timestamp, temperature] and specify 'city' as split column, then you will get a value field for each city.",
107
- "type": "string",
108
- "order": 6
109
- }
110
- }
111
- }
112
94
  }
113
95
  }
114
96
  }
@@ -6,7 +6,6 @@ import '@material/web/switch/switch.js'
6
6
  import { MdSwitch } from '@material/web/switch/switch.js'
7
7
 
8
8
  type Dataseries = Exclude<InputData['dataseries'], undefined>[number] & { needleValue?: number }
9
- type Data = Exclude<Dataseries['data'], undefined>[number]
10
9
  type Theme = {
11
10
  theme_name: string
12
11
  theme_object: any
@@ -90,83 +89,79 @@ export class WidgetSwitch extends LitElement {
90
89
  this.dataSets = new Map()
91
90
  this.inputData?.dataseries
92
91
  // ?.sort((a, b) => a.order - b.order)
93
- ?.forEach((ds) => {
92
+ ?.forEach((ds, idx) => {
94
93
  // pivot data
95
- const distincts = [...new Set(ds.data?.map((d: Data) => d.pivot))].sort() as string[]
96
94
  ds.selected = undefined
97
-
98
- distincts.forEach((piv) => {
99
- const prefix = piv ?? ''
100
- const label = ds.label ?? ''
101
- const value =
102
- distincts.length === 1
103
- ? ds.data?.at(-1)
104
- : ds.data?.filter((d) => d.pivot === piv)?.at(-1)
105
- const pds: Dataseries = {
106
- label: prefix + (!!prefix && !!label ? ' - ' : '') + label,
107
- actionApp: value?.actionApp,
108
- actionDevice: value?.actionDevice,
109
- actionTopic: value?.actionTopic,
110
- styling: ds.styling,
111
- selected: this.isSelected(ds, value)
112
- }
113
- this.dataSets.set(pds.label ?? '', pds)
114
- })
95
+ let label = ds.label
96
+ if (this.dataSets.has(label ?? '')) {
97
+ label += '-' + idx
98
+ }
99
+ const pds: Dataseries = {
100
+ label: label,
101
+ actionApp: ds?.actionApp,
102
+ actionDevice: ds?.actionDevice,
103
+ actionTopic: ds?.actionTopic,
104
+ multiChart: ds.multiChart,
105
+ styling: ds.styling,
106
+ selected: this.isSelected(ds)
107
+ }
108
+ this.dataSets.set(pds.label ?? '', pds)
115
109
  })
116
110
  // console.log('Value Datasets', this.dataSets)
117
111
  }
118
112
 
119
- isSelected(ds: Dataseries, value?: Data): boolean | undefined {
120
- if (!value) return undefined
113
+ isSelected(ds: Dataseries): boolean | undefined {
114
+ const value = ds.value
115
+ if (value === undefined) return undefined
121
116
  const on = ds?.stateMap?.on
122
117
  if (on?.startsWith('<=')) {
123
- const val = parseFloat(value.value ?? '')
118
+ const val = parseFloat(value ?? '')
124
119
  const comp = parseFloat(on.substring(2))
125
120
  return isNaN(val) || isNaN(comp) ? undefined : val <= comp
126
121
  }
127
122
  if (on?.startsWith('<')) {
128
- const val = parseFloat(value.value ?? '')
123
+ const val = parseFloat(value ?? '')
129
124
  const comp = parseFloat(on.substring(1))
130
125
  return isNaN(val) || isNaN(comp) ? undefined : val < comp
131
126
  }
132
127
  if (on?.startsWith('>=')) {
133
- const val = parseFloat(value.value ?? '')
128
+ const val = parseFloat(value ?? '')
134
129
  const comp = parseFloat(on.substring(2))
135
130
  return isNaN(val) || isNaN(comp) ? undefined : val >= comp
136
131
  }
137
132
  if (on?.startsWith('>')) {
138
- const val = parseFloat(value.value ?? '')
133
+ const val = parseFloat(value ?? '')
139
134
  const comp = parseFloat(on.substring(1))
140
135
  return isNaN(val) || isNaN(comp) ? undefined : val > comp
141
136
  }
142
137
 
143
138
  const off = ds?.stateMap?.off
144
139
  if (off?.startsWith('<=')) {
145
- const val = parseFloat(value.value ?? '')
140
+ const val = parseFloat(value ?? '')
146
141
  const comp = parseFloat(off.substring(2))
147
142
  return isNaN(val) || isNaN(comp) ? undefined : val > comp
148
143
  }
149
144
  if (off?.startsWith('<')) {
150
- const val = parseFloat(value.value ?? '')
145
+ const val = parseFloat(value ?? '')
151
146
  const comp = parseFloat(off.substring(1))
152
147
  return isNaN(val) || isNaN(comp) ? undefined : val <= comp
153
148
  }
154
149
  if (off?.startsWith('>=')) {
155
- const val = parseFloat(value.value ?? '')
150
+ const val = parseFloat(value ?? '')
156
151
  const comp = parseFloat(off.substring(2))
157
152
  return isNaN(val) || isNaN(comp) ? undefined : val < comp
158
153
  }
159
154
  if (off?.startsWith('>')) {
160
- const val = parseFloat(value.value ?? '')
155
+ const val = parseFloat(value ?? '')
161
156
  const comp = parseFloat(off.substring(1))
162
157
  return isNaN(val) || isNaN(comp) ? undefined : val <= comp
163
158
  }
164
159
 
165
160
  const onValues = on?.split(',').map((v) => v.trim().replace('"', '').replace("'", '')) ?? []
166
- if (onValues.includes(String(value.value) ?? '')) return true
161
+ if (onValues.includes(String(value) ?? '')) return true
167
162
 
168
163
  const offValues = off?.split(',').map((v) => v.trim().replace('"', '').replace("'", '')) ?? []
169
- if (offValues.includes(String(value.value) ?? '')) return false
164
+ if (offValues.includes(String(value) ?? '')) return false
170
165
 
171
166
  return undefined
172
167
  }