ivoryos 1.0.9__py3-none-any.whl → 1.2.0b1__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.

Files changed (87) hide show
  1. ivoryos/__init__.py +26 -7
  2. ivoryos/routes/api/api.py +56 -0
  3. ivoryos/routes/auth/auth.py +5 -5
  4. ivoryos/routes/control/control.py +77 -372
  5. ivoryos/routes/control/control_file.py +36 -0
  6. ivoryos/routes/control/control_new_device.py +142 -0
  7. ivoryos/routes/control/templates/controllers.html +166 -0
  8. ivoryos/routes/control/templates/controllers_new.html +112 -0
  9. ivoryos/routes/control/utils.py +38 -0
  10. ivoryos/routes/data/data.py +129 -0
  11. ivoryos/routes/data/templates/components/step_card.html +13 -0
  12. ivoryos/routes/{database/templates/database → data/templates}/workflow_database.html +14 -8
  13. ivoryos/routes/{database/templates/database → data/templates}/workflow_view.html +3 -3
  14. ivoryos/routes/design/__init__.py +4 -0
  15. ivoryos/routes/design/design.py +298 -656
  16. ivoryos/routes/design/design_file.py +68 -0
  17. ivoryos/routes/design/design_step.py +145 -0
  18. ivoryos/routes/design/templates/components/action_form.html +53 -0
  19. ivoryos/routes/design/templates/components/actions_panel.html +25 -0
  20. ivoryos/routes/design/templates/components/autofill_toggle.html +10 -0
  21. ivoryos/routes/design/templates/components/canvas.html +5 -0
  22. ivoryos/routes/design/templates/components/canvas_footer.html +9 -0
  23. ivoryos/routes/design/templates/components/canvas_header.html +75 -0
  24. ivoryos/routes/design/templates/components/canvas_main.html +34 -0
  25. ivoryos/routes/design/templates/components/deck_selector.html +10 -0
  26. ivoryos/routes/design/templates/components/edit_action_form.html +38 -0
  27. ivoryos/routes/design/templates/components/instruments_panel.html +66 -0
  28. ivoryos/routes/design/templates/components/modals/drop_modal.html +17 -0
  29. ivoryos/routes/design/templates/components/modals/json_modal.html +22 -0
  30. ivoryos/routes/design/templates/components/modals/new_script_modal.html +17 -0
  31. ivoryos/routes/design/templates/components/modals/rename_modal.html +23 -0
  32. ivoryos/routes/design/templates/components/modals/saveas_modal.html +27 -0
  33. ivoryos/routes/design/templates/components/modals.html +6 -0
  34. ivoryos/routes/design/templates/components/python_code_overlay.html +39 -0
  35. ivoryos/routes/design/templates/components/sidebar.html +15 -0
  36. ivoryos/routes/design/templates/components/text_to_code_panel.html +20 -0
  37. ivoryos/routes/design/templates/experiment_builder.html +41 -0
  38. ivoryos/routes/execute/__init__.py +0 -0
  39. ivoryos/routes/execute/execute.py +317 -0
  40. ivoryos/routes/execute/execute_file.py +78 -0
  41. ivoryos/routes/execute/templates/components/error_modal.html +20 -0
  42. ivoryos/routes/execute/templates/components/logging_panel.html +31 -0
  43. ivoryos/routes/execute/templates/components/progress_panel.html +27 -0
  44. ivoryos/routes/execute/templates/components/run_panel.html +9 -0
  45. ivoryos/routes/execute/templates/components/run_tabs.html +17 -0
  46. ivoryos/routes/execute/templates/components/tab_bayesian.html +399 -0
  47. ivoryos/routes/execute/templates/components/tab_configuration.html +98 -0
  48. ivoryos/routes/execute/templates/components/tab_repeat.html +14 -0
  49. ivoryos/routes/execute/templates/experiment_run.html +294 -0
  50. ivoryos/routes/library/__init__.py +0 -0
  51. ivoryos/routes/library/library.py +159 -0
  52. ivoryos/routes/{database/templates/database/scripts_database.html → library/templates/library.html} +30 -22
  53. ivoryos/routes/main/main.py +1 -1
  54. ivoryos/routes/main/templates/{main/home.html → home.html} +4 -4
  55. ivoryos/socket_handlers.py +52 -0
  56. ivoryos/static/js/action_handlers.js +213 -0
  57. ivoryos/static/js/db_delete.js +23 -0
  58. ivoryos/static/js/script_metadata.js +39 -0
  59. ivoryos/static/js/sortable_design.js +89 -56
  60. ivoryos/static/js/ui_state.js +113 -0
  61. ivoryos/templates/base.html +4 -4
  62. ivoryos/utils/bo_campaign.py +179 -3
  63. ivoryos/utils/db_models.py +14 -5
  64. ivoryos/utils/form.py +5 -9
  65. ivoryos/utils/global_config.py +13 -1
  66. ivoryos/utils/py_to_json.py +225 -0
  67. ivoryos/utils/script_runner.py +49 -7
  68. ivoryos/utils/serilize.py +203 -0
  69. ivoryos/utils/task_runner.py +4 -1
  70. ivoryos/version.py +1 -1
  71. {ivoryos-1.0.9.dist-info → ivoryos-1.2.0b1.dist-info}/METADATA +5 -8
  72. ivoryos-1.2.0b1.dist-info/RECORD +105 -0
  73. ivoryos/routes/control/templates/control/controllers.html +0 -78
  74. ivoryos/routes/control/templates/control/controllers_home.html +0 -55
  75. ivoryos/routes/control/templates/control/controllers_new.html +0 -89
  76. ivoryos/routes/database/database.py +0 -306
  77. ivoryos/routes/database/templates/database/step_card.html +0 -7
  78. ivoryos/routes/design/templates/design/experiment_builder.html +0 -521
  79. ivoryos/routes/design/templates/design/experiment_run.html +0 -558
  80. ivoryos-1.0.9.dist-info/RECORD +0 -61
  81. /ivoryos/routes/auth/templates/{auth/login.html → login.html} +0 -0
  82. /ivoryos/routes/auth/templates/{auth/signup.html → signup.html} +0 -0
  83. /ivoryos/routes/{database → data}/__init__.py +0 -0
  84. /ivoryos/routes/main/templates/{main/help.html → help.html} +0 -0
  85. {ivoryos-1.0.9.dist-info → ivoryos-1.2.0b1.dist-info}/LICENSE +0 -0
  86. {ivoryos-1.0.9.dist-info → ivoryos-1.2.0b1.dist-info}/WHEEL +0 -0
  87. {ivoryos-1.0.9.dist-info → ivoryos-1.2.0b1.dist-info}/top_level.txt +0 -0
@@ -0,0 +1,213 @@
1
+
2
+
3
+
4
+
5
+ function saveWorkflow(link) {
6
+ const url = link.dataset.postUrl;
7
+
8
+ fetch(url, {
9
+ method: 'POST',
10
+ headers: {
11
+ 'Content-Type': 'application/json'
12
+ }
13
+ })
14
+ .then(res => res.json())
15
+ .then(data => {
16
+ if (data.success) {
17
+ // flash a success message
18
+ flash("Workflow saved successfully", "success");
19
+ window.location.reload(); // or update the UI dynamically
20
+ } else {
21
+ alert("Failed to save workflow: " + data.error);
22
+ }
23
+ })
24
+ .catch(err => {
25
+ console.error("Save error:", err);
26
+ alert("Something went wrong.");
27
+ });
28
+ }
29
+
30
+
31
+ function updateInstrumentPanel(link) {
32
+ const url = link.dataset.getUrl;
33
+ fetch(url)
34
+ .then(res => res.json())
35
+ .then(data => {
36
+ if (data.html) {
37
+ document.getElementById("sidebar-wrapper").innerHTML = data.html;
38
+ initializeDragHandlers()
39
+ }
40
+ })
41
+ }
42
+
43
+ function addMethodToDesign(event, form) {
44
+ event.preventDefault(); // Prevent default form submission
45
+
46
+ const formData = new FormData(form);
47
+
48
+ fetch(form.action, {
49
+ method: 'POST',
50
+ body: formData
51
+ })
52
+ .then(response => response.json())
53
+ .then(data => {
54
+ if (data.success) {
55
+ updateActionCanvas(data.html);
56
+ hideModal();
57
+ } else {
58
+ alert("Failed to add method: " + data.error);
59
+ }
60
+ })
61
+ .catch(error => console.error('Error:', error));
62
+ }
63
+
64
+
65
+ function updateActionCanvas(html) {
66
+ document.getElementById("canvas-action-wrapper").innerHTML = html;
67
+ initializeCanvas(); // Reinitialize canvas functionality
68
+ document.querySelectorAll('#pythonCodeOverlay pre code').forEach((block) => {
69
+ hljs.highlightElement(block);
70
+ });
71
+ }
72
+
73
+
74
+ let lastFocusedElement = null;
75
+
76
+
77
+ function hideModal() {
78
+ if (document.activeElement) {
79
+ document.activeElement.blur();
80
+ }
81
+ $('#dropModal').modal('hide');
82
+ if (lastFocusedElement) {
83
+ lastFocusedElement.focus(); // Return focus to the triggering element
84
+ }
85
+ }
86
+
87
+ function submitEditForm(event) {
88
+ event.preventDefault();
89
+ const form = event.target;
90
+ const formData = new FormData(form);
91
+
92
+ fetch(form.action, {
93
+ method: 'POST',
94
+ body: formData
95
+ })
96
+ .then(response => response.text())
97
+ .then(html => {
98
+ if (html) {
99
+ // Update only the action list
100
+ updateActionCanvas(html);
101
+
102
+ if (previousHtmlState) {
103
+ document.getElementById('instrument-panel').innerHTML = previousHtmlState;
104
+ previousHtmlState = null; // Clear the stored state
105
+ }
106
+ }
107
+ })
108
+ .catch(error => {
109
+ console.error('Error:', error);
110
+ });
111
+ }
112
+
113
+ function clearDraft() {
114
+ fetch(scriptDeleteUrl, {
115
+ method: "DELETE",
116
+ headers: {
117
+ "Content-Type": "application/json",
118
+ },
119
+ })
120
+ .then(res => res.json())
121
+ .then(data => {
122
+ if (data.success) {
123
+ window.location.reload();
124
+ } else {
125
+ alert("Failed to clear draft");
126
+ }
127
+ })
128
+ .catch(error => console.error("Failed to clear draft", error));
129
+ }
130
+
131
+
132
+
133
+
134
+ let previousHtmlState = null; // Store the previous state
135
+
136
+ function duplicateAction(uuid) {
137
+ if (!uuid) {
138
+ console.error('Invalid UUID');
139
+ return;
140
+ }
141
+
142
+ fetch(scriptStepDupUrl.replace('0', uuid), {
143
+ method: 'POST',
144
+ headers: {
145
+ 'Content-Type': 'application/json'
146
+ }
147
+ })
148
+
149
+ .then(response => response.text())
150
+ .then(html => {
151
+ updateActionCanvas(html);
152
+ })
153
+ .catch(error => console.error('Error:', error));
154
+ }
155
+
156
+ function editAction(uuid) {
157
+ if (!uuid) {
158
+ console.error('Invalid UUID');
159
+ return;
160
+ }
161
+
162
+ // Save current state before fetching new content
163
+ previousHtmlState = document.getElementById('instrument-panel').innerHTML;
164
+
165
+ fetch(scriptStepUrl.replace('0', uuid), {
166
+ method: 'GET',
167
+ headers: {
168
+ 'Content-Type': 'application/json'
169
+ }
170
+ })
171
+ .then(response => response.text())
172
+ .then(html => {
173
+ document.getElementById('instrument-panel').innerHTML = html;
174
+
175
+ // Add click handler for back button
176
+ document.getElementById('back').addEventListener('click', function(e) {
177
+ e.preventDefault();
178
+ if (previousHtmlState) {
179
+ document.getElementById('instrument-panel').innerHTML = previousHtmlState;
180
+ previousHtmlState = null; // Clear the stored state
181
+ }
182
+ });
183
+ })
184
+ .catch(error => console.error('Error:', error));
185
+ }
186
+
187
+
188
+
189
+ function deleteAction(uuid) {
190
+ if (!uuid) {
191
+ console.error('Invalid UUID');
192
+ return;
193
+ }
194
+
195
+ fetch(scriptStepUrl.replace('0', uuid), {
196
+ method: 'DELETE',
197
+ headers: {
198
+ 'Content-Type': 'application/json'
199
+ }
200
+ })
201
+ .then(response => response.text())
202
+ .then(html => {
203
+ // Find the first list element's content and replace it
204
+ updateActionCanvas(html);
205
+ })
206
+ .catch(error => console.error('Error:', error));
207
+ }
208
+
209
+
210
+
211
+
212
+
213
+
@@ -0,0 +1,23 @@
1
+
2
+ function deleteWorkflow(link) {
3
+ const url = link.dataset.deleteUrl;
4
+
5
+ fetch(url, {
6
+ method: 'DELETE',
7
+ headers: {
8
+ 'Content-Type': 'application/json'
9
+ }
10
+ })
11
+ .then(res => res.json())
12
+ .then(data => {
13
+ if (data.success) {
14
+ window.location.reload(); // or remove the row dynamically
15
+ } else {
16
+ alert("Failed to delete workflow: " + data.error);
17
+ }
18
+ })
19
+ .catch(err => {
20
+ console.error("Delete error:", err);
21
+ alert("Something went wrong.");
22
+ });
23
+ }
@@ -0,0 +1,39 @@
1
+ function editScriptName(event) {
2
+ event.preventDefault(); // Prevent full form submission
3
+ const newName = document.getElementById("new-name").value;
4
+ fetch(scriptMetaUrl, {
5
+ method: "PATCH",
6
+ headers: {
7
+ "Content-Type": "application/json",
8
+ },
9
+ body: JSON.stringify({name: newName})
10
+ })
11
+ .then(res => res.json())
12
+ .then(data => {
13
+ if (data.success) {
14
+ window.location.reload(); // or update the title on page directly
15
+ } else {
16
+ alert("Failed to rename script");
17
+ }
18
+ })
19
+ .catch(error => console.error("Failed to rename script", error));
20
+ }
21
+
22
+ function lockScriptEditing() {
23
+ fetch(scriptMetaUrl, {
24
+ method: "PATCH",
25
+ headers: {
26
+ "Content-Type": "application/json",
27
+ },
28
+ body: JSON.stringify({ status: "finalized" })
29
+ })
30
+ .then(res => res.json())
31
+ .then(data => {
32
+ if (data.success) {
33
+ window.location.reload();
34
+ } else {
35
+ alert("Failed to update script status");
36
+ }
37
+ })
38
+ .catch(error => console.error("Failed to update script status", error));
39
+ }
@@ -1,16 +1,56 @@
1
- $(document).ready(function () {
2
- let dropTargetId = ""; // Store the ID of the drop target
1
+ // Move triggerModal to global scope
2
+ function triggerModal(formHtml, actionName, actionId, dropTargetId) {
3
+ if (formHtml && formHtml.trim() !== "") {
4
+ var $form = $("<div>").html(formHtml);
5
+
6
+ var $hiddenInput = $("<input>")
7
+ .attr("type", "hidden")
8
+ .attr("name", "drop_target_id")
9
+ .attr("id", "dropTargetInput")
10
+ .val(dropTargetId);
11
+
12
+ $form.find("button[type='submit']").before($hiddenInput);
13
+
14
+ $("#modalFormFields").empty().append($form.children());
15
+
16
+ const $modal = $("#dropModal");
17
+
18
+ setTimeout(() => {
19
+ showModal($modal);
20
+ }, 0);
21
+
22
+ $("#modalDropTarget").text(dropTargetId || "N/A");
23
+ $("#modalFormFields")
24
+ .data("action-id", actionId)
25
+ .data("action-name", actionName)
26
+ .data("drop-target-id", dropTargetId);
27
+ } else {
28
+ console.error("Form HTML is undefined or empty!");
29
+ }
30
+ }
31
+
32
+ function showModal($modal) {
33
+ $modal.modal({
34
+ backdrop: 'static',
35
+ keyboard: true,
36
+ focus: true
37
+ }).modal('show');
38
+ }
3
39
 
40
+ const state = {
41
+ dropTargetId: ""
42
+ };
43
+
44
+ function initializeCanvas() {
4
45
  $("#list ul").sortable({
5
46
  cancel: ".unsortable",
6
47
  opacity: 0.8,
7
48
  cursor: "move",
8
49
  placeholder: "drop-placeholder",
9
50
  update: function () {
10
- var item_order = [];
11
- $("ul.reorder li").each(function () {
12
- item_order.push($(this).attr("id"));
13
- });
51
+ const item_order = $("ul.reorder li").map(function () {
52
+ return this.id;
53
+ }).get();
14
54
  var order_string = "order=" + item_order.join(",");
15
55
 
16
56
  $.ajax({
@@ -19,87 +59,80 @@ $(document).ready(function () {
19
59
  data: order_string,
20
60
  cache: false,
21
61
  success: function (data) {
22
- $("#response").html(data);
23
- $("#response").slideDown("slow");
24
- window.location.href = window.location.href;
62
+ // Update the canvas content with the new HTML
63
+ updateActionCanvas(data)
25
64
  }
65
+ }).fail(function (jqXHR, textStatus, errorThrown) {
66
+ console.error("Failed to update order:", textStatus, errorThrown);
26
67
  });
27
68
  }
28
69
  });
29
70
 
30
71
  // Make Entire Accordion Item Draggable
31
- $(".accordion-item").on("dragstart", function (event) {
32
- let formHtml = $(this).find(".accordion-body").html(); // Get the correct form
33
- event.originalEvent.dataTransfer.setData("form", formHtml || ""); // Store form HTML
72
+ $(".accordion-item").off("dragstart").on("dragstart", function (event) {
73
+ let formHtml = $(this).find(".accordion-body").html();
74
+ event.originalEvent.dataTransfer.setData("form", formHtml || "");
34
75
  event.originalEvent.dataTransfer.setData("action", $(this).find(".draggable-action").data("action"));
35
76
  event.originalEvent.dataTransfer.setData("id", $(this).find(".draggable-action").attr("id"));
36
-
37
77
  $(this).addClass("dragging");
38
78
  });
39
79
 
40
-
41
- $("#list ul, .canvas").on("dragover", function (event) {
80
+ $("#list ul, .canvas").off("dragover").on("dragover", function (event) {
42
81
  event.preventDefault();
43
82
  let $target = $(event.target).closest("li");
44
83
 
45
- // If we're over a valid <li> element in the list
46
84
  if ($target.length) {
47
- dropTargetId = $target.attr("id") || ""; // Store the drop target ID
48
-
49
- $(".drop-placeholder").remove(); // Remove existing placeholders
50
- $("<li class='drop-placeholder'></li>").insertBefore($target); // Insert before the target element
85
+ state.dropTargetId = $target.attr("id") || "";
86
+ insertDropPlaceholder($target);
51
87
  } else if (!$("#list ul").children().length && $(this).hasClass("canvas")) {
52
- $(".drop-placeholder").remove(); // Remove any placeholder
53
- // $("#list ul").append("<li class='drop-placeholder'></li>"); // Append placeholder to canvas
88
+ $(".drop-placeholder").remove();
54
89
  } else {
55
- dropTargetId = ""; // Append placeholder to canvas
90
+ state.dropTargetId = "";
56
91
  }
57
92
  });
58
93
 
59
- $("#list ul, .canvas").on("dragleave", function () {
60
- $(".drop-placeholder").remove(); // Remove placeholder on leave
94
+ $("#list ul, .canvas").off("dragleave").on("dragleave", function () {
95
+ $(".drop-placeholder").remove();
61
96
  });
62
97
 
63
- $("#list ul, .canvas").on("drop", function (event) {
98
+ $("#list ul, .canvas").off("drop").on("drop", function (event) {
64
99
  event.preventDefault();
65
-
66
100
  var actionName = event.originalEvent.dataTransfer.getData("action");
67
101
  var actionId = event.originalEvent.dataTransfer.getData("id");
68
- var formHtml = event.originalEvent.dataTransfer.getData("form"); // Retrieve form HTML
102
+ var formHtml = event.originalEvent.dataTransfer.getData("form");
69
103
  let listLength = $("ul.reorder li").length;
70
- dropTargetId = dropTargetId || listLength + 1; // Assign a "last" ID or unique identifier
104
+ state.dropTargetId = state.dropTargetId || listLength + 1;
71
105
  $(".drop-placeholder").remove();
72
- // Trigger the modal with the appropriate action
73
- triggerModal(formHtml, actionName, actionId, dropTargetId);
74
-
106
+ document.activeElement?.blur();
107
+ triggerModal(formHtml, actionName, actionId, state.dropTargetId);
75
108
  });
109
+ }
76
110
 
77
- // Function to trigger the modal (same for both buttons and accordion items)
78
- function triggerModal(formHtml, actionName, actionId, dropTargetId) {
79
- if (formHtml && formHtml.trim() !== "") {
80
- var $form = $("<div>").html(formHtml); // Convert HTML string to jQuery object
111
+ function insertDropPlaceholder($target) {
112
+ $(".drop-placeholder").remove();
113
+ $("<li class='drop-placeholder'></li>").insertBefore($target);
114
+ }
81
115
 
82
- // Create a hidden input for the drop target ID
83
- var $hiddenInput = $("<input>")
84
- .attr("type", "hidden")
85
- .attr("name", "drop_target_id")
86
- .attr("id", "dropTargetInput")
87
- .val(dropTargetId);
116
+ // Add this function to sortable_design.js
117
+ function initializeDragHandlers() {
118
+ $(".accordion-item").off("dragstart").on("dragstart", function (event) {
119
+ let formHtml = $(this).find(".accordion-body form").prop('outerHTML');
88
120
 
89
- // Insert before the submit button
90
- $form.find("button[type='submit']").before($hiddenInput);
121
+ if (!formHtml) {
122
+ console.error("Form not found in accordion-body");
123
+ return false;
124
+ }
91
125
 
92
- $("#modalFormFields").empty().append($form.children());
93
- $("#dropModal").modal("show"); // Show modal
126
+ event.originalEvent.dataTransfer.setData("form", formHtml);
127
+ event.originalEvent.dataTransfer.setData("action", $(this).find(".draggable-action").data("action"));
128
+ event.originalEvent.dataTransfer.setData("id", $(this).find(".draggable-action").attr("id"));
94
129
 
95
- // Store and display drop target ID in the modal
96
- $("#modalDropTarget").text(dropTargetId || "N/A");
130
+ $(this).addClass("dragging");
131
+ });
132
+ }
97
133
 
98
- $("#modalFormFields").data("action-id", actionId);
99
- $("#modalFormFields").data("action-name", actionName);
100
- $("#modalFormFields").data("drop-target-id", dropTargetId);
101
- } else {
102
- console.error("Form HTML is undefined or empty!");
103
- }
104
- }
105
- });
134
+ // Make sure it's called in the document ready function
135
+ $(document).ready(function () {
136
+ initializeCanvas();
137
+ initializeDragHandlers(); // Add this line
138
+ });
@@ -0,0 +1,113 @@
1
+ // Toggle visibility of line numbers
2
+ function toggleLineNumbers(save = true) {
3
+ const show = document.getElementById('toggleLineNumbers').checked;
4
+ document.querySelectorAll('.line-number').forEach(el => {
5
+ el.classList.toggle('d-none', !show);
6
+ });
7
+
8
+ if (save) {
9
+ localStorage.setItem('showLineNumbers', show ? 'true' : 'false');
10
+ }
11
+ }
12
+
13
+ // Toggle visibility of Python code overlay
14
+ function toggleCodeOverlay(state = null) {
15
+ const overlay = document.getElementById("pythonCodeOverlay");
16
+ const checkbox = document.getElementById("showPythonCodeSwitch");
17
+
18
+ const isVisible = overlay.classList.contains("show");
19
+ const newState = state !== null ? state : !isVisible;
20
+
21
+ if (newState) {
22
+ overlay.classList.add("show");
23
+ checkbox.checked = true;
24
+ } else {
25
+ overlay.classList.remove("show");
26
+ checkbox.checked = false;
27
+ }
28
+
29
+ // Save state to session via PATCH
30
+ fetch(scriptUIStateUrl, {
31
+ method: "PATCH",
32
+ headers: { "Content-Type": "application/json" },
33
+ body: JSON.stringify({ show_code: newState })
34
+ });
35
+ }
36
+
37
+
38
+ function setScriptPhase(stype) {
39
+ fetch(scriptUIStateUrl, {
40
+ method: "PATCH",
41
+ headers: {
42
+ "Content-Type": "application/json",
43
+ },
44
+ body: JSON.stringify({ editing_type: stype })
45
+ })
46
+ .then(res => res.json())
47
+ .then(data => {
48
+ if (data.html) {
49
+ document.getElementById("canvas-wrapper").innerHTML = data.html;
50
+ initializeCanvas(); // Reinitialize the canvas functionality
51
+ document.querySelectorAll('#pythonCodeOverlay pre code').forEach((block) => {
52
+ hljs.highlightElement(block);
53
+ });
54
+ }
55
+ })
56
+ .catch(error => console.error("Failed to update editing type", error));
57
+ }
58
+
59
+
60
+
61
+ function changeDeck(deck) {
62
+ fetch(scriptUIStateUrl, {
63
+ method: "PATCH",
64
+ headers: {
65
+ "Content-Type": "application/json",
66
+ },
67
+ body: JSON.stringify({ deck_name: deck })
68
+ })
69
+ .then(res => res.json())
70
+ .then(data => {
71
+ if (data.html) {
72
+ document.getElementById("sidebar-wrapper").innerHTML = data.html;
73
+ }
74
+ })
75
+ .catch(error => console.error("Failed to change deck", error));
76
+ }
77
+
78
+
79
+
80
+ function toggleAutoFill() {
81
+ const instrumentValue = document.querySelector('.form-check.form-switch').dataset.instrument;
82
+
83
+ fetch(scriptUIStateUrl, {
84
+ method: "PATCH",
85
+ headers: {
86
+ "Content-Type": "application/json",
87
+ },
88
+ body: JSON.stringify({
89
+ autofill: document.getElementById("autoFillCheck").checked,
90
+ instrument: instrumentValue
91
+ })
92
+ })
93
+ .then(res => res.json())
94
+ .then(data => {
95
+ if (data.html) {
96
+ document.getElementById("instrument-panel").innerHTML = data.html;
97
+ }
98
+ })
99
+ }
100
+ // Restore state on page load
101
+ document.addEventListener('DOMContentLoaded', () => {
102
+ const savedState = localStorage.getItem('showLineNumbers');
103
+ const checkbox = document.getElementById('toggleLineNumbers');
104
+
105
+ if (savedState === 'true') {
106
+ checkbox.checked = true;
107
+ }
108
+ if (checkbox) {
109
+ toggleLineNumbers(false); // don't overwrite localStorage on load
110
+ checkbox.addEventListener('change', () => toggleLineNumbers());
111
+ }
112
+
113
+ });
@@ -38,16 +38,16 @@
38
38
  </li>
39
39
  {% if enable_design %}
40
40
  <li class="nav-item">
41
- <a class="nav-link" href="{{ url_for('database.load_from_database') }}" aria-current="page">Library</a>
41
+ <a class="nav-link" href="{{ url_for('library.load_from_database') }}" aria-current="page">Library</a>
42
42
  </li>
43
43
  <li class="nav-item">
44
44
  <a class="nav-link" href="{{ url_for('design.experiment_builder') }}">Design</a>
45
45
  </li>
46
46
  <li class="nav-item">
47
- <a class="nav-link" href="{{ url_for('design.experiment_run') }}">Compile/Run</a>
47
+ <a class="nav-link" href="{{ url_for('execute.experiment_run') }}">Compile/Run</a>
48
48
  </li>
49
49
  <li class="nav-item">
50
- <a class="nav-link" href="{{ url_for('database.list_workflows') }}">Data</a>
50
+ <a class="nav-link" href="{{ url_for('data.list_workflows') }}">Data</a>
51
51
  </li>
52
52
  {% endif %}
53
53
 
@@ -116,7 +116,7 @@
116
116
  <h1 class="modal-title fs-5" id="importModal">Import deck by file path</h1>
117
117
  <button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
118
118
  </div>
119
- <form method="POST" action="{{ url_for('control.import_deck') }}" enctype="multipart/form-data">
119
+ <form method="POST" action="{{ url_for('control.temp.import_deck') }}" enctype="multipart/form-data">
120
120
  <div class="modal-body">
121
121
  <h5>from connection history</h5>
122
122
  <div class="form-group">