This is an automated email from the ASF dual-hosted git repository.

xxyu pushed a commit to branch kylin5
in repository https://gitbox.apache.org/repos/asf/kylin.git

commit 63fcd76885c4e333c433a911dbad1899d527ea9c
Author: Qian Xia <lauraxiaq...@gmail.com>
AuthorDate: Wed Jul 12 17:57:59 2023 +0800

    KYLIN-5622 logic view issue
---
 .../src/components/common/DataSourceBar/handler.js |  29 ++++--
 .../src/components/common/DataSourceBar/index.vue  |  83 +++++++++++-----
 .../src/components/common/DataSourceBar/locales.js |  11 ++-
 .../components/layout/layout_left_right_top.vue    |   2 +
 kystudio/src/components/studio/DDL/ddl.vue         |   3 +-
 .../EditLogicalDialog/EditLogicalDialog.vue        | 110 +++++++++++++++++++++
 .../LogicalView/EditLogicalDialog/locales.js       |   9 ++
 .../studio/LogicalView/EditLogicalDialog/store.js  |  41 ++++++++
 .../{DDL/ddl.vue => LogicalView/LogicalView.vue}   | 101 ++++++++++++++++---
 kystudio/src/config/index.js                       |   9 +-
 kystudio/src/config/spec.js                        |   7 +-
 kystudio/src/locale/en.js                          |   1 +
 kystudio/src/router/index.js                       |   4 +
 kystudio/src/service/datasource.js                 |   3 +
 kystudio/src/store/datasource.js                   |   3 +
 kystudio/src/store/system.js                       |  12 ++-
 kystudio/src/store/types.js                        |   1 +
 17 files changed, 369 insertions(+), 60 deletions(-)

diff --git a/kystudio/src/components/common/DataSourceBar/handler.js 
b/kystudio/src/components/common/DataSourceBar/handler.js
index 06aa9acef5..a6a70aa5aa 100644
--- a/kystudio/src/components/common/DataSourceBar/handler.js
+++ b/kystudio/src/components/common/DataSourceBar/handler.js
@@ -26,7 +26,7 @@ export const render = {
   },
   table: {
     render (h, { node, data, store }) {
-      const { label, tags, dateRange, isTopSet } = data
+      const { label, tags, dateRange, isTopSet, datasource, 
isCurrentProLogicalTable } = data // datasource 为L 是逻辑视图表
       const dataRangeTitle = this.$t('dataRange')
       const nodeClass = {
         class: [
@@ -40,14 +40,22 @@ export const render = {
       return (
         <div>
           <div {...nodeClass}>
-            <span title={label}>{label}</span>
+            <span title={label} class={datasource === 'L' && 
!isCurrentProLogicalTable ? 'is-disabled' : ''}>{label}</span>
             <div class="right">
-              <span class="tree-icon" slot="reference">
-                <el-tooltip effect="dark" enterable={false} content={isTopSet 
? this.$t('cancelTopSet') : this.$t('topSet')} placement="top">
-                  <i class="table-date-tip top" onClick={event => 
this.handleToggleTop(data, node, event)}
-                    { ...{class: data.isTopSet ? 
['el-icon-ksd-arrow_up_clean'] : ['el-icon-ksd-arrow_up']} }></i>
-                </el-tooltip>
-              </span>
+              { datasource === 'L' ? (
+                <span class="tree-icon" slot="reference">
+                  <el-tooltip effect="dark" enterable={false} 
content={isCurrentProLogicalTable ? this.$t('editLogicalSql') : 
this.$t('disabledEditLogicalSql') } placement="top">
+                    <i class="table-date-tip top" onClick={event => 
this.edit(data, node, event)}
+                      { ...{class: isCurrentProLogicalTable ? 
['el-ksd-n-icon-edit-outlined'] : ['el-ksd-n-icon-edit-outlined', 
'is-disabled']} }></i>
+                  </el-tooltip>
+                </span>
+              ) : (
+                <span class="tree-icon" slot="reference">
+                  <el-tooltip effect="dark" enterable={false} 
content={isTopSet ? this.$t('cancelTopSet') : this.$t('topSet')} 
placement="top">
+                    <i class="table-date-tip top" onClick={event => 
this.handleToggleTop(data, node, event)}
+                      { ...{class: data.isTopSet ? 
['el-icon-ksd-arrow_up_clean'] : ['el-icon-ksd-arrow_up']} }></i>
+                  </el-tooltip>
+                </span>) }
               { dateRange ? (
                 <el-popover
                   placement="right"
@@ -123,7 +131,7 @@ export function getDatasourceObj (that, sourceType) {
   const sourceName = sourceTypes[sourceType]
   let sourceNameStr = 'kylin.source.jdbc.source.enable' in 
override_kylin_properties && 
override_kylin_properties['kylin.source.jdbc.source.enable'] === 'true' && 
override_kylin_properties['kylin.source.default'] === '8'
     ? override_kylin_properties['kylin.source.jdbc.source.name'] || 
sourceNameMapping[sourceName]
-    : sourceNameMapping[sourceName]
+    : that.$t(sourceNameMapping[sourceName])
   return {
     id: sourceType,
     label: customTreeTitle !== '' ? `${that.$t(customTreeTitle)}` : 
`${that.$t('source')}${sourceNameStr}`,
@@ -191,7 +199,7 @@ export function getTableObj (that, database, table, 
ignoreColumn) {
   const dateRangeStr = _getDateRangeStr(that, dataRange)
   const tableObj = {
     id: table.uuid,
-    label: table.name,
+    label: table.name || table.table_name,
     children: [],
     render: render.table.render.bind(that),
     tags,
@@ -200,6 +208,7 @@ export function getTableObj (that, database, table, 
ignoreColumn) {
     datasource,
     isCentral: table.increment_loading,
     isTopSet: table.top,
+    isCurrentProLogicalTable: table.created_project === 
that.currentProjectData.name, // 逻辑视图表是否是当前项目的
     isHideFactIcon: that.hideFactIcon,
     dateRange: dateRangeStr,
     isSelected: false,
diff --git a/kystudio/src/components/common/DataSourceBar/index.vue 
b/kystudio/src/components/common/DataSourceBar/index.vue
index bd5b8c11d5..afafea0360 100644
--- a/kystudio/src/components/common/DataSourceBar/index.vue
+++ b/kystudio/src/components/common/DataSourceBar/index.vue
@@ -31,7 +31,7 @@
     </section>
     <section class="body">
       <div v-if="isShowLoadTable" class="btn-group">
-        <el-button plain size="medium" v-if="!isLoadingTreeData && 
showAddDatasourceBtn" type="primary" icon="el-ksd-icon-add_data_source_old" 
@click="importDataSource('selectSource', currentProjectData)">
+        <el-button plain size="medium" v-if="!isLoadingTreeData && 
showAddDatasourceBtn && !isLogicalView" type="primary" v-guide.addDatasource 
icon="el-ksd-icon-add_data_source_old" @click="importDataSource('selectSource', 
currentProjectData)">
           {{$t('addDatasource')}}
         </el-button>
       </div>
@@ -188,6 +188,10 @@ import { handleSuccessAsync, handleError, objectClone } 
from '../../../util'
     showDDL: {
       type: Boolean,
       default: false
+    },
+    isLogicalView: {
+      type: Boolean,
+      default: false
     }
   },
   components: {
@@ -198,7 +202,8 @@ import { handleSuccessAsync, handleError, objectClone } 
from '../../../util'
       'isAdminRole',
       'isProjectAdmin',
       'currentProjectData',
-      'datasourceActions'
+      'datasourceActions',
+      'logicalViewDatabaseName'
     ])
   },
   methods: {
@@ -212,7 +217,8 @@ import { handleSuccessAsync, handleError, objectClone } 
from '../../../util'
       fetchDatabases: 'FETCH_DATABASES',
       fetchTables: 'FETCH_TABLES',
       updateTopTable: 'UPDATE_TOP_TABLE',
-      fetchDBandTables: 'FETCH_DB_AND_TABLES'
+      fetchDBandTables: 'FETCH_DB_AND_TABLES',
+      fetchLogicalViewTables: 'FETCH_LOGICAL_VIEW_TABLES'
     }),
     ...mapMutations({
       cacheDatasource: 'CACHE_DATASOURCE'
@@ -359,27 +365,42 @@ export default class DataSourceBar extends Vue {
   async initTree () {
     try {
       this.isSearchIng = false
-      // await this.loadDatasources()
-      // await this.loadDataBases()
-      // await this.loadTables({ isReset: true })
-      // 有加载数据源的情况,才去加载db 和 table,否则就处理loading字段
-      // if (this.datasources.length > 0) {
-      //   await this.loadTreeData()
-      //   this.freshAutoCompleteWords()
-      // } else {
-      //   this.isLoadingTreeData = false
-      // }
-      // freshTreeOrder(this)
-      // this.selectFirstTable()
-      // this.isLoadingTreeData = false
-      await this.loadTreeData()
+      if (this.isLogicalView) {
+        await this.loadLogicalViewData()
+      } else {
+        await this.loadTreeData()
+      }
     } catch (e) {
       handleError(e)
     }
   }
-  // async loadDatasources () {
-  //   this.datasources = this.currentSourceTypes.map(sourceType => 
getDatasourceObj(this, sourceType))
-  // }
+  async loadLogicalViewData (filter) {
+    if (this.$store.state.system.logicalViewEnabled === 'true') {
+      try {
+        this.datasources = []
+        const res = await this.fetchLogicalViewTables({ project: 
this.currentProjectData.name, table: filter })
+        const logicalData = await handleSuccessAsync(res)
+        if (logicalData.length) {
+          const datasource = getDatasourceObj(this, 'L')
+          const resultDatabse = {
+            dbname: this.logicalViewDatabaseName,
+            size: logicalData.length,
+            tables: logicalData
+          }
+          datasource.children.push(getDatabaseTablesObj(this, datasource, 
resultDatabse))
+          datasource.children.forEach((database, index) => {
+            database.children = database.originTables.map(resultTable => 
getTableObj(this, database, resultTable, this.ignoreNodeTypes.indexOf('column') 
>= 0))
+            this.addPagination(database)
+          })
+          this.datasources.push(datasource)
+          this.defaultExpandedKeys.push(datasource.id)
+        }
+      } catch (e) {
+        handleError(e)
+      }
+    }
+  }
+
   async loadTreeData (filterText) { // 根据数据源获取dbs 和tables
     this.isLoadingTreeData = true
     this.treeKey = 'pageTree_' + filterText + Number(new Date())
@@ -493,6 +514,10 @@ export default class DataSourceBar extends Vue {
   }
   async handleFilter (filterText, isNotResetDefaultExpandedKeys) {
     this.isSearchIng = true
+    if (this.isLogicalView) {
+      await this.loadLogicalViewData(filterText)
+      return
+    }
     const scrollDom = this.$el.querySelector('.scroll-content')
     const scrollBarY = 
this.$el.querySelector('.scrollbar-thumb.scrollbar-thumb-y')
     scrollDom && (scrollDom.style.transform = null)
@@ -568,6 +593,9 @@ export default class DataSourceBar extends Vue {
     })
     this.defaultExpandedKeys = defaultExpandedKeysClone
   }
+  edit (data, node, event) {
+    this.$emit('edit', data, node, event)
+  }
   async handleToggleTop (data, node, event) {
     event && event.stopPropagation()
     event && event.preventDefault()
@@ -852,6 +880,9 @@ export default class DataSourceBar extends Vue {
           font-size: 12px;
         }
       }
+      .is-disabled {
+        color: @text-disabled-color;
+      }
       .datatype {
         color: @text-placeholder-color !important;
       }
@@ -909,19 +940,23 @@ export default class DataSourceBar extends Vue {
     }
     // .el-tree-node {
     //   .el-tree-node__content:hover > .tree-item {
-    //     color: #087AC8;
+    //     color: @base-color-11;
     //   }
     // }
     .table-date-tip {
       color: #8E9FA8;
       &:hover {
-        color: #087AC8;
+        color: @base-color-11;
+      }
+      &.is-disabled:hover {
+        color: @text-disabled-color;
+        cursor: not-allowed;
       }
     }
     .table-action {
       color: #000000;
       &:hover {
-        color: #087AC8;
+        color: @base-color-11;
       }
     }
     .table-tag {
@@ -935,7 +970,7 @@ export default class DataSourceBar extends Vue {
     .column-tag {
       display: inline-block;
       font-size: 16px;
-      color: #087AC8;
+      color: @base-color-11;
       margin-right: 2px;
       font-style: normal;
     }
diff --git a/kystudio/src/components/common/DataSourceBar/locales.js 
b/kystudio/src/components/common/DataSourceBar/locales.js
index 6429a88f26..331b042175 100644
--- a/kystudio/src/components/common/DataSourceBar/locales.js
+++ b/kystudio/src/components/common/DataSourceBar/locales.js
@@ -22,6 +22,15 @@ export default {
     factTable: 'Fact Table',
     importFromDatasource: 'Import from Data Source',
     createByDDL: 'DDL Create',
-    createDDLTip: 'Data Definition Language Create Table'
+    createDDLTip: 'Data Definition Language Create Table',
+    Hive: 'Hive',
+    RDBMS: 'RDBMS',
+    Kafka: 'Kafka',
+    RDBMS2: 'RDBMS',
+    CSV: 'CSV',
+    GBASE: 'GBASE',
+    logicalView: 'Logical View',
+    editLogicalSql: 'Edit/View',
+    disabledEditLogicalSql: 'Not current project Logical View Table'
   }
 }
diff --git a/kystudio/src/components/layout/layout_left_right_top.vue 
b/kystudio/src/components/layout/layout_left_right_top.vue
index d07f7bfa81..77c49829cb 100644
--- a/kystudio/src/components/layout/layout_left_right_top.vue
+++ b/kystudio/src/components/layout/layout_left_right_top.vue
@@ -336,6 +336,8 @@ export default class LayoutLeftRightTop extends Vue {
         return this.availableMenus.includes(menuName.toLowerCase()) && 
this.$store.state.system.streamingEnabled === 'true'
       case 'ddl':
         return this.availableMenus.includes(menuName.toLowerCase()) && 
this.$store.state.system.ddlEnabled === 'true'
+      case 'logicalView':
+        return this.availableMenus.includes(menuName.toLowerCase()) && 
this.$store.state.system.logicalViewEnabled === 'true'
       default:
         return this.availableMenus.includes(menuName.toLowerCase())
     }
diff --git a/kystudio/src/components/studio/DDL/ddl.vue 
b/kystudio/src/components/studio/DDL/ddl.vue
index 13a11c2381..c83751e25f 100644
--- a/kystudio/src/components/studio/DDL/ddl.vue
+++ b/kystudio/src/components/studio/DDL/ddl.vue
@@ -148,7 +148,8 @@
         this.running = true
         const res = await this.runDDL({
           sql: this.content,
-          project: this.currentSelectedProject
+          ddl_project: this.currentSelectedProject,
+          restrict: 'hive'
         })
         const resultData = await handleSuccessAsync(res)
         this.running = false
diff --git 
a/kystudio/src/components/studio/LogicalView/EditLogicalDialog/EditLogicalDialog.vue
 
b/kystudio/src/components/studio/LogicalView/EditLogicalDialog/EditLogicalDialog.vue
new file mode 100644
index 0000000000..9b109b64e0
--- /dev/null
+++ 
b/kystudio/src/components/studio/LogicalView/EditLogicalDialog/EditLogicalDialog.vue
@@ -0,0 +1,110 @@
+<template>
+    <el-dialog class="edit-logical-modal"
+      width="800px"
+      :title="$t('editLogical')"
+      :visible="isShow"
+      top="10vh"
+      :close-on-press-escape="false"
+      :close-on-click-modal="false"
+      @close="handleClose">
+      <el-alert type="tip" :closable="false" class="ksd-mb-4" show-icon>
+        <span slot="title">{{$t('replaceTips')}} <a class="import-link" 
v-if="sql.toLocaleLowerCase().indexOf('create') > -1" 
href="javascript:void(0);" @click="goToReplace">{{'create -> 
replace'}}</a></span>
+        <span class="ksd-fs-12">{{$t('dropTips')}}</span>
+      </el-alert>
+      <kap-editor
+        width="100%"
+        :height="400"
+        lang="sql"
+        ref="logicalSql"
+        theme="chrome"
+        :dragable="false"
+        :isAbridge="true"
+        :value="sql"
+        @input="handleChangeSql">
+      </kap-editor>
+      <div slot="footer" class="dialog-footer ky-no-br-space">
+        <el-button size="medium" 
@click="handleCancel">{{$t('kylinLang.common.cancel')}}</el-button>
+        <el-button type="primary" size="medium" @click="handleSubmit" 
:loading="running">{{$t('kylinLang.common.save')}}</el-button>
+      </div>
+    </el-dialog>
+  </template>
+  
+  <script>
+  import Vue from 'vue'
+  import { Component } from 'vue-property-decorator'
+  import { mapState, mapMutations, mapActions, mapGetters } from 'vuex'
+  import { handleError } from 'util'
+  import vuex, { actionTypes } from 'store'
+  import locales from './locales'
+  import store from './store'
+  vuex.registerModule(['modals', 'EditLogicalDialog'], store)
+  @Component({
+    computed: {
+      ...mapGetters([
+        'currentSelectedProject'
+      ]),
+      ...mapState('EditLogicalDialog', {
+        sql: state => state.sql,
+        isShow: state => state.isShow,
+        callback: state => state.callback
+      })
+    },
+    methods: {
+      ...mapMutations('EditLogicalDialog', {
+        setModal: actionTypes.SET_MODAL,
+        hideModal: actionTypes.HIDE_MODAL,
+        initModal: actionTypes.INIT_MODAL
+      }),
+      ...mapActions({
+        runDDL: 'RUN_DDL'
+      })
+    },
+    locales
+  })
+  export default class EditLogicalDialog extends Vue {
+    running = false
+    handleClose (isSubmit = false) {
+      this.hideModal()
+      this.callback && this.callback(isSubmit)
+    }
+    handleCancel () {
+      this.handleClose(false)
+    }
+    goToReplace () {
+      const replaceSql = this.sql.replace(/create/i, 'replace')
+      this.setModal({ sql: replaceSql })
+    }
+    handleChangeSql () {
+      const val = this.$refs.logicalSql.getValue()
+      this.setModal({ sql: val })
+    }
+    goToDataSource () {
+      this.$router.push('/studio/source')
+    }
+    async handleSubmit () {
+      try {
+        this.running = true
+        await this.runDDL({
+          sql: this.sql,
+          ddl_project: this.currentSelectedProject,
+          restrict: 'replaceLogicalView'
+        })
+        this.running = false
+        this.$message({
+          type: 'success',
+          message: (
+            <div>
+              <span>{this.$t('editSuccess') }</span>
+              <a href="javascript:void(0)" onClick={() => 
this.goToDataSource()}>{this.$t('goToDataSource')}</a>
+            </div>
+          )
+        })
+        this.handleClose(true)
+      } catch (e) {
+        handleError(e)
+        this.running = false
+      }
+    }
+  }
+  </script>
+  
\ No newline at end of file
diff --git 
a/kystudio/src/components/studio/LogicalView/EditLogicalDialog/locales.js 
b/kystudio/src/components/studio/LogicalView/EditLogicalDialog/locales.js
new file mode 100644
index 0000000000..97634b5107
--- /dev/null
+++ b/kystudio/src/components/studio/LogicalView/EditLogicalDialog/locales.js
@@ -0,0 +1,9 @@
+export default {
+  'en': {
+    editLogical: 'Edit Logical Table SQL',
+    replaceTips: 'Only supports `replace logical view` syntax. ',
+    dropTips: 'If you want to delete logcial view,please enter Create View 
Page and type \'drop view\' command.',
+    editSuccess: 'If you create,edit or delete columns in logical view,you 
need to reload table to make it take effect.',
+    goToDataSource: 'Go to Data Source reload'
+  }
+}
diff --git 
a/kystudio/src/components/studio/LogicalView/EditLogicalDialog/store.js 
b/kystudio/src/components/studio/LogicalView/EditLogicalDialog/store.js
new file mode 100644
index 0000000000..29816d449d
--- /dev/null
+++ b/kystudio/src/components/studio/LogicalView/EditLogicalDialog/store.js
@@ -0,0 +1,41 @@
+import * as actionTypes from '../../../../store/types'
+
+export function getInitialState () {
+  return {
+    isShow: false,
+    callback: null,
+    sql: ''
+  }
+}
+
+export default {
+  state: getInitialState(),
+  mutations: {
+    [actionTypes.SHOW_MODAL] (state) {
+      state.isShow = true
+    },
+    [actionTypes.HIDE_MODAL] (state) {
+      state.isShow = false
+    },
+    [actionTypes.SET_MODAL] (state, payload) {
+      for (const [key, value] of Object.entries(payload)) {
+        state[key] = value
+      }
+    },
+    [actionTypes.INIT_MODAL] (state) {
+      for (const [key, value] of Object.entries(getInitialState())) {
+        state[key] = value
+      }
+    }
+  },
+  actions: {
+    [actionTypes.CALL_MODAL] ({ commit }, payload) {
+      return new Promise(resolve => {
+        commit(actionTypes.INIT_MODAL)
+        commit(actionTypes.SET_MODAL, { ...payload, callback: resolve })
+        commit(actionTypes.SHOW_MODAL)
+      })
+    }
+  },
+  namespaced: true
+}
diff --git a/kystudio/src/components/studio/DDL/ddl.vue 
b/kystudio/src/components/studio/LogicalView/LogicalView.vue
similarity index 72%
copy from kystudio/src/components/studio/DDL/ddl.vue
copy to kystudio/src/components/studio/LogicalView/LogicalView.vue
index 13a11c2381..ab3ce8404e 100644
--- a/kystudio/src/components/studio/DDL/ddl.vue
+++ b/kystudio/src/components/studio/LogicalView/LogicalView.vue
@@ -1,10 +1,10 @@
 <template>
-    <div class="ddl-container">
+    <div class="logical-view-container">
       <div class="left-layout">
         <div class="header">
-          <span class="title">{{$t('newDDLTable')}}</span>
+          <span class="title">{{$t('newLogicalView')}}</span>
         </div>
-        <el-alert type="warning" show-icon v-if="showCreateSuccessAlert"><span 
slot="title">{{$t('createViewSuccessAlert')}} <a class="import-link" 
href="javascript:void(0);" 
@click="importDataSource">{{$t('goToImport')}}</a></span></el-alert>
+        <el-alert type="warning" show-icon v-if="showCreateSuccessAlert"><span 
slot="title">{{$t('createViewSuccessAlert', {databaseName: 
logicalViewDatabaseName})}} <a class="import-link" href="javascript:void(0);" 
@click="importDataSource">{{$t('goToImport')}}</a></span></el-alert>
         <div class="editor-content">
           <editor class="ddl-editor" v-model="content" ref="ddlEditor" 
lang="sql" theme="chrome" @keydown.meta.enter.native="runSql" 
@keydown.ctrl.enter.native="runSql"></editor>
           <div class="run-btn">
@@ -17,6 +17,11 @@
       </div>
       <div :class="['right-layout', {'expand': !!activeType}]">
         <div class="action-btns">
+          <el-tooltip :content="$t('logicalView')" effect="dark" 
placement="left">
+            <el-badge is-dot class="sign-item" :hidden="true">
+              <el-button :class="{'is-active': activeType === 'logicalView'}" 
text type="primary" icon-button-mini icon="el-ksd-n-icon-symbol-l-filled" 
@click="activeType = 'logicalView'"></el-button>
+            </el-badge>
+          </el-tooltip>
           <el-tooltip :content="$t('datasourceTable')" effect="dark" 
placement="left">
             <el-badge is-dot class="sign-item" :hidden="true">
               <el-button :class="{'is-active': activeType === 'database'}" 
text type="primary" icon-button-mini icon="icon 
el-ksd-n-icon-node-database-filled" @click="activeType = 
'database'"></el-button>
@@ -30,11 +35,34 @@
         </div>
         <div class="panel-content-layout">
           <div class="panel-header" v-if="activeType">
-            <span class="title">{{activeType === 'database' ? 
$t('datasourceTable') : $t('syntaxRules')}}</span>
+            <span class="title">{{expandBlockTitle}}</span>
             <i class="el-ksd-n-icon-close-L-outlined close-btn" 
@click="activeType = ''"></i>
           </div>
+          <div class="datasource-layout" v-if="activeType === 'logicalView'">
+            <data-source-bar
+              key="logicalView"
+              ref="logicalViewDataSource"
+              class="data-source-layout"
+              :project-name="currentSelectedProject"
+              :is-show-action-group="false"
+              :is-show-load-source="false"
+              :is-show-load-table="datasourceActions.includes('loadSource') && 
$store.state.config.platform !== 'iframe'"
+              :is-expand-on-click-node="false"
+              :is-show-drag-width-bar="true"
+              :default-width="240"
+              :expand-node-types="['datasource', 'database']"
+              :ignore-node-types="['column']"
+              :is-logical-view="true"
+              :hide-bar-title="$store.state.config.platform === 'iframe'"
+              :custom-tree-title="$store.state.config.platform !== 'iframe' ? 
'' : 'kylinLang.common.dataDirectory'"
+              @autoComplete="handleAutoComplete"
+              @click="clickTable"
+              @edit="editLogicalSql">
+            </data-source-bar>
+          </div>
           <div class="datasource-layout" v-show="activeType === 'database'">
             <data-source-bar
+              key="database"
               ref="ddlDataSource"
               class="data-source-layout"
               :project-name="currentSelectedProject"
@@ -64,6 +92,7 @@
           </template>
         </div>
       </div>
+      <EditLogicalDialog />
     </div>
   </template>
   <script>
@@ -72,36 +101,59 @@
   import DataSourceBar from '../../common/DataSourceBar'
   import { insightKeyword } from '../../../config'
   import { handleSuccessAsync, handleError } from '../../../util'
+  import EditLogicalDialog from './EditLogicalDialog/EditLogicalDialog'
   @Component({
     computed: {
       ...mapGetters([
         'currentSelectedProject',
         'datasourceActions',
-        'currentProjectData'
+        'currentProjectData',
+        'logicalViewDatabaseName'
       ])
     },
     methods: {
       ...mapActions({
         getDDLDescription: 'DDL_DESCRIPTION',
         runDDL: 'RUN_DDL'
+      }),
+      ...mapActions('EditLogicalDialog', {
+        callEditLogicalDialog: 'CALL_MODAL'
       })
     },
     components: {
-      DataSourceBar
+      DataSourceBar,
+      EditLogicalDialog
     },
     locales: {
       en: {
-        newDDLTable: 'New DDL Table',
+        newLogicalView: 'New Logical View',
+        logicalView: 'Logical View',
+        logicalViewTable: 'Logical View Table',
         datasourceTable: 'Data Source Table',
         syntaxRules: 'Syntax Rules',
-        createDDLSuggestionTitle: 'To create a DDL Table in KE, you need to 
follow the syntax rules of KE.',
+        createDDLSuggestionTitle: 'To create a Logical View in KE, you need to 
follow the syntax rules of KE.',
         importDataSource: 'Import',
         runBtnTip: 'Execute ',
         acceleratorKey: '⌃/⌘ enter',
         runSuccess: 'Execute succeed.',
-        runFailed: 'Execute Failed, Please check and try again.',
-        createViewSuccessAlert: 'The DDL Table is created to hive after 
executing "Create View". Please importing the table to data source to be 
available.',
+        runFailed: 'Execute Failed,Please check and try again.',
+        createViewSuccessAlert: 'The Logical View is created in virtual 
database {databaseName}  after executing "Create Logical View". Please import 
it from the data source to use it.',
         goToImport: 'Go to Import'
+      },
+      'zh-cn': {
+        newLogicalView: '新的逻辑视图',
+        logicalView: '逻辑视图',
+        logicalViewTable: '逻辑视图表',
+        datasourceTable: '数据源表',
+        syntaxRules: '语法规则',
+        createDDLSuggestionTitle: '在 KE 中创建 Logical View 需要遵循 KE 的语法规则。',
+        importDataSource: '导入',
+        runBtnTip: '执行 ',
+        acceleratorKey: '⌃/⌘ 回车',
+        runSuccess: '执行成功',
+        runFailed: '执行失败,请检查后重试',
+        createViewSuccessAlert: '“Create Logical View” 执行后逻辑视图创建至虚拟库 
{databaseName},需要从数据源导入后可用。',
+        goToImport: '立即导入'
       }
     }
   })
@@ -114,8 +166,19 @@
     stacktrace = ''
     running = false
     showCreateSuccessAlert = false
+    get expandBlockTitle () {
+      switch (this.activeType) {
+        case 'logicalView':
+          return this.$t('logicalViewTable')
+        case 'database':
+          return this.$t('datasourceTable')
+        default:
+          return this.$t('syntaxRules')
+      }
+    }
     setOption (option) {
       let editor = this.$refs.ddlEditor.editor
+      if (!editor) return
       editor.setOptions(Object.assign({
         wrap: 'free',
         enableBasicAutocompletion: true,
@@ -133,6 +196,14 @@
         }
       })
     }
+    async editLogicalSql (data, node, event) {
+      event.stopPropagation()
+      if (!data.isCurrentProLogicalTable) return
+      const isSubmit = await this.callEditLogicalDialog({ sql: 
data.__data.created_sql })
+      if (isSubmit) {
+        this.$refs.logicalViewDataSource.initTree()
+      }
+    }
     importDataSource () {
       this.$refs.ddlDataSource && 
this.$refs.ddlDataSource.importDataSource('selectSource', 
this.currentProjectData)
     }
@@ -148,11 +219,12 @@
         this.running = true
         const res = await this.runDDL({
           sql: this.content,
-          project: this.currentSelectedProject
+          ddl_project: this.currentSelectedProject,
+          restrict: 'logic'
         })
         const resultData = await handleSuccessAsync(res)
         this.running = false
-        this.showCreateSuccessAlert = 
this.content.toLocaleLowerCase().indexOf('create view') > -1
+        this.showCreateSuccessAlert = 
this.content.toLocaleLowerCase().indexOf('create logical view') > -1
         resultData && this.insertEditorContent(`\n\n${resultData}`)
         this.resetErrorMsg()
         this.$message({ type: 'success', message: this.$t('runSuccess') })
@@ -174,7 +246,7 @@
     }
     async getDDLRules () {
       try {
-        const result = await this.getDDLDescription({project: 
this.currentSelectedProject, page_type: 'hive'})
+        const result = await this.getDDLDescription({project: 
this.currentSelectedProject, page_type: 'logic'})
         const rules = await handleSuccessAsync(result)
         this.rules = rules
       } catch (e) {
@@ -192,7 +264,7 @@
   
   <style lang="less" scoped>
   @import '../../../assets/styles/variables.less';
-  .ddl-container {
+  .logical-view-container {
     width: 100%;
     height: 100%;
     display: flex;
@@ -367,3 +439,4 @@
     color: @text-disabled-color;
   }
   </style>
+  
\ No newline at end of file
diff --git a/kystudio/src/config/index.js b/kystudio/src/config/index.js
index 160a285fa0..bd269fe1d2 100644
--- a/kystudio/src/config/index.js
+++ b/kystudio/src/config/index.js
@@ -58,7 +58,8 @@ export const menusData = [
       { name: 'source', path: '/studio/source' },
       { name: 'modelList', path: '/studio/model' },
       { name: 'snapshot', path: '/studio/snapshot' },
-      { name: 'ddl', path: '/studio/ddl' }
+      { name: 'ddl', path: '/studio/ddl' },
+      { name: 'logicalView', path: '/studio/logicalview' }
     ]
   },
   {
@@ -709,7 +710,8 @@ export const sourceTypes = getFullMapping({
   RDBMS: 16,
   KAFKA: 1,
   CSV: 13,
-  GBASE: 8
+  GBASE: 8,
+  LOGIC: 'L'
 })
 
 export const sourceNameMapping = {
@@ -718,7 +720,8 @@ export const sourceNameMapping = {
   KAFKA: 'Kafka',
   RDBMS2: 'RDBMS',
   CSV: 'CSV',
-  GBASE: 'GBASE'
+  GBASE: 'GBASE',
+  LOGIC: 'logicalView'
 }
 
 export const pageSizeMapping = {
diff --git a/kystudio/src/config/spec.js b/kystudio/src/config/spec.js
index 236d4d168e..0bf9717b25 100644
--- a/kystudio/src/config/spec.js
+++ b/kystudio/src/config/spec.js
@@ -19,6 +19,7 @@ export default {
       { "id": "modelSubPartitionValues", "value": "modelsubpartitionvalues", 
"title": "Model SubPartition Values" },
       { "id": "snapshot", "value": "snapshot", "title": "Snapshot" },
       { "id": "ddl", "value": "ddl", "title": "DDL" },
+      { "id": "logicalView", "value": "logicalview", "title": "Logical View" },
       { "id": "monitor", "value": "monitor", "title": "Monitor" },
       { "id": "job", "value": "job", "title": "Job" },
       { "id": "streamingJob", "value": "streamingjob", "title": "streamingJob" 
},
@@ -152,10 +153,10 @@ export default {
       "keyPattern": "groupRole-projectRole-menu",
       "entries": [
         { "key": 
"systemAdmin-*-[project,user,group,groupDetail,projectAuthority,diagnostic]", 
"value": "admin,project,user,group,groupDetail,diagnostic,projectAuthority" },
-        { "key": 
"systemAdmin-*-[dashboard,query,insight,queryHistory,studio,setting,source,model,index,modelEdit,modelDetails,modelSubPartitionValues,snapshot,ddl,monitor,job,streamingJob]",
 "value": 
"dashboard,query,insight,queryHistory,studio,setting,source,model,index,modelEdit,modelDetails,modelSubPartitionValues,snapshot,ddl,monitor,job,streamingJob,admin"
 },
+        { "key": 
"systemAdmin-*-[dashboard,query,insight,queryHistory,studio,setting,source,model,index,modelEdit,modelDetails,modelSubPartitionValues,snapshot,ddl,logicalView,monitor,job,streamingJob]",
 "value": 
"dashboard,query,insight,queryHistory,studio,setting,source,model,index,modelEdit,modelDetails,modelSubPartitionValues,snapshot,ddl,logicalView,monitor,job,streamingJob,admin"
 },
         { "key": 
"systemUser-admin-[project,user,group,groupDetail,projectAuthority]", "value": 
"project,admin,projectAuthority" },
-        { "key": 
"systemUser-admin-[dashboard,query,insight,queryHistory,studio,setting,source,model,index,modelEdit,modelDetails,modelSubPartitionValues,snapshot,ddl,monitor,job,streamingJob]",
 "value": 
"dashboard,query,insight,queryHistory,studio,setting,source,model,index,modelEdit,modelDetails,modelSubPartitionValues,snapshot,ddl,monitor,job,streamingJob,admin"
 },
-        { "key": "systemUser-management-*", "value": 
"dashboard,query,insight,queryHistory,studio,source,model,index,modelEdit,modelDetails,modelSubPartitionValues,snapshot,ddl,monitor,job,streamingJob"
 },
+        { "key": 
"systemUser-admin-[dashboard,query,insight,queryHistory,studio,setting,source,model,index,modelEdit,modelDetails,modelSubPartitionValues,snapshot,ddl,logicalView,monitor,job,streamingJob]",
 "value": 
"dashboard,query,insight,queryHistory,studio,setting,source,model,index,modelEdit,modelDetails,modelSubPartitionValues,snapshot,ddl,logicalView,monitor,job,streamingJob,admin"
 },
+        { "key": "systemUser-management-*", "value": 
"dashboard,query,insight,queryHistory,studio,source,model,index,modelEdit,modelDetails,modelSubPartitionValues,snapshot,ddl,logicalView,monitor,job,streamingJob"
 },
         { "key": "systemUser-operation-*", "value": 
"dashboard,query,insight,queryHistory,studio,model,modelDetails,snapshot,ddl,index,monitor,job,streamingJob,modelSubPartitionValues"
 },
         { "key": "systemUser-read-*", "value": 
"dashboard,query,insight,queryHistory,studio,model,modelDetails,snapshot,ddl,index"
 },
         { "key": "systemUser-default-*", "value": "dashboard" }
diff --git a/kystudio/src/locale/en.js b/kystudio/src/locale/en.js
index 855036173d..687c4f382b 100644
--- a/kystudio/src/locale/en.js
+++ b/kystudio/src/locale/en.js
@@ -493,6 +493,7 @@ exports.default = {
     modeledit: 'Model Edit',
     snapshot: 'Snapshot',
     ddl: 'DDL',
+    logicalView: 'Logical View',
     refresh: 'Refresh',
     systemcapacity: 'Capacity'
   },
diff --git a/kystudio/src/router/index.js b/kystudio/src/router/index.js
index 29e93ab054..148c3756f8 100644
--- a/kystudio/src/router/index.js
+++ b/kystudio/src/router/index.js
@@ -89,6 +89,10 @@ let routerOptions = {
         name: 'DDL',
         path: 'studio/ddl',
         component: () => import('../components/studio/DDL/ddl.vue')
+      }, {
+        name: 'LogicalView',
+        path: 'studio/logicalview',
+        component: () => 
import('../components/studio/LogicalView/LogicalView.vue')
       }, {
         name: 'Project',
         path: 'admin/project',
diff --git a/kystudio/src/service/datasource.js 
b/kystudio/src/service/datasource.js
index 7e00128f44..b1112c18d9 100644
--- a/kystudio/src/service/datasource.js
+++ b/kystudio/src/service/datasource.js
@@ -321,5 +321,8 @@ export default {
   },
   runDDL (data) {
     return Vue.resource(apiUrl + 'spark_source/ddl').save(data)
+  },
+  fetchLogicalViewTables (data) {
+    return Vue.resource(apiUrl + 'spark_source/ddl/view_list').get(data)
   }
 }
diff --git a/kystudio/src/store/datasource.js b/kystudio/src/store/datasource.js
index ac31bd3994..40b4014f56 100644
--- a/kystudio/src/store/datasource.js
+++ b/kystudio/src/store/datasource.js
@@ -402,6 +402,9 @@ export default {
     // 执行 ddl 语句
     [types.RUN_DDL]: function (_, data) {
       return api.datasource.runDDL(data)
+    },
+    [types.FETCH_LOGICAL_VIEW_TABLES]: function ({ commit }, data) {
+      return api.datasource.fetchLogicalViewTables(data)
     }
   }
 }
diff --git a/kystudio/src/store/system.js b/kystudio/src/store/system.js
index 7607926d28..2d713afbca 100644
--- a/kystudio/src/store/system.js
+++ b/kystudio/src/store/system.js
@@ -60,7 +60,9 @@ export default {
     isNonAdminGenQueryDiagPackage: 'true',
     streamingEnabled: 'false',
     storageQuery: 'true',
-    ddlEnabled: 'false'
+    ddlEnabled: 'false',
+    logicalViewEnabled: 'false',
+    logicalViewDatabase: 'KYLIN_LOGICAL_VIEW'
   },
   mutations: {
     [types.COLLECT_MESSAGE_DIRECTIVES]: (state, directive) => {
@@ -184,7 +186,9 @@ export default {
           commit(types.GET_CONF_BY_NAME, {name: 
'kylin.model.measure-name-check-enabled', key: 'enableCheckName', defaultValue: 
'true'})
           commit(types.GET_CONF_BY_NAME, {name: 'kylin.streaming.enabled', 
key: 'streamingEnabled', defaultValue: 'false'})
           commit(types.GET_CONF_BY_NAME, {name: 
'kylin.second-storage.query-metric-collect', key: 'storageQuery', defaultValue: 
'true'})
-          commit(types.GET_CONF_BY_NAME, {name: 'kylin.source.ddl.enabled', 
key: 'ddlEnabled', defaultValue: 'false'})
+          commit(types.GET_CONF_BY_NAME, {name: 
'kylin.source.ddl.hive.enabled', key: 'ddlEnabled', defaultValue: 'false'})
+          commit(types.GET_CONF_BY_NAME, {name: 
'kylin.source.ddl.logical-view.enabled', key: 'logicalViewEnabled', 
defaultValue: 'false'})
+          commit(types.GET_CONF_BY_NAME, {name: 
'kylin.source.ddl.logical-view-database', key: 'logicalViewDatabase', 
defaultValue: 'KYLIN_LOGICAL_VIEW'})
           resolve(response)
         }, () => {
           reject()
@@ -239,8 +243,8 @@ export default {
     isNonAdminGenQueryDiagPackage: (state) => {
       return state.isNonAdminGenQueryDiagPackage === 'true'
     },
-    isStreamingEnabled: (state) => {
-      return state.streamingEnabled === 'true'
+    logicalViewDatabaseName: (state) => {
+      return state.logicalViewDatabase
     }
   }
 }
diff --git a/kystudio/src/store/types.js b/kystudio/src/store/types.js
index 7ec5311e22..f88d6607c7 100644
--- a/kystudio/src/store/types.js
+++ b/kystudio/src/store/types.js
@@ -182,6 +182,7 @@ export const EXPORT_CSV = 'EXPORT_CSV'
 
 export const LOAD_DATASOURCE_OF_MODEL = 'LOAD_DATASOURCE_OF_MODEL'
 
+export const FETCH_LOGICAL_VIEW_TABLES = 'FETCH_LOGICAL_VIEW_TABLES'
 export const DDL_DESCRIPTION = 'DDL_DESCRIPTION'
 export const RUN_DDL = 'RUN_DDL'
 // acl table


Reply via email to