From 01abd7ca5d9d8dc739c95dba5929d42765054b1f Mon Sep 17 00:00:00 2001 From: Julian Mundhahs Date: Sun, 19 Jan 2025 22:32:02 +0100 Subject: [PATCH 01/17] support sending query and update requires that qlever also accepts the access token from the authorization header file --- backend/static/js/qleverUI.js | 17 ++++++++++++--- backend/templates/index.html | 40 +++++++++++++++++++++++------------ 2 files changed, 41 insertions(+), 16 deletions(-) diff --git a/backend/static/js/qleverUI.js b/backend/static/js/qleverUI.js index 3895136..a5c288c 100755 --- a/backend/static/js/qleverUI.js +++ b/backend/static/js/qleverUI.js @@ -509,11 +509,23 @@ async function processQuery(sendLimit=0, element=$("#exebtn")) { // in the definition of the `oncklick` action for the "Clear cache" button. // TODO: super ugly, find a better solution. let nothingToShow = false; - var params = {}; + let params = {}; + let headers = {}; if (sendLimit >= 0) { var original_query = editor.getValue(); var query = await rewriteQuery(original_query, { "name_service": "if_checked" }); - params["query"] = query; + let operationType = $("#operationType").val(); + switch (operationType) { + case "query": + params["query"] = query; + break; + case "update": + params["update"] = query; + headers["Authorization"] = `Bearer ${$("#access_token").val()}`; + break + default: + console.log("Unknown operation type", operationType); + } if (sendLimit > 0) { params["send"] = sendLimit; } @@ -522,7 +534,6 @@ async function processQuery(sendLimit=0, element=$("#exebtn")) { nothingToShow = true; } - const headers = {}; let ws = null; let queryId = undefined; if (!nothingToShow) { diff --git a/backend/templates/index.html b/backend/templates/index.html index 5dd5c07..82b9b51 100644 --- a/backend/templates/index.html +++ b/backend/templates/index.html @@ -241,7 +241,7 @@

QLever UI Shortcuts:

-
+
-
-
- -
- -
+ +
+ +
+
+ +
+
+
+ +
+ +
From d0677f67640a0c9169610c3f0362f3d2eeda17e0 Mon Sep 17 00:00:00 2001 From: Julian Mundhahs Date: Thu, 23 Jan 2025 11:16:08 +0100 Subject: [PATCH 02/17] move access token input to Backend Information --- backend/templates/index.html | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/backend/templates/index.html b/backend/templates/index.html index 82b9b51..5fc5620 100644 --- a/backend/templates/index.html +++ b/backend/templates/index.html @@ -91,6 +91,10 @@

Basic settings

Languages:{{ backend.filteredLanguage }} Default maximum{{ backend.maxDefault }} rows Default mode: {% if backend.dynamicSuggestions == 0 %}1. SPARQL syntax & keywords only{% elif backend.dynamicSuggestions == 1 %}2. SPARQL & context insensitive entities{% else %}3. SPARQL & context sensitive entities{% endif %} + + Access Token + +
@@ -268,9 +272,6 @@

QLever UI Shortcuts:

-
- -
-
- -
-
+
-
+
+ + + + + + + + + + + +
@@ -197,7 +213,7 @@

QLever UI Shortcuts:

- From 17deac655ff4139e96d7eb65da64e785c753485c Mon Sep 17 00:00:00 2001 From: Julian Mundhahs Date: Thu, 13 Feb 2025 18:40:39 +0100 Subject: [PATCH 12/17] change update message --- backend/static/js/qleverUI.js | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/backend/static/js/qleverUI.js b/backend/static/js/qleverUI.js index bea2664..0bd7b9e 100755 --- a/backend/static/js/qleverUI.js +++ b/backend/static/js/qleverUI.js @@ -625,15 +625,9 @@ async function processQuery(sendLimit=0, element=$("#exebtn")) { switch (operationType.type) { case "Update": $('#answerBlock, #infoBlock, #errorBlock').hide(); - let updateMessage = "Update successful."; const inserted = result["delta-triples"].difference.inserted; const deleted = result["delta-triples"].difference.deleted; - if (inserted > 0) { - updateMessage += ` Inserted ${inserted} triples.`; - } - if (deleted > 0) { - updateMessage += ` Deleted ${deleted} triples.`; - } + let updateMessage = `Update successful. (insert triples: ${inserted}, delete triples: ${deleted})`; $('#updateMetadata').html(updateMessage); $('#updatedBlock').show(); $("html, body").animate({ From 2c000166039a5d3a404cc6ca5ab4012a1d5040e4 Mon Sep 17 00:00:00 2001 From: Julian Mundhahs Date: Thu, 13 Feb 2025 18:55:44 +0100 Subject: [PATCH 13/17] foo --- backend/static/js/qleverUI.js | 9 ++++++++- backend/templates/index.html | 27 +++++++++++---------------- 2 files changed, 19 insertions(+), 17 deletions(-) diff --git a/backend/static/js/qleverUI.js b/backend/static/js/qleverUI.js index 0bd7b9e..e243b92 100755 --- a/backend/static/js/qleverUI.js +++ b/backend/static/js/qleverUI.js @@ -365,6 +365,14 @@ $(document).ready(function () { document.execCommand("copy"); $(this).parent().parent().parent().find(".ok-text").collapse("show"); }); + + $("#access_token").on("input", function () { + if($(this).val().trim() === "") { + $("#backend_commands").hide(); + } else { + $("#backend_commands").show(); + } + }); }); @@ -556,7 +564,6 @@ async function executeBackendCommand(command, element) { try { await fetchQleverBackend(params, headers); } catch (error) { - $(element).find('.glyphicon').removeClass('glyphicon-refresh'); $(element).find('.glyphicon').addClass('glyphicon-remove'); $(element).find('.glyphicon').css('color', 'red'); } finally { diff --git a/backend/templates/index.html b/backend/templates/index.html index b5e9738..fcfdaaf 100644 --- a/backend/templates/index.html +++ b/backend/templates/index.html @@ -93,22 +93,17 @@

Basic settings

Default mode: {% if backend.dynamicSuggestions == 0 %}1. SPARQL syntax & keywords only{% elif backend.dynamicSuggestions == 1 %}2. SPARQL & context insensitive entities{% else %}3. SPARQL & context sensitive entities{% endif %} Access Token - - - - - - - - - - - - + + From 6b0b2e3a488ffb14abc48480b728374f708816c4 Mon Sep 17 00:00:00 2001 From: Julian Mundhahs Date: Fri, 14 Feb 2025 10:49:31 +0100 Subject: [PATCH 14/17] changes noted from codereview - Show backend command buttons (Clear Delta Triples, Clear Cache (Complete) iff Access Token is not empty. Fixed that the buttons would not be shown if the field was not empty on load. - Backend command button icons are set correctly when transitioning between states (running, failed, succeeded). The buttons now also return to the green color after a successful execution. - Columns of Basic settings table in Backend Information changed widths when the backend command buttons where shown/hidden. Fixed by having them beneath each other. - Backend command buttons have some padding. - If the operation type was not detected this could also cause indefinite operation execution (although this seems to not be the only cause). Display an error in this case and prompt to report it. --- backend/static/js/helper.js | 10 ++++-- backend/static/js/qleverUI.js | 63 ++++++++++++++++++++++++++--------- backend/templates/index.html | 8 ++--- 3 files changed, 58 insertions(+), 23 deletions(-) diff --git a/backend/static/js/helper.js b/backend/static/js/helper.js index f6d1002..c8ffa49 100644 --- a/backend/static/js/helper.js +++ b/backend/static/js/helper.js @@ -757,6 +757,12 @@ function expandEditor() { } } +function displayInErrorBlock(message) { + $('#errorReason').html(message); + $('#errorBlock').show(); + $('#answerBlock, #infoBlock, #updatedBlock').hide(); +} + function displayError(response, queryId = undefined) { console.error("Either the GET request failed or the backend returned an error:", response); if (response["exception"] == undefined || response["exception"] == "") { @@ -784,9 +790,7 @@ function displayError(response, queryId = undefined) { queryToDisplay = htmlEscape(queryToDisplay); } disp += "Your query was: " + "
" + queryToDisplay + "
"; - $('#errorReason').html(disp); - $('#errorBlock').show(); - $('#answerBlock, #infoBlock, #updatedBlock').hide(); + displayInErrorBlock(disp); // If error response contains query and runtime info, append to runtime log. // diff --git a/backend/static/js/qleverUI.js b/backend/static/js/qleverUI.js index e243b92..fd75d32 100755 --- a/backend/static/js/qleverUI.js +++ b/backend/static/js/qleverUI.js @@ -366,12 +366,19 @@ $(document).ready(function () { $(this).parent().parent().parent().find(".ok-text").collapse("show"); }); - $("#access_token").on("input", function () { - if($(this).val().trim() === "") { - $("#backend_commands").hide(); + const accessToken = $("#access_token"); + + function updateBackendCommandVisibility() { + if (accessToken.val().trim() === "") { + $("#backend_commands").hide(); } else { $("#backend_commands").show(); } + } + + updateBackendCommandVisibility(); + accessToken.on("input", function () { + updateBackendCommandVisibility(); }); }); @@ -506,6 +513,7 @@ function createWebSocketForQuery(queryId, startTimeStamp, query) { function determineOperationType(operation) { // Strip all PREFIX, BASE and WITH statements from the beginning of the query const strippedOp = operation + .trim() .replace(/BASE\s+<[^<]*>\s*/gi, "") .replace(/PREFIX\s+\w+:\s+<[^<]*>\s*/gi, "") .replace(/WITH\s+((<[^<]*>)|(\w*:\w*))\s*/gi, ""); @@ -547,9 +555,33 @@ function determineOperationType(operation) { return {type: "Update", subtype: "Delete Where"}; } return {type: "Update", subtype: "Modify"}; + default: + return {type: "Unknown", subtype: "Unknown"}; + } +} + +function setRunningIndicator(element) { + const icon = $(element).find('.glyphicon'); + icon.addClass('glyphicon-spin glyphicon-refresh'); + icon.removeClass('glyphicon-remove'); + icon.css('color', $(element).css('color')); +} + +function removeRunningIndicator(element) { + const icon = $(element).find('.glyphicon'); + icon.removeClass('glyphicon-spin'); + if (icon.css("color") !== 'rgb(255, 0, 0)') { + icon.css('color', ''); } } +function setErrorIndicator(element) { + const icon = $(element).find('.glyphicon'); + icon.removeClass('glyphicon-refresh'); + icon.addClass('glyphicon-remove'); + icon.css('color', 'red'); +} + // Executes a backend command (e.g. `clear-cache`). async function executeBackendCommand(command, element) { log("Executing command: " + command); @@ -558,16 +590,13 @@ async function executeBackendCommand(command, element) { if (access_token.length > 0) headers["Authorization"] = `Bearer ${access_token}`; const params = {"cmd": command}; - $(element).find('.glyphicon').addClass('glyphicon-spin'); - $(element).find('.glyphicon').removeClass('glyphicon-remove'); - $(element).find('.glyphicon').css('color', $(element).css('color')); + setRunningIndicator(element); try { await fetchQleverBackend(params, headers); } catch (error) { - $(element).find('.glyphicon').addClass('glyphicon-remove'); - $(element).find('.glyphicon').css('color', 'red'); + setErrorIndicator(element) } finally { - $(element).find('.glyphicon').removeClass('glyphicon-spin'); + removeRunningIndicator(element); } } @@ -577,9 +606,7 @@ async function processQuery(sendLimit=0, element=$("#exebtn")) { log('Element: ' + element, 'other'); if (sendLimit >= 0) { displayStatus("Waiting for response..."); } - $(element).find('.glyphicon').addClass('glyphicon-spin glyphicon-refresh'); - $(element).find('.glyphicon').removeClass('glyphicon-remove'); - $(element).find('.glyphicon').css('color', $(element).css('color')); + setRunningIndicator(element); log('Sending request...', 'other'); let params = {}; @@ -601,6 +628,12 @@ async function processQuery(sendLimit=0, element=$("#exebtn")) { break default: console.log("Unknown operation type", operationType); + disp = "

Error processing operation

"; + disp += "Could not determine operation type (Query or Update). Please report this operation to us."; + displayInErrorBlock(disp); + setErrorIndicator(element); + removeRunningIndicator(element); + return; } if (sendLimit > 0) { params["send"] = sendLimit; @@ -797,9 +830,7 @@ async function processQuery(sendLimit=0, element=$("#exebtn")) { renderRuntimeInformationToDom(); } } catch (error) { - $(element).find('.glyphicon').removeClass('glyphicon-refresh'); - $(element).find('.glyphicon').addClass('glyphicon-remove'); - $(element).find('.glyphicon').css('color', 'red'); + setErrorIndicator(element); const errorContent = { "exception" : error.message || "Unknown error", "query": query @@ -807,7 +838,7 @@ async function processQuery(sendLimit=0, element=$("#exebtn")) { displayError(errorContent, queryId); } finally { currentlyActiveQueryWebSocket = null; - $(element).find('.glyphicon').removeClass('glyphicon-spin'); + removeRunningIndicator(element); // Make sure we have no socket that stays open forever if (ws) { closeWebSocket(ws); diff --git a/backend/templates/index.html b/backend/templates/index.html index fcfdaaf..327bfea 100644 --- a/backend/templates/index.html +++ b/backend/templates/index.html @@ -93,12 +93,12 @@

Basic settings

Default mode: {% if backend.dynamicSuggestions == 0 %}1. SPARQL syntax & keywords only{% elif backend.dynamicSuggestions == 1 %}2. SPARQL & context insensitive entities{% else %}3. SPARQL & context sensitive entities{% endif %} Access Token - -