diff --git a/sparqlGraphWeb/sparqlGraph/js/plotlyplotter.js b/sparqlGraphWeb/sparqlGraph/js/plotlyplotter.js index 05e1c9c62..1aa640a53 100644 --- a/sparqlGraphWeb/sparqlGraph/js/plotlyplotter.js +++ b/sparqlGraphWeb/sparqlGraph/js/plotlyplotter.js @@ -59,13 +59,13 @@ define([ // properly require.config'ed bootstrap-modal this.spec.spec = specJson; }, - addPlotToDiv : function(div, tableRes, optImgElem) { + addPlotToDiv : function(div, tableRes, optImgElem, optCallback) { var utilityClient = new MsiClientUtility(g.service.utility.url); - utilityClient.execProcessPlotSpec(this.spec, tableRes.getTable(), this.processSpecSuccess.bind(this, div, optImgElem)); + utilityClient.execProcessPlotSpec(this.spec, tableRes.getTable(), this.processSpecSuccess.bind(this, div, optImgElem, optCallback)); }, - processSpecSuccess : function(div, optImgElem, msiRes) { + processSpecSuccess : function(div, optImgElem, optCallback, msiRes) { var data = msiRes.getSimpleResultField("plot").spec.data; var layout = msiRes.getSimpleResultField("plot").spec.layout; var config = msiRes.getSimpleResultField("plot").spec.config; @@ -89,6 +89,8 @@ define([ // properly require.config'ed bootstrap-modal //Plotly.newPlot( plotDiv, [ { x: [0,1,2,3,1,1,6],type: 'histogram',}]); div.appendChild(plotDiv); + if (optCallback) + optCallback(); }, adjustLayoutDimensions : function(layout, div) { diff --git a/sparqlGraphWeb/sparqlGraph/js/runtimeconstraints.js b/sparqlGraphWeb/sparqlGraph/js/runtimeconstraints.js index 9bf7a8fbf..df6a7d7ac 100644 --- a/sparqlGraphWeb/sparqlGraph/js/runtimeconstraints.js +++ b/sparqlGraphWeb/sparqlGraph/js/runtimeconstraints.js @@ -43,8 +43,17 @@ define([ // properly require.config'ed /** * Runtime constraints object */ - var RuntimeConstraints = function () { - this.constraintsJson = []; // a list of jsons, each for a single constraint + var RuntimeConstraints = function (optJsonString) { + try { + this.constraintsJson = optJsonString ? JSON.parse(optJsonString) : []; + } catch (err) { + throw new Error("Invalid constraints json: " + optJsonString + "\n" + err); + } + + // silently clean up error where a single constraint is given instead of a list + if (!Array.isArray(this.constraintsJson)) { + this.constraintsJson = [this.constraintsJson]; + } }; RuntimeConstraints.prototype = { diff --git a/sparqlGraphWeb/sparqlGraph/js/sparqlgraph.js b/sparqlGraphWeb/sparqlGraph/js/sparqlgraph.js index c00d9ae52..f4fa984f3 100644 --- a/sparqlGraphWeb/sparqlGraph/js/sparqlgraph.js +++ b/sparqlGraphWeb/sparqlGraph/js/sparqlgraph.js @@ -173,12 +173,22 @@ console.log(e.stack); } } + + var nodegroupId = getUrlParameter("nodegroupId"); + var constraintsStr = getUrlParameter("constraints"); + var runFlagStr = getUrlParameter("runFlag"); // defaults to true, next line + var runFlag = (! runFlagStr) || runFlagStr.toLowerCase() == "true" || runFlagStr.toLowerCase() == "t"; - if (conn) { + if (nodegroupId) { + // run a nodegroup at startup + runQueryFromUrl(conn, connStr, nodegroupId, constraintsStr, runFlag); + + } else if (conn) { + // load last connection (from cookies) or conn param doLoadConnection(conn); } else if (g.customization.autoRunDemo.toLowerCase() == "true") { - + // no params or cookies: try the demo ModalIidx.okCancel( "Demo", "Loading demo nodegroup, and
Launching demo documentation pop-up.
(You may need to override your pop-up blocker.)
", function() { @@ -229,6 +239,70 @@ }); }); + /* + URL used to launch SPARQLgraph contains a nodegroupId to run now + + @param {SparqlConnection} conn - the connection from last session OR the connection URL parameter OR null + @param {str} connStr - conn URL param, or falsey + @param {str} nodegroupId - nodegroup Id + @param {str} constraintsStr - constraints string, or falsey + @param {boolean} runFlag = should the nodegroup be run + */ + var runQueryFromUrl = function(conn, connStr, nodegroupId, constraintsStr, runFlag) { + if (connStr) { + doLoadConnection(conn, runQueryFromUrl1.bind(this, nodegroupId, constraintsStr, runFlag)); + } else { + runQueryFromUrl1(nodegroupId, constraintsStr, runFlag); + } + }; + + /* + Now that correct or no override conn is loaded, + continue running nodegroupId at startup + + @param {str} nodegroupId - nodegroupId + @param {str} constraintsStr - constraints string, or falsey + @param {boolean} runFlag = should the nodegroup be run + + */ + var runQueryFromUrl1= function(nodegroupId, constraintsStr, runFlag) { + require( [ 'sparqlgraph/js/msiclientnodegroupstore', + ], function (MsiClientNodeGroupStore) { + + var mq = new MsiClientNodeGroupStore(g.service.nodeGroupStore.url); + mq.getStoredItemByIdToStr(nodegroupId, MsiClientNodeGroupStore.TYPE_NODEGROUP, runQueryFromUrl2.bind(this, nodegroupId, constraintsStr, runFlag)); + }); + }; + + /* + Load nodegroup, keeping current connection if any, and run + + @param {str} constraintsStr - constraints string, or falsey + @param {str} nodegroupId - nodegroupId + @param {boolean} runFlag = should the nodegroup be run + @param {str} jsonStr - the nodegroup json as str + + */ + var runQueryFromUrl2= function(nodegroupId, constraintsStr, runFlag, jsonStr) { + + require( [ 'sparqlgraph/js/runtimeconstraints', + ], function (RuntimeConstraints) { + var forceKeepCurrent = true; + var skipValidation = false; + + var callbackRunQuery = function () { + if (runFlag) { + // change from possibly falsey string to possibly-undefined RuntimeConstraints object + var optConstraints = constraintsStr ? new RuntimeConstraints(constraintsStr) : undefined; + runGraphByQueryType(optConstraints); + } + }; + + doQueryLoadJsonStr(jsonStr, nodegroupId, skipValidation, forceKeepCurrent, callbackRunQuery); + }); + }; + + var getUrlParameter = function getUrlParameter(sParam) { var sPageURL = window.location.search.substring(1); var sURLVariables = sPageURL.split('&'); @@ -1323,7 +1397,14 @@ } }; - var doQueryLoadJsonStr = function(jsonStr, optNgName, optSkipValidation) { + // load a nodegroup + // + // jsonStr - str : sgjson string + // optNgName - str : nodegroup name + // optSkipValidation - boolean : don't validate + // optForceKeepCurrent - boolean : keep current connection if any w/o asking + // optCallback - func() : call this when done + var doQueryLoadJsonStr = function(jsonStr, optNgName, optSkipValidation, optForceKeepCurrent, optCallback) { require(['sparqlgraph/js/sparqlgraphjson', 'sparqlgraph/js/modaliidx'], function(SparqlGraphJson, ModalIidx) { @@ -1346,8 +1427,19 @@ clearNodeGroup(); } - // no conn provided in json - if (conn == null) { + if (optForceKeepCurrent) { + // force use current conn if loaded + if (gConn) { + doQueryLoadFile2(sgJson, optNgName, optSkipValidation, optCallback); + } else if (conn == null) { + ModalIidx.alert("No connection", "This JSON has no connection information.
Load a connection first."); + } else { + doQueryLoadConn(sgJson, conn, optNgName, optSkipValidation, optCallback); + } + + } else if (conn == null) { + // no conn provided in json + if (!gConn) { ModalIidx.alert("No connection", "This JSON has no connection information.
Load a connection first."); clearNodeGroup(); @@ -1381,7 +1473,7 @@ * loads connection and makes call to load rest of sgJson * part of doQueryLoadJsonStr callback chain */ - var doQueryLoadConn = function(sgJson, conn, optNgName, optSkipValidation) { + var doQueryLoadConn = function(sgJson, conn, optNgName, optSkipValidation, optCallback) { require(['sparqlgraph/js/sparqlgraphjson', 'sparqlgraph/js/modaliidx'], function(SparqlGraphJson, ModalIidx) { @@ -1390,7 +1482,7 @@ // function pointer for the thing we do next no matter what happens: // doLoadConnection() with doQueryLoadFile2() as the callback - var doLoadConnectionCall = doLoadConnection.bind(this, conn, doQueryLoadFile2.bind(this, sgJson, optNgName, optSkipValidation)); + var doLoadConnectionCall = doLoadConnection.bind(this, conn, doQueryLoadFile2.bind(this, sgJson, optNgName, optSkipValidation, optCallback)); if (! existName) { // new connection: ask if user wants to save it locally @@ -1398,9 +1490,12 @@ "Connection is not saved locally.

Do you want to save it?", ["Cancel", "Don't Save", "Save"], [function(){}, - doLoadConnectionCall, - function(){ gLoadDialog.addConnection(conn); - doLoadConnectionCall(); + function() { + doLoadConnectionCall() + }, + function(){ + gLoadDialog.addConnection(conn); + doLoadConnectionCall(); } ] ); @@ -1427,7 +1522,7 @@ * @param {JSON} grpJson node group * @param {JSON} importJson import spec */ - var doQueryLoadFile2 = function(sgJson, optNgName, optSkipValidation) { + var doQueryLoadFile2 = function(sgJson, optNgName, optSkipValidation, optCallback) { // by the time this is called, the correct oInfo is loaded. // and the gNodeGroup is empty. require(['sparqlgraph/js/modaliidx', 'sparqlgraph/js/iidxhelper', 'sparqlgraph/js/msiclientnodegroupservice', 'sparqlgraph/js/sparqlgraphjson'], @@ -1464,11 +1559,11 @@ if (optSkipValidation) { nodeGroupChanged(false, newNgName); saveUndoState(); - buildQuery(); + buildQuery(optCallback); } else { // inflate and validate the nodegroup var client = new MsiClientNodeGroupService(g.service.nodeGroup.url, validateFailure.bind(this)); - client.execAsyncInflateAndValidate(new SparqlGraphJson(gConn, gNodeGroup, gMappingTab.getImportSpec()), validateCallback.bind(this, newNgName), validateFailure); + client.execAsyncInflateAndValidate(new SparqlGraphJson(gConn, gNodeGroup, gMappingTab.getImportSpec()), validateCallback.bind(this, newNgName, optCallback), validateFailure); } }); }; @@ -1482,7 +1577,7 @@ }; // callback: successfully determined whether there are modelErrors - var validateCallback = function(newNgName, nodegroupJson, modelErrors, invalidItemStrings, warnings) { + var validateCallback = function(newNgName, optSuccessCallback, nodegroupJson, modelErrors, invalidItemStrings, warnings) { if (modelErrors.length > 0) { // some errors @@ -1515,7 +1610,7 @@ gNodeGroup.addJson(nodegroupJson); nodeGroupChanged(false, newNgName); saveUndoState(); - buildQuery(); + buildQuery(optSuccessCallback); }; var reValidateNodegroup = function(successCallback, optSkipSuccessDialog) { @@ -2075,16 +2170,17 @@ resultsPara.appendChild(headerTable); resultsPara.appendChild(resultsDiv); + var scrollCallback = function() { resultsDiv.scrollIntoViewIfNeeded(); } // display results var plotter = gPlotSpecsHandler == null ? null : gPlotSpecsHandler.getDefaultPlotter(); if (plotter != null) { - plotter.addPlotToDiv(resultsDiv, tableResults); + plotter.addPlotToDiv(resultsDiv, tableResults, undefined, scrollCallback); butColOrder.disabled = true; } else { - tableResults.putTableResultsDatagridInDiv(resultsDiv, undefined, noSort); + tableResults.putTableResultsDatagridInDiv(resultsDiv, scrollCallback, noSort); butColOrder.disabled = false; } - + guiUnDisableAll(); guiResultsNonEmpty(); setStatus(""); @@ -2167,6 +2263,7 @@ return; } + var rawJsonArr = res.getGraphResultsJsonArr(); if (rawJsonArr.length >= RESULTS_MAX_ROWS) { div.innerHTML = "Graphing first " + RESULTS_MAX_ROWS.toString() + " data points. "; @@ -2261,6 +2358,8 @@ buildButton.onclick = this.constructBuildNodegroupCallback.bind(this, network); removeButton.onclick = this.constructRemoveCallback.bind(this, network); + div.scrollIntoViewIfNeeded(); + // add data var jsonLd = res.getGraphResultsJsonArr(true, true, true); jsonLd.slice(0, RESULTS_MAX_ROWS); @@ -2788,7 +2887,7 @@ status.appendChild(table); }; - var buildQuery = function() { + var buildQuery = function(optSuccessCallback) { if (gNodeGroup.getNodeCount() == 0) { document.getElementById('queryText').value = ""; @@ -2797,6 +2896,8 @@ return; } + var successCallback = optSuccessCallback ? optSuccessCallback : function(){}; + require(['sparqlgraph/js/msiclientnodegroupservice', ], function(MsiClientNodeGroupService) { @@ -2805,19 +2906,19 @@ var client = new MsiClientNodeGroupService(g.service.nodeGroup.url, buildQueryFailure.bind(this)); switch (gNodeGroup.getQueryType()) { case SemanticNodeGroup.QT_DISTINCT: - client.execAsyncGenerateSelect(gNodeGroup, gConn, buildQuerySuccess.bind(this), buildQueryFailure.bind(this)); + client.execAsyncGenerateSelect(gNodeGroup, gConn, buildQuerySuccess.bind(this, successCallback), buildQueryFailure.bind(this)); break; case SemanticNodeGroup.QT_COUNT: - client.execAsyncGenerateCountAll(gNodeGroup, gConn, buildQuerySuccess.bind(this), buildQueryFailure.bind(this)); + client.execAsyncGenerateCountAll(gNodeGroup, gConn, buildQuerySuccess.bind(this, successCallback), buildQueryFailure.bind(this)); break; case SemanticNodeGroup.QT_ASK: - client.execAsyncGenerateAsk(gNodeGroup, gConn, buildQuerySuccess.bind(this), buildQueryFailure.bind(this)); + client.execAsyncGenerateAsk(gNodeGroup, gConn, buildQuerySuccess.bind(this, successCallback), buildQueryFailure.bind(this)); break; case SemanticNodeGroup.QT_CONSTRUCT: - client.execAsyncGenerateConstruct(gNodeGroup, gConn, buildQuerySuccess.bind(this), buildQueryFailure.bind(this)); + client.execAsyncGenerateConstruct(gNodeGroup, gConn, buildQuerySuccess.bind(this, successCallback), buildQueryFailure.bind(this)); break; case SemanticNodeGroup.QT_DELETE: - client.execAsyncGenerateDelete(gNodeGroup, gConn, buildQuerySuccess.bind(this), buildQueryFailure.bind(this)); + client.execAsyncGenerateDelete(gNodeGroup, gConn, buildQuerySuccess.bind(this, successCallback), buildQueryFailure.bind(this)); break; default: throw new Error("Internal error: Unknown query type."); @@ -2825,7 +2926,7 @@ }); }; - var buildQuerySuccess = function (sparql, optMsg) { + var buildQuerySuccess = function (successCallback, sparql, optMsg) { document.getElementById('queryText').value = sparql; if (optMsg) { setStatus(optMsg, true); @@ -2839,6 +2940,8 @@ } else { guiQueryEmpty(); } + + successCallback(); };