diff --git a/fe/computation-window.html b/fe/computation-window.html index 904400c..d840e8f 100644 --- a/fe/computation-window.html +++ b/fe/computation-window.html @@ -54,6 +54,12 @@ + + +
+ v0.0.0 @@ -98,6 +104,8 @@

Bifurcation Fun

+ + diff --git a/fe/explorer.html b/fe/explorer.html index 9955c10..b4d82a7 100644 --- a/fe/explorer.html +++ b/fe/explorer.html @@ -54,6 +54,12 @@ + + +
+

Aeon/BIODIVINE

@@ -90,5 +96,7 @@

Witness update

+ + \ No newline at end of file diff --git a/fe/index.html b/fe/index.html index dac5e4f..a2d57a2 100644 --- a/fe/index.html +++ b/fe/index.html @@ -64,6 +64,12 @@ + + +
+
@@ -191,8 +197,8 @@

● Update Function

+ - diff --git a/fe/script/Results.js b/fe/script/Results.js index fde86bc..210bd2f 100644 --- a/fe/script/Results.js +++ b/fe/script/Results.js @@ -10,8 +10,10 @@ let Results = { }, show() { + UI.isLoading(true) ComputationEndpoints.getResults() .then((resultsObject) => { + UI.isLoading(false) let isPartial = resultsObject["isPartial"] let isCancelled = resultsObject["isCancelled"] @@ -68,6 +70,7 @@ let Results = { } }) .catch((errorMessage) => { + UI.isLoading(false) Dialog.errorMessage(errorMessage) }) }, diff --git a/fe/script/UI.js b/fe/script/UI.js index 560f995..c35fb94 100644 --- a/fe/script/UI.js +++ b/fe/script/UI.js @@ -264,10 +264,14 @@ let UI = { }, isLoading(status) { + const windowContent = document.getElementById("content") + const loading = document.getElementById("loading-indicator") if (status) { - document.getElementById("loading-indicator").classList.remove("invisible"); + windowContent.classList.add("freeze") + loading.classList.remove("invisible") } else { - document.getElementById("loading-indicator").classList.add("invisible"); + windowContent.classList.remove("freeze") + loading.classList.add("invisible"); } }, @@ -296,11 +300,14 @@ let UI = { filename = "model"; } + this.isLoading(true) ModelEndpoints.aeonToSbml(aeonModel) .then((sbmlModel) => { + this.isLoading(false) this._downloadFile(filename + ".sbml", sbmlModel); }) .catch((errorMessage) => { + this.isLoading(false) Dialog.errorMessage(errorMessage) }) }, @@ -316,11 +323,14 @@ let UI = { filename = "model"; } + this.isLoading(true) ModelEndpoints.aeonToSbmlInstantiated(aeonModel) .then((sbmlModel) => { + this.isLoading(false) this._downloadFile(filename + "_instantiated.sbml", sbmlModel); }) .catch((errorMessage) => { + this.isLoading(false) Dialog.errorMessage(errorMessage); }) }, @@ -378,11 +388,14 @@ let UI = { const sbmlFileContent = await TAURI.fs.readTextFile(filePath); + this.isLoading(true) ModelEndpoints.sbmlToAeon(sbmlFileContent) .then((model) => { + this.isLoading(false) LiveModel.handleAeonModelImport(model); }) .catch((errorMessage) => { + this.isLoading(false) Dialog.errorMessage(errorMessage); }) }, diff --git a/fe/script/Windows.js b/fe/script/Windows.js index 0d97983..5d7de18 100644 --- a/fe/script/Windows.js +++ b/fe/script/Windows.js @@ -58,31 +58,40 @@ let Windows = { }, openWitnessWindow(witness) { + UI.isLoading(true) ComputationResultsEndpoints.getWitness(witness) .then((witness) => { + UI.isLoading(false) this.newWitnessWindow(witness) }) .catch((errorMessage) => { + UI.isLoading(false) Dialog.errorMessage(errorMessage) }) }, openTreeWitnessWindow(node) { + UI.isLoading(true) ComputationResultsEndpoints.getTreeWitness(node) .then((witness) => { + UI.isLoading(false) this.newWitnessWindow(witness) }) .catch((errorMessage) => { + UI.isLoading(false) Dialog.errorMessage(errorMessage) }) }, openStabilityWitnessWindow(node, behavior, variable, vector) { + UI.isLoading(true) ComputationResultsEndpoints.getStabilityWitness(node, behavior, variable, vector) .then((witness) => { + UI.isLoading(false) this.newWitnessWindow(witness) }) .catch((errorMessage) => { + UI.isLoading(false) Dialog.errorMessage(errorMessage) }) }, diff --git a/fe/script/events/ExplorerWindowEvent.js b/fe/script/events/ExplorerWindowEvent.js index c58a7ea..a74a72b 100644 --- a/fe/script/events/ExplorerWindowEvent.js +++ b/fe/script/events/ExplorerWindowEvent.js @@ -3,11 +3,15 @@ TAURI.event.listen('get-attractors', (event) => { Computation.setWindowSessionKey(event.payload['windowSessionKey']) const behavior = event.payload['behavior'] + + UI.isLoading(true) ComputationResultsEndpoints.getAttractors(behavior) .then((okJson) => { + UI.isLoading(false) showInExplorer(okJson) }) .catch((errorMessage) => { + UI.isLoading(false) Dialog.errorMessage(errorMessage) }) }); @@ -17,11 +21,15 @@ TAURI.event.listen('get-tree-attractors', (event) => { Computation.setWindowSessionKey(event.payload['windowSessionKey']) const node = event.payload['node'] + + UI.isLoading(true) ComputationResultsEndpoints.getTreeAttractors(node) .then((okJson) => { + UI.isLoading(false) showInExplorer(okJson) }) .catch((errorMessage) => { + UI.isLoading(false) Dialog.errorMessage(errorMessage) }) }); @@ -34,11 +42,15 @@ TAURI.event.listen('get-stability-attractors', (event) => { const behavior = event.payload['behavior'] const variable = event.payload['variable'] const vector = event.payload['vector'] + + UI.isLoading(true) ComputationResultsEndpoints.getStabilityAttractors(node, behavior, variable, vector) .then((okJson) => { + UI.isLoading(false) showInExplorer(okJson) }) .catch((errorMessage) => { + UI.isLoading(false) Dialog.errorMessage(errorMessage) }) }); diff --git a/fe/script/treeExplorerMain.js b/fe/script/treeExplorerMain.js index d7ab7be..9b89843 100644 --- a/fe/script/treeExplorerMain.js +++ b/fe/script/treeExplorerMain.js @@ -286,8 +286,10 @@ function autoExpandBifurcationTree(nodeId, depth, fit = true) { Dialog.errorMessage("No node selected.") } + UI.isLoading(true) TreeExplorerEndpoints.autoExpandBifurcationTree(nodeId, depth) .then((okResponseObject) => { + UI.isLoading(false) if (okResponseObject.length > 0) { for (node of okResponseObject) { CytoscapeEditor.ensureNode(node); @@ -305,6 +307,7 @@ function autoExpandBifurcationTree(nodeId, depth, fit = true) { } }) .catch((errorMessage) => { + UI.isLoading(false) Dialog.errorMessage(errorMessage) }) @@ -312,8 +315,10 @@ function autoExpandBifurcationTree(nodeId, depth, fit = true) { } function loadBifurcationTree(fit = true) { + UI.isLoading(true) ComputationResultsEndpoints.getBifurcationTree() .then((okResponseObject) => { + UI.isLoading(false) if (okResponseObject.length > 0) { CytoscapeEditor.removeAll(); // remove old tree if present for (node of okResponseObject) { @@ -333,16 +338,20 @@ function loadBifurcationTree(fit = true) { } }) .catch((errorMessage) => { + UI.isLoading(false) Dialog.errorMessage(errorMessage) }) } function setPrecision(precision) { + UI.isLoading(true) TreeExplorerEndpoints.applyTreePrecision(precision) .then((okResponse) => { + UI.isLoading(false) loadBifurcationTree(false); }) .catch((errorMessage) => { + UI.isLoading(false) Dialog.errorMessage(errorMessage) }) } @@ -447,9 +456,10 @@ function vector_to_string(vector) { function initStabilityButton(id, button, dropdown, container) { button.onclick = function() { let behaviour = dropdown.value; - console.log(id) + UI.isLoading(true) TreeExplorerEndpoints.getStabilityData(id, behaviour) .then((okResponseObject) => { + UI.isLoading(false) let content = "

Stability analysis:

"; for (item of okResponseObject) { let variableName = item.variable; @@ -466,6 +476,7 @@ function initStabilityButton(id, button, dropdown, container) { container.innerHTML = content; }) .catch((errorMessage) => { + UI.isLoading(false) Dialog.errorMessage("Cannot load stability data: " + errorMessage) }) } diff --git a/fe/style.css b/fe/style.css index f4354ef..634133b 100644 --- a/fe/style.css +++ b/fe/style.css @@ -44,6 +44,10 @@ body { transition: 0.3s; } +.freeze { + pointer-events: none +} + #logo { width: fit-content; width: -moz-fit-content; diff --git a/fe/tree_explorer.html b/fe/tree_explorer.html index fd1baed..e691764 100644 --- a/fe/tree_explorer.html +++ b/fe/tree_explorer.html @@ -1,6 +1,6 @@ - + Biodivine/Aeon - Bifurcation tree @@ -39,6 +39,7 @@ + @@ -62,6 +63,13 @@ + + + +
+ v0.0.0 @@ -298,5 +306,8 @@

Aeon/BIODIVINE

+ + + \ No newline at end of file diff --git a/src-tauri/src/computation_commands.rs b/src-tauri/src/computation_commands.rs index 1a0b680..11401a5 100644 --- a/src-tauri/src/computation_commands.rs +++ b/src-tauri/src/computation_commands.rs @@ -199,7 +199,7 @@ pub fn cancel_computation(window_session_key: &str) -> Result { /// Get result of computation. #[tauri::command] -pub fn get_results(window_session_key: &str) -> Result { +pub async fn get_results(window_session_key: &str) -> Result { let locked_computation: Arc>> = get_locked_computation(window_session_key); let read_computation = locked_computation.read().unwrap(); diff --git a/src-tauri/src/computation_results_commands.rs b/src-tauri/src/computation_results_commands.rs index b60c3f7..1d7b503 100644 --- a/src-tauri/src/computation_results_commands.rs +++ b/src-tauri/src/computation_results_commands.rs @@ -11,7 +11,7 @@ use biodivine_lib_param_bn::biodivine_std::traits::Set; use serde_json::{from_str, Value}; #[tauri::command] -pub fn get_witness(class_str: String, window_session_key: &str) -> Result { +pub async fn get_witness(class_str: String, window_session_key: &str) -> Result { let mut class = Class::new_empty(); for char in class_str.chars() { match char { @@ -49,7 +49,7 @@ pub fn get_witness(class_str: String, window_session_key: &str) -> Result Result { +pub async fn get_tree_witness(node_id: String, window_session_key: &str) -> Result { let locked_tree = get_locked_tree(window_session_key); let read_tree = locked_tree.read().unwrap(); return if let Some(tree) = read_tree.as_ref() { @@ -71,7 +71,7 @@ pub fn get_tree_witness(node_id: String, window_session_key: &str) -> Result Result { +pub async fn get_attractors(class_str: String, window_session_key: &str) -> Result { let mut class = Class::new_empty(); for char in class_str.chars() { match char { @@ -202,7 +202,7 @@ pub fn get_attractors(class_str: String, window_session_key: &str) -> Result Result { @@ -227,7 +227,7 @@ pub fn get_tree_attractors( } #[tauri::command] -pub fn get_stability_attractors( +pub async fn get_stability_attractors( node_id: String, behaviour_str: String, variable_str: String, @@ -322,7 +322,7 @@ pub fn get_stability_attractors( } #[tauri::command] -pub fn get_bifurcation_tree(window_session_key: &str) -> Result { +pub async fn get_bifurcation_tree(window_session_key: &str) -> Result { let locked_tree = get_locked_tree(window_session_key); let read_tree = locked_tree.read().unwrap(); if let Some(tree) = read_tree.as_ref() { diff --git a/src-tauri/src/model_commands.rs b/src-tauri/src/model_commands.rs index 0f2d3a9..fa33898 100644 --- a/src-tauri/src/model_commands.rs +++ b/src-tauri/src/model_commands.rs @@ -50,7 +50,7 @@ pub fn check_update_function(data: &str) -> Result { /// If everything goes well, return a standard result object with a parsed model, or /// error if something fails. #[tauri::command] -pub fn sbml_to_aeon(sbml_string: &str) -> Result { +pub async fn sbml_to_aeon(sbml_string: &str) -> Result { match BooleanNetwork::try_from_sbml(sbml_string) { Ok((model, layout)) => { let mut model_string = format!("{}", model); // convert back to aeon @@ -85,7 +85,7 @@ pub fn read_layout(aeon_string: &str) -> HashMap { /// which will then be translated into SBML (XML) representation. /// Preserve layout metadata. #[tauri::command] -pub fn aeon_to_sbml(aeon_string: &str) -> Result { +pub async fn aeon_to_sbml(aeon_string: &str) -> Result { match BooleanNetwork::try_from(aeon_string) { Ok(network) => { let layout = read_layout(aeon_string); @@ -100,7 +100,7 @@ pub fn aeon_to_sbml(aeon_string: &str) -> Result { /// Note that this can take quite a while for large models since we have to actually build /// the unit BDD right now (in the future, we might opt to use a SAT solver which might be faster). #[tauri::command] -pub fn aeon_to_sbml_instantiated(aeon_string: &str) -> Result { +pub async fn aeon_to_sbml_instantiated(aeon_string: &str) -> Result { match BooleanNetwork::try_from(aeon_string).and_then(SymbolicAsyncGraph::new) { Ok(graph) => { let witness = graph.pick_witness(graph.unit_colors()); diff --git a/src-tauri/src/tree_explorer_commands.rs b/src-tauri/src/tree_explorer_commands.rs index 93091cd..adc47a3 100644 --- a/src-tauri/src/tree_explorer_commands.rs +++ b/src-tauri/src/tree_explorer_commands.rs @@ -9,7 +9,7 @@ use json::{array, object, JsonValue}; use serde_json::{from_str, Value}; #[tauri::command] -pub fn auto_expand( +pub async fn auto_expand( node_id: String, depth: String, window_session_key: &str, @@ -61,7 +61,7 @@ pub fn get_attributes(node_id: String, window_session_key: &str) -> Result Result { @@ -157,7 +157,7 @@ pub fn revert_decision(node_id: String, window_session_key: &str) -> Result