emhass 0.10.6__py3-none-any.whl → 0.15.5__py3-none-any.whl

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.
emhass/static/script.js CHANGED
@@ -1,419 +1,474 @@
1
+ //configuration for dynamically processing index page
2
+ //loads either the basic or advance html
3
+
4
+ //used static files
5
+ //advanced.html : template html for displaying all the actions + runtime parameter input
6
+ //basic.html : template html for displaying a minimal view of actions
7
+
1
8
  //on page reload get saved data
2
9
  window.onload = async function () {
10
+ await loadBasicOrAdvanced();
3
11
 
4
- pageSelected = await loadBasicOrAdvanced();
5
-
6
- //add listener for basic and advanced html switch
7
- document.getElementById("basicOrAdvanced").addEventListener("click", () => SwitchBasicOrAdvanced());
12
+ //add listener for basic and advanced html switch
13
+ document
14
+ .getElementById("basicOrAdvanced")
15
+ .addEventListener("click", () => SwitchBasicOrAdvanced());
8
16
  };
9
17
 
10
18
  //add listeners to buttons (based on page)
11
- function loadButtons(page) {
12
- switch (page) {
13
- case "advanced":
14
- [
15
- "dayahead-optim",
16
- "forecast-model-fit",
17
- "forecast-model-predict",
18
- "forecast-model-tune",
19
- "regressor-model-fit",
20
- "regressor-model-predict",
21
- "perfect-optim",
22
- "publish-data",
23
- "naive-mpc-optim"
24
- ].forEach((id) =>
25
- document.getElementById(id).addEventListener("click", () => formAction(id, "advanced"))
26
- );
27
- ["input-plus", "input-minus"].forEach((id) =>
28
- document.getElementById(id).addEventListener("click", () => dictInputs(id))
29
- );
30
- document.getElementById("input-select").addEventListener("change", () => getSavedData());
31
- document.getElementById("input-clear").addEventListener("click", () => ClearInputData());
32
- break;
33
- case "basic":
34
- document.getElementById("dayahead-optim-basic").addEventListener("click", () => formAction("dayahead-optim", "basic"));
35
- break;
36
- }
19
+ async function loadButtons(page) {
20
+ switch (page) {
21
+ case "advanced":
22
+ [
23
+ "dayahead-optim",
24
+ "forecast-model-fit",
25
+ "forecast-model-predict",
26
+ "forecast-model-tune",
27
+ "regressor-model-fit",
28
+ "regressor-model-predict",
29
+ "export-influxdb-to-csv",
30
+ "perfect-optim",
31
+ "publish-data",
32
+ "naive-mpc-optim",
33
+ ].forEach((id) =>
34
+ document
35
+ .getElementById(id)
36
+ .addEventListener("click", () => formAction(id, "advanced"))
37
+ );
38
+ ["input-plus", "input-minus"].forEach((id) =>
39
+ document
40
+ .getElementById(id)
41
+ .addEventListener("click", () => dictInputs(id))
42
+ );
43
+ document
44
+ .getElementById("input-select")
45
+ .addEventListener("change", () => getSavedData());
46
+ document
47
+ .getElementById("input-clear")
48
+ .addEventListener("click", () => ClearInputData());
49
+
50
+ // Check if InfluxDB is enabled and show/hide export section
51
+ await checkInfluxDBAndShowExport();
52
+ break;
53
+ case "basic":
54
+ document
55
+ .getElementById("dayahead-optim-basic")
56
+ .addEventListener("click", () => formAction("dayahead-optim", "basic"));
57
+ break;
58
+ }
37
59
  }
38
60
 
39
61
  //on check present basic or advanced html inside form element
40
62
  async function loadBasicOrAdvanced(RequestedPage) {
41
- let basicFile = "basic.html";
42
- let advencedFile = "advanced.html";
43
- var formContainer = document.getElementById("TabSelection"); //container element to house basic or advanced data
44
- //first check any function arg
45
- if (arguments.length == 1) {
46
- switch (RequestedPage) {
47
- case "basic":
48
- htmlData = await getHTMLData(basicFile);
49
- formContainer.innerHTML = htmlData;
50
- loadButtons("basic"); //load buttons based on basic or advanced
51
- if (testStorage()) { localStorage.setItem("TabSelection", "basic") } //remember mode (save to localStorage)
52
- return "basic"; //return basic to get saved data
53
- case "advanced":
54
- htmlData = await getHTMLData(advencedFile);
55
- formContainer.innerHTML = htmlData;
56
- loadButtons("advanced");
57
- if (testStorage()) { localStorage.setItem("TabSelection", "advanced") }
58
- getSavedData();
59
- return "advanced";
60
- default:
61
- htmlData = await getHTMLData(advencedFile);
62
- formContainer.innerHTML = htmlData;
63
- loadButtons("advanced");
64
- getSavedData();
65
- return "advanced";
66
- }
67
- }
68
- //then check localStorage
69
- if (testStorage()) {
70
- if (localStorage.getItem("TabSelection") !== null && localStorage.getItem("TabSelection") === "advanced") { //if advance
71
- htmlData = await getHTMLData(advencedFile);
72
- formContainer.innerHTML = htmlData;
73
- loadButtons("advanced");
74
- getSavedData();
75
- return "advanced";
76
- }
77
- else { //else run basic (first time)
78
- htmlData = await getHTMLData(basicFile);
79
- formContainer.innerHTML = htmlData;
80
- loadButtons("basic");
81
- return "basic";
63
+ let basicFile = "basic.html";
64
+ let advencedFile = "advanced.html";
65
+ let formContainer = document.getElementById("TabSelection"); //container element to house basic or advanced data
66
+ let htmlData
67
+ //first check any function arg
68
+ if (arguments.length == 1) {
69
+ switch (RequestedPage) {
70
+ case "basic":
71
+ htmlData = await getHTMLData(basicFile);
72
+ formContainer.innerHTML = htmlData;
73
+ loadButtons("basic"); //load buttons based on basic or advanced
74
+ if (testStorage()) {
75
+ localStorage.setItem("TabSelection", "basic");
76
+ } //remember mode (save to localStorage)
77
+ return "basic"; //return basic to get saved data
78
+ case "advanced":
79
+ htmlData = await getHTMLData(advencedFile);
80
+ formContainer.innerHTML = htmlData;
81
+ loadButtons("advanced");
82
+ if (testStorage()) {
83
+ localStorage.setItem("TabSelection", "advanced");
82
84
  }
83
- } else {
84
- //if localStorage not supported, set to advanced page
85
+ getSavedData();
86
+ return "advanced";
87
+ default:
85
88
  htmlData = await getHTMLData(advencedFile);
86
89
  formContainer.innerHTML = htmlData;
87
90
  loadButtons("advanced");
91
+ getSavedData();
88
92
  return "advanced";
89
93
  }
94
+ }
95
+ //then check localStorage
96
+ if (testStorage()) {
97
+ if (
98
+ localStorage.getItem("TabSelection") !== null &&
99
+ localStorage.getItem("TabSelection") === "advanced"
100
+ ) {
101
+ //if advance
102
+ let htmlData = await getHTMLData(advencedFile);
103
+ formContainer.innerHTML = htmlData;
104
+ loadButtons("advanced");
105
+ getSavedData();
106
+ return "advanced";
107
+ } else {
108
+ //else run basic (first time)
109
+ htmlData = await getHTMLData(basicFile);
110
+ formContainer.innerHTML = htmlData;
111
+ loadButtons("basic");
112
+ return "basic";
113
+ }
114
+ } else {
115
+ //if localStorage not supported, set to advanced page
116
+ htmlData = await getHTMLData(advencedFile);
117
+ formContainer.innerHTML = htmlData;
118
+ loadButtons("advanced");
119
+ return "advanced";
120
+ }
90
121
  }
91
122
 
92
123
  //on button press, check current displayed page data and switch
93
124
  function SwitchBasicOrAdvanced() {
94
- var formContainerChildID = document.getElementById("TabSelection").firstElementChild.id
95
- if (formContainerChildID === 'basic') {
96
- loadBasicOrAdvanced("advanced")
97
- }
98
- else {
99
- loadBasicOrAdvanced("basic")
100
- }
125
+ let formContainerChildID =
126
+ document.getElementById("TabSelection").firstElementChild.id;
127
+ if (formContainerChildID === "basic") {
128
+ loadBasicOrAdvanced("advanced");
129
+ } else {
130
+ loadBasicOrAdvanced("basic");
131
+ }
101
132
  }
102
133
 
103
-
104
134
  //get html data from basic.html or advanced.html
105
135
  async function getHTMLData(htmlFile) {
106
- const response = await fetch(`static/` + htmlFile);
107
- blob = await response.blob(); //get data blob
108
- htmlTemplateData = await new Response(blob).text(); //obtain html from blob
109
- return await htmlTemplateData;
136
+ const response = await fetch(`static/` + htmlFile);
137
+ let blob = await response.blob(); //get data blob
138
+ let htmlTemplateData = await new Response(blob).text(); //obtain html from blob
139
+ return htmlTemplateData;
110
140
  }
111
141
 
112
142
  //function pushing data via post, triggered by button action
113
143
  async function formAction(action, page) {
144
+ let data = {}
145
+ if (page !== "basic") {
146
+ //dont try to get input data in basic mode
147
+ data = inputToJson();
148
+ } else {
149
+ data = {};
150
+ } //send no data
114
151
 
115
- if (page !== "basic") { //dont try to get input data in basic mode
116
- var data = inputToJson(page);
117
- }
118
- else { var data = {} } //send no data
119
-
120
- if (data !== 0) { //don't run if there is an error in the input (box/list) Json data
121
- showChangeStatus("loading", {}); // show loading div for status
122
- const response = await fetch(`action/` + action, {
123
- //fetch data from webserver.py
124
- method: "POST",
125
- headers: {
126
- "Content-Type": "application/json",
127
- },
128
- body: JSON.stringify(data), //note that post can only send data via strings
129
- });
130
- if (response.status == 201) {
131
- showChangeStatus(response.status, {});
132
- if (page !== "basic") {
133
- saveStorage(); //save to storage if successful
134
- }
135
- return true
136
- } //if successful
137
- else {
138
- showChangeStatus(response.status, await response.json());
139
- return false
140
- } // else get Log data from response
141
- } else {
142
- showChangeStatus("remove"); //replace loading, show tick or cross with none
143
- return false
144
- }
152
+ if (data !== 0) {
153
+ //don't run if there is an error in the input (box/list) Json data
154
+ showChangeStatus("loading", {}); // show loading div for status
155
+ const response = await fetch(`action/` + action, {
156
+ //fetch data from webserver.py
157
+ method: "POST",
158
+ headers: {
159
+ "Content-Type": "application/json",
160
+ 'Transfer-Encoding': 'chunked'
161
+ },
162
+ body: JSON.stringify(data), //note that post can only send data via strings
163
+ });
164
+ if (response.status == 201) {
165
+ showChangeStatus(response.status, {});
166
+ if (page !== "basic") {
167
+ saveStorage(); //save to storage if successful
168
+ }
169
+ return true;
170
+ } //if successful
171
+ else {
172
+ showChangeStatus(response.status, await response.json());
173
+ return false;
174
+ } // else get Log data from response
175
+ } else {
176
+ showChangeStatus("remove"); //replace loading, show tick or cross with none
177
+ return false;
178
+ }
145
179
  }
146
180
 
147
181
  //function in control of status icons of post above
148
182
  async function showChangeStatus(status, logJson) {
149
- var loading = document.getElementById("loader"); //element showing statuses
150
- if (status === "remove") {
151
- //remove all
152
- loading.innerHTML = "";
153
- loading.classList.remove("loading");
154
- } else if (status === "loading") {
155
- //show loading logo
156
- loading.innerHTML = "";
157
- loading.classList.add("loading"); //append class with loading animation styling
158
- } else if (status === 201) {
159
- //if status is 201, then show a tick
160
- loading.classList.remove("loading");
161
- loading.innerHTML = `<p class=tick>&#x2713;</p>`;
162
- getTemplate(); //get updated templates
163
- } else {
164
- //then show a cross
165
- loading.classList.remove("loading");
166
- loading.innerHTML = `<p class=cross>&#x292C;</p>`; //show cross icon to indicate an error
167
- if (logJson.length != 0) {
168
- document.getElementById("alert-text").textContent =
169
- "\r\n\u2022 " + logJson.join("\r\n\u2022 "); //show received log data in alert box
170
- document.getElementById("alert").style.display = "block";
171
- document.getElementById("alert").style.textAlign = "left";
172
- }
183
+ let loading = document.getElementById("loader"); //element showing statuses
184
+ if (status === "remove") {
185
+ //remove all
186
+ loading.innerHTML = "";
187
+ loading.classList.remove("loading");
188
+ } else if (status === "loading") {
189
+ //show loading logo
190
+ loading.innerHTML = "";
191
+ loading.classList.add("loading"); //append class with loading animation styling
192
+ } else if (status === 201) {
193
+ //if status is 201, then show a tick
194
+ loading.classList.remove("loading");
195
+ loading.innerHTML = `<p class=tick>&#x2713;</p>`;
196
+ getTemplate(); //get updated templates
197
+ } else {
198
+ //then show a cross
199
+ loading.classList.remove("loading");
200
+ loading.innerHTML = `<p class=cross>&#x292C;</p>`; //show cross icon to indicate an error
201
+ if (logJson.length != 0 && document.getElementById("alert-text") !== null) {
202
+ document.getElementById("alert-text").textContent =
203
+ "\r\n\u2022 " + logJson.join("\r\n\u2022 "); //show received log data in alert box
204
+ document.getElementById("alert").style.display = "block";
205
+ document.getElementById("alert").style.textAlign = "left";
173
206
  }
207
+ }
174
208
  }
175
209
 
176
210
  //get rendered html template with containing new table data
177
211
  async function getTemplate() {
178
- //fetch data from webserver.py
179
- let htmlTemplateData = "";
180
- response = await fetch(`template/table-template`, {
181
- method: "GET",
182
- });
183
- blob = await response.blob(); //get data blob
184
- htmlTemplateData = await new Response(blob).text(); //obtain html from blob
185
- templateDiv = document.getElementById("template"); //get template container element to override
186
- templateDiv.innerHTML = htmlTemplateData; //override container inner html with new data
187
- var scripts = Array.from(templateDiv.getElementsByTagName("script")); //replace script tags manually
188
- for (const script of scripts) {
189
- var TempScript = document.createElement("script");
190
- TempScript.innerHTML = script.innerHTML;
191
- script.parentElement.appendChild(TempScript);
192
- }
212
+ //fetch data from webserver.py
213
+ let htmlTemplateData = "";
214
+ let response = await fetch(`template`, {
215
+ method: "GET",
216
+ });
217
+ let blob = await response.blob(); //get data blob
218
+ htmlTemplateData = await new Response(blob).text(); //obtain html from blob
219
+ let templateDiv = document.getElementById("template"); //get template container element to override
220
+ templateDiv.innerHTML = htmlTemplateData; //override container inner html with new data
221
+ let scripts = Array.from(templateDiv.getElementsByTagName("script")); //replace script tags manually
222
+ for (const script of scripts) {
223
+ let TempScript = document.createElement("script");
224
+ TempScript.innerHTML = script.innerHTML;
225
+ script.parentElement.appendChild(TempScript);
226
+ }
193
227
  }
194
228
 
195
229
  //test localStorage support
196
230
  function testStorage() {
197
- try {
198
- localStorage.setItem("test", { test: "123" });
199
- localStorage.removeItem("test");
200
- return true;
201
- } catch (error) {
202
- return false;
203
- }
231
+ try {
232
+ localStorage.setItem("test", { test: "123" });
233
+ localStorage.removeItem("test");
234
+ return true;
235
+ } catch (error) {
204
236
  return false;
237
+ }
205
238
  }
206
239
 
207
240
  //function gets saved data (if any)
208
241
  function getSavedData() {
209
- dictInputs(); //check selected current (List or Box) is correct
210
- if (testStorage()) {
211
- //if local storage exists and works
212
- let selectElement = document.getElementById("input-select"); // select button element
213
- var input_container = document.getElementById("input-container"); // container div containing all dynamic input elements (Box/List)
214
- if (
215
- localStorage.getItem("input_container_content") &&
216
- localStorage.getItem("input_container_content") !== "{}"
217
- ) {
218
- //If items already stored in local storage, then override default
219
- if (selectElement.value == "Box") {
220
- //if Box is selected, show saved json data into box
221
- document.getElementById("text-area").value = localStorage.getItem(
222
- "input_container_content"
223
- );
224
- }
225
- if (selectElement.value == "List") {
226
- //if List is selected, show saved json data into box
227
- storedJson = JSON.parse(
228
- localStorage.getItem("input_container_content")
229
- );
230
- if (Object.keys(storedJson).length > 0) {
231
- input_container.innerHTML = "";
232
- i = 1;
233
- for (const ikey in storedJson) {
234
- input_container.appendChild(
235
- createInputListDiv(ikey, JSON.stringify(storedJson[ikey]))
236
- ); //call function to present each key as an list div element (with saved values)
237
- }
238
- }
239
- }
242
+ dictInputs(); //check selected current (List or Box) is correct
243
+ if (testStorage()) {
244
+ //if local storage exists and works
245
+ let selectElement = document.getElementById("input-select"); // select button element
246
+ let input_container = document.getElementById("input-container"); // container div containing all dynamic input elements (Box/List)
247
+ if (
248
+ localStorage.getItem("input_container_content") &&
249
+ localStorage.getItem("input_container_content") !== "{}"
250
+ ) {
251
+ //If items already stored in local storage, then override default
252
+ if (selectElement.value == "Box") {
253
+ //if Box is selected, show saved json data into box
254
+ document.getElementById("text-area").value = localStorage.getItem(
255
+ "input_container_content"
256
+ );
257
+ }
258
+ if (selectElement.value == "List") {
259
+ //if List is selected, show saved json data into box
260
+ let storedJson = JSON.parse(
261
+ localStorage.getItem("input_container_content")
262
+ );
263
+ if (Object.keys(storedJson).length > 0) {
264
+ input_container.innerHTML = "";
265
+ for (const ikey in storedJson) {
266
+ input_container.appendChild(
267
+ createInputListDiv(ikey, JSON.stringify(storedJson[ikey]))
268
+ ); //call function to present each key as an list div element (with saved values)
269
+ }
240
270
  }
271
+ }
241
272
  }
273
+ }
242
274
  }
243
275
 
244
276
  //using localStorage, store json data from input-list(List)/text-area(from input-box) elements for saved state save on page refresh (will save state on successful post)
245
277
  function saveStorage() {
246
- var data = JSON.stringify(inputToJson());
247
- if (testStorage() && data != "{}") {
248
- //don't bother saving if empty and/or storage don't exist
249
- localStorage.setItem("input_container_content", data);
250
- }
278
+ let data = JSON.stringify(inputToJson());
279
+ if (testStorage() && data != "{}") {
280
+ //don't bother saving if empty and/or storage don't exist
281
+ localStorage.setItem("input_container_content", data);
282
+ }
251
283
  }
252
284
 
253
285
  //function gets values from input-list/text-area(from input-box) elements and return json dict object
254
286
  function inputToJson() {
255
- var input_container = document.getElementById("input-container"); //container
256
- let inputListArr = document.getElementsByClassName("input-list"); //list
257
- let inputTextArea = document.getElementById("text-area"); //box
258
- let input_container_child = null;
259
- input_container_child = input_container.firstElementChild; //work out which element is first inside container div
260
- var jsonReturnData = {};
287
+ let input_container = document.getElementById("input-container"); //container
288
+ let inputListArr = document.getElementsByClassName("input-list"); //list
289
+ let inputTextArea = document.getElementById("text-area"); //box
290
+ let input_container_child = null;
291
+ input_container_child = input_container.firstElementChild; //work out which element is first inside container div
292
+ let jsonReturnData = {};
261
293
 
262
- if (input_container_child == null) {
263
- //if no elements in container then return empty
264
- return jsonReturnData;
265
- }
266
- //if List return box json
267
- if (
268
- input_container_child.className == "input-list" &&
269
- inputListArr.length > 0
270
- ) {
271
- //if list is first and if list is greater then 0, otherwise give empty dict
294
+ if (input_container_child == null) {
295
+ //if no elements in container then return empty
296
+ return jsonReturnData;
297
+ }
298
+ //if List return box json
299
+ if (
300
+ input_container_child.className == "input-list" &&
301
+ inputListArr.length > 0
302
+ ) {
303
+ //if list is first and if list is greater then 0, otherwise give empty dict
272
304
 
273
- let jsonTempData = "{";
274
- for (let i = 0; i < inputListArr.length; i++) {
275
- let key = inputListArr[i].getElementsByClassName("input-key")[0].value;
276
- var value =
277
- inputListArr[i].getElementsByClassName("input-value")[0].value;
278
- //curate a string with list elements to parse into json later
279
- if (key !== "") {
280
- //key must not be empty
281
- if (i !== 0) {
282
- jsonTempData = jsonTempData.concat(",");
283
- } //add comma before every parameter, exuding the first
284
- jsonTempData = jsonTempData.concat('"' + key + '":' + value);
285
- }
286
- }
287
- jsonTempData = jsonTempData.concat("}");
288
- try {
289
- jsonReturnData = JSON.parse(jsonTempData);
290
- } catch (error) {
291
- //if json error, show in alert box
292
- document.getElementById("alert-text").textContent =
293
- "\r\n" +
294
- error +
295
- "\r\n" +
296
- "JSON Error: String values may not be wrapped in quotes";
297
- document.getElementById("alert").style.display = "block";
298
- document.getElementById("alert").style.textAlign = "center";
299
- return 0;
300
- }
305
+ let jsonTempData = "{";
306
+ for (let i = 0; i < inputListArr.length; i++) {
307
+ let key = inputListArr[i].getElementsByClassName("input-key")[0].value;
308
+ let value =
309
+ inputListArr[i].getElementsByClassName("input-value")[0].value;
310
+ //curate a string with list elements to parse into json later
311
+ if (key !== "") {
312
+ //key must not be empty
313
+ if (i !== 0) {
314
+ jsonTempData = jsonTempData.concat(",");
315
+ } //add comma before every parameter, exuding the first
316
+ jsonTempData = jsonTempData.concat('"' + key + '":' + value);
317
+ }
301
318
  }
302
- //if Box return box json
303
- if (
304
- input_container_child.className == "input-box" &&
305
- inputTextArea.value != ""
306
- ) {
307
- //if Box is first and text is not empty, otherwise give empty dict
308
- try {
309
- jsonReturnData = JSON.parse(inputTextArea.value);
310
- } catch (error) {
311
- //if json error, show in alert box
312
- document.getElementById("alert-text").textContent = "\r\n" + error;
313
- document.getElementById("alert").style.display = "block";
314
- return 0;
315
- }
319
+ jsonTempData = jsonTempData.concat("}");
320
+ try {
321
+ jsonReturnData = JSON.parse(jsonTempData);
322
+ } catch (error) {
323
+ //if json error, show in alert box
324
+ document.getElementById("alert-text").textContent =
325
+ "\r\n" +
326
+ error +
327
+ "\r\n" +
328
+ "JSON Error: String values may not be wrapped in quotes";
329
+ document.getElementById("alert").style.display = "block";
330
+ document.getElementById("alert").style.textAlign = "center";
331
+ return 0;
316
332
  }
317
- return jsonReturnData;
333
+ }
334
+ //if Box return box json
335
+ if (
336
+ input_container_child.className == "input-box" &&
337
+ inputTextArea.value != ""
338
+ ) {
339
+ //if Box is first and text is not empty, otherwise give empty dict
340
+ try {
341
+ jsonReturnData = JSON.parse(inputTextArea.value);
342
+ } catch (error) {
343
+ //if json error, show in alert box
344
+ document.getElementById("alert-text").textContent = "\r\n" + error;
345
+ document.getElementById("alert").style.display = "block";
346
+ return 0;
347
+ }
348
+ }
349
+ return jsonReturnData;
318
350
  }
319
351
 
320
352
  //function creates input list div element (and pass it values if given)
321
353
  function createInputListDiv(ikey, ivalue) {
322
- let div = document.createElement("div");
323
- div.className = "input-list";
324
- div.innerHTML = `
354
+ let div = document.createElement("div");
355
+ div.className = "input-list";
356
+ div.innerHTML = `
325
357
  <input class="input-key" type="text" placeholder="pv_power_forecast" >
326
358
  <p>:</p>
327
359
  <input class="input-value" type="text" placeholder="[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 70, 141.22, 246.18, 513.5, 753.27, 1049.89, 1797.93, 1697.3, 3078.93, 1164.33, 1046.68, 1559.1, 2091.26, 1556.76, 1166.73, 1516.63, 1391.13, 1720.13, 820.75, 804.41, 251.63, 79.25, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]" >
328
360
  `;
329
361
 
330
- if (ikey && ivalue) {
331
- //if value and key is provided (from local storage) then add as elements values
332
- div.getElementsByClassName("input-key")[0].value = String(ikey);
333
- div.getElementsByClassName("input-value")[0].value = String(ivalue);
334
- }
362
+ if (ikey && ivalue) {
363
+ //if value and key is provided (from local storage) then add as elements values
364
+ div.getElementsByClassName("input-key")[0].value = String(ikey);
365
+ div.getElementsByClassName("input-value")[0].value = String(ivalue);
366
+ }
335
367
 
336
- return div;
368
+ return div;
337
369
  }
338
370
 
339
371
  //function assigned to control (add and remove) input (Box and List) elements
340
372
  function dictInputs(action) {
341
- var input_container = document.getElementById("input-container"); // container div containing all dynamic input elements
342
- let selectElement = document.getElementById("input-select"); // select button
343
- let input_container_child = null;
344
- let input_container_child_name = null;
345
- if (input_container.children.length > 0) {
346
- input_container_child = input_container.firstElementChild; // figure out what is the first element inside of container (ie: "text-area" (input-box) or "input-list" (list))
347
- input_container_child_name = input_container.firstElementChild.className;
373
+ let input_container = document.getElementById("input-container"); // container div containing all dynamic input elements
374
+ let selectElement = document.getElementById("input-select"); // select button
375
+ let input_container_child = null;
376
+ let input_container_child_name = null;
377
+ if (input_container.children.length > 0) {
378
+ input_container_child = input_container.firstElementChild; // figure out what is the first element inside of container (ie: "text-area" (input-box) or "input-list" (list))
379
+ input_container_child_name = input_container.firstElementChild.className;
380
+ }
381
+ //if list is selected, remove text-area (from Box) element and replace (with input-list)
382
+ if (selectElement.value == "List") {
383
+ if (action == "input-plus" || input_container_child_name == "input-box") {
384
+ //if plus button pressed, or Box element exists
385
+ if (input_container_child_name == "input-box") {
386
+ input_container_child.remove();
387
+ }
388
+ input_container.appendChild(createInputListDiv(false, false)); //call to createInputListDiv function to craft input-list element (with no values) and append inside container element
348
389
  }
349
- //if list is selected, remove text-area (from Box) element and replace (with input-list)
350
- if (selectElement.value == "List") {
351
- if (action == "input-plus" || input_container_child_name == "input-box") {
352
- //if plus button pressed, or Box element exists
353
- if (input_container_child_name == "input-box") {
354
- input_container_child.remove();
355
- }
356
- input_container.appendChild(createInputListDiv(false, false)); //call to createInputListDiv function to craft input-list element (with no values) and append inside container element
357
- }
358
- if (action == "input-minus") {
359
- //minus button pressed, remove input-list element
360
- if (input_container.children.length > 0) {
361
- let inputListArr = document.getElementsByClassName("input-list");
362
- let obj = inputListArr.item(inputListArr.length - 1);
363
- obj.innerHTML = "";
364
- obj.remove();
365
- }
366
- }
390
+ if (action == "input-minus") {
391
+ //minus button pressed, remove input-list element
392
+ if (input_container.children.length > 0) {
393
+ let inputListArr = document.getElementsByClassName("input-list");
394
+ let obj = inputListArr.item(inputListArr.length - 1);
395
+ obj.innerHTML = "";
396
+ obj.remove();
397
+ }
367
398
  }
368
- //if box is selected, remove input-list elements and replace (with text-area)
369
- if (selectElement.value == "Box") {
370
- if (
371
- input_container_child_name == "input-list" ||
372
- input_container_child === null
373
- ) {
374
- // if input list exists or no Box element
375
- input_container.innerHTML = ""; //remove input-list list elements via erasing container innerHTML
376
- let div = document.createElement("div"); //add input-box element
377
- div.className = "input-box";
378
- div.innerHTML = `
399
+ }
400
+ //if box is selected, remove input-list elements and replace (with text-area)
401
+ if (selectElement.value == "Box") {
402
+ if (
403
+ input_container_child_name == "input-list" ||
404
+ input_container_child === null
405
+ ) {
406
+ // if input list exists or no Box element
407
+ input_container.innerHTML = ""; //remove input-list list elements via erasing container innerHTML
408
+ let div = document.createElement("div"); //add input-box element
409
+ div.className = "input-box";
410
+ div.innerHTML = `
379
411
  <textarea id="text-area" rows="30" placeholder="{}"></textarea>
380
412
  `;
381
- input_container.appendChild(div); //append inside of container element
382
- }
413
+ input_container.appendChild(div); //append inside of container element
383
414
  }
415
+ }
384
416
  }
385
417
 
386
418
  //clear stored input data from localStorage (if any), clear input elements
387
419
  async function ClearInputData(id) {
388
- if (
389
- testStorage() &&
390
- localStorage.getItem("input_container_content") !== null
391
- ) {
392
- localStorage.setItem("input_container_content", "{}");
393
- }
394
- ClearInputElements();
420
+ if (
421
+ testStorage() &&
422
+ localStorage.getItem("input_container_content") !== null
423
+ ) {
424
+ localStorage.setItem("input_container_content", "{}");
425
+ }
426
+ ClearInputElements();
395
427
  }
396
428
 
397
429
  //clear input elements
398
430
  async function ClearInputElements() {
399
- let selectElement = document.getElementById("input-select");
400
- var input_container = document.getElementById("input-container");
401
- if (selectElement.value == "Box") {
402
- document.getElementById("text-area").value = "{}";
403
- }
404
- if (selectElement.value == "List") {
405
- input_container.innerHTML = "";
406
- }
431
+ let selectElement = document.getElementById("input-select");
432
+ let input_container = document.getElementById("input-container");
433
+ if (selectElement.value == "Box") {
434
+ document.getElementById("text-area").value = "{}";
435
+ }
436
+ if (selectElement.value == "List") {
437
+ input_container.innerHTML = "";
438
+ }
407
439
  }
408
440
 
409
441
  // //Run day ahead, then publish actions
410
442
  // async function DayheadOptimPublish() {
411
443
  // response = await formAction("dayahead-optim", "basic")
412
- // if (response) { //if successful publish data
444
+ // if (response) { //if successful publish data
413
445
  // formAction("publish-data", "basic")
414
446
  // }
415
447
  //}
416
448
 
417
-
418
-
419
-
449
+ // Check if InfluxDB is configured and show/hide export section
450
+ async function checkInfluxDBAndShowExport() {
451
+ try {
452
+ const response = await fetch("/get-config");
453
+ if (response.ok) {
454
+ const config = await response.json();
455
+ const exportSection = document.getElementById("export-influxdb-section");
456
+ if (exportSection) {
457
+ // Show export if InfluxDB is configured (has host and port)
458
+ // Users can export from InfluxDB even if use_influxdb is false for optimization
459
+ const isInfluxDBConfigured =
460
+ config.influxdb_host &&
461
+ config.influxdb_host !== "" &&
462
+ config.influxdb_port;
463
+
464
+ if (isInfluxDBConfigured) {
465
+ exportSection.style.display = "block";
466
+ } else {
467
+ exportSection.style.display = "none";
468
+ }
469
+ }
470
+ }
471
+ } catch (error) {
472
+ console.error("Error checking InfluxDB configuration:", error);
473
+ }
474
+ }