ivoryos 0.1.20__py3-none-any.whl → 0.1.22__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.
Potentially problematic release.
This version of ivoryos might be problematic. Click here for more details.
- ivoryos/__init__.py +21 -16
- ivoryos/routes/control/control.py +2 -2
- ivoryos/routes/control/templates/control/controllers_home.html +6 -1
- ivoryos/routes/database/database.py +45 -2
- ivoryos/routes/database/templates/database/experiment_database.html +4 -2
- ivoryos/routes/database/templates/database/workflow_run_database.html +81 -0
- ivoryos/routes/design/design.py +74 -18
- ivoryos/routes/design/templates/design/experiment_builder.html +84 -94
- ivoryos/routes/design/templates/design/experiment_run.html +188 -101
- ivoryos/routes/main/templates/main/home.html +80 -47
- ivoryos/static/js/socket_handler.js +59 -16
- ivoryos/static/js/sortable_design.js +102 -33
- ivoryos/static/style.css +9 -0
- ivoryos/templates/base.html +9 -6
- ivoryos/utils/client_proxy.py +57 -0
- ivoryos/utils/db_models.py +66 -11
- ivoryos/utils/form.py +50 -2
- ivoryos/utils/global_config.py +10 -0
- ivoryos/utils/llm_agent.py +1 -1
- ivoryos/utils/script_runner.py +115 -43
- ivoryos/utils/utils.py +24 -1
- ivoryos/version.py +1 -1
- {ivoryos-0.1.20.dist-info → ivoryos-0.1.22.dist-info}/METADATA +7 -3
- {ivoryos-0.1.20.dist-info → ivoryos-0.1.22.dist-info}/RECORD +27 -25
- {ivoryos-0.1.20.dist-info → ivoryos-0.1.22.dist-info}/LICENSE +0 -0
- {ivoryos-0.1.20.dist-info → ivoryos-0.1.22.dist-info}/WHEEL +0 -0
- {ivoryos-0.1.20.dist-info → ivoryos-0.1.22.dist-info}/top_level.txt +0 -0
|
@@ -28,7 +28,7 @@
|
|
|
28
28
|
<div class="accordion-body">
|
|
29
29
|
{% if script['script'] or script['prep'] or script['cleanup'] %}
|
|
30
30
|
<div class="row">
|
|
31
|
-
<div class="col-lg-6 col-sm-12" id="run-panel">
|
|
31
|
+
<div class="col-lg-6 col-sm-12" id="run-panel" style="{{ 'display: none;' if pause_status else '' }}">
|
|
32
32
|
<ul class="nav nav-tabs" id="myTabs" role="tablist">
|
|
33
33
|
<li class="nav-item" role="presentation">
|
|
34
34
|
<a class="nav-link {{ 'disabled' if config_list else '' }} {{ 'active' if not config_list else '' }}" id="tab1-tab" data-bs-toggle="tab" href="#tab1" role="tab" aria-controls="tab1" aria-selected="false">Repeat</a>
|
|
@@ -128,75 +128,132 @@
|
|
|
128
128
|
{% endif %}
|
|
129
129
|
</div>
|
|
130
130
|
|
|
131
|
-
<div class="tab-pane fade " id="tab3" role="tabpanel" aria-labelledby="tab3-tab"
|
|
132
|
-
<form role="form" method='POST' name="bo" action="{{ url_for('design.experiment_run')}}"
|
|
133
|
-
<div class="form-group"
|
|
134
|
-
<p><h5>Parameters:</h5><p
|
|
135
|
-
{% for config in config_list %}
|
|
136
|
-
<div class="row g-3 align-items-center"
|
|
137
|
-
<div class="col-lg-3 col-sm-6 "
|
|
138
|
-
{{config}}
|
|
139
|
-
</div
|
|
131
|
+
{# <div class="tab-pane fade " id="tab3" role="tabpanel" aria-labelledby="tab3-tab">#}
|
|
132
|
+
{# <form role="form" method='POST' name="bo" action="{{ url_for('design.experiment_run')}}">#}
|
|
133
|
+
{# <div class="form-group">#}
|
|
134
|
+
{# <p><h5>Parameters:</h5><p>#}
|
|
135
|
+
{# {% for config in config_list %}#}
|
|
136
|
+
{# <div class="row g-3 align-items-center">#}
|
|
137
|
+
{# <div class="col-lg-3 col-sm-6 ">#}
|
|
138
|
+
{# {{config}}:#}
|
|
139
|
+
{# </div>#}
|
|
140
140
|
{# <div class="col-auto">#}
|
|
141
141
|
{# <label class="col-form-label" for="{{config}}_type">Type</label>#}
|
|
142
142
|
{# </div>#}
|
|
143
|
-
<div class="col-auto"
|
|
144
|
-
<select class="form-select" id="{{config}}_type" name="{{config}}_type"
|
|
145
|
-
<option selected value="range">range</option
|
|
146
|
-
<option value="choice">choice</option
|
|
147
|
-
<option value="fixed">fixed</option
|
|
148
|
-
</select
|
|
149
|
-
</div
|
|
150
|
-
<div class="col-auto"
|
|
151
|
-
<label class="" for="{{config}}_value">Values</label
|
|
152
|
-
</div
|
|
153
|
-
<div class="col-auto"
|
|
154
|
-
<input type="text" class="form-control" id="{{config}}_value" name="{{config}}_value" placeholder="1, 2, 3"
|
|
155
|
-
</div
|
|
143
|
+
{# <div class="col-auto">#}
|
|
144
|
+
{# <select class="form-select" id="{{config}}_type" name="{{config}}_type">#}
|
|
145
|
+
{# <option selected value="range">range</option>#}
|
|
146
|
+
{# <option value="choice">choice</option>#}
|
|
147
|
+
{# <option value="fixed">fixed</option>#}
|
|
148
|
+
{# </select>#}
|
|
149
|
+
{# </div>#}
|
|
150
|
+
{# <div class="col-auto">#}
|
|
151
|
+
{# <label class="" for="{{config}}_value">Values</label>#}
|
|
152
|
+
{# </div>#}
|
|
153
|
+
{# <div class="col-auto">#}
|
|
154
|
+
{# <input type="text" class="form-control" id="{{config}}_value" name="{{config}}_value" placeholder="1, 2, 3">#}
|
|
155
|
+
{# </div>#}
|
|
156
156
|
{# <div class="col-auto">#}
|
|
157
157
|
{# <input type="text" class="form-control" id="{{config}}_value_max" style="display: none;" placeholder="1, 2, 3">#}
|
|
158
158
|
{# </div>#}
|
|
159
|
-
</div
|
|
160
|
-
{% endfor %}
|
|
161
|
-
<p><h5>Objective:</h5><p
|
|
162
|
-
{% for objective in return_list %}
|
|
163
|
-
<div class="row gy-2 gx-3 align-items-center input-group"
|
|
164
|
-
<div class="col-3"
|
|
165
|
-
{{objective}}
|
|
166
|
-
</div
|
|
159
|
+
{# </div>#}
|
|
160
|
+
{# {% endfor %}#}
|
|
161
|
+
{# <p><h5>Objective:</h5><p>#}
|
|
162
|
+
{# {% for objective in return_list %}#}
|
|
163
|
+
{# <div class="row gy-2 gx-3 align-items-center input-group">#}
|
|
164
|
+
{# <div class="col-3">#}
|
|
165
|
+
{# {{objective}}:#}
|
|
166
|
+
{# </div>#}
|
|
167
167
|
{# <div class="col-auto">#}
|
|
168
168
|
{# <label class="" for="{{objective}}_min">Minimize</label>#}
|
|
169
169
|
{# </div>#}
|
|
170
|
-
<div class="col-auto"
|
|
171
|
-
<select class="form-select" id="{{objective}}_min" name="{{objective}}_min"
|
|
172
|
-
<option selected>minimize</option
|
|
173
|
-
<option>maximize</option
|
|
174
|
-
<option>none</option
|
|
175
|
-
</select
|
|
176
|
-
</div
|
|
170
|
+
{# <div class="col-auto">#}
|
|
171
|
+
{# <select class="form-select" id="{{objective}}_min" name="{{objective}}_min">#}
|
|
172
|
+
{# <option selected>minimize</option>#}
|
|
173
|
+
{# <option>maximize</option>#}
|
|
174
|
+
{# <option>none</option>#}
|
|
175
|
+
{# </select>#}
|
|
176
|
+
{# </div>#}
|
|
177
177
|
{# <div class="col-auto">#}
|
|
178
178
|
{# <label class="" for="{{objective}}_threshold">Threshold</label>#}
|
|
179
179
|
{# </div>#}
|
|
180
180
|
{# <div class="col-auto">#}
|
|
181
181
|
{# <input type="text" class="form-control" id="{{objective}}_threshold" name="{{objective}}_threshold" placeholder="None">#}
|
|
182
182
|
{# </div>#}
|
|
183
|
-
</div
|
|
184
|
-
{% endfor %}
|
|
185
|
-
<p><h5>Budget:</h5></p
|
|
186
|
-
<div class="input-group mb-3"
|
|
187
|
-
<label class="input-group-text" for="repeat">Max iteration </label
|
|
188
|
-
<input class="form-control" type="number" id="repeat" name="repeat" min="1" max="1000" value="25"
|
|
189
|
-
</div
|
|
190
|
-
{% if not no_deck_warning%}
|
|
191
|
-
<div class="input-group mb-3"
|
|
192
|
-
<button class="form-control" type="submit" name="bo">Run</button
|
|
193
|
-
</div
|
|
194
|
-
{% endif %}
|
|
195
|
-
</div
|
|
196
|
-
</form
|
|
197
|
-
</div
|
|
183
|
+
{# </div>#}
|
|
184
|
+
{# {% endfor %}#}
|
|
185
|
+
{# <p><h5>Budget:</h5></p>#}
|
|
186
|
+
{# <div class="input-group mb-3">#}
|
|
187
|
+
{# <label class="input-group-text" for="repeat">Max iteration </label>#}
|
|
188
|
+
{# <input class="form-control" type="number" id="repeat" name="repeat" min="1" max="1000" value="25">#}
|
|
189
|
+
{# </div>#}
|
|
190
|
+
{# {% if not no_deck_warning%}#}
|
|
191
|
+
{# <div class="input-group mb-3">#}
|
|
192
|
+
{# <button class="form-control" type="submit" name="bo">Run</button>#}
|
|
193
|
+
{# </div>#}
|
|
194
|
+
{# {% endif %}#}
|
|
195
|
+
{# </div>#}
|
|
196
|
+
{# </form>#}
|
|
197
|
+
{# </div>#}
|
|
198
|
+
<div class="tab-pane fade" id="tab3" role="tabpanel" aria-labelledby="tab3-tab">
|
|
199
|
+
<form method="POST" name="bo" action="{{ url_for('design.experiment_run') }}">
|
|
200
|
+
<div class="container py-2">
|
|
201
|
+
|
|
202
|
+
<!-- Parameters -->
|
|
203
|
+
<h6 class="fw-bold mt-2 mb-1">Parameters</h6>
|
|
204
|
+
{% for config in config_list %}
|
|
205
|
+
<div class="row align-items-center mb-2">
|
|
206
|
+
<div class="col-3 col-form-label-sm">
|
|
207
|
+
{{ config }}:
|
|
208
|
+
</div>
|
|
209
|
+
<div class="col-6">
|
|
210
|
+
<select class="form-select form-select-sm" id="{{config}}_type" name="{{config}}_type">
|
|
211
|
+
<option selected value="range">range</option>
|
|
212
|
+
<option value="choice">choice</option>
|
|
213
|
+
<option value="fixed">fixed</option>
|
|
214
|
+
</select>
|
|
215
|
+
</div>
|
|
216
|
+
<div class="col-3">
|
|
217
|
+
<input type="text" class="form-control form-control-sm" id="{{config}}_value" name="{{config}}_value" placeholder="1, 2, 3">
|
|
218
|
+
</div>
|
|
219
|
+
</div>
|
|
220
|
+
{% endfor %}
|
|
221
|
+
|
|
222
|
+
<!-- Objective -->
|
|
223
|
+
<h6 class="fw-bold mt-3 mb-1">Objectives</h6>
|
|
224
|
+
{% for objective in return_list %}
|
|
225
|
+
<div class="row align-items-center mb-2">
|
|
226
|
+
<div class="col-3 col-form-label-sm">
|
|
227
|
+
{{ objective }}:
|
|
228
|
+
</div>
|
|
229
|
+
<div class="col-6">
|
|
230
|
+
<select class="form-select form-select-sm" id="{{objective}}_min" name="{{objective}}_min">
|
|
231
|
+
<option selected>minimize</option>
|
|
232
|
+
<option>maximize</option>
|
|
233
|
+
<option>none</option>
|
|
234
|
+
</select>
|
|
235
|
+
</div>
|
|
236
|
+
</div>
|
|
237
|
+
{% endfor %}
|
|
238
|
+
|
|
239
|
+
<h6 class="fw-bold mt-3 mb-1">Budget</h6>
|
|
240
|
+
|
|
241
|
+
<div class="input-group mb-3">
|
|
242
|
+
<label class="input-group-text" for="repeat">Max iteration </label>
|
|
243
|
+
<input class="form-control" type="number" id="repeat" name="repeat" min="1" max="1000" value="25">
|
|
244
|
+
</div>
|
|
245
|
+
{% if not no_deck_warning%}
|
|
246
|
+
<div class="input-group mb-3">
|
|
247
|
+
<button class="form-control" type="submit" name="bo">Run</button>
|
|
248
|
+
</div>
|
|
249
|
+
{% endif %}
|
|
250
|
+
</div>
|
|
251
|
+
</form>
|
|
252
|
+
</div>
|
|
253
|
+
|
|
254
|
+
|
|
198
255
|
<div class="tab-pane fade {{ 'show active' if config_list and config_list|count<=5 else '' }}" id="tab4" role="tabpanel" aria-labelledby="tab4-tab">
|
|
199
|
-
<p><h5>Control panel:</h5></p
|
|
256
|
+
{# <p><h5>Control panel:</h5></p>#}
|
|
200
257
|
<div>
|
|
201
258
|
<form method="POST" name="online-config" id="online-config" action="{{url_for('design.experiment_run')}}">
|
|
202
259
|
<table id="dataInputTable" class="table table-striped">
|
|
@@ -210,21 +267,43 @@
|
|
|
210
267
|
<tbody>
|
|
211
268
|
</tbody>
|
|
212
269
|
</table>
|
|
213
|
-
<div class="
|
|
214
|
-
|
|
270
|
+
<div class="d-flex align-items-center gap-2">
|
|
271
|
+
<div class="btn btn-light" onclick="addRow()">
|
|
272
|
+
<i class="bi bi-plus-circle"></i>
|
|
273
|
+
</div>
|
|
274
|
+
<button type="submit" name="online-config" class="form-control">Run</button>
|
|
275
|
+
</div>
|
|
215
276
|
</form>
|
|
216
277
|
</div>
|
|
217
278
|
</div>
|
|
218
279
|
</div>
|
|
219
280
|
</div>
|
|
220
|
-
<div class="col-lg-6 col-sm-12" id="code-panel" style="display: none;">
|
|
281
|
+
<div class="col-lg-6 col-sm-12" id="code-panel" style="{{ '' if pause_status else 'display: none;'}}">
|
|
221
282
|
<p>
|
|
222
283
|
<h5>Progress:</h5>
|
|
223
|
-
{%
|
|
224
|
-
{%
|
|
284
|
+
{% if "prep" in line_collection.keys() %} {% set stype = "cleanup" %}
|
|
285
|
+
{% set stype = "prep" %}
|
|
286
|
+
|
|
287
|
+
<h6>Preparation:</h6>
|
|
288
|
+
{% for code in line_collection["prep"] %}
|
|
289
|
+
<pre style="margin: 0; padding: 0; line-height: 1;"><code class="python" id="{{ stype }}-{{ loop.index0 }}" >{{code}}</code></pre>
|
|
290
|
+
{% endfor %}
|
|
291
|
+
{% endif %}
|
|
292
|
+
{% if "script" in line_collection.keys() %}
|
|
293
|
+
{% set stype = "script" %}
|
|
294
|
+
|
|
295
|
+
<h6>Experiment:</h6>
|
|
296
|
+
{% for code in line_collection["script"] %}
|
|
297
|
+
<pre style="margin: 0; padding: 0; line-height: 1;"><code class="python" id="{{ stype }}-{{ loop.index0 }}" >{{code}}</code></pre>
|
|
298
|
+
{% endfor %}
|
|
299
|
+
{% endif %}
|
|
300
|
+
{% if "cleanup" in line_collection.keys() %}
|
|
301
|
+
{% set stype = "cleanup" %}
|
|
302
|
+
<h6>Experiment:</h6>
|
|
303
|
+
{% for code in line_collection["cleanup"] %}
|
|
225
304
|
<pre style="margin: 0; padding: 0; line-height: 1;"><code class="python" id="{{ stype }}-{{ loop.index0 }}" >{{code}}</code></pre>
|
|
226
305
|
{% endfor %}
|
|
227
|
-
{%
|
|
306
|
+
{% endif %}
|
|
228
307
|
</p>
|
|
229
308
|
</div>
|
|
230
309
|
<div class="col-lg-6 col-sm-12 logging-panel">
|
|
@@ -233,7 +312,11 @@
|
|
|
233
312
|
<h5>Progress:</h5>
|
|
234
313
|
<div class="d-flex gap-2 ms-auto">
|
|
235
314
|
<button id="pause-resume" class="btn btn-info text-white" data-bs-toggle="tooltip" title="Pause execution">
|
|
236
|
-
|
|
315
|
+
{% if pause_status %}
|
|
316
|
+
<i class="bi bi-play-circle"></i> <!-- Icon for Pause -->
|
|
317
|
+
{% else %}
|
|
318
|
+
<i class="bi bi-pause-circle"></i> <!
|
|
319
|
+
{% endif %}
|
|
237
320
|
</button>
|
|
238
321
|
<button id="abort-current" class="btn btn-danger text-white" data-bs-toggle="tooltip" title="Stop execution after current step">
|
|
239
322
|
<i class="bi bi-stop-circle"></i> <!-- Icon for Stop After This Step -->
|
|
@@ -258,28 +341,28 @@
|
|
|
258
341
|
</div>
|
|
259
342
|
</div>
|
|
260
343
|
</div>
|
|
261
|
-
<div class="accordion-item design-control"
|
|
262
|
-
<h2 class="accordion-header"
|
|
263
|
-
<button class="accordion-button collapsed" type="button" data-bs-toggle="collapse" data-bs-target="#data" aria-expanded="false" aria-controls="script"
|
|
264
|
-
Download experiment data csv
|
|
265
|
-
</button
|
|
266
|
-
</h2
|
|
267
|
-
<div id="data" class="accordion-collapse collapse"
|
|
268
|
-
<div class="accordion-body"
|
|
269
|
-
{% if session["most_recent_result"] %}
|
|
270
|
-
<p><a href="{{ url_for('design.download_results', filename=session["most_recent_result"]) }}">Download the latest data <i class="bi bi-download"></i></a></p
|
|
271
|
-
{% endif %}
|
|
272
|
-
<p
|
|
273
|
-
<h5>All data files</h5
|
|
274
|
-
{% for datafile in data_list %}
|
|
275
|
-
<div
|
|
276
|
-
{{ datafile }} <a href="{{ url_for('design.download_results', filename=datafile) }} "><i class="bi bi-download"></i></a
|
|
277
|
-
</div
|
|
278
|
-
{% endfor %}
|
|
279
|
-
</p
|
|
280
|
-
</div
|
|
281
|
-
</div
|
|
282
|
-
</div
|
|
344
|
+
{# <div class="accordion-item design-control">#}
|
|
345
|
+
{# <h2 class="accordion-header">#}
|
|
346
|
+
{# <button class="accordion-button collapsed" type="button" data-bs-toggle="collapse" data-bs-target="#data" aria-expanded="false" aria-controls="script">#}
|
|
347
|
+
{# Download experiment data csv#}
|
|
348
|
+
{# </button>#}
|
|
349
|
+
{# </h2>#}
|
|
350
|
+
{# <div id="data" class="accordion-collapse collapse">#}
|
|
351
|
+
{# <div class="accordion-body">#}
|
|
352
|
+
{# {% if session["most_recent_result"] %}#}
|
|
353
|
+
{# <p><a href="{{ url_for('design.download_results', filename=session["most_recent_result"]) }}">Download the latest data <i class="bi bi-download"></i></a></p>#}
|
|
354
|
+
{# {% endif %}#}
|
|
355
|
+
{# <p>#}
|
|
356
|
+
{# <h5>All data files</h5>#}
|
|
357
|
+
{# {% for datafile in data_list %}#}
|
|
358
|
+
{# <div>#}
|
|
359
|
+
{# {{ datafile }} <a href="{{ url_for('design.download_results', filename=datafile) }} "><i class="bi bi-download"></i></a>#}
|
|
360
|
+
{# </div>#}
|
|
361
|
+
{# {% endfor %}#}
|
|
362
|
+
{# </p>#}
|
|
363
|
+
{# </div>#}
|
|
364
|
+
{# </div>#}
|
|
365
|
+
{# </div>#}
|
|
283
366
|
<div class="accordion-item design-control">
|
|
284
367
|
<h2 class="accordion-header">
|
|
285
368
|
<button class="accordion-button collapsed" type="button" data-bs-toggle="collapse" data-bs-target="#script" aria-expanded="false" aria-controls="script">
|
|
@@ -326,6 +409,28 @@
|
|
|
326
409
|
</div>
|
|
327
410
|
</div>
|
|
328
411
|
</div>
|
|
412
|
+
|
|
413
|
+
<!-- Error Modal -->
|
|
414
|
+
<div class="modal fade" id="error-modal" tabindex="-1" aria-labelledby="errorModalLabel" aria-hidden="true">
|
|
415
|
+
<div class="modal-dialog">
|
|
416
|
+
<div class="modal-content">
|
|
417
|
+
<div class="modal-header">
|
|
418
|
+
<h5 class="modal-title" id="errorModalLabel">Error Detected</h5>
|
|
419
|
+
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
|
|
420
|
+
</div>
|
|
421
|
+
<div class="modal-body">
|
|
422
|
+
<p id="error-message">An error has occurred.</p>
|
|
423
|
+
<p>Do you want to continue execution or stop?</p>
|
|
424
|
+
</div>
|
|
425
|
+
<div class="modal-footer">
|
|
426
|
+
<button type="button" class="btn btn-danger" id="stop-btn" data-bs-dismiss="modal">Stop Execution</button>
|
|
427
|
+
<button type="button" class="btn btn-success" id="continue-btn" data-bs-dismiss="modal">Continue</button>
|
|
428
|
+
</div>
|
|
429
|
+
</div>
|
|
430
|
+
</div>
|
|
431
|
+
</div>
|
|
432
|
+
|
|
433
|
+
|
|
329
434
|
<script src="{{ url_for('static', filename='js/socket_handler.js') }}"></script>
|
|
330
435
|
<script>
|
|
331
436
|
var rowCount = 0; // Initialize row count
|
|
@@ -347,22 +452,4 @@
|
|
|
347
452
|
}
|
|
348
453
|
});
|
|
349
454
|
</script>
|
|
350
|
-
|
|
351
|
-
<script>
|
|
352
|
-
var socket = io.connect(window.location.origin);
|
|
353
|
-
|
|
354
|
-
socket.on('execution', function(data) {
|
|
355
|
-
// Remove highlighting from all lines
|
|
356
|
-
document.querySelectorAll('pre code').forEach(el => el.style.backgroundColor = '');
|
|
357
|
-
|
|
358
|
-
// Get the currently executing line and highlight it
|
|
359
|
-
let executingLine = document.getElementById(data.section);
|
|
360
|
-
if (executingLine) {
|
|
361
|
-
executingLine.style.backgroundColor = '#cce5ff'; // Highlight
|
|
362
|
-
executingLine.style.transition = 'background-color 0.3s ease-in-out';
|
|
363
|
-
|
|
364
|
-
}
|
|
365
|
-
});
|
|
366
|
-
</script>
|
|
367
|
-
|
|
368
455
|
{% endblock %}
|
|
@@ -1,70 +1,103 @@
|
|
|
1
1
|
{% extends 'base.html' %}
|
|
2
|
-
{% block title %}IvoryOS | Welcome
|
|
3
|
-
|
|
2
|
+
{% block title %}IvoryOS | Welcome{% endblock %}
|
|
4
3
|
|
|
5
4
|
{% block body %}
|
|
6
|
-
<div class="p-4"
|
|
7
|
-
<h1 style="
|
|
5
|
+
<div class="p-4">
|
|
6
|
+
<h1 class="mb-4" style="font-size: 3rem; font-weight: bold; color: #343a40;">
|
|
8
7
|
Welcome
|
|
9
8
|
</h1>
|
|
10
|
-
<p>Version: {{ version }}</p>
|
|
9
|
+
<p class="mb-5">Version: {{ version }}</p>
|
|
10
|
+
|
|
11
|
+
{% if enable_design %}
|
|
12
|
+
<!-- Workflow Design Section -->
|
|
13
|
+
<h4 class="mb-3">Workflow Design</h4>
|
|
11
14
|
<div class="row">
|
|
12
|
-
|
|
13
|
-
<div class="
|
|
14
|
-
<div class="card
|
|
15
|
-
<
|
|
16
|
-
<
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
15
|
+
<div class="col-lg-6 mb-3 d-flex align-items-stretch">
|
|
16
|
+
<div class="card rounded shadow-sm flex-fill">
|
|
17
|
+
<div class="card-body">
|
|
18
|
+
<h5 class="card-title">
|
|
19
|
+
<i class="bi bi-folder2-open me-2"></i>Browse designs
|
|
20
|
+
</h5>
|
|
21
|
+
<p class="card-text">View all saved workflows from the database.</p>
|
|
22
|
+
<a href="{{ url_for('database.load_from_database') }}" class="stretched-link"></a>
|
|
20
23
|
</div>
|
|
21
24
|
</div>
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
<
|
|
28
|
-
</
|
|
25
|
+
</div>
|
|
26
|
+
<div class="col-lg-6 mb-3 d-flex align-items-stretch">
|
|
27
|
+
<div class="card rounded shadow-sm flex-fill">
|
|
28
|
+
<div class="card-body">
|
|
29
|
+
<h5 class="card-title">
|
|
30
|
+
<i class="bi bi-pencil-square me-2"></i>Edit designs
|
|
31
|
+
</h5>
|
|
32
|
+
<p class="card-text">Create or modify workflows using available functions.</p>
|
|
33
|
+
<a href="{{ url_for('design.experiment_builder') }}" class="stretched-link"></a>
|
|
29
34
|
</div>
|
|
30
35
|
</div>
|
|
31
|
-
|
|
36
|
+
</div>
|
|
32
37
|
</div>
|
|
38
|
+
{% endif %}
|
|
33
39
|
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
<
|
|
43
|
-
|
|
44
|
-
|
|
40
|
+
<!-- Workflow Control and Monitor Section -->
|
|
41
|
+
<h4 class="mt-5 mb-3">Workflow Control & Monitoring</h4>
|
|
42
|
+
<div class="row">
|
|
43
|
+
<!-- Always visible: Experiment data -->
|
|
44
|
+
<div class="col-lg-6 mb-3 d-flex align-items-stretch">
|
|
45
|
+
<div class="card rounded shadow-sm flex-fill">
|
|
46
|
+
<div class="card-body">
|
|
47
|
+
<h5 class="card-title">
|
|
48
|
+
<i class="bi bi-graph-up-arrow me-2"></i>Experiment data
|
|
49
|
+
</h5>
|
|
50
|
+
<p class="card-text">Browse workflow logs and output data.</p>
|
|
51
|
+
<a href="{{ url_for('database.list_workflows') }}" class="stretched-link"></a>
|
|
45
52
|
</div>
|
|
46
53
|
</div>
|
|
47
|
-
|
|
54
|
+
</div>
|
|
48
55
|
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
+
<!-- Conditionally visible: Run current workflow -->
|
|
57
|
+
{% if not off_line %}
|
|
58
|
+
<div class="col-lg-6 mb-3 d-flex align-items-stretch">
|
|
59
|
+
<div class="card rounded shadow-sm flex-fill">
|
|
60
|
+
<div class="card-body">
|
|
61
|
+
<h5 class="card-title">
|
|
62
|
+
<i class="bi bi-play-circle me-2"></i>Run current workflow
|
|
63
|
+
</h5>
|
|
64
|
+
<p class="card-text">Execute workflows with configurable parameters.</p>
|
|
65
|
+
<a href="{{ url_for('design.experiment_run') }}" class="stretched-link"></a>
|
|
56
66
|
</div>
|
|
57
67
|
</div>
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
68
|
+
</div>
|
|
69
|
+
{% endif %}
|
|
70
|
+
</div>
|
|
71
|
+
|
|
72
|
+
|
|
73
|
+
|
|
74
|
+
{% if not off_line %}
|
|
75
|
+
<!-- Direct Control Section -->
|
|
76
|
+
<h4 class="mt-5 mb-3">Direct Control</h4>
|
|
77
|
+
<div class="row">
|
|
78
|
+
<div class="col-lg-6 mb-3 d-flex align-items-stretch">
|
|
79
|
+
<div class="card rounded shadow-sm flex-fill">
|
|
80
|
+
<div class="card-body">
|
|
81
|
+
<h5 class="card-title">
|
|
82
|
+
<i class="bi bi-toggle-on me-2"></i>Direct control
|
|
83
|
+
</h5>
|
|
84
|
+
<p class="card-text">Manually control individual components.</p>
|
|
85
|
+
<a href="{{ url_for('control.deck_controllers') }}" class="stretched-link"></a>
|
|
65
86
|
</div>
|
|
66
87
|
</div>
|
|
67
88
|
</div>
|
|
89
|
+
<div class="col-lg-6 mb-3 d-flex align-items-stretch">
|
|
90
|
+
<div class="card rounded shadow-sm flex-fill">
|
|
91
|
+
<div class="card-body">
|
|
92
|
+
<h5 class="card-title">
|
|
93
|
+
<i class="bi bi-usb-plug me-2"></i>Connect a new device
|
|
94
|
+
</h5>
|
|
95
|
+
<p class="card-text">Add new hardware temporarily or for testing purposes.</p>
|
|
96
|
+
<a href="{{ url_for('control.controllers_home') }}" class="stretched-link"></a>
|
|
97
|
+
</div>
|
|
98
|
+
</div>
|
|
99
|
+
</div>
|
|
100
|
+
</div>
|
|
68
101
|
{% endif %}
|
|
69
102
|
</div>
|
|
70
103
|
{% endblock %}
|
|
@@ -27,6 +27,57 @@ document.addEventListener("DOMContentLoaded", function() {
|
|
|
27
27
|
}, 1000); // Small delay to let users see the completion
|
|
28
28
|
}
|
|
29
29
|
});
|
|
30
|
+
|
|
31
|
+
socket.on('error', function(errorData) {
|
|
32
|
+
console.error("Error received:", errorData);
|
|
33
|
+
var progressBar = document.getElementById('progress-bar-inner');
|
|
34
|
+
|
|
35
|
+
progressBar.classList.remove('bg-success');
|
|
36
|
+
progressBar.classList.add('bg-danger'); // Red color for error
|
|
37
|
+
// Show error modal
|
|
38
|
+
var errorModal = new bootstrap.Modal(document.getElementById('error-modal'));
|
|
39
|
+
document.getElementById('error-message').innerText = "An error occurred: " + errorData.message;
|
|
40
|
+
errorModal.show();
|
|
41
|
+
|
|
42
|
+
});
|
|
43
|
+
|
|
44
|
+
// Handle Pause/Resume Button
|
|
45
|
+
document.getElementById('pause-resume').addEventListener('click', function() {
|
|
46
|
+
socket.emit('pause');
|
|
47
|
+
console.log('Pause/Resume is toggled.');
|
|
48
|
+
var button = this;
|
|
49
|
+
var icon = button.querySelector("i");
|
|
50
|
+
|
|
51
|
+
// Toggle Pause and Resume
|
|
52
|
+
if (icon.classList.contains("bi-pause-circle")) {
|
|
53
|
+
icon.classList.remove("bi-pause-circle");
|
|
54
|
+
icon.classList.add("bi-play-circle");
|
|
55
|
+
button.innerHTML = '<i class="bi bi-play-circle"></i>';
|
|
56
|
+
button.setAttribute("title", "Resume execution");
|
|
57
|
+
} else {
|
|
58
|
+
icon.classList.remove("bi-play-circle");
|
|
59
|
+
icon.classList.add("bi-pause-circle");
|
|
60
|
+
button.innerHTML = '<i class="bi bi-pause-circle"></i>';
|
|
61
|
+
button.setAttribute("title", "Pause execution");
|
|
62
|
+
}
|
|
63
|
+
});
|
|
64
|
+
|
|
65
|
+
// Handle Modal Buttons
|
|
66
|
+
document.getElementById('continue-btn').addEventListener('click', function() {
|
|
67
|
+
socket.emit('pause'); // Resume execution
|
|
68
|
+
console.log("Execution resumed.");
|
|
69
|
+
});
|
|
70
|
+
|
|
71
|
+
document.getElementById('stop-btn').addEventListener('click', function() {
|
|
72
|
+
socket.emit('pause'); // Resume execution
|
|
73
|
+
socket.emit('abort_current'); // Stop execution
|
|
74
|
+
console.log("Execution stopped.");
|
|
75
|
+
|
|
76
|
+
// Reset UI back to initial state
|
|
77
|
+
document.getElementById("code-panel").style.display = "none";
|
|
78
|
+
document.getElementById("run-panel").style.display = "block";
|
|
79
|
+
});
|
|
80
|
+
|
|
30
81
|
socket.on('log', function(data) {
|
|
31
82
|
var logMessage = data.message;
|
|
32
83
|
console.log(logMessage);
|
|
@@ -49,24 +100,16 @@ document.addEventListener("DOMContentLoaded", function() {
|
|
|
49
100
|
}
|
|
50
101
|
});
|
|
51
102
|
|
|
52
|
-
|
|
103
|
+
socket.on('execution', function(data) {
|
|
104
|
+
// Remove highlighting from all lines
|
|
105
|
+
document.querySelectorAll('pre code').forEach(el => el.style.backgroundColor = '');
|
|
53
106
|
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
107
|
+
// Get the currently executing line and highlight it
|
|
108
|
+
let executingLine = document.getElementById(data.section);
|
|
109
|
+
if (executingLine) {
|
|
110
|
+
executingLine.style.backgroundColor = '#cce5ff'; // Highlight
|
|
111
|
+
executingLine.style.transition = 'background-color 0.3s ease-in-out';
|
|
58
112
|
|
|
59
|
-
// Toggle between Pause and Resume
|
|
60
|
-
if (icon.classList.contains("bi-pause-circle")) {
|
|
61
|
-
icon.classList.remove("bi-pause-circle");
|
|
62
|
-
icon.classList.add("bi-play-circle");
|
|
63
|
-
button.innerHTML = '<i class="bi bi-play-circle"></i>';
|
|
64
|
-
button.setAttribute("title", "Resume execution");
|
|
65
|
-
} else {
|
|
66
|
-
icon.classList.remove("bi-play-circle");
|
|
67
|
-
icon.classList.add("bi-pause-circle");
|
|
68
|
-
button.innerHTML = '<i class="bi bi-pause-circle"></i>';
|
|
69
|
-
button.setAttribute("title", "Pause execution");
|
|
70
113
|
}
|
|
71
114
|
});
|
|
72
115
|
});
|