Explorar o código

HUE-9485 [frontend] Fix the SqlText Vue component and add option to format

Johan Ahlen %!s(int64=5) %!d(string=hai) anos
pai
achega
071d0c66e7
Modificáronse 1 ficheiros con 91 adicións e 94 borrados
  1. 91 94
      desktop/core/src/desktop/js/components/SqlText.vue

+ 91 - 94
desktop/core/src/desktop/js/components/SqlText.vue

@@ -23,6 +23,7 @@
 </template>
 
 <script lang="ts">
+  import { formatSql } from 'apps/notebook2/apiUtils';
   import $ from 'jquery';
   import Vue from 'vue';
   import Component from 'vue-class-component';
@@ -43,117 +44,113 @@
     @Prop({ required: false })
     value = '';
     @Prop({ required: false })
-    formatted = false;
+    format = false;
     @Prop({ required: false })
     enableOverflow = false;
     @Prop({ required: false })
     splitLines = false;
 
     @Watch('value')
-    renderAce(): void {
-      if (this.value) {
-        const ace = getAce();
-        const impalaRules = ace.require('ace/mode/impala_highlight_rules');
-        const hiveRules = ace.require('ace/mode/hive_highlight_rules');
-        const tokenizer = ace.require('ace/tokenizer');
-        const text = ace.require('ace/layer/text');
-        const config = ace.require('ace/config');
-
-        const Tokenizer = tokenizer.Tokenizer;
-        const Rules =
-          this.dialect === 'impala'
-            ? impalaRules.ImpalaHighlightRules
-            : hiveRules.HiveHighlightRules;
-
-        const res: string[] = [];
-
-        // eslint-disable-next-line @typescript-eslint/ban-ts-comment
-        // @ts-ignore: totalStorage interface missing
-        config.loadModule(['theme', $.totalStorage('hue.ace.theme') || 'ace/theme/hue']);
-
-        const Text = text.Text;
-
-        const tok = new Tokenizer(new Rules().getRules());
-        const lines = this.value.split('\n');
-
-        // eslint-disable-next-line @typescript-eslint/no-explicit-any
-        const renderSimpleLine = (txt: any, stringBuilder: string[], tokens: any[]) => {
-          let screenColumn = 0;
-          let token = tokens[0];
-          let value = token.value;
-          if (value) {
-            try {
-              screenColumn = txt.$renderToken(stringBuilder, screenColumn, token, value);
-            } catch (e) {
+    async renderAce(): Promise<void> {
+      if (!this.value) {
+        return;
+      }
+      const ace = getAce();
+      const impalaRules = ace.require('ace/mode/impala_highlight_rules');
+      const hiveRules = ace.require('ace/mode/hive_highlight_rules');
+      const tokenizer = ace.require('ace/tokenizer');
+      const text = ace.require('ace/layer/text');
+      const config = ace.require('ace/config');
+
+      const Tokenizer = tokenizer.Tokenizer;
+      const Rules =
+        this.dialect === 'impala' ? impalaRules.ImpalaHighlightRules : hiveRules.HiveHighlightRules;
+
+      const res: string[] = [];
+
+      // eslint-disable-next-line @typescript-eslint/ban-ts-comment
+      // @ts-ignore: totalStorage interface missing
+      config.loadModule(['theme', $.totalStorage('hue.ace.theme') || 'ace/theme/hue']);
+
+      const Text = text.Text;
+
+      const tok = new Tokenizer(new Rules().getRules());
+
+      let editorText = this.value;
+      if (this.format) {
+        editorText = await formatSql({ statements: this.value, silenceErrors: true });
+      }
+      const lines = editorText.split('\n');
+
+      // eslint-disable-next-line @typescript-eslint/no-explicit-any
+      const renderSimpleLine = (txt: any, stringBuilder: string[], tokens: any[]) => {
+        let screenColumn = 0;
+        let token = tokens[0];
+        let value = token.value;
+        if (value) {
+          try {
+            screenColumn = txt.$renderToken(stringBuilder, screenColumn, token, value);
+          } catch (e) {
+            console.warn(
+              value,
+              'Failed to get screen column due to some parsing errors, skip rendering.'
+            );
+          }
+        }
+        for (let i = 1; i < tokens.length; i++) {
+          token = tokens[i];
+          value = token.value;
+          try {
+            screenColumn = txt.$renderToken(stringBuilder, screenColumn, token, value);
+          } catch (e) {
+            if (console && console.warn) {
               console.warn(
                 value,
-                'Failed to get screen column due to some parsing errors, skip rendering.'
+                'This token has some parsing errors and it has been rendered without highlighting.'
               );
             }
+            stringBuilder.push(value);
+            screenColumn = screenColumn + value.length;
           }
-          for (let i = 1; i < tokens.length; i++) {
-            token = tokens[i];
-            value = token.value;
-            try {
-              screenColumn = txt.$renderToken(stringBuilder, screenColumn, token, value);
-            } catch (e) {
-              if (console && console.warn) {
-                console.warn(
-                  value,
-                  'This token has some parsing errors and it has been rendered without highlighting.'
-                );
-              }
-              stringBuilder.push(value);
-              screenColumn = screenColumn + value.length;
-            }
-          }
-        };
-
-        let additionalClass = '';
-        if (!this.splitLines && !this.formatted) {
-          additionalClass = 'pull-left';
-        } else if (this.formatted) {
-          additionalClass = 'ace-highlight-pre';
         }
+      };
 
-        lines.forEach(line => {
-          const renderedTokens: string[] = [];
-          const tokens = tok.getLineTokens(line);
+      let additionalClass = 'pull-left';
+      if (!this.splitLines && !this.format) {
+        additionalClass = 'pull-left';
+      } else if (this.format) {
+        additionalClass = 'ace-highlight-pre';
+      }
 
-          if (tokens && tokens.tokens.length) {
-            renderSimpleLine(
-              new Text(document.createElement('div')),
-              renderedTokens,
-              tokens.tokens
-            );
-          }
+      lines.forEach(line => {
+        const renderedTokens: string[] = [];
+        const tokens = tok.getLineTokens(line);
 
-          res.push(
-            '<div class="ace_line ' +
-              additionalClass +
-              '">' +
-              renderedTokens.join('') +
-              '&nbsp;</div>'
-          );
-        });
-
-        const element = this.$el.firstElementChild;
-        if (!element) {
-          return;
+        if (tokens && tokens.tokens.length) {
+          renderSimpleLine(new Text(document.createElement('div')), renderedTokens, tokens.tokens);
         }
-        element.innerHTML =
-          '<div class="ace_editor ace-hue"' +
-          (this.enableOverflow ? ' style="overflow: initial !important;"' : '') +
-          '><div class="ace_layer" style="position: static;' +
-          (this.enableOverflow ? ' overflow: initial !important;' : '') +
-          '">' +
-          res.join('') +
-          '</div></div>';
-        if (this.enableOverflow) {
-          $(element).css({ overflow: 'auto' });
-        }
-        $(element).find('.ace_invisible_space').remove();
+
+        res.push(
+          '<div class="ace_line ' +
+            additionalClass +
+            '">' +
+            renderedTokens.join('') +
+            '&nbsp;</div>'
+        );
+      });
+
+      this.$el.innerHTML =
+        '<div class="ace_editor ace-hue"' +
+        (this.enableOverflow ? ' style="overflow: initial !important;"' : '') +
+        '><div class="ace_layer" style="position: static;' +
+        (this.enableOverflow ? ' overflow: initial !important;' : '') +
+        '">' +
+        res.join('') +
+        '</div></div>';
+      if (this.enableOverflow) {
+        $(this.$el).css({ overflow: 'auto' });
       }
+      $(this.$el).find('.ace_invisible_space').remove();
     }
 
     mounted(): void {