diff --git a/web-client/public/js/constants.js b/web-client/public/js/constants.js index f826612ae..4f624be5a 100644 --- a/web-client/public/js/constants.js +++ b/web-client/public/js/constants.js @@ -55,6 +55,7 @@ export const MIN_EDGE_WEIGHT_NORMALIZATION = 0.0001; export const MAX_EDGE_WEIGHT_NORMALIZATION = 1000; export const DEFAULT_ZOOM_VALUE = 100; +export const BOUNDARY_MARGIN = 5; export const GREY_EDGE_THRESHOLD_MENU = "#gray-edge-threshold-menu"; export const GREY_EDGE_THRESHOLD_SLIDER_SIDEBAR = "#grayThresholdInput"; diff --git a/web-client/public/js/graph.js b/web-client/public/js/graph.js index c204adbf2..6b1155f21 100644 --- a/web-client/public/js/graph.js +++ b/web-client/public/js/graph.js @@ -11,7 +11,8 @@ import { ZOOM_DISPLAY_MAXIMUM_VALUE, ZOOM_DISPLAY_MIDDLE, ZOOM_ADAPTIVE_MAX_SCALE, - NETWORK_GRN_MODE + NETWORK_GRN_MODE, + BOUNDARY_MARGIN } from "./constants"; /* globals d3 */ @@ -456,8 +457,6 @@ export var drawGraph = function (workbook) { center(); } updateAppBasedOnZoomValue(); // Update zoom value within bounds - // Refresh the graph so that nodes and paths are adjusted to fit in viewport - tick(); }; d3.select("#restrict-graph-to-viewport").on("click", function () { @@ -1118,6 +1117,9 @@ export var drawGraph = function (workbook) { .attr("stroke-width", "0px") .style("fill", function (d) { d = d || 0; // missing values are changed to 0 + if (d === 0) { + return "white"; + } var scale = d3.scaleLinear() .domain([-logFoldChangeMaxValue, logFoldChangeMaxValue]) .range([0, 1]); @@ -1383,8 +1385,6 @@ export var drawGraph = function (workbook) { } }; - const BOUNDARY_MARGIN = 5; - function viewportBoundsMoveDrag (graphZoom, dx, dy) { updateZoomContainerInfo(); flexibleContainer = calcFlexiBox(); @@ -1526,7 +1526,6 @@ export var drawGraph = function (workbook) { try { node.attr("x", function (d) { var selfReferringEdge = getSelfReferringEdge(d); - var selfReferringEdgeWidth = (selfReferringEdge ? getSelfReferringRadius(selfReferringEdge) + selfReferringEdge.strokeWidth + 2 : 0); var rightBoundary = width - (d.textWidth + OFFSET_VALUE) - BOUNDARY_MARGIN - selfReferringEdgeWidth; @@ -1541,9 +1540,7 @@ export var drawGraph = function (workbook) { } // currentXPos bounds the graph when toggle to !adaptive and moves each of the nodes to be in bounds var currentXPos = Math.max(getLeftXBoundaryMargin(), Math.min(rightBoundary, d.x)); - if ( - adaptive && - width < MAX_WIDTH && + if (adaptive && width < MAX_WIDTH && (currentXPos === getLeftXBoundaryMargin() || currentXPos === rightBoundary) ) { diff --git a/web-client/public/js/grnstate.js b/web-client/public/js/grnstate.js index 67b0d011e..ffa20b93f 100644 --- a/web-client/public/js/grnstate.js +++ b/web-client/public/js/grnstate.js @@ -85,6 +85,7 @@ export const grnState = { lastDataset: null, bottomDataSameAsTop: true, nodeColoringOptions: [], + ppiNodeColorWarningDisplayed: false, }, diff --git a/web-client/public/js/update-app.js b/web-client/public/js/update-app.js index a49ed5e0c..7fcf3716e 100644 --- a/web-client/public/js/update-app.js +++ b/web-client/public/js/update-app.js @@ -51,6 +51,7 @@ import { NODE_COLORING_MENU_CLASS, NODE_COLORING_NAVBAR_OPTIONS, NODE_COLORING_SIDEBAR_BODY, + NODE_COLORING_SIDEBAR_PANEL, NODE_COLORING_SIDEBAR_HEADER_LINK, NODE_COLORING_TOGGLE_SIDEBAR, AVG_REPLICATE_VALS_TOP_MENU, @@ -108,7 +109,7 @@ import { NETWORK_MODE_GRN, EXPORT_TO_UNWEIGHTED_GML_MENU, NETWORK_GRN_MODE, - NETWORK_PPI_MODE + NETWORK_PPI_MODE, // EXPRESSION_SOURCE, } from "./constants"; @@ -507,12 +508,19 @@ const updatetoGridLayout = () => {}; // Node Coloring Functions const showNodeColoringMenus = () => { - $(NODE_COLORING_SIDEBAR_BODY).removeClass("hidden"); + $(NODE_COLORING_SIDEBAR_PANEL).removeClass("disabled"); + $(NODE_COLORING_SIDEBAR_PANEL).addClass("in"); $(NODE_COLORING_MENU).removeClass("disabled"); $(NODE_COLORING_MENU_CLASS).removeClass("disabled"); $(NODE_COLORING_SIDEBAR_HEADER_LINK).attr("data-toggle", "collapse"); - $(NODE_COLORING_MENU).removeClass("hidden"); - $(NODE_COLORING_NAVBAR_OPTIONS).removeClass("hidden"); +}; + +const disableNodeColoringMenus = () => { + $(NODE_COLORING_SIDEBAR_PANEL).addClass("disabled"); + $(NODE_COLORING_SIDEBAR_PANEL).removeClass("in"); + $(NODE_COLORING_MENU_CLASS).addClass("disabled"); + $(NODE_COLORING_MENU).addClass("disabled"); + $(NODE_COLORING_SIDEBAR_HEADER_LINK).attr("data-toggle", ""); }; const isNewWorkbook = (name) => { @@ -520,7 +528,6 @@ const isNewWorkbook = (name) => { }; // Workbook Mode Functions - const updateModeViews = () =>{ // Select correct dropdown item $(`${NETWORK_MODE_DROPDOWN} option`).removeAttr("selected"); @@ -535,16 +542,18 @@ const updateModeViews = () =>{ }; const checkWorkbookModeSettings = () => { - showNodeColoringMenus(); - if (grnState.mode === NETWORK_PPI_MODE) { grnState.nodeColoring.nodeColoringEnabled = false; + grnState.nodeColoring.showMenu = true; grnState.colorOptimal = false; + showNodeColoringMenus(); hideEdgeWeightOptions(); updateModeViews(); } else if (grnState.mode === NETWORK_GRN_MODE) { grnState.nodeColoring.nodeColoringEnabled = true; + grnState.nodeColoring.showMenu = true; grnState.colorOptimal = true; + showNodeColoringMenus(); showEdgeWeightOptions(); updateModeViews(); } @@ -784,6 +793,7 @@ export const updateApp = grnState => { identifySpeciesOrTaxon(workbookSpecies); identifySpeciesOrTaxon(workbookTaxon); } + // nodeColoringEnabled will only be set the very first time; because otherwise the user will have // made a choice and we will let the choice stick. if (hasExpressionData(grnState.workbook.expression)) { @@ -859,44 +869,57 @@ export const updateApp = grnState => { // Node Coloring if (grnState.workbook !== null && grnState.nodeColoring.nodeColoringEnabled - ) { + && hasExpressionData(grnState.workbook.expression)) { grnState.nodeColoring.showMenu = true; $(AVG_REPLICATE_VALS_TOP_SIDEBAR).prop("checked", true); $(AVG_REPLICATE_VALS_BOTTOM_SIDEBAR).prop("checked", true); $(`${NODE_COLORING_TOGGLE_MENU} span`).addClass("glyphicon-ok"); $(NODE_COLORING_TOGGLE_SIDEBAR).prop("checked", true); $(LOG_FOLD_CHANGE_MAX_VALUE_CLASS).val(DEFAULT_MAX_LOG_FOLD_CHANGE); + $(NODE_COLORING_SIDEBAR_BODY).removeClass("hidden"); $(NODE_COLORING_MENU).removeClass("hidden"); $(NODE_COLORING_NAVBAR_OPTIONS).removeClass("hidden"); - - if (hasExpressionData(grnState.workbook.expression)) { - if (grnState.database.expressionDatasets.includes(grnState.nodeColoring.topDataset) && + if (grnState.mode === NETWORK_PPI_MODE) { + displayPPINodeColorWarning(grnState.ppiNodeColorWarningDisplayed); + grnState.ppiNodeColorWarningDisplayed = true; + } + if (grnState.database.expressionDatasets.includes(grnState.nodeColoring.topDataset) && grnState.workbook.expression[grnState.nodeColoring.topDataset] === undefined) { - if ($(NODE_COLORING_TOGGLE_SIDEBAR).prop("checked")) { - loadExpressionDatabase(true); - } - } else if (grnState.database.expressionDatasets.includes(grnState.nodeColoring.bottomDataset) && - !grnState.nodeColoring.bottomDataSameAsTop && - grnState.workbook.expression[grnState.nodeColoring.bottomDataset] === undefined) { - if (!grnState.nodeColoring.bottomDataSameAsTop) { - loadExpressionDatabase(false); - } - } else { - updaters.renderNodeColoring(); + if ($(NODE_COLORING_TOGGLE_SIDEBAR).prop("checked")) { + loadExpressionDatabase(true); } - } else { - grnState.nodeColoring.topDataset = grnState.nodeColoring.topDataset ? - grnState.nodeColoring.topDataset : "Dahlquist_2018_wt"; - grnState.nodeColoring.bottomDataset = grnState.nodeColoring.bottomDataset ? - grnState.nodeColoring.bottomDataset : "Dahlquist_2018_wt"; - - if ((grnState.workbook.expression[grnState.nodeColoring.topDataset] === undefined) || - (!grnState.nodeColoring.bottomDataSameAsTop && - grnState.workbook.expression[grnState.nodeColoring.bottomDataset] === undefined)) { - updaters.removeNodeColoring(); - resetDatasetDropdownMenus(grnState.workbook); + } else if (grnState.database.expressionDatasets.includes(grnState.nodeColoring.bottomDataset) && + !grnState.nodeColoring.bottomDataSameAsTop && + grnState.workbook.expression[grnState.nodeColoring.bottomDataset] === undefined) { + if (!grnState.nodeColoring.bottomDataSameAsTop) { + loadExpressionDatabase(false); } - + } else { + updaters.renderNodeColoring(); + } + } else if (grnState.workbook !== null && !hasExpressionData(grnState.workbook.expression) + && grnState.nodeColoring.nodeColoringEnabled) { + if ((grnState.workbook.expression[grnState.nodeColoring.topDataset] === undefined) || + (!grnState.nodeColoring.bottomDataSameAsTop && + grnState.workbook.expression[grnState.nodeColoring.bottomDataset] === undefined)) { + updaters.removeNodeColoring(); + resetDatasetDropdownMenus(grnState.workbook); + } + grnState.nodeColoring.showMenu = true; + grnState.nodeColoring.topDataset = grnState.nodeColoring.topDataset ? + grnState.nodeColoring.topDataset : "Dahlquist_2018_wt"; + grnState.nodeColoring.bottomDataset = grnState.nodeColoring.bottomDataset ? + grnState.nodeColoring.bottomDataset : "Dahlquist_2018_wt"; + $(NODE_COLORING_TOGGLE_SIDEBAR).prop("checked", true); + $(`${NODE_COLORING_TOGGLE_MENU} span`).addClass("glyphicon-ok"); + $(NODE_COLORING_SIDEBAR_BODY).removeClass("hidden"); + $(NODE_COLORING_MENU).removeClass("hidden"); + $(NODE_COLORING_NAVBAR_OPTIONS).removeClass("hidden"); + $(LOG_FOLD_CHANGE_MAX_VALUE_CLASS).val(DEFAULT_MAX_LOG_FOLD_CHANGE); + $(LOG_FOLD_CHANGE_MAX_VALUE_CLASS).addClass("hidden"); + $(LOG_FOLD_CHANGE_MAX_VALUE_SIDEBAR_BUTTON).addClass("hidden"); + $(LOG_FOLD_CHANGE_MAX_VALUE_HEADER).addClass("hidden"); + if ($(NODE_COLORING_TOGGLE_SIDEBAR).prop("checked")) { if (grnState.workbook.expression[grnState.nodeColoring.topDataset] === undefined) { loadExpressionDatabase(true); } else if (!grnState.nodeColoring.bottomDataSameAsTop && @@ -919,18 +942,21 @@ export const updateApp = grnState => { // Investigate why a timeout is required in order for node coloring to take place // successfully in this case. setTimeout(() => updaters.renderNodeColoring(), 250); - } if (grnState.mode === NETWORK_PPI_MODE) { - displayPPINodeColorWarning(); + displayPPINodeColorWarning(grnState.ppiNodeColorWarningDisplayed); + grnState.ppiNodeColorWarningDisplayed = true; } } - refreshApp(); } else if (grnState.workbook !== null && !grnState.nodeColoring.nodeColoringEnabled) { $(NODE_COLORING_SIDEBAR_BODY).addClass("hidden"); + $(NODE_COLORING_MENU).addClass("disabled"); $(NODE_COLORING_NAVBAR_OPTIONS).addClass("hidden"); $(`${NODE_COLORING_TOGGLE_MENU} span`).removeClass("glyphicon-ok"); $(NODE_COLORING_TOGGLE_SIDEBAR).prop("checked", false); + if (grnState.mode === NETWORK_PPI_MODE) { + grnState.ppiNodeColorWarningDisplayed = false; + } } if (grnState.workbook !== null && grnState.workbook.sheetType === "weighted") { @@ -969,6 +995,8 @@ export const updateApp = grnState => { if (grnState.nodeColoring.showMenu) { showNodeColoringMenus(); + } else { + disableNodeColoringMenus(); } updateLogFoldChangeMaxValue(); diff --git a/web-client/public/js/warnings.js b/web-client/public/js/warnings.js index 09e58f2ea..b229603bc 100644 --- a/web-client/public/js/warnings.js +++ b/web-client/public/js/warnings.js @@ -43,7 +43,6 @@ export var displayWarnings = function (warnings) { index++; } - var screenHeight = $(window).height(); var MIN_SCREEN_HEIGHT = 600; var BORDER = 425; @@ -58,10 +57,15 @@ export var displayWarnings = function (warnings) { $("#warningsModal").modal("show"); }; -export var displayPPINodeColorWarning = function() { +export var displayPPINodeColorWarning = function (warningDisplayed) { + if (warningDisplayed) { + return; + } + $("#warningIntro").html("Protein-protein interaction node coloring warning."); - $("#warningsList").html("You are displaying mRNA-level expression data on a protein-protein interaction network." + - "Please note that this may not be the most appropriate representation of the data." + $("#warningsList").html( + ["You are displaying mRNA-level expression data on a protein-protein interaction network.", + "Please note that this may not be the most appropriate representation of the data."].join(" ") ); var screenHeight = $(window).height(); @@ -70,9 +74,9 @@ export var displayPPINodeColorWarning = function() { var setPanel = screenHeight - BORDER + "px"; var minPanel = MIN_SCREEN_HEIGHT - BORDER + "px"; if (screenHeight > MIN_SCREEN_HEIGHT) { - $("#list-frame").css({ height: setPanel }); + $("#list-frame").css({ height: setPanel }); } else { - $("#list-frame").css({ height: minPanel }); + $("#list-frame").css({ height: minPanel }); } $("#warningsModal").modal("show");