Selaa lähdekoodia

HUE-5764 [metadata] Further style the complexity and syntax validation

Enrico Berti 8 vuotta sitten
vanhempi
commit
ab68c76

+ 43 - 8
desktop/core/src/desktop/static/desktop/js/ace.extended.js

@@ -73,38 +73,73 @@ try {
       $(".ace-inline-button").hide();
     }
 
-    editor.clearErrorsAndWarnings = function() {
+    editor.clearAnnotations = function (type) {
+      if (type === 'error') {
+        this.session.setAnnotations(this.session.getAnnotations().filter(function (item) {
+          return item.type === 'warning'
+        }));
+      }
+      else if (type === 'warning') {
+        this.session.setAnnotations(this.session.getAnnotations().filter(function (item) {
+          return item.type === 'error'
+        }));
+      }
+      else {
+        this.session.clearAnnotations();
+      }
+    }
+
+    editor.clearErrorsAndWarnings = function (type) {
       for (var id in this.session.getMarkers()) {
         var _marker = this.session.getMarkers()[id];
-        if (_marker.clazz == "ace_error-line" || _marker.clazz == "ace_warning-line"){
+        var _condition = _marker.clazz == "ace_error-line" || _marker.clazz == "ace_warning-line";
+        if (type === 'error') {
+          _condition = _marker.clazz == "ace_error-line";
+        }
+        if (type === 'warning') {
+          _condition = _marker.clazz == "ace_warning-line";
+        }
+        if (_condition) {
           this.session.removeMarker(_marker.id);
         }
-      };
-      this.session.clearAnnotations();
+      }
+      editor.clearAnnotations(type);
+    }
+
+    editor.clearErrors = function () {
+      editor.clearErrorsAndWarnings('error');
+    }
+
+    editor.clearWarnings = function () {
+      editor.clearErrorsAndWarnings('warning');
     }
 
     editor.addError = function (message, line) {
       var _range = new AceRange(line, 0, line, this.session.getLine(line).length);
       this.session.addMarker(_range, "ace_error-line");
-      this.session.setAnnotations([{
+      var errors = this.session.getAnnotations();
+      errors.push({
         row: _range.start.row,
         column: _range.start.column,
         raw: message,
         text: message,
         type: "error"
-      }]);
+      });
+      this.session.setAnnotations(errors);
     }
 
     editor.addWarning = function (message, line) {
       var _range = new AceRange(line, 0, line, this.session.getLine(line).length);
       this.session.addMarker(_range, "ace_warning-line");
-      this.session.setAnnotations([{
+      var warnings = this.session.getAnnotations();
+      warnings.push({
         row: _range.start.row,
         column: _range.start.column,
         raw: message,
         text: message,
         type: "warning"
-      }]);
+      });
+      this.session.setAnnotations(warnings);
     }
 
     return editor;

+ 8 - 18
desktop/core/src/desktop/static/desktop/js/ko.hue-bindings.js

@@ -573,21 +573,6 @@
     }
   };
 
-  ko.bindingHandlers.toggleIconExplanation = {
-    init: function (element, valueAccessor) {
-      var $explanation = $(element).next('.icon-explanation');
-      $explanation.addClass('hide');
-      $(element).addClass('pointer').on('click', function(){
-        if ($explanation.hasClass('hide')) {
-          $explanation.removeClass('hide');
-        }
-        else {
-          $explanation.addClass('hide');
-        }
-      });
-    }
-  };
-
   /**
    * This binding can be used to show a custom context menu on right-click,
    * It assumes that the context menu is nested within the bound element and
@@ -3165,7 +3150,7 @@
       }
 
       function processErrorsAndWarnings(type, list) {
-        editor.clearErrorsAndWarnings();
+        editor.clearErrorsAndWarnings(type);
         var offset = 0;
         if (snippet.isSqlDialect()) {
           if (editor.getSelectedText()) {
@@ -3197,11 +3182,16 @@
         }
       }
 
-      snippet.warnings.subscribe(function (newWarnings) {
+
+      snippet.errors.subscribe(function (newErrors) {
+        processErrorsAndWarnings('error', newErrors);
+      });
+
+      snippet.aceWarnings.subscribe(function (newWarnings) {
         processErrorsAndWarnings('warning', newWarnings);
       });
 
-      snippet.errors.subscribe(function (newErrors) {
+      snippet.aceErrors.subscribe(function (newErrors) {
         processErrorsAndWarnings('error', newErrors);
       });
 

Tiedoston diff-näkymää rajattu, sillä se on liian suuri
+ 0 - 0
desktop/libs/notebook/src/notebook/static/notebook/css/notebook.css


+ 31 - 13
desktop/libs/notebook/src/notebook/static/notebook/js/notebook.ko.js

@@ -274,7 +274,16 @@ var EditorViewModel = (function() {
     // Ace stuff
     self.ace = ko.observable(null);
     self.errors = ko.observableArray([]);
-    self.warnings = ko.observableArray([]);
+
+    self.aceErrorsHolder = ko.observableArray([]);
+    self.aceWarningsHolder = ko.observableArray([]);
+
+    self.aceErrors = ko.pureComputed(function(){
+      return self.showOptimizer() ? self.aceErrorsHolder() : [];
+    });
+    self.aceWarnings = ko.pureComputed(function(){
+      return self.showOptimizer() ? self.aceWarningsHolder() : [];
+    });
 
     self.availableSnippets = vm.availableSnippets();
     self.inFocus = ko.observable(false);
@@ -809,26 +818,28 @@ var EditorViewModel = (function() {
     self.complexityCheckActive = ko.observable(true);
     self.compatibilityCheckActive = ko.observable(true);
 
+    self.showOptimizer = ko.observable(false);
+
     self.isOptimizing = ko.observable(false);
 
     if (HAS_OPTIMIZER) {
-      var lastRequest;
-      var lastCheckedStatement;
+      var lastComplexityRequest;
+      var lastCheckedComplexityStatement;
 
-      self.delayedStatement = ko.pureComputed(self.statement).extend({ rateLimit: { method: "notifyWhenChangesStop", timeout: 3000 } });
+      self.delayedStatement = ko.pureComputed(self.statement).extend({ rateLimit: { method: "notifyWhenChangesStop", timeout: 2000 } });
 
       self.checkComplexity = function () {
-        if (lastCheckedStatement === self.statement_raw()) {
+        if (lastCheckedComplexityStatement === self.statement_raw()) {
           return;
         }
 
-        if (lastRequest && lastRequest.readyState < 4) {
-          lastRequest.abort();
+        if (lastComplexityRequest && lastComplexityRequest.readyState < 4) {
+          lastComplexityRequest.abort();
         }
 
         logGA('get_query_risk');
         self.isOptimizing(true);
-        lastRequest = $.ajax({
+        lastComplexityRequest = $.ajax({
           type: 'POST',
           url: '/notebook/api/optimizer/statement/risk',
           timeout: 10000, // 10 seconds
@@ -843,7 +854,7 @@ var EditorViewModel = (function() {
               // TODO: Silence errors
               $(document).trigger('error', data.message);
             }
-            lastCheckedStatement = self.statement_raw();
+            lastCheckedComplexityStatement = self.statement_raw();
             self.isOptimizing(false);
           }
         });
@@ -1151,7 +1162,13 @@ var EditorViewModel = (function() {
 
     self.compatibilityTarget = ko.observable('');
 
+    var lastCompatibilityRequest;
+
     self.queryCompatibility = function (targetPlatform) {
+      if (lastCompatibilityRequest && lastCompatibilityRequest.readyState < 4) {
+        lastCompatibilityRequest.abort();
+      }
+
       logGA('compatibility');
       self.isOptimizing(true);
 
@@ -1161,17 +1178,19 @@ var EditorViewModel = (function() {
 
       self.compatibilityTarget(targetPlatform);
 
-      $.post("/notebook/api/optimizer/statement/compatibility", {
+      lastCompatibilityRequest = $.post("/notebook/api/optimizer/statement/compatibility", {
         notebook: ko.mapping.toJSON(notebook.getContext()),
         snippet: ko.mapping.toJSON(self.getContext()),
         sourcePlatform: self.type(),
         targetPlatform: targetPlatform
       }, function (data) {
         if (data.status == 0) {
+          self.aceErrorsHolder([]);
+          self.aceWarningsHolder([]);
           self.suggestion(ko.mapping.fromJS(data.query_compatibility));
           if (self.suggestion().queryError.errorString()) {
             var match = ERROR_REGEX.exec(self.suggestion().queryError.errorString());
-            self.warnings.push({
+            self.aceWarningsHolder.push({
               message: self.suggestion().queryError.errorString(),
               line: match === null ? null : parseInt(match[1]) - 1,
               col: match === null ? null : (typeof match[3] !== 'undefined' ? parseInt(match[3]) : null)
@@ -1179,13 +1198,12 @@ var EditorViewModel = (function() {
           }
           if (self.suggestion().parseError()) {
             var match = ERROR_REGEX.exec(self.suggestion().parseError());
-            self.errors.push({
+            self.aceErrorsHolder.push({
               message: self.suggestion().parseError(),
               line: match === null ? null : parseInt(match[1]) - 1,
               col: match === null ? null : (typeof match[3] !== 'undefined' ? parseInt(match[3]) : null)
             });
           }
-
           self.hasSuggestion(true);
         } else {
           $(document).trigger("error", data.message);

+ 43 - 0
desktop/libs/notebook/src/notebook/static/notebook/less/notebook.less

@@ -1189,6 +1189,49 @@ h4.header {
   filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#F1F1F1', endColorstr='#00ffffff', GradientType=1);
 }
 
+.alert-warning {
+  background-color: #fcf8e3;
+  border: 1px solid #f0c36d;
+  color: #c09853;
+}
+
+.round-icon {
+  display: inline-block;
+  width: 16px;
+  height: 16px;
+  text-align: center;
+  line-height: 16px;
+  border-radius: 8px;
+  font-size: 12px;
+  color: #FFF;
+  opacity: .8;
+  cursor: pointer;
+  margin-bottom: 12px;
+  &.empty {
+    width: 1px;
+  }
+  &.idle {
+    background-color: #CCC;
+  }
+  &:hover {
+    opacity: 1;
+  }
+  &.success {
+    background-color: #468847;
+  }
+  &.warning {
+    background-color: #f0c36d;
+    color: #FFF;
+  }
+  &.error {
+    background-color: #b94a48;
+  }
+}
+
+.active .round-icon {
+  opacity: 1;
+}
+
 .alert-neutral {
   border: none;
   margin-top: -3px;

+ 58 - 29
desktop/libs/notebook/src/notebook/templates/editor_components.mako

@@ -1026,40 +1026,59 @@ from notebook.conf import ENABLE_QUERY_BUILDER, ENABLE_QUERY_SCHEDULING, ENABLE_
 
 <script type="text/html" id="code-editor-snippet-body">
   <!-- ko if: HAS_OPTIMIZER -->
-  <div class="alert alert-empty">
-    &nbsp;
-    <!-- ko if: hasComplexity() -->
-      <!-- ko if: complexity() && complexity().risk() -->
-      <div class="alert alert-neutral" data-bind="css: {'alert-success': complexity().risk().length == 0, 'alert-warning': complexity().risk().length > 0 && complexity().risk() !== 'high', 'alert-error': complexity().risk() === 'high' }">
-        <!-- ko if: complexity().risk().length == 0 -->
-        <i class="fa fa-check-circle" data-bind="toggleIconExplanation"></i> <span class="icon-explanation">${ _('No risks were detected in this query.') }</span>
-        <!-- /ko -->
-        <!-- ko if: complexity().risk().length > 0 && complexity().risk() !== 'high' -->
-        <i class="fa fa-arrow-circle-down" data-bind="toggleIconExplanation"></i> <span class="icon-explanation">${ _('This query has a low risk profile.') }</span>
-        <!-- /ko -->
-        <!-- ko if: complexity().risk() === 'high' -->
-        <i class="fa fa-exclamation-circle" data-bind="toggleIconExplanation"></i> <span class="icon-explanation"><strong data-bind="text: complexity().riskAnalysis"></strong> <span data-bind="text: complexity().riskRecommendation"></span></span>
-        <!-- /ko -->
-      </div>
-      <!-- /ko -->
+  <div title="${ _('Query Validator') }" data-bind="click: function(){ showOptimizer(!showOptimizer()) }, css: { 'active': showOptimizer }">
+    <div class="round-icon empty">&nbsp;</div>
+    <!-- ko if: !hasSuggestion() -->
+    <div class="round-icon idle">
+      <i class="fa fa-check"></i>
+    </div>
     <!-- /ko -->
-
     <!-- ko if: hasSuggestion() -->
-      <!-- ko with: suggestion() -->
-        <div class="alert alert-neutral" data-bind="css: {'alert-success': queryError.encounteredString().length == 0 && !parseError(), 'alert-warning': queryError.encounteredString().length > 0 && !parseError(), 'alert-error': parseError() }">
-        <!-- ko if: !parseError() && $parent.compatibilityTarget() != $parent.type() && queryError.encounteredString().length == 0 -->
-          <i class="fa fa-check" data-bind="toggleIconExplanation"></i> <span class="icon-explanation">${ _('The query is compatible with Impala.') } <a href="javascript:void(0)" data-bind="click: function() { $parent.type('impala') }">${ _('Execute it now in Impala!') }</a></span>
-        <!-- /ko -->
-        <!-- ko if: !parseError() && $parent.compatibilityTarget() == $parent.type() -->
-          <i class="fa fa-check" data-bind="toggleIconExplanation"></i> <span class="icon-explanation">${ _('The query has no errors.') }</span>
-        <!-- /ko -->
-        <!-- ko if: parseError -->
-          <i class="fa fa-exclamation" data-bind="toggleIconExplanation"></i> <span class="icon-explanation"><span data-bind="text: parseError"></span></span>
+        <!-- ko with: suggestion() -->
+          <!-- ko if: parseError -->
+            <div class="round-icon error">
+              <i class="fa fa-exclamation"></i>
+            </div>
+            <!-- ko if: $parent.showOptimizer -->
+            <span class="icon-explanation alert-error alert-neutral">${ _('The query has a parse error.') }</span>
+            <!-- /ko -->
+          <!-- /ko -->
+          <!-- ko if: !parseError() && $parent.compatibilityTarget() != $parent.type() -->
+            <!-- ko if: queryError.encounteredString().length == 0 -->
+              <div class="round-icon success">
+                <i class="fa fa-check"></i>
+              </div>
+              <!-- ko if: $parent.showOptimizer -->
+              <span class="icon-explanation alert-success alert-neutral">${ _('The query is compatible with Impala.') } <a href="javascript:void(0)" data-bind="click: function() { $parent.type('impala') }">${ _('Execute it now in Impala!') }</a></span>
+              <!-- /ko -->
+            <!-- /ko -->
+            <!-- ko ifnot: queryError.encounteredString().length == 0 -->
+              <div class="round-icon warning">
+                <i class="fa fa-exclamation"></i>
+              </div>
+              <!-- ko if: $parent.showOptimizer -->
+              <span class="icon-explanation alert-warning alert-neutral">${ _('This query is not compatible with Impala.') }</span>
+              <!-- /ko -->
+            <!-- /ko -->
+          <!-- /ko -->
         <!-- /ko -->
-        <!-- ko if: queryError.encounteredString -->
-          <i class="fa fa-exclamation" data-bind="toggleIconExplanation"></i> <span class="icon-explanation">${ _('This query is not compatible with Impala.') }</span>
+    <!-- /ko -->
+    <!-- ko if: hasComplexity() && hasSuggestion() && compatibilityTarget() === type() && suggestion() && !suggestion().parseError() -->
+      <!-- ko if: complexity() && complexity().risk() && (complexity().risk().length === 0 || complexity().risk() === 'low') -->
+        <div class="round-icon success">
+          <i class="fa fa-check"></i>
+        </div>
+        <!-- ko if: showOptimizer -->
+        <span class="icon-explanation alert-success alert-neutral">${ _('Query validated.') }</span>
         <!-- /ko -->
+      <!-- /ko -->
+      <!-- ko if: complexity() && complexity().risk() && complexity().risk() === 'high' -->
+        <div class="round-icon error">
+          <i class="fa fa-exclamation"></i>
         </div>
+        <!-- ko if: showOptimizer -->
+        <span class="icon-explanation alert-error alert-neutral"><strong data-bind="text: complexity().riskAnalysis"></strong> <span data-bind="text: complexity().riskRecommendation"></span></span>
+        <!-- /ko -->
       <!-- /ko -->
     <!-- /ko -->
   </div>
@@ -1559,6 +1578,16 @@ from notebook.conf import ENABLE_QUERY_BUILDER, ENABLE_QUERY_SCHEDULING, ENABLE_
         <li data-bind="text: message"></li>
       </ul>
     </div>
+    <div class="snippet-error-container alert alert-error alert-error-gradient" style="margin-bottom: 0" data-bind="visible: aceErrors().length > 0">
+      <ul class="unstyled" data-bind="foreach: aceErrors">
+        <li data-bind="text: message"></li>
+      </ul>
+    </div>
+    <div class="snippet-error-container alert alert-gradient" style="margin-bottom: 0" data-bind="visible: aceWarnings().length > 0">
+      <ul class="unstyled" data-bind="foreach: aceWarnings">
+        <li data-bind="text: message"></li>
+      </ul>
+    </div>
     <div class="snippet-error-container alert alert-error alert-error-gradient" style="margin-bottom: 0" data-bind="visible: status() == 'canceled', click: function() { status('ready'); }" title="${ _('Click to hide') }">
       <ul class="unstyled">
         <li>${ _("The statement was canceled.") }</li>

Kaikkia tiedostoja ei voida näyttää, sillä liian monta tiedostoa muuttui tässä diffissä