diff --git a/package-lock.json b/package-lock.json index 458105ede..7242fe568 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,6 +1,6 @@ { "name": "grnsight", - "version": "4.0.5", + "version": "4.0.6", "lockfileVersion": 1, "requires": true, "dependencies": { diff --git a/server/controllers/spreadsheet-controller.js b/server/controllers/spreadsheet-controller.js index fac8e752e..c04e6a60d 100644 --- a/server/controllers/spreadsheet-controller.js +++ b/server/controllers/spreadsheet-controller.js @@ -250,11 +250,11 @@ var parseSheet = function (sheet) { // Look for the worksheet containing the network data for (var i = 0; i < sheet.length; i++) { - if (sheet[i].name === "network") { + if (sheet[i].name.toLowerCase() === "network") { // Here we have found a sheet containing simple data. We keep looking // in case there is also a sheet with optimized weights currentSheet = sheet[i]; - } else if (sheet[i].name === "network_optimized_weights") { + } else if (sheet[i].name.toLowerCase() === "network_optimized_weights") { // We found a sheet with optimized weights, which is the ideal data source. // So we stop looking. currentSheet = sheet[i]; diff --git a/test-files/spreadsheet-controller-test-files/sheet-name-capitalized-network-optimized-weights.xlsx b/test-files/spreadsheet-controller-test-files/sheet-name-capitalized-network-optimized-weights.xlsx new file mode 100644 index 000000000..0fb11036c Binary files /dev/null and b/test-files/spreadsheet-controller-test-files/sheet-name-capitalized-network-optimized-weights.xlsx differ diff --git a/test-files/spreadsheet-controller-test-files/sheet-name-capitalized-network.xlsx b/test-files/spreadsheet-controller-test-files/sheet-name-capitalized-network.xlsx new file mode 100644 index 000000000..154b5f5b0 Binary files /dev/null and b/test-files/spreadsheet-controller-test-files/sheet-name-capitalized-network.xlsx differ diff --git a/test/errors-sheet-modifications.js b/test/errors-sheet-modifications.js index 8e53824ad..e55a49b7e 100644 --- a/test/errors-sheet-modifications.js +++ b/test/errors-sheet-modifications.js @@ -34,6 +34,13 @@ describe("errors-sheet-modifications", function () { }); }); + describe("sheet-name-capitalized", function () { + it("should return no errors", function () { + test.noErrors("test-files/spreadsheet-controller-test-files/sheet-name-capitalized-network-optimized-weights.xlsx"); + test.noErrors("test-files/spreadsheet-controller-test-files/sheet-name-capitalized-network.xlsx", 1); + }); + }); + // Sheet Modifications - Cell A1 Modifications describe("and-symbol", function () { diff --git a/web-client/public/js/graph.js b/web-client/public/js/graph.js index 21076ce88..20e0e3418 100644 --- a/web-client/public/js/graph.js +++ b/web-client/public/js/graph.js @@ -109,10 +109,13 @@ export var drawGraph = function (network) { } } + const maxWeight = Math.max(Math.abs(d3.max(allWeights)), Math.abs(d3.min(allWeights))); + // Get the largest magnitude weight and set that as the default normalization factor - var maxWeight = Math.max(Math.abs(d3.max(allWeights)), Math.abs(d3.min(allWeights))); - grnState.normalizationMax = maxWeight; - grnState.resetNormalizationMax = maxWeight; + if (grnState.newNetwork) { + grnState.normalizationMax = maxWeight; + grnState.resetNormalizationMax = maxWeight; + } // Normalize all weights b/w 2-14 var normMax = +$("#normalization-max").val(); @@ -658,6 +661,7 @@ export var drawGraph = function (network) { .attr("class", "weight") .attr("text-anchor", "middle") .attr("text-anchor", "middle") + .attr("fill", "rgb(0,0,0)") .style("font-family", "sans-serif") .text(function (d) { return d.value.toPrecision(4); @@ -667,6 +671,7 @@ export var drawGraph = function (network) { .enter().append("text") .attr("class", "weight") .attr("text-anchor", "middle") + .attr("fill", "rgb(0,0,0)") .style("font-family", "sans-serif") .text(function (d) { return d.value.toPrecision(4); @@ -914,11 +919,11 @@ export var drawGraph = function (network) { node.selectAll(".nodeText").remove(); var text = node.append("text") .attr("dy", NODE_HEIGHT) - .attr("text-anchor", "middle") .attr("class", "nodeText") + .attr("fill", "rgb(0, 0, 0)") + .style("text-anchor", "middle") .style("font-size", "18px") .style("stroke-width", "0") - .style("fill", "black") .style("font-family", "sans-serif") .text(function (d) { return d.name; @@ -1099,6 +1104,7 @@ export var drawGraph = function (network) { label.setAttribute("text-anchor", legendLabels[key].textAnchor); label.setAttribute("x", legendLabels[key].x); label.setAttribute("y", height + textYOffset + "px"); + label.setAttribute("fill", "rgb(0,0,0)"); g.appendChild(label); } }; diff --git a/web-client/public/js/setup-handlers.js b/web-client/public/js/setup-handlers.js index 6dd24d3ac..c414efb0d 100644 --- a/web-client/public/js/setup-handlers.js +++ b/web-client/public/js/setup-handlers.js @@ -78,19 +78,88 @@ export const setupHandlers = grnState => { } }; - const exportSVG = (svgElement, name) => { - var serializer = new XMLSerializer(); - var source = serializer.serializeToString(svgElement); +// thank you for the help https://github.com/nytimes/svg-crowbar/blob/gh-pages/svg-crowbar-2.js + const setInlineStyles = (svg) => { + var emptySvg = window.document.createElementNS("http://www.w3.org/2000/svg", "svg"); + window.document.body.appendChild(emptySvg); + var emptySvgDeclarationComputed = getComputedStyle(emptySvg); + + const traverse = svg => { + var tree = []; + tree.push(svg); + // implement DFS + const visit = (node) => { + if (node && node.hasChildNodes()) { + var child = node.firstChild; + while (child) { + if (child.nodeType === 1 && child.nodeName !== "SCRIPT") { + tree.push(child); + visit(child); + } + child = child.nextSibling; + } + } + }; + visit(svg); + return tree; + }; + + const explicitlySetStyle = element => { + const cSSStyleDeclarationComputed = window.getComputedStyle(element); + let i; + let len; + let key; + let value; + let computedStyleStr = ""; + + for (i = 0, len = cSSStyleDeclarationComputed.length; i < len; i++) { + key = cSSStyleDeclarationComputed[i]; + value = cSSStyleDeclarationComputed.getPropertyValue(key); + if (value !== emptySvgDeclarationComputed.getPropertyValue(key)) { + // Don't set computed style of width and height. Makes SVG elmements disappear. + if ((key !== "height") && (key !== "width")) { + computedStyleStr += key + ":" + value + ";"; + } + + } + } + element.setAttribute("style", computedStyleStr); + }; + + // hardcode computed css styles inside svg + var allElements = traverse(svg); + var i = allElements.length; + while (i--) { + explicitlySetStyle(allElements[i]); + } + }; + + const sourceAttributeSetter = (svg) => { + svg.setAttribute("version", "1.1"); + + svg.removeAttribute("xmlns"); + svg.removeAttribute("xlink"); - if (!source.match(/^]+xmlns="http\:\/\/www\.w3\.org\/2000\/svg"/)) { - source = source.replace(/^]+"http\:\/\/www\.w3\.org\/1999\/xlink"/)) { - source = source.replace(/^ { + let source = svgElement; + + sourceAttributeSetter(source); + setInlineStyles(source); + + var doctype = ""; // eslint-disable-line + var sourceString = (new XMLSerializer()).serializeToString(source); + const finalSvgString = [doctype + sourceString]; - source = "\r\n" + source; - var svgUrl = "data:image/svg+xml;charset=utf-8," + encodeURIComponent(source); + var svgUrl = window.URL.createObjectURL(new Blob(finalSvgString, { "type" : "image\/svg+xml" })); $("#exportAsSvg").attr("href", svgUrl); $("#exportAsSvg").attr("download", name); diff --git a/web-client/public/js/setup-load-and-import-handlers.js b/web-client/public/js/setup-load-and-import-handlers.js index 4587f7464..81ae81b71 100644 --- a/web-client/public/js/setup-load-and-import-handlers.js +++ b/web-client/public/js/setup-load-and-import-handlers.js @@ -5,9 +5,15 @@ import { UNWEIGHTED_DEMO_PATH, WEIGHTED_DEMO_PATH, SCHADE_INPUT_PATH, - SCHADE_OUTPUT_PATH + SCHADE_OUTPUT_PATH, + WEIGHTED_DEMO_NAME, + UNWEIGHTED_DEMO_NAME, + SCHADE_INPUT_NAME, + SCHADE_OUTPUT_NAME, } from "./constants"; +const demoFiles = [UNWEIGHTED_DEMO_PATH, WEIGHTED_DEMO_PATH, SCHADE_INPUT_PATH, SCHADE_OUTPUT_PATH]; + const submittedFilename = $upload => { let path = $upload.val(); let fakePathCheck = path.search("\\\\") + 1; @@ -87,7 +93,6 @@ const networkErrorDisplayer = xhr => { let reloader = () => { }; const returnUploadRoute = filename => { - var demoFiles = [UNWEIGHTED_DEMO_PATH, WEIGHTED_DEMO_PATH, SCHADE_INPUT_PATH, SCHADE_OUTPUT_PATH]; if (demoFiles.indexOf(filename) !== -1) { return filename; } else if (filename.includes(".xlsx")) { @@ -116,6 +121,22 @@ export const setupLoadAndImportHandlers = grnState => { $.getJSON(fullUrl) ).done((network, textStatus, jqXhr) => { grnState.name = name || jqXhr.getResponseHeader("X-GRNsight-Filename"); + if (demoFiles.indexOf(name) > -1) { + switch (name) { + case WEIGHTED_DEMO_PATH: + grnState.name = WEIGHTED_DEMO_NAME; + break; + case UNWEIGHTED_DEMO_PATH: + grnState.name = UNWEIGHTED_DEMO_NAME; + break; + case SCHADE_INPUT_PATH: + grnState.name = SCHADE_INPUT_NAME; + break; + case SCHADE_OUTPUT_PATH: + grnState.name = SCHADE_OUTPUT_NAME; + break; + } + } grnState.network = network; if (uploadRoute !== "upload") { grnState.annotateLinks(); diff --git a/web-client/views/upload.jade b/web-client/views/upload.jade index 5fe38257e..cdca803cd 100644 --- a/web-client/views/upload.jade +++ b/web-client/views/upload.jade @@ -35,6 +35,7 @@ html label(for='upload' id='open') span(class='glyphicon glyphicon-folder-open') |   Open File + i (.xlsx .sif, .graphml) input(type='file' name='upload' id='upload' accept='application/vnd.openxmlformats-officedocument.spreadsheetml.sheet, .sif, .graphml') input(type='hidden' id='service-root' value='#{serviceRoot}') li(class='startDisabled disabled') @@ -355,7 +356,7 @@ html div(id="edgeSidebarPanel" class="panel-collapse collapse") div(class="panel-body") form(class='weightedGraphOptions hidden') - input(id='colorEdgesSidebar', type='checkbox') + input(id='colorEdgesSidebar', type='checkbox' checked) label(for='colorEdgesSidebar' class='sideLabel') Enable Edge Coloring p(class='sideHeader') Hide/Show Edge Weights input(type='radio' id='weightsMouseOverSide' class='weightsMouseOver' name='size' class='selected' checked)