Ver Fonte

Cancel all queries on page nav

Andrew Kane há 8 anos atrás
pai
commit
6d057d44e3

+ 1 - 0
CHANGELOG.md

@@ -1,5 +1,6 @@
 ## 1.7.2 [unreleased]
 
+- Cancel all queries on page nav
 - Prevent Ace from taking over find command
 
 ## 1.7.1

+ 81 - 192
app/assets/javascripts/blazer/application.js

@@ -14,133 +14,31 @@
 //= require ./bootstrap
 //= require ./vue
 //= require ./routes
+//= require ./queries
 
 Vue.config.devtools = false
 
 $(document).on('mouseenter', '.dropdown-toggle', function () {
-  $(this).parent().addClass('open');
-});
+  $(this).parent().addClass('open')
+})
 
 $(document).on("change", "#bind input, #bind select", function () {
-  submitIfCompleted($(this).closest("form"));
-});
+  submitIfCompleted($(this).closest("form"))
+})
 
 $(document).on("click", "#code", function () {
-  $(this).addClass("expanded");
-});
-
-function uuid() {
-  return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function(c) {
-    var r = Math.random()*16|0, v = c == 'x' ? r : (r&0x3|0x8);
-    return v.toString(16);
-  });
-}
-
-function cancelQuery(runningQuery) {
-  runningQuery.canceled = true;
-  var xhr = runningQuery.xhr;
-  if (xhr) {
-    xhr.abort();
-  }
-  remoteCancelQuery(runningQuery);
-  queryComplete();
-}
-
-function csrfProtect(payload) {
-  var param = $("meta[name=csrf-param]").attr("content");
-  var token = $("meta[name=csrf-token]").attr("content");
-  if (param && token) payload[param] = token;
-  return new Blob([JSON.stringify(payload)], {type : "application/json; charset=utf-8"});
-}
-
-function remoteCancelQuery(runningQuery) {
-  var path = Routes.blazer_cancel_queries_path();
-  var data = {run_id: runningQuery.run_id, data_source: runningQuery.data_source};
-  if (navigator.sendBeacon) {
-    navigator.sendBeacon(path, csrfProtect(data));
-  } else {
-    // TODO make sync
-    $.post(path, data);
-  }
-}
-
-var queriesQueue = [];
-var runningQueries = 0;
-var maxQueries = 3;
-
-function queueQuery(callback) {
-  queriesQueue.push(callback);
-  runNext();
-}
-
-function runNext() {
-  if (runningQueries < maxQueries) {
-    var callback = queriesQueue.shift();
-    if (callback) {
-      runningQueries++;
-      callback();
-      runNext();
-    }
-  }
-}
-
-function queryComplete() {
-  runningQueries--;
-  runNext();
-}
-
-function runQuery(data, success, error, runningQuery) {
-  queueQuery( function () {
-    runningQuery = runningQuery || {};
-    runningQuery.run_id = data.run_id = uuid();
-    runningQuery.data_source = data.data_source;
-    return runQueryHelper(data, success, error, runningQuery);
-  });
-}
-
-function runQueryHelper(data, success, error, runningQuery) {
-  var xhr = $.ajax({
-    url: Routes.blazer_run_queries_path(),
-    method: "POST",
-    data: data,
-    dataType: "html"
-  }).done( function (d) {
-    if (d[0] == "{") {
-      var response = $.parseJSON(d);
-      data.blazer = response;
-      setTimeout( function () {
-        if (!(runningQuery && runningQuery.canceled)) {
-          runQueryHelper(data, success, error, runningQuery);
-        }
-      }, 1000);
-    } else {
-      if (!(runningQuery && runningQuery.canceled)) {
-        success(d);
-      }
-      queryComplete();
-    }
-  }).fail( function(jqXHR, textStatus, errorThrown) {
-    if (!(runningQuery && runningQuery.canceled)) {
-      var message = (typeof errorThrown === "string") ? errorThrown : errorThrown.message;
-      error(message);
-    }
-    queryComplete();
-  });
-  if (runningQuery) {
-    runningQuery.xhr = xhr;
-  }
-  return xhr;
-}
+  $(this).addClass("expanded")
+})
 
 function submitIfCompleted($form) {
-  var completed = true;
+  var completed = true
   $form.find("input[name], select").each( function () {
     if ($(this).val() == "") {
-      completed = false;
+      completed = false
     }
-  });
+  })
   if (completed) {
-    $form.submit();
+    $form.submit()
   }
 }
 
@@ -148,140 +46,131 @@ function submitIfCompleted($form) {
 // Adapted from Biff MaGriff: http://stackoverflow.com/a/7895814/1196499
 function preventBackspaceNav() {
   $(document).keydown(function (e) {
-    var preventKeyPress;
+    var preventKeyPress
     if (e.keyCode == 8) {
-      var d = e.srcElement || e.target;
+      var d = e.srcElement || e.target
       switch (d.tagName.toUpperCase()) {
         case 'TEXTAREA':
-          preventKeyPress = d.readOnly || d.disabled;
-          break;
+          preventKeyPress = d.readOnly || d.disabled
+          break
         case 'INPUT':
-          preventKeyPress = d.readOnly || d.disabled || (d.attributes["type"] && $.inArray(d.attributes["type"].value.toLowerCase(), ["radio", "reset", "checkbox", "submit", "button"]) >= 0);
-          break;
+          preventKeyPress = d.readOnly || d.disabled || (d.attributes["type"] && $.inArray(d.attributes["type"].value.toLowerCase(), ["radio", "reset", "checkbox", "submit", "button"]) >= 0)
+          break
         case 'DIV':
-          preventKeyPress = d.readOnly || d.disabled || !(d.attributes["contentEditable"] && d.attributes["contentEditable"].value == "true");
-          break;
+          preventKeyPress = d.readOnly || d.disabled || !(d.attributes["contentEditable"] && d.attributes["contentEditable"].value == "true")
+          break
         default:
-          preventKeyPress = true;
-          break;
+          preventKeyPress = true
+          break
       }
     }
     else {
-      preventKeyPress = false;
+      preventKeyPress = false
     }
 
     if (preventKeyPress) {
-      e.preventDefault();
+      e.preventDefault()
     }
-  });
+  })
 }
 
-var editor;
+var editor
 
 // http://stackoverflow.com/questions/11584061/
 function adjustHeight() {
-  var lines = editor.getSession().getScreenLength();
+  var lines = editor.getSession().getScreenLength()
   if (lines < 9) {
-    lines = 9;
+    lines = 9
   }
 
-  var newHeight = (lines + 1) * 16;
-  $("#editor").height(newHeight.toString() + "px");
-  editor.resize();
-};
+  var newHeight = (lines + 1) * 16
+  $("#editor").height(newHeight.toString() + "px")
+  editor.resize()
+}
 
 function getSQL() {
-  var selectedText = editor.getSelectedText();
-  var text = selectedText.length < 10 ? editor.getValue() : selectedText;
-  return text.replace(/\n/g, "\r\n");
+  var selectedText = editor.getSelectedText()
+  var text = selectedText.length < 10 ? editor.getValue() : selectedText
+  return text.replace(/\n/g, "\r\n")
 }
 
 function getErrorLine() {
-  var error_line = /LINE (\d+)/g.exec($("#results").find('.alert-danger').text());
+  var error_line = /LINE (\d+)/g.exec($("#results").find('.alert-danger').text())
 
   if (error_line) {
-    error_line = parseInt(error_line[1], 10);
+    error_line = parseInt(error_line[1], 10)
     if (editor.getSelectedText().length >= 10) {
-      error_line += editor.getSelectionRange().start.row;
+      error_line += editor.getSelectionRange().start.row
     }
-    return error_line;
+    return error_line
   }
 }
 
-var error_line = null;
-var runningQuery;
-
-function queryDone() {
-  runningQuery = null
-  $("#run").removeClass("hide")
-  $("#cancel").addClass("hide")
-}
+var error_line = null
 
 $(document).on("click", "#cancel", function (e) {
   e.preventDefault()
 
-  cancelQuery(runningQuery)
+  cancelAllQueries()
+
   queryDone()
 
   $("#results").html("")
 })
 
-function cancelQuery2() {
-  if (runningQuery) {
-    remoteCancelQuery(runningQuery)
-  }
+function queryDone() {
+  $("#run").removeClass("hide")
+  $("#cancel").addClass("hide")
 }
 
-$(window).unload(cancelQuery2)
-
 $(document).on("click", "#run", function (e) {
-  e.preventDefault();
+  e.preventDefault()
 
   $(this).addClass("hide")
   $("#cancel").removeClass("hide")
 
   if (error_line) {
-    editor.getSession().removeGutterDecoration(error_line - 1, "error");
-    error_line = null;
+    editor.getSession().removeGutterDecoration(error_line - 1, "error")
+    error_line = null
   }
 
-  $("#results").html('<p class="text-muted">Loading...</p>');
+  $("#results").html('<p class="text-muted">Loading...</p>')
 
-  var data = $.extend({}, params, {statement: getSQL(), data_source: $("#query_data_source").val()});
+  var data = $.extend({}, params, {statement: getSQL(), data_source: $("#query_data_source").val()})
 
-  runningQuery = {};
+  cancelAllQueries()
 
   runQuery(data, function (data) {
     queryDone()
 
-    $("#results").html(data);
+    $("#results").html(data)
 
-    error_line = getErrorLine();
+    error_line = getErrorLine()
     if (error_line) {
-      editor.getSession().addGutterDecoration(error_line - 1, "error");
-      editor.scrollToLine(error_line, true, true, function () {});
-      editor.gotoLine(error_line, 0, true);
-      editor.focus();
+      editor.getSession().addGutterDecoration(error_line - 1, "error")
+      editor.scrollToLine(error_line, true, true, function () {})
+      editor.gotoLine(error_line, 0, true)
+      editor.focus()
     }
   }, function (data) {
     // TODO show error
     queryDone()
-  }, runningQuery);
-});
+  })
+})
 
 $(document).on("change", "#table_names", function () {
-  var val = $(this).val();
+  var val = $(this).val()
   if (val.length > 0) {
-    var dataSource = $("#query_data_source").val();
-    editor.setValue(previewStatement[dataSource].replace("{table}", val), 1);
-    $("#run").click();
+    var dataSource = $("#query_data_source").val()
+    editor.setValue(previewStatement[dataSource].replace("{table}", val), 1)
+    $("#run").click()
   }
-});
+})
 
 function showEditor() {
-  editor = ace.edit("editor");
-  editor.setTheme("ace/theme/twilight");
-  editor.getSession().setMode("ace/mode/sql");
+  editor = ace.edit("editor")
+  editor.setTheme("ace/theme/twilight")
+  editor.getSession().setMode("ace/mode/sql")
   editor.setOptions({
     enableBasicAutocompletion: false,
     enableSnippets: false,
@@ -289,32 +178,32 @@ function showEditor() {
     highlightActiveLine: false,
     fontSize: 12,
     minLines: 10
-  });
-  editor.renderer.setShowGutter(true);
-  editor.renderer.setPrintMarginColumn(false);
-  editor.renderer.setPadding(10);
-  editor.getSession().setUseWrapMode(true);
+  })
+  editor.renderer.setShowGutter(true)
+  editor.renderer.setPrintMarginColumn(false)
+  editor.renderer.setPadding(10)
+  editor.getSession().setUseWrapMode(true)
   editor.commands.addCommand({
     name: 'run',
     bindKey: {win: 'Ctrl-Enter',  mac: 'Command-Enter'},
     exec: function(editor) {
-      $("#run").click();
+      $("#run").click()
     },
     readOnly: false // false if this command should not apply in readOnly mode
-  });
+  })
   // fix command+L
-  editor.commands.removeCommands(["gotoline", "find"]);
+  editor.commands.removeCommands(["gotoline", "find"])
 
   editor.getSession().on("change", function () {
-    $("#query_statement").val(editor.getValue());
-    adjustHeight();
-  });
-  adjustHeight();
-  $("#editor").show();
-  editor.focus();
+    $("#query_statement").val(editor.getValue())
+    adjustHeight()
+  })
+  adjustHeight()
+  $("#editor").show()
+  editor.focus()
 }
 
-preventBackspaceNav();
+preventBackspaceNav()
 
 function updatePreviewSelect() {
   var dataSource = $("#query_data_source").val()

+ 107 - 0
app/assets/javascripts/blazer/queries.js

@@ -0,0 +1,107 @@
+var pendingQueries = []
+var runningQueries = []
+var maxQueries = 3
+
+function runQuery(data, success, error) {
+  data.run_id = uuid()
+  var query = {
+    data: data,
+    success: success,
+    error: error,
+    run_id: data.run_id,
+    data_source: data.data_source,
+    canceled: false
+  }
+  pendingQueries.push(query)
+  runNext()
+  return query
+}
+
+function runNext() {
+  if (runningQueries.length < maxQueries) {
+    var query = pendingQueries.shift()
+    if (query) {
+      runningQueries.push(query)
+      runQueryHelper(query)
+      runNext()
+    }
+  }
+}
+
+function runQueryHelper(query) {
+  var xhr = $.ajax({
+    url: Routes.blazer_run_queries_path(),
+    method: "POST",
+    data: query.data,
+    dataType: "html"
+  }).done( function (d) {
+    if (d[0] == "{") {
+      var response = $.parseJSON(d)
+      query.data.blazer = response
+      setTimeout( function () {
+        if (!query.canceled) {
+          runQueryHelper(query)
+        }
+      }, 1000)
+    } else {
+      if (!query.canceled) {
+        query.success(d)
+      }
+      queryComplete(query)
+    }
+  }).fail( function(jqXHR, textStatus, errorThrown) {
+    if (!query.canceled) {
+      var message = (typeof errorThrown === "string") ? errorThrown : errorThrown.message
+      query.error(message)
+    }
+    queryComplete(query)
+  })
+  query.xhr = xhr
+  return xhr
+}
+
+function queryComplete(query) {
+  var index = runningQueries.indexOf(query)
+  runningQueries.splice(index, 1)
+  runNext()
+}
+
+function uuid() {
+  return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function(c) {
+    var r = Math.random()*16|0, v = c == 'x' ? r : (r&0x3|0x8)
+    return v.toString(16)
+  })
+}
+
+function cancelAllQueries() {
+  pendingQueries = []
+  for (var i = 0; i < runningQueries.length; i++) {
+    cancelQuery(runningQueries[i])
+  }
+}
+
+$(window).unload(cancelAllQueries)
+
+function cancelQuery(query) {
+  query.canceled = true
+  if (query.xhr) {
+    query.xhr.abort()
+  }
+
+  // tell server
+  var path = Routes.blazer_cancel_queries_path()
+  var data = {run_id: query.run_id, data_source: query.data_source}
+  if (navigator.sendBeacon) {
+    navigator.sendBeacon(path, csrfProtect(data))
+  } else {
+    // TODO make sync
+    $.post(path, data)
+  }
+}
+
+function csrfProtect(payload) {
+  var param = $("meta[name=csrf-param]").attr("content")
+  var token = $("meta[name=csrf-token]").attr("content")
+  if (param && token) payload[param] = token
+  return new Blob([JSON.stringify(payload)], {type : "application/json charset=utf-8"})
+}