瀏覽代碼

HUE-294 [beeswax] Query editor should have line numbers

Added textarea plugin
Added client side parsing of the error line number
Enrico Berti 13 年之前
父節點
當前提交
a052b146a1

+ 104 - 57
apps/beeswax/src/beeswax/templates/execute.mako

@@ -23,29 +23,21 @@
 <%namespace name="layout" file="layout.mako" />
 
 <%def name="query()">
-    <h1>${_('Query Editor')}</h1>
-    <fieldset>
-        % if design and not design.is_auto and design.name:
-            <legend>${design.name}</legend>
-            % if design.desc:
-              <p>${design.desc}</p>
-            % endif
-
-          % else:
-            <legend>${_('Query')}</legend>
-          % endif
-
-      <div class="clearfix">
-        <div class="input">
-            <textarea class="span9" rows="18" placeholder="${_('Example: SELECT * FROM tablename')}" name="${form.query["query"].html_name | n}" id="queryField">${extract_field_data(form.query["query"]) or ''}</textarea>
-            <div id="validationResults">
-            % if len(form.query["query"].errors):
-                ${unicode(form.query["query"].errors) | n}
-             % endif
-            </div>
-        </div>
-      </div>
-    </fieldset>
+    % if design and not design.is_auto and design.name:
+      <h1>${_('Query Editor')} : ${design.name}</h1>
+      % if design.desc:
+        <p>${design.desc}</p>
+      % endif
+    % else:
+      <h1>${_('Query Editor')}</h1>
+    % endif
+
+    <textarea class="span9" rows="18" placeholder="${_('Example: SELECT * FROM tablename')}" name="${form.query["query"].html_name | n}" id="queryField">${extract_field_data(form.query["query"]) or ''}</textarea>
+    <div id="validationResults">
+    % if len(form.query["query"].errors):
+        ${unicode(form.query["query"].errors) | n}
+     % endif
+    </div>
 
     <div class="actions">
         <a id="executeQuery" class="btn btn-primary">${_('Execute')}</a>
@@ -218,7 +210,7 @@ ${layout.menubar(section='query')}
             % if error_message:
                 <div class="alert alert-error">
                     <p><strong>${_('Your query has the following error(s):')}</strong></p>
-                    <p>${error_message}</p>
+                    <p class="queryErrorMessage">${error_message}</p>
                     % if log:
                         <small>${_('click the')} <b>${_('Error Log')}</b> ${_('tab below for details')}</small>
                     % endif
@@ -308,43 +300,82 @@ ${layout.menubar(section='query')}
     </div>
 </div>
 
+<link rel="stylesheet" href="/static/ext/css/jquery-linedtextarea.css" type="text/css" media="screen" title="no title" charset="utf-8" />
+<script src="/static/ext/js/jquery/plugins/jquery-linedtextarea.js" type="text/javascript" charset="utf-8"></script>
+
 <style>
-    #filechooser {
-        min-height:100px;
-        overflow-y:scroll;
-    }
-    .control-group label {
-        float: left;
-        padding-top: 5px;
-        text-align: left;
-        width: 40px;
-    }
-    .nav-list {
-        padding:0;
-    }
-    .param {
-        background:#FDFDFD;
-        padding: 8px 8px 1px 8px;
-        border-radius: 4px;
-        -webkit-border-radius: 4px;
-        -moz-border-radius: 4px;
-        margin-bottom:5px;
-        border:1px solid #EEE;
-    }
-    .remove {
-        float:right;
-    }
-    .file_resourcesField {
-        border-radius: 3px 0 0 3px;
-        border-right:0;
-    }
-    .fileChooserBtn {
-        border-radius: 0 3px 3px 0;
-    }
+  h1 {
+    margin-bottom: 5px;
+  }
+  #filechooser {
+    min-height: 100px;
+    overflow-y: scroll;
+  }
+
+  .control-group label {
+    float: left;
+    padding-top: 5px;
+    text-align: left;
+    width: 40px;
+  }
+
+  .nav-list {
+    padding: 0;
+  }
+
+  .param {
+    background: #FDFDFD;
+    padding: 8px 8px 1px 8px;
+    border-radius: 4px;
+    -webkit-border-radius: 4px;
+    -moz-border-radius: 4px;
+    margin-bottom: 5px;
+    border: 1px solid #EEE;
+  }
+
+  .remove {
+    float: right;
+  }
+
+  .file_resourcesField {
+    border-radius: 3px 0 0 3px;
+    border-right: 0;
+  }
+
+  .fileChooserBtn {
+    border-radius: 0 3px 3px 0;
+  }
+
+  .linedwrap {
+    margin-top: 20px;
+    margin-bottom: 10px;
+    -webkit-border-radius: 4px;
+    -moz-border-radius: 4px;
+    border-radius: 4px;
+    background-color: #ffffff;
+    border: 1px solid #cccccc;
+    -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);
+    -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);
+    box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);
+    -webkit-transition: border linear 0.2s, box-shadow linear 0.2s;
+    -moz-transition: border linear 0.2s, box-shadow linear 0.2s;
+    -o-transition: border linear 0.2s, box-shadow linear 0.2s;
+    transition: border linear 0.2s, box-shadow linear 0.2s;
+  }
+
+  .linedtextarea textarea {
+    -webkit-box-shadow: none;
+    -moz-box-shadow: none;
+    box-shadow: none;
+  }
+
+  .linedwrap .codelines .lineselect {
+    color: #B94A48;
+    background-color: #F2DEDE;
+  }
 
 </style>
 
-
 <script type="text/javascript" charset="utf-8">
     $(document).ready(function(){
         $("*[rel=tooltip]").tooltip({
@@ -434,6 +465,22 @@ ${layout.menubar(section='query')}
             $("#validationResults").empty();
         });
 
+        var selectedLine = -1;
+        if ($(".queryErrorMessage")){
+          var err = $(".queryErrorMessage").text().toLowerCase();
+          var firstPos = err.indexOf("line");
+          selectedLine = $.trim(err.substring(err.indexOf(" ", firstPos), err.indexOf(":", firstPos)))*1;
+        }
+
+        if (selectedLine > -1){
+          $("#queryField").linedtextarea({
+            selectedLine: selectedLine
+          });
+        }
+        else {
+          $("#queryField").linedtextarea();
+        }
+
         function checkAndSubmit(){
             $(".query").val($("#queryField").val());
             $("#advancedSettingsForm").submit();

+ 68 - 0
desktop/core/static/ext/css/jquery-linedtextarea.css

@@ -0,0 +1,68 @@
+/**
+ * jQuery Lined Textarea Plugin
+ *   http://alan.blog-city.com/jquerylinedtextarea.htm
+ *
+ * Copyright (c) 2010 Alan Williamson
+ *
+ * Released under the MIT License:
+ * http://www.opensource.org/licenses/mit-license.php
+ * 
+ * Usage:
+ *   Displays a line number count column to the left of the textarea
+ *   
+ *   Class up your textarea with a given class, or target it directly
+ *   with JQuery Selectors
+ *   
+ *   $(".lined").linedtextarea({
+ *   	selectedLine: 10,
+ *    selectedClass: 'lineselect'
+ *   });
+ *
+ */
+
+.linedwrap {
+  border: 1px solid #c0c0c0;
+  padding: 3px;
+}
+
+.linedtextarea {
+  padding: 0px;
+  margin: 0px;
+}
+
+.linedtextarea textarea, .linedwrap .codelines .lineno {
+  font-size: 10pt;
+  font-family: monospace;
+  line-height: normal !important;
+}
+
+.linedtextarea textarea {
+  padding-right: 0.3em;
+  padding-top: 0.3em;
+  border: 0;
+}
+
+.linedwrap .lines {
+  margin-top: 0px;
+  width: 50px;
+  float: left;
+  overflow: hidden;
+  border-right: 1px solid #c0c0c0;
+  margin-right: 10px;
+}
+
+.linedwrap .codelines {
+  padding-top: 5px;
+}
+
+.linedwrap .codelines .lineno {
+  color: #AAAAAA;
+  padding-right: 0.5em;
+  padding-top: 0.0em;
+  text-align: right;
+  white-space: nowrap;
+}
+
+.linedwrap .codelines .lineselect {
+  color: red;
+}

+ 126 - 0
desktop/core/static/ext/js/jquery/plugins/jquery-linedtextarea.js

@@ -0,0 +1,126 @@
+/**
+ * jQuery Lined Textarea Plugin
+ *   http://alan.blog-city.com/jquerylinedtextarea.htm
+ *
+ * Copyright (c) 2010 Alan Williamson
+ *
+ * Version:
+ *    $Id: jquery-linedtextarea.js 464 2010-01-08 10:36:33Z alan $
+ *
+ * Released under the MIT License:
+ *    http://www.opensource.org/licenses/mit-license.php
+ *
+ * Usage:
+ *   Displays a line number count column to the left of the textarea
+ *
+ *   Class up your textarea with a given class, or target it directly
+ *   with JQuery Selectors
+ *
+ *   $(".lined").linedtextarea({
+ *   	selectedLine: 10,
+ *    selectedClass: 'lineselect'
+ *   });
+ *
+ * History:
+ *   - 2010.01.08: Fixed a Google Chrome layout problem
+ *   - 2010.01.07: Refactored code for speed/readability; Fixed horizontal sizing
+ *   - 2010.01.06: Initial Release
+ *
+ */
+(function ($) {
+
+  $.fn.linedtextarea = function (options) {
+
+    // Get the Options
+    var opts = $.extend({}, $.fn.linedtextarea.defaults, options);
+
+
+    /*
+     * Helper function to make sure the line numbers are always
+     * kept up to the current system
+     */
+    var fillOutLines = function (codeLines, h, lineNo) {
+      while ((codeLines.height() - h ) <= 0) {
+        if (lineNo == opts.selectedLine)
+          codeLines.append("<div class='lineno lineselect'>" + lineNo + "</div>");
+        else
+          codeLines.append("<div class='lineno'>" + lineNo + "</div>");
+
+        lineNo++;
+      }
+      return lineNo;
+    };
+
+
+    /*
+     * Iterate through each of the elements are to be applied to
+     */
+    return this.each(function () {
+      var lineNo = 1;
+      var textarea = $(this);
+
+      /* Turn off the wrapping of as we don't want to screw up the line numbers */
+      textarea.attr("wrap", "off");
+      textarea.css({resize:'none'});
+      var originalTextAreaWidth = textarea.outerWidth();
+
+      /* Wrap the text area in the elements we need */
+      textarea.wrap("<div class='linedtextarea'></div>");
+      var linedTextAreaDiv = textarea.parent().wrap("<div class='linedwrap' style='width:" + originalTextAreaWidth + "px'></div>");
+      var linedWrapDiv = linedTextAreaDiv.parent();
+
+      linedWrapDiv.prepend("<div class='lines' style='width:50px'></div>");
+
+      var linesDiv = linedWrapDiv.find(".lines");
+      linesDiv.height(textarea.height() + 6);
+
+
+      /* Draw the number bar; filling it out where necessary */
+      linesDiv.append("<div class='codelines'></div>");
+      var codeLinesDiv = linesDiv.find(".codelines");
+      lineNo = fillOutLines(codeLinesDiv, linesDiv.height(), 1);
+
+
+      /* Set the width */
+      var sidebarWidth = linesDiv.outerWidth();
+      var paddingHorizontal = parseInt(linedWrapDiv.css("border-left-width")) + parseInt(linedWrapDiv.css("border-right-width")) + parseInt(linedWrapDiv.css("padding-left")) + parseInt(linedWrapDiv.css("padding-right"));
+      var linedWrapDivNewWidth = originalTextAreaWidth - paddingHorizontal;
+      var textareaNewWidth = originalTextAreaWidth - sidebarWidth - paddingHorizontal - 20;
+
+      textarea.width(textareaNewWidth);
+      linedWrapDiv.width(linedWrapDivNewWidth);
+
+
+      /* React to the scroll event */
+      textarea.scroll(function (tn) {
+        var domTextArea = $(this)[0];
+        var scrollTop = domTextArea.scrollTop;
+        var clientHeight = domTextArea.clientHeight;
+        codeLinesDiv.css({'margin-top':(-1 * scrollTop) + "px"});
+        lineNo = fillOutLines(codeLinesDiv, scrollTop + clientHeight, lineNo);
+      });
+
+
+      /* Should the textarea get resized outside of our control */
+      textarea.resize(function (tn) {
+        var domTextArea = $(this)[0];
+        linesDiv.height(domTextArea.clientHeight + 6);
+      });
+
+      /* Move the textarea to the selected line */
+      if (opts.selectedLine != -1 && !isNaN(opts.selectedLine)) {
+        var fontSize = parseInt(textarea.height() / (lineNo - 2));
+        var position = parseInt(fontSize * opts.selectedLine) - (textarea.height() / 2);
+        textarea[0].scrollTop = position;
+      }
+
+
+    });
+  };
+
+  // default options
+  $.fn.linedtextarea.defaults = {
+    selectedLine:-1,
+    selectedClass:'lineselect'
+  };
+})(jQuery);