From 6f019c24902bad77e7bfeb864bc24245f49a84f4 Mon Sep 17 00:00:00 2001 From: Shailesh Appukuttan Date: Thu, 18 Mar 2021 19:29:48 +0100 Subject: [PATCH] Multiple changes; see PR --- .vscode/launch.json | 21 -- .vscode/settings.json | 3 - .../src/CompareMultiGraphs.js | 305 ++++++++++++++---- .../src/CompareMultiResults.js | 90 +++--- .../src/MUIDataTableCustomToolbar.js | 1 - .../src/ModelDetail.js | 10 +- .../src/ModelDetailContent.js | 26 +- .../src/ModelDetailHeader.js | 8 +- .../src/ModelEditForm.js | 2 +- .../src/ModelInstanceEditForm.js | 2 +- .../validation_framework_v2/src/ModelTable.js | 8 +- .../src/ResultDetailContent.js | 14 +- .../src/ResultDetailHeader.js | 22 +- .../src/ResultGraphs.js | 11 +- .../src/ResultModelTestInfo.js | 18 +- .../src/ResultRelatedFiles.js | 10 +- .../validation_framework_v2/src/TestDetail.js | 8 +- .../src/TestDetailContent.js | 20 +- .../src/TestDetailHeader.js | 8 +- apps/validation_framework_v2/src/TestTable.js | 8 +- .../src/ValidationFramework.js | 159 ++++++++- .../src/ViewSelected.js | 6 +- apps/validation_framework_v2/src/globals.js | 2 +- apps/validation_framework_v2/src/utils.js | 18 +- 24 files changed, 539 insertions(+), 241 deletions(-) delete mode 100644 .vscode/launch.json delete mode 100644 .vscode/settings.json diff --git a/.vscode/launch.json b/.vscode/launch.json deleted file mode 100644 index 1e2d6f819..000000000 --- a/.vscode/launch.json +++ /dev/null @@ -1,21 +0,0 @@ -{ - // Use IntelliSense to learn about possible Node.js debug attributes. - // Hover to view descriptions of existing attributes. - // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387 - "version": "0.2.0", - "configurations": [ - { - "type": "node", - "request": "launch", - "name": "Lancer le programme", - "program": "${workspaceRoot}/index.js", - "cwd": "${workspaceRoot}" - }, - { - "type": "node", - "request": "attach", - "name": "Attacher au processus", - "port": 5858 - } - ] -} \ No newline at end of file diff --git a/.vscode/settings.json b/.vscode/settings.json deleted file mode 100644 index fe7159848..000000000 --- a/.vscode/settings.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "python.linting.pylintEnabled": false -} \ No newline at end of file diff --git a/apps/validation_framework_v2/src/CompareMultiGraphs.js b/apps/validation_framework_v2/src/CompareMultiGraphs.js index d06f86438..069fd59b0 100644 --- a/apps/validation_framework_v2/src/CompareMultiGraphs.js +++ b/apps/validation_framework_v2/src/CompareMultiGraphs.js @@ -28,7 +28,203 @@ const ToggleSwitch = withStyles({ track: {}, })(Switch); -function ResultsFiguresSummary_XaxisModels(props) { +function shortenLabels(traces) { + // shorter group labels; preferable max length = 20 + traces = shortenLabelsUniquely(traces, 0, 20); + // shorten instance labels; preferable max length = 10 + traces = shortenLabelsUniquely(traces, 1, 10); + return traces +} + +function shortenLabelsUniquely(traces, type, pref_length) { + // we shorten labels so that long labels do not + // overlap each other in the generated figures + + // simply clipping the labels to some pre-defined length + // can result in non-unique labels. As Plotly uses the + // labels to merge items into groups, this can cause + // unrelated items to be merged into same group. + + // this method tries to shorten the labels, while trying + // to keep them distinct for proper grouping. + + // Approach: + // remove common prefix, and also suffix (if required to shorten length further) + + // sorting the labels orders them, so any prefix + // that is common to all labels, will also be common to + // the first and last labels. Thus we only need to compare + // the first and last labels to determine the common prefix. + // The same can be done for common suffix by reversing labels. + + // to avoid copy by reference - deep copy + const traces_original = JSON.parse(JSON.stringify(traces)); + + function mergeUnique(arr1, arr2){ + return arr1.concat(arr2.filter(function (item) { + return arr1.indexOf(item) === -1; + })); + } + + // check if any labels too long, if yes then find them + var labels = []; + traces.forEach(function(entry) { + labels = mergeUnique(labels, entry["x"][type]); + }); + console.log(labels); + // get subset of labels that are above pref_length + // these need to be manipulated appropriately + // we use this subset to have more chance of + // obtaining a common prefix/suffix + var labels_long = labels.filter(function(label) { + return label.length > pref_length; + }); + console.log(labels_long); + if (labels_long.length === 0) { + return traces; + } + + // find common prefix for long labels + function findPrefix(strings) { + console.log(strings) + if(!strings.length) { + return null; + } + var sorted = strings.slice(0).sort(), // copy the array before sorting! + string1 = sorted[0], + string2 = sorted[sorted.length-1], + i = 0, + l = Math.min(string1.length, string2.length); + + while(i < l && string1[i] === string2[i]) { + i++; + } + return string1.slice(0, i); + } + + var common_prefix = findPrefix(labels_long); + console.log("common_prefix = ", common_prefix); + + if (common_prefix) { + // update the original traces object wherever required + traces.forEach(function(item1, ind1) { + var trace_item = item1; + var labels_final = trace_item["x"][type].map(function(item2) { + if (item2.length > pref_length) { + if (item2.startsWith(common_prefix)) { + return item2.slice(common_prefix.length) + } else { + return item2; + } + } else { + return item2; + } + }); + console.log(labels_final); + this[ind1]["x"][type] = labels_final; + }, traces); + } + + // check if any labels too long (after removing prefix) + // if yes then find them + labels = []; + traces.forEach(function(entry) { + labels = mergeUnique(labels, entry["x"][type]); + }); + console.log(labels); + labels_long = labels.filter(function(label) { + return label.length > pref_length; + }); + console.log(labels_long); + if (labels_long.length === 0) { + return traces; + } + + // else, try to remove suffix + function reverse(string){ + return string.split('').reverse().join(''); + } + + function findSuffix(strings){ + if(!strings || strings.length === 0){ + console.log("NULL") + return null; + } + return reverse(findPrefix(strings.map(reverse))); + } + + var common_suffix = findSuffix(labels_long); + console.log("common_suffix = ", common_suffix); + + if (common_suffix) { + // update the original traces object wherever required + traces.forEach(function(item1, ind1) { + var trace_item = item1; + var labels_final = trace_item["x"][type].map(function(item2) { + if (item2.length > pref_length) { + if (item2.endsWith(common_suffix)) { + return item2.slice(0, -common_suffix.length) + } else { + return item2; + } + } else { + return item2; + } + }); + console.log(labels_final); + this[ind1]["x"][type] = labels_final; + }, traces); + } + + // check if any labels too long (after removing prefix and suffix) + // if yes then find them + labels = []; + traces.forEach(function(entry) { + labels = mergeUnique(labels, entry["x"][type]); + }); + console.log(labels); + labels_long = labels.filter(function(label) { + return label.length > pref_length; + }); + console.log(labels_long); + if (labels_long.length === 0) { + return traces; + } + + // else try to create an acronym from labels + console.log(traces_original); + var traces_acronym = traces_original; + traces_acronym.forEach(function(item1, ind1) { + var trace_item = item1; + var labels_final = trace_item["x"][type].map(function(item2) { + if (item2.length > pref_length) { + return item2.split(/[\s-_]+/).reduce((response,word)=> response+=word.slice(0,1),'') + } else { + return item2; + } + }); + console.log(labels_final); + this[ind1]["x"][type] = labels_final; + }, traces_acronym); + + // acronym labels are fine only if all are distinct + var labels_count_before = labels.length; + labels = []; + traces.forEach(function(entry) { + labels = mergeUnique(labels, entry["x"][type]); + }); + var labels_count_after = labels.length; + + if (labels_count_before === labels_count_after) { + console.log("Acronyms OK"); + return traces_acronym; + } else { + console.log("Acronyms not OK"); + return traces; + } +} + +function ResultsFiguresSummaryXaxisModels(props) { console.log(props.dict_results); let dict_results = props.dict_results; @@ -36,7 +232,6 @@ function ResultsFiguresSummary_XaxisModels(props) { var traces = []; var layout = {}; var label_resultJSON_map = {}; - var customdata = []; // a separate trace for each test instance for (let test_id in dict_results) { @@ -44,21 +239,22 @@ function ResultsFiguresSummary_XaxisModels(props) { // a seperate bar group for each model (all instances of same model within the same bar group) var model_labels = []; var model_version_labels = []; - var model_version_result_ids = []; var model_version_scores = []; var customdata = []; for (let model_id in dict_results[test_id]["test_instances"][test_inst_id]["models"]) { for (let model_inst_id in dict_results[test_id]["test_instances"][test_inst_id]["models"][model_id]["model_instances"]) { // since we have ordered the results from newest to oldest in `groupResults_XaxisModels()`, we simply take the very first result as latest let result_entry = dict_results[test_id]["test_instances"][test_inst_id]["models"][model_id]["model_instances"][model_inst_id]["results"][0] - model_labels.push(dict_results[test_id]["test_instances"][test_inst_id]["models"][model_id]["model_name"]); + model_labels.push(dict_results[test_id]["test_instances"][test_inst_id]["models"][model_id]["model_alias"] ? dict_results[test_id]["test_instances"][test_inst_id]["models"][model_id]["model_alias"] : dict_results[test_id]["test_instances"][test_inst_id]["models"][model_id]["model_name"]); model_version_labels.push(dict_results[test_id]["test_instances"][test_inst_id]["models"][model_id]["model_instances"][model_inst_id]["model_version"]); // customdata is used for setting hover description - customdata.push([dict_results[test_id]["test_instances"][test_inst_id]["models"][model_id]["model_name"], - dict_results[test_id]["test_instances"][test_inst_id]["models"][model_id]["model_instances"][model_inst_id]["model_version"], - dict_results[test_id]["test_name"], - dict_results[test_id]["test_instances"][test_inst_id]["test_version"]]) - model_version_result_ids.push(result_entry["result_id"]); + customdata.push([ + dict_results[test_id]["test_instances"][test_inst_id]["models"][model_id]["model_name"], + dict_results[test_id]["test_instances"][test_inst_id]["models"][model_id]["model_instances"][model_inst_id]["model_version"], + dict_results[test_id]["test_name"], + dict_results[test_id]["test_instances"][test_inst_id]["test_version"], + result_entry["result_id"] + ]) model_version_scores.push(result_entry.score); label_resultJSON_map[result_entry["result_id"]] = result_entry.result_json; } @@ -66,32 +262,18 @@ function ResultsFiguresSummary_XaxisModels(props) { traces.push( { x: [ - model_labels.map(function (item) { - if (item.length <= 35) { - return item - } else { - return item.substr(0, 17) + "..." + item.substr(item.length - 15, item.length) - } - }), - model_version_labels.map(function (item) { - if (item.length <= 15) { - return item - } else { - return item.substr(0, 7) + "..." + item.substr(item.length - 5, item.length) - } - }) + model_labels, + model_version_labels ], y: model_version_scores, // text:model_labels, - // Note: hovertext is only being used hold a unique identifier for onClick() - hovertext: model_version_result_ids, // customdata is used for setting hover description customdata: customdata, - hovertemplate: 'Model: %{customdata[0]}
' + - 'Model Version: %{customdata[1]}
' + - 'Test: %{customdata[2]}
' + - 'Test Version: %{customdata[3]}
' + - 'Score: %{y}', + hovertemplate: 'Model: %{customdata[0]}
' + + 'Model Version: %{customdata[1]}
' + + 'Test: %{customdata[2]}
' + + 'Test Version: %{customdata[3]}
' + + 'Score: %{y}', name: dict_results[test_id]["test_name"] + " (" + dict_results[test_id]["test_instances"][test_inst_id]["test_version"] + ")", type: 'bar', // marker: { size: 16, color: Theme.plotBarColor } @@ -128,11 +310,14 @@ function ResultsFiguresSummary_XaxisModels(props) { }; console.log(traces); + traces = shortenLabels(traces); + console.log(traces); + return ( props.handleResultEntryClick(label_resultJSON_map[data["points"][0]["hovertext"]])} + onClick={(data) => props.handleResultEntryClick(label_resultJSON_map[data["points"][0]["customdata"][4]])} config={{ displaylogo: false, }} @@ -140,7 +325,7 @@ function ResultsFiguresSummary_XaxisModels(props) { ) } -function ResultsFiguresSummary_XaxisTests(props) { +function ResultsFiguresSummaryXaxisTests(props) { console.log(props.dict_results); let dict_results = props.dict_results; @@ -148,7 +333,6 @@ function ResultsFiguresSummary_XaxisTests(props) { var traces = []; var layout = {}; var label_resultJSON_map = {}; - var customdata = []; // a separate trace for each model instance for (let model_id in dict_results) { @@ -156,21 +340,22 @@ function ResultsFiguresSummary_XaxisTests(props) { // a seperate bar group for each test (all instances of same test within the same bar group) var test_labels = []; var test_version_labels = []; - var test_version_result_ids = []; var test_version_scores = []; var customdata = []; for (let test_id in dict_results[model_id]["model_instances"][model_inst_id]["tests"]) { for (let test_inst_id in dict_results[model_id]["model_instances"][model_inst_id]["tests"][test_id]["test_instances"]) { // since we have ordered the results from newest to oldest in `groupResults_XaxisTests()`, we simply take the very first result as latest let result_entry = dict_results[model_id]["model_instances"][model_inst_id]["tests"][test_id]["test_instances"][test_inst_id]["results"][0] - test_labels.push(dict_results[model_id]["model_instances"][model_inst_id]["tests"][test_id]["test_name"]); + test_labels.push(dict_results[model_id]["model_instances"][model_inst_id]["tests"][test_id]["test_alias"] ? dict_results[model_id]["model_instances"][model_inst_id]["tests"][test_id]["test_alias"] : dict_results[model_id]["model_instances"][model_inst_id]["tests"][test_id]["test_name"]); test_version_labels.push(dict_results[model_id]["model_instances"][model_inst_id]["tests"][test_id]["test_instances"][test_inst_id]["test_version"]); // customdata is used for setting hover description - customdata.push([dict_results[model_id]["model_instances"][model_inst_id]["tests"][test_id]["test_name"], - dict_results[model_id]["model_instances"][model_inst_id]["tests"][test_id]["test_instances"][test_inst_id]["test_version"], - dict_results[model_id]["model_name"], - dict_results[model_id]["model_instances"][model_inst_id]["model_version"]]) - test_version_result_ids.push(result_entry["result_id"]); + customdata.push([ + dict_results[model_id]["model_instances"][model_inst_id]["tests"][test_id]["test_name"], + dict_results[model_id]["model_instances"][model_inst_id]["tests"][test_id]["test_instances"][test_inst_id]["test_version"], + dict_results[model_id]["model_name"], + dict_results[model_id]["model_instances"][model_inst_id]["model_version"], + result_entry["result_id"] + ]) test_version_scores.push(result_entry.score); label_resultJSON_map[result_entry["result_id"]] = result_entry.result_json; } @@ -178,32 +363,18 @@ function ResultsFiguresSummary_XaxisTests(props) { traces.push( { x: [ - test_labels.map(function (item) { - if (item.length <= 35) { - return item - } else { - return item.substr(0, 17) + "..." + item.substr(item.length - 15, item.length) - } - }), - test_version_labels.map(function (item) { - if (item.length <= 15) { - return item - } else { - return item.substr(0, 7) + "..." + item.substr(item.length - 5, item.length) - } - }) + test_labels, + test_version_labels ], y: test_version_scores, // text:test_labels, - // Note: hovertext is only being used hold a unique identifier for onClick() - hovertext: test_version_result_ids, // customdata is used for setting hover description customdata: customdata, - hovertemplate: 'Model: %{customdata[2]}
' + - 'Model Version: %{customdata[3]}
' + - 'Test: %{customdata[0]}
' + - 'Test Version: %{customdata[1]}
' + - 'Score: %{y}', + hovertemplate: 'Model: %{customdata[2]}
' + + 'Model Version: %{customdata[3]}
' + + 'Test: %{customdata[0]}
' + + 'Test Version: %{customdata[1]}
' + + 'Score: %{y}', name: dict_results[model_id]["model_name"] + " (" + dict_results[model_id]["model_instances"][model_inst_id]["model_version"] + ")", type: 'bar', // marker: { size: 16, color: Theme.plotBarColor } @@ -226,7 +397,8 @@ function ResultsFiguresSummary_XaxisTests(props) { // width: 640, // height: 480, // title: 'Plot Title', - xaxis: {//tickvals: ["1", "2", "3", "4", "5"], + xaxis: { + //tickvals: ["1", "2", "3", "4", "5"], //ticktext : ["a", "b", "c", "d" ,"e"], title: "Test Instance", automargin: true, @@ -239,11 +411,14 @@ function ResultsFiguresSummary_XaxisTests(props) { }; console.log(traces); + traces = shortenLabels(traces); + console.log(traces); + return ( props.handleResultEntryClick(label_resultJSON_map[data["points"][0]["hovertext"]])} + onClick={(data) => props.handleResultEntryClick(label_resultJSON_map[data["points"][0]["customdata"][4]])} config={{ displaylogo: false, }} @@ -639,12 +814,12 @@ export default class CompareMultiGraphs extends React.Component { { this.state.summary_xaxis_models ? - : - diff --git a/apps/validation_framework_v2/src/CompareMultiResults.js b/apps/validation_framework_v2/src/CompareMultiResults.js index f74287580..1a46b58bf 100644 --- a/apps/validation_framework_v2/src/CompareMultiResults.js +++ b/apps/validation_framework_v2/src/CompareMultiResults.js @@ -317,42 +317,6 @@ class CompareMultiResults extends React.Component { this.state = { model_dict: context.compareModels[0], test_dict: context.compareTests[0], - // model_dict: { - // "01da73a6-8715-431b-aaa7-efcd9358c786": { - // "name": "CA1_pyr_cACpyr_mpg141208_B_idA_20190328144006", - // "alias": null, - // "selected_instances": { - // "d6340679-9534-40ef-bd35-651be3ce0609": { "version": "1.0", "timestamp": "2019-06-18T15:15:18.595899+00:00" }, - // "5a9cd261-6018-48e0-a803-74dca89e88c6": { "version": "2.0", "timestamp": "2020-02-19T10:44:48.820740+00:00" } - // } - // }, - // "03e67e24-6df5-405a-8299-7d797ecee58b": { - // "name": "CA1_pyr_cACpyr_mpg150305_A_idB_20190305112012", - // "alias": null, - // "selected_instances": { - // "a21af2da-dedd-4f94-afe9-7564f76368b4": { "version": "1.0", "timestamp": "2019-06-18T15:15:28.260093+00:00" }, - // "cadba67c-06b2-4819-8f4d-43bcb501d7b8": { "version": "2.0", "timestamp": "2020-02-19T10:45:21.300875+00:00" } - // } - // } - // }, - // test_dict: { - // "dd0842c0-c016-42be-98a6-18d32c2e9a3b": { - // "name": "Hippocampus_CA1_PSPAttenuationTest", - // "alias": "hippo_ca1_psp_attenuation", - // "selected_instances": { - // "d20c56a6-b9ff-4fe5-a687-1a9e1a2c0489": { "version": "1.0", "timestamp": "2018-03-08T15:51:44.177419+00:00" }, - // "621d76cb-8591-4c8d-adff-c913899a6420": { "version": "1.3.5", "timestamp": "2020-05-29T13:07:58.738175+00:00" } - // } - // }, - // "100abccb-6d30-4c1e-a960-bc0489e0d82d": { - // "name": "Hippocampus_SomaticFeaturesTest_CA1_pyr_cACpyr", - // "alias": "hippo_somafeat_CA1_pyr_cACpyr", - // "selected_instances": { - // "1d22e1c0-5a74-49b4-b114-41d233d3250a": { "version": "1.0", "timestamp": "2019-03-28T12:54:19.318444+00:00" }, - // "b645536f-fd2c-4a84-9e3e-9372018fbe5d": { "version": "1.3.5", "timestamp": "2020-05-29T13:07:38.909226+00:00" } - // } - // } - // }, model_inst_ids: [], test_inst_ids: [], results: [], @@ -662,7 +626,7 @@ class CompareMultiResults extends React.Component { let test_dict = this.state.test_dict; // loop every model - Object.keys(model_dict).map(function (m_key, index) { + Object.keys(model_dict).forEach(function (m_key, index) { // console.log(m_key); // check if model exists in results if (!(m_key in results_grouped)) { @@ -674,7 +638,7 @@ class CompareMultiResults extends React.Component { }; } // loop every model instance - Object.keys(model_dict[m_key].selected_instances).map(function (m_inst_key, index) { + Object.keys(model_dict[m_key].selected_instances).forEach(function (m_inst_key, index) { // console.log(m_inst_key); // check if model instance exists for this model in results if (!(m_inst_key in results_grouped[m_key]["model_instances"])) { @@ -686,7 +650,7 @@ class CompareMultiResults extends React.Component { }; } // loop every test - Object.keys(test_dict).map(function (t_key, index) { + Object.keys(test_dict).forEach(function (t_key, index) { // console.log(t_key); // check if test exists in results for this model instance if (!(t_key in results_grouped[m_key]["model_instances"][m_inst_key]["tests"])) { @@ -698,7 +662,7 @@ class CompareMultiResults extends React.Component { }; } // loop every test instance - Object.keys(test_dict[t_key].selected_instances).map(function (t_inst_key, index) { + Object.keys(test_dict[t_key].selected_instances).forEach(function (t_inst_key, index) { // console.log(t_inst_key); // check if test instance exists for this test in results if (!(t_inst_key in results_grouped[m_key]["model_instances"][m_inst_key]["tests"][t_key]["test_instances"])) { @@ -1142,10 +1106,23 @@ class CompareMultiResults extends React.Component { launchCompare() { let results = this.state.results; let required_results = []; - + console.log(this.state.compareShow); + console.log(results); if (this.state.compareShow === "common_models") { + let test_inst_ids = []; + if (this.state.test_inst_ids.length === 0) { + results.forEach(function(item) { + if (test_inst_ids.indexOf(item.test_instance_id) === -1) { + test_inst_ids.push(item.test_instance_id); + } + }); + } else { + test_inst_ids = this.state.test_inst_ids; + } + console.log(test_inst_ids) // filter to get test instances that exist in results for every model instance - for (let t_inst_key of this.state.test_inst_ids) { + for (let t_inst_key of test_inst_ids) { + console.log(t_inst_key); let t_inst_results = []; let t_inst_for_m_inst = []; results.forEach(function (result) { @@ -1163,8 +1140,19 @@ class CompareMultiResults extends React.Component { } } } else if (this.state.compareShow === "common_tests") { + let model_inst_ids = []; + if (this.state.model_inst_ids.length === 0) { + results.forEach(function(item) { + if (model_inst_ids.indexOf(item.model_instance_id) === -1) { + model_inst_ids.push(item.model_instance_id); + } + }); + } else { + model_inst_ids = this.state.model_inst_ids; + } + console.log(model_inst_ids) // filter to get model instances that exist in results for every test instance - for (let m_inst_key of this.state.model_inst_ids) { + for (let m_inst_key of model_inst_ids) { console.log(m_inst_key); let m_inst_results = []; let m_inst_for_t_inst = []; @@ -1339,8 +1327,8 @@ class CompareMultiResults extends React.Component { let model_dict = this.state.model_dict; let results = this.state.results; - Object.keys(model_dict).map(function (m_key) { - Object.keys(model_dict[m_key].selected_instances).map(function (m_inst_key) { + Object.keys(model_dict).forEach(function (m_key) { + Object.keys(model_dict[m_key].selected_instances).forEach(function (m_inst_key) { delete model_dict[m_key].selected_instances[m_inst_key] results = results.filter(function (result) { return result.model_instance.id !== m_inst_key; }); }) @@ -1349,7 +1337,9 @@ class CompareMultiResults extends React.Component { this.setState({ model_dict: model_dict, - results: results + results: results, + compareShow: false, + loadingResults: false }) this.evalModelDict().then(() => { if (Object.keys(model_dict).length === 0) { @@ -1362,8 +1352,8 @@ class CompareMultiResults extends React.Component { let test_dict = this.state.test_dict; let results = this.state.results; - Object.keys(test_dict).map(function (t_key) { - Object.keys(test_dict[t_key].selected_instances).map(function (t_inst_key) { + Object.keys(test_dict).forEach(function (t_key) { + Object.keys(test_dict[t_key].selected_instances).forEach(function (t_inst_key) { delete test_dict[t_key].selected_instances[t_inst_key] results = results.filter(function (result) { return result.test_instance.id !== t_inst_key; }); }) @@ -1372,7 +1362,9 @@ class CompareMultiResults extends React.Component { this.setState({ test_dict: test_dict, - results: results + results: results, + compareShow: false, + loadingResults: false }) this.evalTestDict().then(() => { if (Object.keys(test_dict).length === 0) { diff --git a/apps/validation_framework_v2/src/MUIDataTableCustomToolbar.js b/apps/validation_framework_v2/src/MUIDataTableCustomToolbar.js index 3672758f4..3a78fb8ce 100644 --- a/apps/validation_framework_v2/src/MUIDataTableCustomToolbar.js +++ b/apps/validation_framework_v2/src/MUIDataTableCustomToolbar.js @@ -3,7 +3,6 @@ import IconButton from "@material-ui/core/IconButton"; import Tooltip from "@material-ui/core/Tooltip"; import FlipIcon from "@material-ui/icons/Flip"; import AddIcon from '@material-ui/icons/Add'; -import AccountTreeIcon from '@material-ui/icons/AccountTree'; import { withStyles } from "@material-ui/core/styles"; const defaultToolbarStyles = { diff --git a/apps/validation_framework_v2/src/ModelDetail.js b/apps/validation_framework_v2/src/ModelDetail.js index 7bdbcb55f..ad4f859c1 100644 --- a/apps/validation_framework_v2/src/ModelDetail.js +++ b/apps/validation_framework_v2/src/ModelDetail.js @@ -184,7 +184,7 @@ class ModelDetail extends React.Component { console.log(compareModels); setCompareModels(compareModels); this.setState({ compareFlag: true }) - showNotification(this.props.enqueueSnackbar, "Model added to compare!", "info") + showNotification(this.props.enqueueSnackbar, this.props.closeSnackbar, "Model added to compare!", "info") } removeModelCompare() { @@ -199,7 +199,7 @@ class ModelDetail extends React.Component { console.log(compareModels); setCompareModels(compareModels); this.setState({ compareFlag: false }) - showNotification(this.props.enqueueSnackbar, "Model removed from compare!", "info") + showNotification(this.props.enqueueSnackbar, this.props.closeSnackbar, "Model removed from compare!", "info") } addModelInstanceCompare(model_inst_id) { @@ -228,7 +228,7 @@ class ModelDetail extends React.Component { this.setState({ compareFlag: this.checkCompareStatus() }) console.log(compareModels); setCompareModels(compareModels); - showNotification(this.props.enqueueSnackbar, "Model instance added to compare!", "info") + showNotification(this.props.enqueueSnackbar, this.props.closeSnackbar, "Model instance added to compare!", "info") } removeModelInstanceCompare(model_inst_id) { @@ -249,7 +249,7 @@ class ModelDetail extends React.Component { console.log(compareModels); setCompareModels(compareModels); this.forceUpdate(); - showNotification(this.props.enqueueSnackbar, "Model instance removed from compare!", "info") + showNotification(this.props.enqueueSnackbar, this.props.closeSnackbar, "Model instance removed from compare!", "info") } handleClose() { @@ -297,7 +297,7 @@ class ModelDetail extends React.Component { axios.get(url, config) .then(res => { res.data.forEach(proj => { - if (((proj.project_id == model.project_id) || proj.project_id == ADMIN_PROJECT_ID) && (proj.permissions.UPDATE)) { + if (((proj.project_id === model.project_id) || proj.project_id === ADMIN_PROJECT_ID) && (proj.permissions.UPDATE)) { this.setState({ canEdit: true }); diff --git a/apps/validation_framework_v2/src/ModelDetailContent.js b/apps/validation_framework_v2/src/ModelDetailContent.js index b97844b03..a85d37661 100644 --- a/apps/validation_framework_v2/src/ModelDetailContent.js +++ b/apps/validation_framework_v2/src/ModelDetailContent.js @@ -43,7 +43,7 @@ function InstanceParameter(props) { - copyToClipboard(props.value, props.enqueueSnackbar, props.label + " copied")}>{props.value} + copyToClipboard(props.value, props.enqueueSnackbar, props.closeSnackbar, props.label + " copied")}>{props.value} @@ -63,7 +63,7 @@ function InstanceParameter(props) { - copyToClipboard(props.value, props.enqueueSnackbar, props.label + " copied")}>{props.value} + copyToClipboard(props.value, props.enqueueSnackbar, props.closeSnackbar, props.label + " copied")}>{props.value} @@ -80,7 +80,7 @@ function InstanceParameter(props) { {props.label}: - copyToClipboard(props.value, props.enqueueSnackbar, props.label + " copied")}>{props.value} + copyToClipboard(props.value, props.enqueueSnackbar, props.closeSnackbar, props.label + " copied")}>{props.value} ) @@ -168,7 +168,7 @@ class ModelDetailContent extends React.Component { this.setState({ instances: instances, }); - showNotification(this.props.enqueueSnackbar, "Model instance added!", "success") + showNotification(this.props.enqueueSnackbar, this.props.closeSnackbar, "Model instance added!", "success") } } @@ -181,7 +181,7 @@ class ModelDetailContent extends React.Component { this.setState({ instances: instances.map(obj => [modelInstance].find(o => o.id === obj.id) || obj) }); - showNotification(this.props.enqueueSnackbar, "Model instance edited!", "success") + showNotification(this.props.enqueueSnackbar, this.props.closeSnackbar, "Model instance edited!", "success") } } @@ -279,7 +279,7 @@ class ModelDetailContent extends React.Component { -

Version: copyToClipboard(instance.version, this.props.enqueueSnackbar, "Model version copied")}>{instance.version}

+

Version: copyToClipboard(instance.version, this.props.enqueueSnackbar, this.props.closeSnackbar, "Model version copied")}>{instance.version}

{ this.state.instancesWithResults && this.props.canEdit && @@ -299,18 +299,18 @@ class ModelDetailContent extends React.Component {
- ID: copyToClipboard(instance.id, this.props.enqueueSnackbar, "Model instance UUID copied")}>{instance.id} + ID: copyToClipboard(instance.id, this.props.enqueueSnackbar, this.props.closeSnackbar, "Model instance UUID copied")}>{instance.id}
{formatTimeStampToLongString(instance.timestamp)} - - - - - - + + + + + +
))} diff --git a/apps/validation_framework_v2/src/ModelDetailHeader.js b/apps/validation_framework_v2/src/ModelDetailHeader.js index 78314bbbe..2105b081c 100644 --- a/apps/validation_framework_v2/src/ModelDetailHeader.js +++ b/apps/validation_framework_v2/src/ModelDetailHeader.js @@ -100,7 +100,7 @@ class ModelDetailHeader extends React.Component { this.setState({ 'openEditForm': false }); if (model) { this.props.updateCurrentModelData(model) - showNotification(this.props.enqueueSnackbar, "Model edited!", "success") + showNotification(this.props.enqueueSnackbar, this.props.closeSnackbar, "Model edited!", "success") } } @@ -130,7 +130,7 @@ class ModelDetailHeader extends React.Component { - copyToClipboard(this.props.name, this.props.enqueueSnackbar, "Model name copied")}> {this.props.name} + copyToClipboard(this.props.name, this.props.enqueueSnackbar, this.props.closeSnackbar, "Model name copied")}> {this.props.name} @@ -138,9 +138,9 @@ class ModelDetailHeader extends React.Component { {this.props.authors} - ID: copyToClipboard(this.props.id, this.props.enqueueSnackbar, "Model UUID copied")}>{this.props.id} + ID: copyToClipboard(this.props.id, this.props.enqueueSnackbar, this.props.closeSnackbar, "Model UUID copied")}>{this.props.id}        - {this.props.alias ? "Alias: " : ""} {this.props.alias ? copyToClipboard(this.props.alias, this.props.enqueueSnackbar, "Model alias copied")}>{this.props.alias} : ""} + {this.props.alias ? "Alias: " : ""} {this.props.alias ? copyToClipboard(this.props.alias, this.props.enqueueSnackbar, this.props.closeSnackbar, "Model alias copied")}>{this.props.alias} : ""} Created: {formatTimeStampToLongString(this.props.dateCreated)} diff --git a/apps/validation_framework_v2/src/ModelEditForm.js b/apps/validation_framework_v2/src/ModelEditForm.js index 414ce2ab4..a5e777bf1 100644 --- a/apps/validation_framework_v2/src/ModelEditForm.js +++ b/apps/validation_framework_v2/src/ModelEditForm.js @@ -371,7 +371,7 @@ export default class ModelEditForm extends React.Component { Cancel diff --git a/apps/validation_framework_v2/src/ModelInstanceEditForm.js b/apps/validation_framework_v2/src/ModelInstanceEditForm.js index 7a669916b..5a0e47da7 100644 --- a/apps/validation_framework_v2/src/ModelInstanceEditForm.js +++ b/apps/validation_framework_v2/src/ModelInstanceEditForm.js @@ -220,7 +220,7 @@ export default class ModelInstanceEditForm extends React.Component { Cancel diff --git a/apps/validation_framework_v2/src/ModelTable.js b/apps/validation_framework_v2/src/ModelTable.js index 61aa1dfcd..2b866c86c 100644 --- a/apps/validation_framework_v2/src/ModelTable.js +++ b/apps/validation_framework_v2/src/ModelTable.js @@ -89,7 +89,7 @@ class ModelTable extends React.Component { selectedModels.push(ordered_data) } downloadJSON(JSON.stringify(selectedModels), "selectedModels.json") - showNotification(this.props.enqueueSnackbar, "Saved to selectedModels.json", "info") + showNotification(this.props.enqueueSnackbar, this.props.closeSnackbar, "Saved to selectedModels.json", "info") } hideTableRows(selectedRows) { @@ -100,7 +100,7 @@ class ModelTable extends React.Component { } const updated_data = this.state.data.filter((item, index) => !selectedIndices.includes(index)); this.setState({ data: updated_data }); - showNotification(this.props.enqueueSnackbar, "Chosen model(s) have been hidden!", "info") + showNotification(this.props.enqueueSnackbar, this.props.closeSnackbar, "Chosen model(s) have been hidden!", "info") } viewSelectedItems(selectedRows) { @@ -155,9 +155,9 @@ class ModelTable extends React.Component { } } } - showNotification(this.props.enqueueSnackbar, "Model '" + model.name + "' added to compare!", "info") + showNotification(this.props.enqueueSnackbar, this.props.closeSnackbar, "Model '" + model.name + "' added to compare!", "info") } else { - showNotification(this.props.enqueueSnackbar, "Skipped: model '" + model.name + "' (0 instances)!", "error") + showNotification(this.props.enqueueSnackbar, this.props.closeSnackbar, "Skipped: model '" + model.name + "' (0 instances)!", "error") } } console.log(compareModels); diff --git a/apps/validation_framework_v2/src/ResultDetailContent.js b/apps/validation_framework_v2/src/ResultDetailContent.js index fc9a6cdd4..45dbcdecd 100644 --- a/apps/validation_framework_v2/src/ResultDetailContent.js +++ b/apps/validation_framework_v2/src/ResultDetailContent.js @@ -23,7 +23,7 @@ function ResultParameter(props) { return ( {props.label}: - copyToClipboard(props.value, props.enqueueSnackbar, props.label + " copied")} width="75%">{props.value} + copyToClipboard(props.value, props.enqueueSnackbar, props.closeSnackbar, props.label + " copied")} width="75%">{props.value} ) } else { @@ -51,12 +51,12 @@ class ResultDetailContent extends React.Component { */} - - - - - - + + + + + +
diff --git a/apps/validation_framework_v2/src/ResultDetailHeader.js b/apps/validation_framework_v2/src/ResultDetailHeader.js index c5b3b72dc..a887e5970 100644 --- a/apps/validation_framework_v2/src/ResultDetailHeader.js +++ b/apps/validation_framework_v2/src/ResultDetailHeader.js @@ -12,7 +12,7 @@ class ResultDetailHeader extends React.Component { - Validation Result ID: copyToClipboard(this.props.id, this.props.enqueueSnackbar, "Result UUID copied")}> {this.props.id} + Validation Result ID: copyToClipboard(this.props.id, this.props.enqueueSnackbar, this.props.closeSnackbar, "Result UUID copied")}> {this.props.id} Timestamp: {formatTimeStampToLongString(this.props.timestamp)} @@ -26,35 +26,35 @@ class ResultDetailHeader extends React.Component { Validated Model: - copyToClipboard(this.props.modelName, this.props.enqueueSnackbar, "Model name copied")}> {this.props.modelName} + copyToClipboard(this.props.modelName, this.props.enqueueSnackbar, this.props.closeSnackbar, "Model name copied")}> {this.props.modelName} - Alias: copyToClipboard(this.props.modelAlias, this.props.enqueueSnackbar, "Model alias copied")}> {this.props.modelAlias} + Alias: copyToClipboard(this.props.modelAlias, this.props.enqueueSnackbar, this.props.closeSnackbar, "Model alias copied")}> {this.props.modelAlias}     - Version: copyToClipboard(this.props.modelVersion, this.props.enqueueSnackbar, "Model version copied")}> {this.props.modelVersion} + Version: copyToClipboard(this.props.modelVersion, this.props.enqueueSnackbar, this.props.closeSnackbar, "Model version copied")}> {this.props.modelVersion} - Model ID: copyToClipboard(this.props.modelID, this.props.enqueueSnackbar, "Model UUID copied")}> {this.props.modelID} + Model ID: copyToClipboard(this.props.modelID, this.props.enqueueSnackbar, this.props.closeSnackbar, "Model UUID copied")}> {this.props.modelID} - Instance ID: copyToClipboard(this.props.modelInstID, this.props.enqueueSnackbar, "Model instance UUID copied")}> {this.props.modelInstID} + Instance ID: copyToClipboard(this.props.modelInstID, this.props.enqueueSnackbar, this.props.closeSnackbar, "Model instance UUID copied")}> {this.props.modelInstID} Validation Test: - copyToClipboard(this.props.testName, this.props.enqueueSnackbar, "Test name copied")}> {this.props.testName} + copyToClipboard(this.props.testName, this.props.enqueueSnackbar, this.props.closeSnackbar, "Test name copied")}> {this.props.testName} - Alias: copyToClipboard(this.props.testAlias, this.props.enqueueSnackbar, "Test alias copied")}> {this.props.testAlias} + Alias: copyToClipboard(this.props.testAlias, this.props.enqueueSnackbar, this.props.closeSnackbar, "Test alias copied")}> {this.props.testAlias}     - Version: copyToClipboard(this.props.testVersion, this.props.enqueueSnackbar, "Test version copied")}> {this.props.testVersion} + Version: copyToClipboard(this.props.testVersion, this.props.enqueueSnackbar, this.props.closeSnackbar, "Test version copied")}> {this.props.testVersion} - Test ID: copyToClipboard(this.props.testID, this.props.enqueueSnackbar, "Test UUID copied")}> {this.props.testID} + Test ID: copyToClipboard(this.props.testID, this.props.enqueueSnackbar, this.props.closeSnackbar, "Test UUID copied")}> {this.props.testID} - Instance ID: copyToClipboard(this.props.testInstID, this.props.enqueueSnackbar, "Test instance UUID copied")}> {this.props.testInstID} + Instance ID: copyToClipboard(this.props.testInstID, this.props.enqueueSnackbar, this.props.closeSnackbar, "Test instance UUID copied")}> {this.props.testInstID} diff --git a/apps/validation_framework_v2/src/ResultGraphs.js b/apps/validation_framework_v2/src/ResultGraphs.js index d4e301ad0..8b2bc8a7b 100644 --- a/apps/validation_framework_v2/src/ResultGraphs.js +++ b/apps/validation_framework_v2/src/ResultGraphs.js @@ -26,15 +26,14 @@ function ResultsFiguresTestIntance(props) { var traces = []; var layout = {}; var label_resultJSON_map = {}; - var customdata = []; for (let model_entry of Object.values(props.test_inst_entry["models"])) { // a seperate bar group for each model (all instances of same model within the same bar group) - var model_labels = []; - var model_version_labels = []; - var model_version_result_ids = []; - var model_version_scores = []; - var customdata = []; + let model_labels = []; + let model_version_labels = []; + let model_version_result_ids = []; + let model_version_scores = []; + let customdata = []; for (let model_inst_entry of Object.values(model_entry["model_instances"])) { model_inst_entry["results"].forEach(function (result_entry, r_ind) { diff --git a/apps/validation_framework_v2/src/ResultModelTestInfo.js b/apps/validation_framework_v2/src/ResultModelTestInfo.js index 8dbc8725d..93de1331d 100644 --- a/apps/validation_framework_v2/src/ResultModelTestInfo.js +++ b/apps/validation_framework_v2/src/ResultModelTestInfo.js @@ -24,7 +24,7 @@ function CommonParameter(props) { return ( - copyToClipboard(m_value, props.enqueueSnackbar, "Model " + props.entity + formatLabel(props.label) + " copied")}> + copyToClipboard(m_value, props.enqueueSnackbar, props.closeSnackbar, "Model " + props.entity + formatLabel(props.label) + " copied")}> {m_value} @@ -32,7 +32,7 @@ function CommonParameter(props) { {formatLabel(props.label)} - copyToClipboard(t_value, props.enqueueSnackbar, "Test " + props.entity + formatLabel(props.label) + " copied")}> + copyToClipboard(t_value, props.enqueueSnackbar, props.closeSnackbar, "Test " + props.entity + formatLabel(props.label) + " copied")}> {t_value} @@ -48,7 +48,7 @@ function OtherParameter(props) { {formatLabel(props.label)}: - copyToClipboard(value, props.enqueueSnackbar, props.entity + " " + formatLabel(props.label) + " copied")}> + copyToClipboard(value, props.enqueueSnackbar, props.closeSnackbar, props.entity + " " + formatLabel(props.label) + " copied")}> {value} @@ -84,7 +84,7 @@ class ResultModelTestInfo extends React.Component { {["id", "uri", "name", "alias", "date_created", "species", "brain_region", "cell_type"].map((param) => ( - + ))} @@ -114,7 +114,7 @@ class ResultModelTestInfo extends React.Component { {["author", "owner", "project_id", "organization", "private", "model_scope", "abstraction_level"].map((param) => ( - + ))} @@ -130,7 +130,7 @@ class ResultModelTestInfo extends React.Component { {["author", "implementation_status", "data_location", "data_type", "recording_modality", "test_type", "score_type"].map((param) => ( - + ))} @@ -209,7 +209,7 @@ class ResultModelTestInfo extends React.Component { {["id", "uri", "version", "timestamp"].map((param) => ( - + ))} @@ -238,7 +238,7 @@ class ResultModelTestInfo extends React.Component { {["morphology", "source", "code_format", "parameters", "hash", "license"].map((param) => ( - + ))} @@ -254,7 +254,7 @@ class ResultModelTestInfo extends React.Component { {["repository", "path", "parameters"].map((param) => ( - + ))} diff --git a/apps/validation_framework_v2/src/ResultRelatedFiles.js b/apps/validation_framework_v2/src/ResultRelatedFiles.js index f31eb3ea1..d0f30a063 100644 --- a/apps/validation_framework_v2/src/ResultRelatedFiles.js +++ b/apps/validation_framework_v2/src/ResultRelatedFiles.js @@ -60,14 +60,16 @@ class ResultFile extends React.Component { config["headers"] = { 'Authorization': 'Bearer ' + this.state.auth.token, } - const url_parts = this.state.url.match('.*\/lib\/(.*)\/file(\/.*)'); + const url_parts = this.state.url.match('.*/lib/(.*)/file(/.*)'); query_url = "https://drive.ebrains.eu/api2/repos/" + url_parts[1] + "/file/detail/?p=" + url_parts[2]; } else { query_url = this.state.url } // Since Collaboratory v2 storage and CSCS storage gives CORS related issues, // we use an intermediate proxy server to resolve this - query_url = "https://cors-anywhere.herokuapp.com/" + query_url + // previously used https://cors-anywhere.herokuapp.com/ - but now has request limits + // other options: https://cors-fixer.herokuapp.com/, https://cors-handler.herokuapp.com/ + query_url = "https://cors-clear.herokuapp.com/" + query_url axios.head(query_url, config) .then(res => { @@ -127,7 +129,7 @@ class ResultFile extends React.Component { - copyToClipboard(this.state.url, this.props.enqueueSnackbar, "File URL copied")}>File URL: {this.state.url} + copyToClipboard(this.state.url, this.props.enqueueSnackbar, this.props.closeSnackbar, "File URL copied")}>File URL: {this.state.url}
{/* check to avoid loading file if not requested by clicking on the exapansion panel */} {/* If file is accessible (valid = true) */} @@ -185,7 +187,7 @@ class ResultRelatedFiles extends React.Component { */} {this.props.result_files.map((r_file, ind) => ( - + ))}
diff --git a/apps/validation_framework_v2/src/TestDetail.js b/apps/validation_framework_v2/src/TestDetail.js index 22e9684b0..6b8a5f375 100644 --- a/apps/validation_framework_v2/src/TestDetail.js +++ b/apps/validation_framework_v2/src/TestDetail.js @@ -178,7 +178,7 @@ class TestDetail extends React.Component { console.log(compareTests); setCompareTests(compareTests); this.setState({ compareFlag: true }) - showNotification(this.props.enqueueSnackbar, "Test added to compare!", "info") + showNotification(this.props.enqueueSnackbar, this.props.closeSnackbar, "Test added to compare!", "info") } removeTestCompare() { @@ -193,7 +193,7 @@ class TestDetail extends React.Component { console.log(compareTests); setCompareTests(compareTests); this.setState({ compareFlag: false }) - showNotification(this.props.enqueueSnackbar, "Test removed from compare!", "info") + showNotification(this.props.enqueueSnackbar, this.props.closeSnackbar, "Test removed from compare!", "info") } addTestInstanceCompare(test_inst_id) { @@ -222,7 +222,7 @@ class TestDetail extends React.Component { this.setState({ compareFlag: this.checkCompareStatus() }) console.log(compareTests); setCompareTests(compareTests); - showNotification(this.props.enqueueSnackbar, "Test instance added to compare!", "info") + showNotification(this.props.enqueueSnackbar, this.props.closeSnackbar, "Test instance added to compare!", "info") } removeTestInstanceCompare(test_inst_id) { @@ -243,7 +243,7 @@ class TestDetail extends React.Component { console.log(compareTests); setCompareTests(compareTests); this.forceUpdate(); - showNotification(this.props.enqueueSnackbar, "Test instance removed from compare!", "info") + showNotification(this.props.enqueueSnackbar, this.props.closeSnackbar, "Test instance removed from compare!", "info") } handleClose() { diff --git a/apps/validation_framework_v2/src/TestDetailContent.js b/apps/validation_framework_v2/src/TestDetailContent.js index 5e9264e4b..9d35629bb 100644 --- a/apps/validation_framework_v2/src/TestDetailContent.js +++ b/apps/validation_framework_v2/src/TestDetailContent.js @@ -22,7 +22,7 @@ function InstanceParameter(props) { {props.label}: - copyToClipboard(props.value, props.enqueueSnackbar, props.label + " copied")}>{props.value} + copyToClipboard(props.value, props.enqueueSnackbar, props.closeSnackbar, props.label + " copied")}>{props.value} ) @@ -93,7 +93,7 @@ class TestDetailContent extends React.Component { this.setState({ instances: instances, }); - showNotification(this.props.enqueueSnackbar, "Test instance added!", "success") + showNotification(this.props.enqueueSnackbar, this.props.closeSnackbar, "Test instance added!", "success") } } @@ -106,7 +106,7 @@ class TestDetailContent extends React.Component { this.setState({ instances: instances.map(obj => [testInstance].find(o => o.id === obj.id) || obj) }); - showNotification(this.props.enqueueSnackbar, "Test instance edited!", "success") + showNotification(this.props.enqueueSnackbar, this.props.closeSnackbar, "Test instance edited!", "success") } } @@ -170,7 +170,7 @@ class TestDetailContent extends React.Component { Data Location: {this.props.dataLocation.map((dataItem, index) => ( - copyToClipboard(dataItem, this.props.enqueueSnackbar, "Data location copied")} width="100%"> + copyToClipboard(dataItem, this.props.enqueueSnackbar, this.props.closeSnackbar, "Data location copied")} width="100%"> {dataItem} ))} @@ -202,7 +202,7 @@ class TestDetailContent extends React.Component { -

Version: copyToClipboard(instance.version, this.props.enqueueSnackbar, "Test version copied")}>{instance.version}

+

Version: copyToClipboard(instance.version, this.props.enqueueSnackbar, this.props.closeSnackbar, "Test version copied")}>{instance.version}

{ this.state.instancesWithResults && @@ -216,16 +216,16 @@ class TestDetailContent extends React.Component {
- ID: copyToClipboard(instance.id, this.props.enqueueSnackbar, "Test instance UUID copied")}>{instance.id} + ID: copyToClipboard(instance.id, this.props.enqueueSnackbar, this.props.closeSnackbar, "Test instance UUID copied")}>{instance.id}
{formatTimeStampToLongString(instance.timestamp)} - - - - + + + +
))} diff --git a/apps/validation_framework_v2/src/TestDetailHeader.js b/apps/validation_framework_v2/src/TestDetailHeader.js index 8433d118f..58d749bfe 100644 --- a/apps/validation_framework_v2/src/TestDetailHeader.js +++ b/apps/validation_framework_v2/src/TestDetailHeader.js @@ -66,7 +66,7 @@ class TestDetailHeader extends React.Component { this.setState({ 'openEditForm': false }); if (test) { this.props.updateCurrentTestData(test) - showNotification(this.props.enqueueSnackbar, "Test edited!", "success") + showNotification(this.props.enqueueSnackbar, this.props.closeSnackbar, "Test edited!", "success") } } @@ -95,7 +95,7 @@ class TestDetailHeader extends React.Component { - copyToClipboard(this.props.name, this.props.enqueueSnackbar, "Test name copied")}> {this.props.name} + copyToClipboard(this.props.name, this.props.enqueueSnackbar, this.props.closeSnackbar, "Test name copied")}> {this.props.name} this.handleEditClick()} style={{ backgroundColor: Theme.buttonSecondary, marginLeft: 10 }}> @@ -107,9 +107,9 @@ class TestDetailHeader extends React.Component { {this.props.authors} - ID: copyToClipboard(this.props.id, this.props.enqueueSnackbar, "Test UUID copied")}>{this.props.id} + ID: copyToClipboard(this.props.id, this.props.enqueueSnackbar, this.props.closeSnackbar, "Test UUID copied")}>{this.props.id}        - {this.props.alias ? "Alias: " : ""} {this.props.alias ? copyToClipboard(this.props.alias, this.props.enqueueSnackbar, "Test alias copied")}>{this.props.alias} : ""} + {this.props.alias ? "Alias: " : ""} {this.props.alias ? copyToClipboard(this.props.alias, this.props.enqueueSnackbar, this.props.closeSnackbar, "Test alias copied")}>{this.props.alias} : ""} Created: {formatTimeStampToLongString(this.props.dateCreated)} diff --git a/apps/validation_framework_v2/src/TestTable.js b/apps/validation_framework_v2/src/TestTable.js index 4ab0c9be6..6c256cd27 100644 --- a/apps/validation_framework_v2/src/TestTable.js +++ b/apps/validation_framework_v2/src/TestTable.js @@ -88,7 +88,7 @@ class TestTable extends React.Component { selectedTests.push(ordered_data) } downloadJSON(JSON.stringify(selectedTests), "selectedTests.json") - showNotification(this.props.enqueueSnackbar, "Saved to selectedTests.json", "info") + showNotification(this.props.enqueueSnackbar, this.props.closeSnackbar, "Saved to selectedTests.json", "info") } hideTableRows(selectedRows) { @@ -99,7 +99,7 @@ class TestTable extends React.Component { } const updated_data = this.state.data.filter((item, index) => !selectedIndices.includes(index)); this.setState({ data: updated_data }); - showNotification(this.props.enqueueSnackbar, "Chosen test(s) have been hidden!", "info") + showNotification(this.props.enqueueSnackbar, this.props.closeSnackbar, "Chosen test(s) have been hidden!", "info") } viewSelectedItems(selectedRows) { @@ -154,9 +154,9 @@ class TestTable extends React.Component { } } } - showNotification(this.props.enqueueSnackbar, "Test '" + test.name + "' added to compare!", "info") + showNotification(this.props.enqueueSnackbar, this.props.closeSnackbar, "Test '" + test.name + "' added to compare!", "info") } else { - showNotification(this.props.enqueueSnackbar, "Skipped: test '" + test.name + "' (0 instances)!", "error") + showNotification(this.props.enqueueSnackbar, this.props.closeSnackbar, "Skipped: test '" + test.name + "' (0 instances)!", "error") } } console.log(compareTests); diff --git a/apps/validation_framework_v2/src/ValidationFramework.js b/apps/validation_framework_v2/src/ValidationFramework.js index 7e5c3eb0e..0725d0e1d 100644 --- a/apps/validation_framework_v2/src/ValidationFramework.js +++ b/apps/validation_framework_v2/src/ValidationFramework.js @@ -163,7 +163,9 @@ class ValidationFramework extends React.Component { this.updateModels = this.updateModels.bind(this); this.updateTests = this.updateTests.bind(this); this.getModel = this.getModel.bind(this); + this.getModelFromInstance = this.getModelFromInstance.bind(this); this.getTest = this.getTest.bind(this); + this.getTestFromInstance = this.getTestFromInstance.bind(this); this.modelTableFullWidth = this.modelTableFullWidth.bind(this); this.testTableFullWidth = this.testTableFullWidth.bind(this); this.openCompareResults = this.openCompareResults.bind(this); @@ -216,7 +218,7 @@ class ValidationFramework extends React.Component { modelDetailOpen: true }); updateHash("model_id." + currentModel.id); - showNotification(this.props.enqueueSnackbar, "Model has been added!", "info") + showNotification(this.props.enqueueSnackbar, this.props.closeSnackbar, "Model has been added!", "info") } } @@ -234,7 +236,7 @@ class ValidationFramework extends React.Component { testDetailOpen: true }); updateHash("test_id." + currentTest.id); - showNotification(this.props.enqueueSnackbar, "Test has been added!", "info") + showNotification(this.props.enqueueSnackbar, this.props.closeSnackbar, "Test has been added!", "info") } } @@ -278,10 +280,18 @@ class ValidationFramework extends React.Component { this.setState({ loadingOpen: true }); if (key.startsWith("model")) { // get a specific model - this.getModel(key, value); + if (key === "model_instance_id") { + this.getModelFromInstance(value); + } else { + this.getModel(key, value); + } } else if (key.startsWith("test")) { // get a specific test - this.getTest(key, value); + if (key === "test_instance_id") { + this.getTestFromInstance(value); + } else { + this.getTest(key, value); + } } else if (key === "result_id") { // get a specific result this.getResult(key, value); @@ -375,6 +385,76 @@ class ValidationFramework extends React.Component { ); }; + getModelFromInstance(value) { + let url = baseUrl + "/models/query/instances/" + encodeURI(value); + console.log(url); + let config = { + cancelToken: this.signal.token, + headers: { + 'Authorization': 'Bearer ' + this.props.auth.token, + } + } + // this.setState({loadingModel: true}); + axios.get(url, config) + .then(res => { + url = baseUrl + "/models/" + encodeURI(res.data.model_id); + axios.get(url, config) + .then(m_res => { + this.setState({ + currentModel: m_res.data, + loadingOpen: false, + errorGet: null, + modelDetailOpen: true + }); + updateHash('model_id.'+res.data.model_id); + }) + .catch(err => { + if (axios.isCancel(err)) { + console.log('errorGet: ', err.message); + this.setState({ + loadingOpen: false, + }); + } else { + // Something went wrong. Save the error in state and re-render. + let error_message = ""; + try { + error_message = err.response.data.detail; + } catch { + error_message = err + } + this.setState({ + loadingOpen: false, + errorGet: error_message + }); + } + updateHash(''); + } + ); + }) + .catch(err => { + if (axios.isCancel(err)) { + console.log('errorGet: ', err.message); + this.setState({ + loadingOpen: false, + }); + } else { + // Something went wrong. Save the error in state and re-render. + let error_message = ""; + try { + error_message = err.response.data.detail; + } catch { + error_message = err + } + this.setState({ + loadingOpen: false, + errorGet: error_message + }); + } + updateHash(''); + } + ); + }; + getTest(key, value) { let url = ""; if (key === "test_id") { @@ -422,6 +502,75 @@ class ValidationFramework extends React.Component { ); }; + getTestFromInstance(value) { + let url = baseUrl + "/tests/query/instances/" + encodeURI(value); + let config = { + cancelToken: this.signal.token, + headers: { + 'Authorization': 'Bearer ' + this.props.auth.token, + } + } + // this.setState({loadingModel: true}); + axios.get(url, config) + .then(res => { + url = baseUrl + "/tests/" + encodeURI(res.data.test_id); + axios.get(url, config) + .then(t_res => { + this.setState({ + currentTest: t_res.data, + loadingOpen: false, + errorGet: null, + testDetailOpen: true + }); + updateHash('test_id.'+res.data.test_id); + }) + .catch(err => { + if (axios.isCancel(err)) { + console.log('errorGet: ', err.message); + this.setState({ + loadingOpen: false, + }); + } else { + // Something went wrong. Save the error in state and re-render. + let error_message = ""; + try { + error_message = err.response.data.detail; + } catch { + error_message = err + } + this.setState({ + loadingOpen: false, + errorGet: error_message + }); + } + updateHash(''); + } + ); + }) + .catch(err => { + if (axios.isCancel(err)) { + console.log('errorGet: ', err.message); + this.setState({ + loadingOpen: false, + }); + } else { + // Something went wrong. Save the error in state and re-render. + let error_message = ""; + try { + error_message = err.response.data.detail; + } catch { + error_message = err + } + this.setState({ + loadingOpen: false, + errorGet: error_message + }); + } + updateHash(''); + } + ); + }; + getResult(key, value) { let url = baseUrl + "/results-extended/" + value; let config = { @@ -626,7 +775,7 @@ class ValidationFramework extends React.Component { update_test_flag = true; this.updateTests(testFilters); } - showNotification(this.props.enqueueSnackbar, "App config updated!", "success") + showNotification(this.props.enqueueSnackbar, this.props.closeSnackbar, "App config updated!", "success") } console.log(update_model_flag) console.log(update_test_flag) diff --git a/apps/validation_framework_v2/src/ViewSelected.js b/apps/validation_framework_v2/src/ViewSelected.js index 5e058956a..14d19ccc6 100644 --- a/apps/validation_framework_v2/src/ViewSelected.js +++ b/apps/validation_framework_v2/src/ViewSelected.js @@ -22,7 +22,7 @@ function EntityParameter(props) { {formatLabel(props.label)} {props.data.map((entity, ind) => ( - copyToClipboard(formatValue(props.label, entity[props.label]), props.enqueueSnackbar, formatLabel(props.label) + " copied")}>{formatValue(props.label, entity[props.label])} + copyToClipboard(formatValue(props.label, entity[props.label]), props.enqueueSnackbar, props.closeSnackbar, formatLabel(props.label) + " copied")}>{formatValue(props.label, entity[props.label])} ))} ) @@ -31,7 +31,7 @@ function EntityParameter(props) { {formatLabel(props.label)} {props.data.map((entity, ind) => ( - copyToClipboard(formatValue(props.label, entity[props.label]), props.enqueueSnackbar, formatLabel(props.label) + " copied")}>{formatValue(props.label, entity[props.label])} + copyToClipboard(formatValue(props.label, entity[props.label]), props.enqueueSnackbar, props.closeSnackbar, formatLabel(props.label) + " copied")}>{formatValue(props.label, entity[props.label])} ))} ) @@ -58,7 +58,7 @@ class ViewSelected extends React.Component { {params.map((param) => ( - + ))}
diff --git a/apps/validation_framework_v2/src/globals.js b/apps/validation_framework_v2/src/globals.js index ab5857dd8..b86d71527 100755 --- a/apps/validation_framework_v2/src/globals.js +++ b/apps/validation_framework_v2/src/globals.js @@ -19,7 +19,7 @@ export const filterTestKeys = [...new Set([...filterCommonKeys, ...filterTestOnl export const filterModelInstanceKeys = ["license"]; export const filterTestInstanceKeys = []; export const displayValid = ["Only Models", "Models and Tests", "Only Tests"]; -export const queryValid = ["model_id", "model_alias", "test_id", "test_alias", "result_id"]; +export const queryValid = ["model_id", "model_alias", "model_instance_id", "test_id", "test_alias", "test_instance_id", "result_id"]; export const ADMIN_PROJECT_ID = "model-validation"; export const updateHash = (value) => { diff --git a/apps/validation_framework_v2/src/utils.js b/apps/validation_framework_v2/src/utils.js index 5404871db..cd19f9863 100644 --- a/apps/validation_framework_v2/src/utils.js +++ b/apps/validation_framework_v2/src/utils.js @@ -103,28 +103,34 @@ export function isUUID(uuid) { } -export function copyToClipboard(value, enqueueSnackbar, message, type = 'default') { +export function copyToClipboard(value, enqueueSnackbar, closeSnackbar, message, type = 'default') { // type: default, success, error, warning, info navigator.clipboard.writeText(value) - enqueueSnackbar(message, { + const key = enqueueSnackbar(message, { variant: type, anchorOrigin: { vertical: 'bottom', horizontal: 'right', }, - }) + onClick: () => { + closeSnackbar(key); + }, + }); } -export function showNotification(enqueueSnackbar, message, type = 'default') { +export function showNotification(enqueueSnackbar, closeSnackbar, message, type = 'default') { // type: default, success, error, warning, info - enqueueSnackbar(message, { + const key = enqueueSnackbar(message, { variant: type, anchorOrigin: { vertical: 'bottom', horizontal: 'right', }, - }) + onClick: () => { + closeSnackbar(key); + }, + }); }