ivoryos 1.2.0b1__py3-none-any.whl → 1.2.1__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 +22 -1
- ivoryos/config.py +1 -0
- ivoryos/routes/auth/auth.py +3 -1
- ivoryos/routes/data/data.py +2 -0
- ivoryos/routes/design/design.py +4 -4
- ivoryos/routes/library/library.py +4 -4
- ivoryos/utils/script_runner.py +1 -1
- ivoryos/utils/utils.py +2 -1
- ivoryos/version.py +1 -1
- {ivoryos-1.2.0b1.dist-info → ivoryos-1.2.1.dist-info}/METADATA +52 -31
- ivoryos-1.2.1.dist-info/RECORD +51 -0
- ivoryos/routes/api/api.py +0 -56
- ivoryos/routes/auth/templates/login.html +0 -25
- ivoryos/routes/auth/templates/signup.html +0 -32
- ivoryos/routes/control/templates/controllers.html +0 -166
- ivoryos/routes/control/templates/controllers_new.html +0 -112
- ivoryos/routes/data/templates/components/step_card.html +0 -13
- ivoryos/routes/data/templates/workflow_database.html +0 -109
- ivoryos/routes/data/templates/workflow_view.html +0 -130
- ivoryos/routes/design/templates/components/action_form.html +0 -53
- ivoryos/routes/design/templates/components/actions_panel.html +0 -25
- ivoryos/routes/design/templates/components/autofill_toggle.html +0 -10
- ivoryos/routes/design/templates/components/canvas.html +0 -5
- ivoryos/routes/design/templates/components/canvas_footer.html +0 -9
- ivoryos/routes/design/templates/components/canvas_header.html +0 -75
- ivoryos/routes/design/templates/components/canvas_main.html +0 -34
- ivoryos/routes/design/templates/components/deck_selector.html +0 -10
- ivoryos/routes/design/templates/components/edit_action_form.html +0 -38
- ivoryos/routes/design/templates/components/instruments_panel.html +0 -66
- ivoryos/routes/design/templates/components/modals/drop_modal.html +0 -17
- ivoryos/routes/design/templates/components/modals/json_modal.html +0 -22
- ivoryos/routes/design/templates/components/modals/new_script_modal.html +0 -17
- ivoryos/routes/design/templates/components/modals/rename_modal.html +0 -23
- ivoryos/routes/design/templates/components/modals/saveas_modal.html +0 -27
- ivoryos/routes/design/templates/components/modals.html +0 -6
- ivoryos/routes/design/templates/components/python_code_overlay.html +0 -39
- ivoryos/routes/design/templates/components/sidebar.html +0 -15
- ivoryos/routes/design/templates/components/text_to_code_panel.html +0 -20
- ivoryos/routes/design/templates/experiment_builder.html +0 -41
- ivoryos/routes/execute/templates/components/error_modal.html +0 -20
- ivoryos/routes/execute/templates/components/logging_panel.html +0 -31
- ivoryos/routes/execute/templates/components/progress_panel.html +0 -27
- ivoryos/routes/execute/templates/components/run_panel.html +0 -9
- ivoryos/routes/execute/templates/components/run_tabs.html +0 -17
- ivoryos/routes/execute/templates/components/tab_bayesian.html +0 -399
- ivoryos/routes/execute/templates/components/tab_configuration.html +0 -98
- ivoryos/routes/execute/templates/components/tab_repeat.html +0 -14
- ivoryos/routes/execute/templates/experiment_run.html +0 -294
- ivoryos/routes/library/templates/library.html +0 -91
- ivoryos/routes/main/templates/help.html +0 -141
- ivoryos/routes/main/templates/home.html +0 -103
- ivoryos/static/favicon.ico +0 -0
- ivoryos/static/gui_annotation/Slide1.png +0 -0
- ivoryos/static/gui_annotation/Slide2.PNG +0 -0
- ivoryos/static/js/action_handlers.js +0 -213
- ivoryos/static/js/db_delete.js +0 -23
- ivoryos/static/js/overlay.js +0 -12
- ivoryos/static/js/script_metadata.js +0 -39
- ivoryos/static/js/socket_handler.js +0 -125
- ivoryos/static/js/sortable_card.js +0 -24
- ivoryos/static/js/sortable_design.js +0 -138
- ivoryos/static/js/ui_state.js +0 -113
- ivoryos/static/logo.webp +0 -0
- ivoryos/static/style.css +0 -211
- ivoryos/templates/base.html +0 -157
- ivoryos-1.2.0b1.dist-info/RECORD +0 -105
- {ivoryos-1.2.0b1.dist-info → ivoryos-1.2.1.dist-info}/LICENSE +0 -0
- {ivoryos-1.2.0b1.dist-info → ivoryos-1.2.1.dist-info}/WHEEL +0 -0
- {ivoryos-1.2.0b1.dist-info → ivoryos-1.2.1.dist-info}/top_level.txt +0 -0
|
@@ -1,294 +0,0 @@
|
|
|
1
|
-
{% extends 'base.html' %}
|
|
2
|
-
{% block title %}IvoryOS | Design execution{% endblock %}
|
|
3
|
-
|
|
4
|
-
{% block body %}
|
|
5
|
-
<script src="https://cdnjs.cloudflare.com/ajax/libs/socket.io/4.4.1/socket.io.js"></script>
|
|
6
|
-
|
|
7
|
-
{% if no_deck_warning and not dismiss %}
|
|
8
|
-
{# auto pop import when there is no deck#}
|
|
9
|
-
<script type="text/javascript">
|
|
10
|
-
function OpenBootstrapPopup() {
|
|
11
|
-
$("#importModal").modal('show');
|
|
12
|
-
}
|
|
13
|
-
window.onload = function () {
|
|
14
|
-
OpenBootstrapPopup();
|
|
15
|
-
};
|
|
16
|
-
</script>
|
|
17
|
-
{% endif %}
|
|
18
|
-
|
|
19
|
-
<div class="row">
|
|
20
|
-
{% include 'components/run_panel.html' %}
|
|
21
|
-
{% include 'components/progress_panel.html' %}
|
|
22
|
-
{% include 'components/logging_panel.html' %}
|
|
23
|
-
</div>
|
|
24
|
-
|
|
25
|
-
{# Include error modal #}
|
|
26
|
-
{% include 'components/error_modal.html' %}
|
|
27
|
-
|
|
28
|
-
<script src="{{ url_for('static', filename='js/socket_handler.js') }}"></script>
|
|
29
|
-
<script>
|
|
30
|
-
var rowCount = 0;
|
|
31
|
-
var configColumns = [
|
|
32
|
-
{% for column in config_list %}
|
|
33
|
-
'{{ column }}'{{ ',' if not loop.last else '' }}
|
|
34
|
-
{% endfor %}
|
|
35
|
-
];
|
|
36
|
-
var configTypes = {
|
|
37
|
-
{% for column, type in config_type_list.items() %}
|
|
38
|
-
'{{ column }}': '{{ type }}'{{ ',' if not loop.last else '' }}
|
|
39
|
-
{% endfor %}
|
|
40
|
-
};
|
|
41
|
-
|
|
42
|
-
// State management
|
|
43
|
-
var originalFileData = null;
|
|
44
|
-
var isModifiedFromFile = false;
|
|
45
|
-
var saveTimeout = null;
|
|
46
|
-
var lastSavedData = null;
|
|
47
|
-
|
|
48
|
-
function addRow(data = null, skipSave = false) {
|
|
49
|
-
rowCount++;
|
|
50
|
-
var tableBody = document.getElementById("tableBody");
|
|
51
|
-
var newRow = tableBody.insertRow(-1);
|
|
52
|
-
|
|
53
|
-
// Row number cell
|
|
54
|
-
var rowNumCell = newRow.insertCell(-1);
|
|
55
|
-
rowNumCell.innerHTML = '<span class="badge bg-secondary">' + rowCount + '</span>';
|
|
56
|
-
|
|
57
|
-
// Data cells
|
|
58
|
-
configColumns.forEach(function(column, index) {
|
|
59
|
-
var cell = newRow.insertCell(-1);
|
|
60
|
-
var value = data && data[column] ? data[column] : '';
|
|
61
|
-
var placeholder = configTypes[column] || 'value';
|
|
62
|
-
cell.innerHTML = '<input type="text" class="form-control form-control-sm" name="' +
|
|
63
|
-
column + '[' + rowCount + ']" value="' + value + '" placeholder="' + placeholder +
|
|
64
|
-
'" oninput="onInputChange()" onchange="onInputChange()">';
|
|
65
|
-
});
|
|
66
|
-
|
|
67
|
-
// Action cell
|
|
68
|
-
var actionCell = newRow.insertCell(-1);
|
|
69
|
-
actionCell.innerHTML = '<button type="button" class="btn btn-sm btn-outline-danger" onclick="removeRow(this)" title="Remove row">' +
|
|
70
|
-
'<i class="bi bi-trash"></i></button>';
|
|
71
|
-
|
|
72
|
-
if (!skipSave) {
|
|
73
|
-
markAsModified();
|
|
74
|
-
debouncedSave();
|
|
75
|
-
}
|
|
76
|
-
}
|
|
77
|
-
|
|
78
|
-
function removeRow(button) {
|
|
79
|
-
var row = button.closest('tr');
|
|
80
|
-
row.remove();
|
|
81
|
-
updateRowNumbers();
|
|
82
|
-
markAsModified();
|
|
83
|
-
debouncedSave();
|
|
84
|
-
}
|
|
85
|
-
|
|
86
|
-
function updateRowNumbers() {
|
|
87
|
-
var tableBody = document.getElementById("tableBody");
|
|
88
|
-
var rows = tableBody.getElementsByTagName('tr');
|
|
89
|
-
for (var i = 0; i < rows.length; i++) {
|
|
90
|
-
var badge = rows[i].querySelector('.badge');
|
|
91
|
-
if (badge) {
|
|
92
|
-
badge.textContent = i + 1;
|
|
93
|
-
}
|
|
94
|
-
}
|
|
95
|
-
}
|
|
96
|
-
|
|
97
|
-
function clearAllRows() {
|
|
98
|
-
if (confirm('Are you sure you want to clear all rows?')) {
|
|
99
|
-
var tableBody = document.getElementById("tableBody");
|
|
100
|
-
tableBody.innerHTML = '';
|
|
101
|
-
rowCount = 0;
|
|
102
|
-
markAsModified();
|
|
103
|
-
clearSavedData();
|
|
104
|
-
// Add 5 empty rows by default
|
|
105
|
-
for (let i = 0; i < 5; i++) {
|
|
106
|
-
addRow(null, true);
|
|
107
|
-
}
|
|
108
|
-
debouncedSave();
|
|
109
|
-
}
|
|
110
|
-
}
|
|
111
|
-
|
|
112
|
-
function resetToFile() {
|
|
113
|
-
if (originalFileData && confirm('Reset to original file data? This will lose all manual changes.')) {
|
|
114
|
-
loadDataFromSource(originalFileData, false);
|
|
115
|
-
isModifiedFromFile = false;
|
|
116
|
-
updateStatusIndicators();
|
|
117
|
-
debouncedSave();
|
|
118
|
-
}
|
|
119
|
-
}
|
|
120
|
-
|
|
121
|
-
function onInputChange() {
|
|
122
|
-
markAsModified();
|
|
123
|
-
debouncedSave();
|
|
124
|
-
}
|
|
125
|
-
|
|
126
|
-
function markAsModified() {
|
|
127
|
-
if (originalFileData) {
|
|
128
|
-
isModifiedFromFile = true;
|
|
129
|
-
updateStatusIndicators();
|
|
130
|
-
}
|
|
131
|
-
}
|
|
132
|
-
|
|
133
|
-
function updateStatusIndicators() {
|
|
134
|
-
var modifiedStatus = document.getElementById('modifiedStatus');
|
|
135
|
-
var resetBtn = document.getElementById('resetToFileBtn');
|
|
136
|
-
|
|
137
|
-
if (isModifiedFromFile && originalFileData) {
|
|
138
|
-
modifiedStatus.style.display = 'inline-block';
|
|
139
|
-
resetBtn.style.display = 'inline-block';
|
|
140
|
-
} else {
|
|
141
|
-
modifiedStatus.style.display = 'none';
|
|
142
|
-
resetBtn.style.display = 'none';
|
|
143
|
-
}
|
|
144
|
-
}
|
|
145
|
-
|
|
146
|
-
function showSaveStatus() {
|
|
147
|
-
var saveStatus = document.getElementById('saveStatus');
|
|
148
|
-
saveStatus.style.display = 'inline-block';
|
|
149
|
-
setTimeout(function() {
|
|
150
|
-
saveStatus.style.display = 'none';
|
|
151
|
-
}, 2000);
|
|
152
|
-
}
|
|
153
|
-
|
|
154
|
-
function debouncedSave() {
|
|
155
|
-
clearTimeout(saveTimeout);
|
|
156
|
-
saveTimeout = setTimeout(function() {
|
|
157
|
-
saveFormData();
|
|
158
|
-
showSaveStatus();
|
|
159
|
-
}, 1000); // Save 1 second after user stops typing
|
|
160
|
-
}
|
|
161
|
-
|
|
162
|
-
function saveFormData() {
|
|
163
|
-
var formData = getCurrentFormData();
|
|
164
|
-
try {
|
|
165
|
-
sessionStorage.setItem('configFormData', JSON.stringify(formData));
|
|
166
|
-
sessionStorage.setItem('configModified', isModifiedFromFile.toString());
|
|
167
|
-
lastSavedData = formData;
|
|
168
|
-
} catch (e) {
|
|
169
|
-
console.warn('Could not save form data to sessionStorage:', e);
|
|
170
|
-
}
|
|
171
|
-
}
|
|
172
|
-
|
|
173
|
-
function getCurrentFormData() {
|
|
174
|
-
var tableBody = document.getElementById("tableBody");
|
|
175
|
-
var rows = tableBody.getElementsByTagName('tr');
|
|
176
|
-
var data = [];
|
|
177
|
-
|
|
178
|
-
for (var i = 0; i < rows.length; i++) {
|
|
179
|
-
var inputs = rows[i].getElementsByTagName('input');
|
|
180
|
-
var rowData = {};
|
|
181
|
-
var hasData = false;
|
|
182
|
-
|
|
183
|
-
for (var j = 0; j < inputs.length; j++) {
|
|
184
|
-
var input = inputs[j];
|
|
185
|
-
var name = input.name;
|
|
186
|
-
if (name) {
|
|
187
|
-
var columnName = name.substring(0, name.indexOf('['));
|
|
188
|
-
rowData[columnName] = input.value;
|
|
189
|
-
if (input.value.trim() !== '') {
|
|
190
|
-
hasData = true;
|
|
191
|
-
}
|
|
192
|
-
}
|
|
193
|
-
}
|
|
194
|
-
|
|
195
|
-
if (hasData) {
|
|
196
|
-
data.push(rowData);
|
|
197
|
-
}
|
|
198
|
-
}
|
|
199
|
-
|
|
200
|
-
return data;
|
|
201
|
-
}
|
|
202
|
-
|
|
203
|
-
function loadSavedData() {
|
|
204
|
-
try {
|
|
205
|
-
var savedData = sessionStorage.getItem('configFormData');
|
|
206
|
-
var savedModified = sessionStorage.getItem('configModified');
|
|
207
|
-
|
|
208
|
-
if (savedData) {
|
|
209
|
-
var parsedData = JSON.parse(savedData);
|
|
210
|
-
isModifiedFromFile = savedModified === 'true';
|
|
211
|
-
return parsedData;
|
|
212
|
-
}
|
|
213
|
-
} catch (e) {
|
|
214
|
-
console.warn('Could not load saved form data:', e);
|
|
215
|
-
}
|
|
216
|
-
return null;
|
|
217
|
-
}
|
|
218
|
-
|
|
219
|
-
function clearSavedData() {
|
|
220
|
-
try {
|
|
221
|
-
sessionStorage.removeItem('configFormData');
|
|
222
|
-
sessionStorage.removeItem('configModified');
|
|
223
|
-
} catch (e) {
|
|
224
|
-
console.warn('Could not clear saved data:', e);
|
|
225
|
-
}
|
|
226
|
-
}
|
|
227
|
-
|
|
228
|
-
function loadDataFromSource(data, isFromFile = false) {
|
|
229
|
-
// Clear existing rows
|
|
230
|
-
var tableBody = document.getElementById("tableBody");
|
|
231
|
-
tableBody.innerHTML = '';
|
|
232
|
-
rowCount = 0;
|
|
233
|
-
|
|
234
|
-
// Add rows with data
|
|
235
|
-
data.forEach(function(rowData) {
|
|
236
|
-
addRow(rowData, true);
|
|
237
|
-
});
|
|
238
|
-
|
|
239
|
-
// Add a few empty rows for additional input
|
|
240
|
-
for (let i = 0; i < 3; i++) {
|
|
241
|
-
addRow(null, true);
|
|
242
|
-
}
|
|
243
|
-
|
|
244
|
-
if (isFromFile) {
|
|
245
|
-
originalFileData = JSON.parse(JSON.stringify(data)); // Deep copy
|
|
246
|
-
isModifiedFromFile = false;
|
|
247
|
-
clearSavedData(); // Clear saved data when loading from file
|
|
248
|
-
}
|
|
249
|
-
|
|
250
|
-
updateStatusIndicators();
|
|
251
|
-
}
|
|
252
|
-
|
|
253
|
-
function loadConfigData() {
|
|
254
|
-
// Check for saved form data first
|
|
255
|
-
var savedData = loadSavedData();
|
|
256
|
-
|
|
257
|
-
{% if config_preview %}
|
|
258
|
-
var fileData = {{ config_preview | tojson | safe }};
|
|
259
|
-
originalFileData = JSON.parse(JSON.stringify(fileData)); // Deep copy
|
|
260
|
-
|
|
261
|
-
if (savedData && savedData.length > 0) {
|
|
262
|
-
// Load saved data if available
|
|
263
|
-
loadDataFromSource(savedData, false);
|
|
264
|
-
console.log('Loaded saved form data');
|
|
265
|
-
} else {
|
|
266
|
-
// Load from file
|
|
267
|
-
loadDataFromSource(fileData, true);
|
|
268
|
-
console.log('Loaded file data');
|
|
269
|
-
}
|
|
270
|
-
{% else %}
|
|
271
|
-
if (savedData && savedData.length > 0) {
|
|
272
|
-
// Load saved data
|
|
273
|
-
loadDataFromSource(savedData, false);
|
|
274
|
-
console.log('Loaded saved form data');
|
|
275
|
-
} else {
|
|
276
|
-
// Add default empty rows
|
|
277
|
-
for (let i = 0; i < 5; i++) {
|
|
278
|
-
addRow(null, true);
|
|
279
|
-
}
|
|
280
|
-
}
|
|
281
|
-
{% endif %}
|
|
282
|
-
}
|
|
283
|
-
|
|
284
|
-
// Handle page unload
|
|
285
|
-
window.addEventListener('beforeunload', function() {
|
|
286
|
-
saveFormData();
|
|
287
|
-
});
|
|
288
|
-
|
|
289
|
-
// Initialize table when page loads
|
|
290
|
-
document.addEventListener("DOMContentLoaded", function() {
|
|
291
|
-
loadConfigData();
|
|
292
|
-
});
|
|
293
|
-
</script>
|
|
294
|
-
{% endblock %}
|
|
@@ -1,91 +0,0 @@
|
|
|
1
|
-
{% extends 'base.html' %}
|
|
2
|
-
|
|
3
|
-
{% block title %}IvoryOS | Design Database{% endblock %}
|
|
4
|
-
{% block body %}
|
|
5
|
-
<!-- Deck Filter Buttons -->
|
|
6
|
-
<div class="btn-group" role="group">
|
|
7
|
-
{% for deck in deck_list %}
|
|
8
|
-
<a class="btn {% if deck == current_deck_name %}btn-primary{% else %}btn-secondary{% endif %}"
|
|
9
|
-
href="{{ url_for('library.load_from_database', deck_name=deck) }}">
|
|
10
|
-
{{ deck }}
|
|
11
|
-
</a>
|
|
12
|
-
{% endfor %}
|
|
13
|
-
</div>
|
|
14
|
-
|
|
15
|
-
<!-- Search Form -->
|
|
16
|
-
<form id="search" class="d-flex " method="GET" style="display: inline-block;float: right;"
|
|
17
|
-
action="{{ url_for('library.load_from_database', deck_name=current_deck_name or 'ALL') }}">
|
|
18
|
-
<div class="input-group">
|
|
19
|
-
<input type="search" name="keyword" id="keyword" class="form-control"
|
|
20
|
-
placeholder="Search workflows..." value="{{ request.args.get('keyword', '') }}">
|
|
21
|
-
<button type="submit" class="btn btn-primary">
|
|
22
|
-
<i class="bi bi-search"></i>
|
|
23
|
-
</button>
|
|
24
|
-
</div>
|
|
25
|
-
</form>
|
|
26
|
-
|
|
27
|
-
<table class="table table-hover" id="workflowLibrary">
|
|
28
|
-
<thead>
|
|
29
|
-
<tr>
|
|
30
|
-
<th scope="col">Workflow name</th>
|
|
31
|
-
<th scope="col">Deck </th>
|
|
32
|
-
<th scope="col">Editing</th>
|
|
33
|
-
<th scope="col">Time created</th>
|
|
34
|
-
<th scope="col">Last modified</th>
|
|
35
|
-
<th scope="col">Author</th>
|
|
36
|
-
{# <th scope="col">Registered</th>#}
|
|
37
|
-
<th scope="col"></th>
|
|
38
|
-
</tr>
|
|
39
|
-
</thead>
|
|
40
|
-
<tbody>
|
|
41
|
-
{% for script in scripts %}
|
|
42
|
-
<tr>
|
|
43
|
-
<td><a href="{{ url_for('library.workflow_script', script_name=script.name) }}">{{ script.name }}</a></td>
|
|
44
|
-
<td>{{ script.deck }}</td>
|
|
45
|
-
<td>{{ script.status }}</td>
|
|
46
|
-
<td>{{ script.time_created }}</td>
|
|
47
|
-
<td>{{ script.last_modified }}</td>
|
|
48
|
-
<td>{{ script.author }}</td>
|
|
49
|
-
{# <td>{{ workflow.registered }}</td>#}
|
|
50
|
-
<td>
|
|
51
|
-
{#not workflow.status == "finalized" or#}
|
|
52
|
-
{% if session['user'] == 'admin' or session['user'] == script.author %}
|
|
53
|
-
<a href="#"
|
|
54
|
-
class="text-danger"
|
|
55
|
-
data-delete-url="{{ url_for('library.workflow_script', script_name=script.name) }}"
|
|
56
|
-
onclick="deleteWorkflow(this); return false;">
|
|
57
|
-
Delete
|
|
58
|
-
</a>
|
|
59
|
-
{% else %}
|
|
60
|
-
<a class="disabled-link">delete</a>
|
|
61
|
-
{% endif %}
|
|
62
|
-
<td>
|
|
63
|
-
</tr>
|
|
64
|
-
{% endfor %}
|
|
65
|
-
</tbody>
|
|
66
|
-
</table>
|
|
67
|
-
|
|
68
|
-
{# paging#}
|
|
69
|
-
<div class="pagination justify-content-center">
|
|
70
|
-
<div class="page-item {{ 'disabled' if not scripts.has_prev else '' }}">
|
|
71
|
-
<a class="page-link" href="{{ url_for('library.load_from_database', page=scripts.prev_num) }}">Previous</a>
|
|
72
|
-
</div>
|
|
73
|
-
|
|
74
|
-
{% for num in scripts.iter_pages() %}
|
|
75
|
-
{% if num %}
|
|
76
|
-
<div class="page-item {{ 'active' if num == scripts.page else '' }}">
|
|
77
|
-
<a class="page-link" href="{{ url_for('library.load_from_database', page=num) }}">{{ num }}</a>
|
|
78
|
-
</div>
|
|
79
|
-
{% else %}
|
|
80
|
-
<div class="page-item disabled">
|
|
81
|
-
<span class="page-link">…</span>
|
|
82
|
-
</div>
|
|
83
|
-
{% endif %}
|
|
84
|
-
{% endfor %}
|
|
85
|
-
|
|
86
|
-
<div class="page-item {{ 'disabled' if not scripts.has_next else '' }}">
|
|
87
|
-
<a class="page-link" href="{{ url_for('library.load_from_database', page=scripts.next_num) }}">Next</a>
|
|
88
|
-
</div>
|
|
89
|
-
</div>
|
|
90
|
-
<script src="{{ url_for('static', filename='js/db_delete.js') }}"></script>
|
|
91
|
-
{% endblock %}
|
|
@@ -1,141 +0,0 @@
|
|
|
1
|
-
{% extends 'base.html' %}
|
|
2
|
-
{% block title %}IvoryOS | Documentation {% endblock %}
|
|
3
|
-
|
|
4
|
-
{% block body %}
|
|
5
|
-
<h2>Documentations:</h2>
|
|
6
|
-
<div class="accordion accordion-flush" id="helpPage" >
|
|
7
|
-
<div class="accordion-item">
|
|
8
|
-
<h2 class="accordion-header">
|
|
9
|
-
<button class="accordion-button collapsed" type="button" data-bs-toggle="collapse" data-bs-target="#overall" aria-expanded="false" aria-controls="helpPageControl">
|
|
10
|
-
General information - What is ivoryOS?
|
|
11
|
-
</button>
|
|
12
|
-
</h2>
|
|
13
|
-
<div id="overall" class="accordion-collapse collapse" data-bs-parent="#helpPage">
|
|
14
|
-
<div class="accordion-body">
|
|
15
|
-
<p>
|
|
16
|
-
This web app aims to ease up the control of any Python-based self-driving labs (SDLs) by extracting and displaying functions and parameters for initialized modules dynamically.
|
|
17
|
-
The modules can be hardware API, high-level functions, or experiment workflow. This can potentially be used for general visual programming purposes.
|
|
18
|
-
</p>
|
|
19
|
-
{# <p>Controller: single instrument mode and multi-instrument interface.</p>#}
|
|
20
|
-
{# <p>Workflow editor: automation workflow editor#}
|
|
21
|
-
</div>
|
|
22
|
-
</div>
|
|
23
|
-
</div>
|
|
24
|
-
{# <p>In the Controller tab, you can connect any instrument or instruments from a complete automation deck. The GUI will parse and show available functions and prompt user to the input argument values if need.</p>#}
|
|
25
|
-
{# <p>In the Build Workflow tab, you can edit your own automation workflow from scratch or from the workflow library, where stores the ongoing projects and some basic example workflows.</p>#}
|
|
26
|
-
|
|
27
|
-
<div class="accordion-item">
|
|
28
|
-
<h2 class="accordion-header">
|
|
29
|
-
<button class="accordion-button collapsed" type="button" data-bs-toggle="collapse" data-bs-target="#connect-device" aria-expanded="false" aria-controls="helpPageControl">
|
|
30
|
-
General information - start ivoryOS from script
|
|
31
|
-
</button>
|
|
32
|
-
</h2>
|
|
33
|
-
<div id="connect-device" class="accordion-collapse collapse" data-bs-parent="#helpPage">
|
|
34
|
-
<div class="accordion-body">
|
|
35
|
-
<pre ><code class="python" >{{ sample_deck }}</code></pre>
|
|
36
|
-
</div>
|
|
37
|
-
</div>
|
|
38
|
-
</div>
|
|
39
|
-
<div class="accordion-item">
|
|
40
|
-
<h2 class="accordion-header">
|
|
41
|
-
<button class="accordion-button collapsed" type="button" data-bs-toggle="collapse" data-bs-target="#library" aria-expanded="false" aria-controls="helpPageControl">
|
|
42
|
-
Script Editor - Library
|
|
43
|
-
</button>
|
|
44
|
-
</h2>
|
|
45
|
-
<div id="library" class="accordion-collapse collapse" data-bs-parent="#helpPage">
|
|
46
|
-
<div class="accordion-body">
|
|
47
|
-
<p>In "Library" Tab, the interactive database displays all workflow information</p>
|
|
48
|
-
<p>On top of the library page, you can click filter to choose your desired deck out of other automation platforms. You can also search for experiment keyword on the right</p>
|
|
49
|
-
<p>Note that you can edit/delete your own workflow anytime, but in case you would like to adapt other author's workflow, you need to save as your own in a different file name.</p>
|
|
50
|
-
</div>
|
|
51
|
-
</div>
|
|
52
|
-
</div>
|
|
53
|
-
<div class="accordion-item">
|
|
54
|
-
<h2 class="accordion-header">
|
|
55
|
-
<button class="accordion-button collapsed" type="button" data-bs-toggle="collapse" data-bs-target="#editor" aria-expanded="false" aria-controls="helpPageControl">
|
|
56
|
-
Script Editor - How to use script editor?
|
|
57
|
-
</button>
|
|
58
|
-
</h2>
|
|
59
|
-
<div id="editor" class="accordion-collapse collapse" data-bs-parent="#helpPage">
|
|
60
|
-
<div class="accordion-body">
|
|
61
|
-
<p>You can browse and load other's workflow in "Library" Tab or go to "Build Workflow" Tab to build from scratch.</p>
|
|
62
|
-
<p>On the workflow canvas, there are three coding blocks: Prep, Experiment and Clean up. As the names indicated, the Prep and Clean up are steps taken prior and after to the main experiment, they cannot be repeated. On the other hand, the Experiment section can be repeated by a designated times or <a href="#config">a .csv configuration file</a></p>
|
|
63
|
-
<p>On the left panel, you can choose the deck profile on the top, and browse deck action and builtin python functions. Click to input your argument and add to the canvas, then drag the action to change their order.</p>
|
|
64
|
-
<img src="{{url_for('static', filename='gui_annotation/Slide1.PNG')}}">
|
|
65
|
-
</div>
|
|
66
|
-
</div>
|
|
67
|
-
</div>
|
|
68
|
-
<div class="accordion-item">
|
|
69
|
-
<h2 class="accordion-header">
|
|
70
|
-
<button class="accordion-button collapsed" type="button" data-bs-toggle="collapse" data-bs-target="#editor-advanced" aria-expanded="false" aria-controls="helpPageControl">
|
|
71
|
-
Script Editor - How to save data and configure reaction?
|
|
72
|
-
</button>
|
|
73
|
-
</h2>
|
|
74
|
-
<div id="editor-advanced" class="accordion-collapse collapse" data-bs-parent="#helpPage">
|
|
75
|
-
<div class="accordion-body">
|
|
76
|
-
|
|
77
|
-
<img src="{{url_for('static', filename='gui_annotation/Slide2.PNG')}}">
|
|
78
|
-
</div>
|
|
79
|
-
</div>
|
|
80
|
-
</div>
|
|
81
|
-
<div class="accordion-item">
|
|
82
|
-
<h2 class="accordion-header">
|
|
83
|
-
<button class="accordion-button collapsed" type="button" data-bs-toggle="collapse" data-bs-target="#config" aria-expanded="false" aria-controls="helpPageControl">
|
|
84
|
-
Run my script - How to execute my workflow?
|
|
85
|
-
</button>
|
|
86
|
-
</h2>
|
|
87
|
-
<div id="config" class="accordion-collapse collapse" data-bs-parent="#helpPage">
|
|
88
|
-
<div class="accordion-body">
|
|
89
|
-
<p>For workflow with no parameters, simply input repeat times to run.</p>
|
|
90
|
-
<p>To configure your workflow, if there are less or equal than 5 parameters, one can use the web form or import a csv file.
|
|
91
|
-
For workflow with more than 5 parameters, web form is not available.</p>
|
|
92
|
-
<p>If there is any output, Bayesian Optimization will be available for adaptive experimentation. Note that the outputs need to be numeric values. </p>
|
|
93
|
-
{# <img src="{{url_for('static', filename='gui_annotation/Slide3.PNG')}}">#}
|
|
94
|
-
</div>
|
|
95
|
-
</div>
|
|
96
|
-
</div>
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
<div class="accordion-item">
|
|
101
|
-
<h2 class="accordion-header">
|
|
102
|
-
<button class="accordion-button collapsed" type="button" data-bs-toggle="collapse" data-bs-target="#controller" aria-expanded="false" aria-controls="helpPageControl">
|
|
103
|
-
Control - How to use device interface?
|
|
104
|
-
</button>
|
|
105
|
-
</h2>
|
|
106
|
-
<div id="controller" class="accordion-collapse collapse" data-bs-parent="#helpPage">
|
|
107
|
-
<div class="accordion-body">
|
|
108
|
-
<p>The function cards are draggable for customized layout. The hidden icon is to remove functions from the interface. </p>
|
|
109
|
-
{# <p>(1) Import a python script where devices are connected using Deck Deice tab (e.g. applied to a complete automation deck with a deck.py file).</p>#}
|
|
110
|
-
{# <p>(2) Connect devices in the web app using New Deice tab. There are builtin instruments, but you can always import your own API.</p>#}
|
|
111
|
-
</div>
|
|
112
|
-
</div>
|
|
113
|
-
</div>
|
|
114
|
-
<div class="accordion-item">
|
|
115
|
-
<h2 class="accordion-header">
|
|
116
|
-
<button class="accordion-button collapsed" type="button" data-bs-toggle="collapse" data-bs-target="#deck" aria-expanded="false" aria-controls="helpPageControl">
|
|
117
|
-
Control - Connect new devices
|
|
118
|
-
</button>
|
|
119
|
-
</h2>
|
|
120
|
-
<div id="deck" class="accordion-collapse collapse" data-bs-parent="#helpPage">
|
|
121
|
-
<div class="accordion-body">
|
|
122
|
-
<p>When temporarily connecting instruments, New device -> New connection -> Import API. Use absolute path of your Python API file.
|
|
123
|
-
Then enter required info (e.g. COM port) to connect a device.</p>
|
|
124
|
-
</div>
|
|
125
|
-
</div>
|
|
126
|
-
</div>
|
|
127
|
-
<div class="accordion-item">
|
|
128
|
-
<h2 class="accordion-header">
|
|
129
|
-
<button class="accordion-button collapsed" type="button" data-bs-toggle="collapse" data-bs-target="#install" aria-expanded="false" aria-controls="helpPageControl">
|
|
130
|
-
Supports
|
|
131
|
-
</button>
|
|
132
|
-
</h2>
|
|
133
|
-
<div id="install" class="accordion-collapse collapse" data-bs-parent="#helpPage">
|
|
134
|
-
<div class="accordion-body">
|
|
135
|
-
This is project is a work in progress. In case of any bugs or suggestions, reach out to Ivory: ivoryzhang@chem.ubc.ca or create an issue on GitLab:
|
|
136
|
-
<a href="https://gitlab.com/heingroup/ivoryos">https://gitlab.com/heingroup/ivoryos</a>.
|
|
137
|
-
</div>
|
|
138
|
-
</div>
|
|
139
|
-
</div>
|
|
140
|
-
</div>
|
|
141
|
-
{% endblock %}
|
|
@@ -1,103 +0,0 @@
|
|
|
1
|
-
{% extends 'base.html' %}
|
|
2
|
-
{% block title %}IvoryOS | Welcome{% endblock %}
|
|
3
|
-
|
|
4
|
-
{% block body %}
|
|
5
|
-
<div class="p-4">
|
|
6
|
-
<h1 class="mb-4" style="font-size: 3rem; font-weight: bold; color: #343a40;">
|
|
7
|
-
Welcome
|
|
8
|
-
</h1>
|
|
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>
|
|
14
|
-
<div class="row">
|
|
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('library.load_from_database') }}" class="stretched-link"></a>
|
|
23
|
-
</div>
|
|
24
|
-
</div>
|
|
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>
|
|
34
|
-
</div>
|
|
35
|
-
</div>
|
|
36
|
-
</div>
|
|
37
|
-
</div>
|
|
38
|
-
{% endif %}
|
|
39
|
-
|
|
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('data.list_workflows') }}" class="stretched-link"></a>
|
|
52
|
-
</div>
|
|
53
|
-
</div>
|
|
54
|
-
</div>
|
|
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('execute.experiment_run') }}" class="stretched-link"></a>
|
|
66
|
-
</div>
|
|
67
|
-
</div>
|
|
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>
|
|
86
|
-
</div>
|
|
87
|
-
</div>
|
|
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.temp.new_controller') }}" class="stretched-link"></a>
|
|
97
|
-
</div>
|
|
98
|
-
</div>
|
|
99
|
-
</div>
|
|
100
|
-
</div>
|
|
101
|
-
{% endif %}
|
|
102
|
-
</div>
|
|
103
|
-
{% endblock %}
|
ivoryos/static/favicon.ico
DELETED
|
Binary file
|
|
Binary file
|
|
Binary file
|