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 2878bb8279c6d5c9e7614ff461ddc6f67c3386c2 Author: Qian Xia <lauraxiaq...@gmail.com> AuthorDate: Mon Jun 5 17:54:59 2023 +0800 KYLIN-5543 support ddl --- .../src/components/common/DataSourceBar/index.vue | 48 ++- .../src/components/common/DataSourceBar/locales.js | 5 +- .../components/layout/layout_left_right_top.vue | 17 +- kystudio/src/components/studio/DDL/ddl.vue | 377 +++++++++++++++++++++ .../src/components/studio/StudioSource/index.vue | 1 + kystudio/src/config/index.js | 3 +- kystudio/src/config/spec.js | 14 +- kystudio/src/locale/en.js | 2 + kystudio/src/router/index.js | 4 + kystudio/src/service/datasource.js | 6 + kystudio/src/store/datasource.js | 8 + kystudio/src/store/system.js | 4 +- kystudio/src/store/types.js | 3 + 13 files changed, 466 insertions(+), 26 deletions(-) diff --git a/kystudio/src/components/common/DataSourceBar/index.vue b/kystudio/src/components/common/DataSourceBar/index.vue index 5c5b7c482e..bd5b8c11d5 100644 --- a/kystudio/src/components/common/DataSourceBar/index.vue +++ b/kystudio/src/components/common/DataSourceBar/index.vue @@ -1,21 +1,32 @@ <template> <div style="height: 100%;" class="clearfix"> <aside class="data-source-bar" :style="dataSourceStyle"> - <section class="header clearfix" v-if="isShowActionGroup && !hideBarTitle"> + <section class="header" v-if="isShowActionGroup && !hideBarTitle"> <div class="header-text ksd-title-module"> - <span>{{$t('kylinLang.common.dataSource')}}</span> + <span>{{$t('kylinLang.common.dataSourceTable')}}</span> </div> - <div class="icon-btns clearfix"> + <div class="icon-btns"> <!-- <div :class="['header-icons', 'clearfix', {selected: isSwitchSource}]" v-if="isShowSourceSwitch"> <el-tooltip :content="$t('sourceManagement')" effect="dark" placement="top"> <i class="ksd-fs-14 el-icon-ksd-setting" @click="handleSwitchSource"></i> </el-tooltip> </div> --> - <div class="add-source-table-icon" v-if="isShowLoadTable"> + <!-- <div class="add-source-table-icon" v-if="isShowLoadTable"> <el-tooltip :content="$t('addDatasource')" effect="dark" placement="top"> <i class="ksd-fs-14 el-icon-ksd-project_add" @click="importDataSource('selectSource', currentProjectData)"></i> </el-tooltip> - </div> + </div> --> + <el-dropdown @command="addDataSource"> + <el-button text type="primary" icon-button-mini icon="el-ksd-n-icon-plus-outlined"></el-button> + <el-dropdown-menu slot="dropdown"> + <el-dropdown-item command="default" :disabled="!isShowLoadTable">{{$t('importFromDatasource')}}</el-dropdown-item> + <!-- <el-tooltip effect="dark" placement="top" :disabled="!hasSecData || hasOrderbyOrSkipIndex('orderBy', 'current')"> + <span slot="content">{{$t('disableAddOrderByIndexTip')}}<a href="javascript:void(0)" @click="$emit('jumpToSegment')">{{$t('goToDelete')}}</a></span> + <span><el-dropdown-item command="orderBy" :disabled="hasSecData || hasOrderbyOrSkipIndex('orderBy', 'current')">{{$t('orderByIndex')}}</el-dropdown-item></span> + </el-tooltip> --> + <el-dropdown-item command="ddl" v-if="$store.state.config.platform !== 'iframe' && datasourceActions.includes('ddl') && showDDL && $store.state.system.ddlEnabled === 'true'">{{$t('createByDDL')}} <el-tooltip effect="dark" :content="$t('createDDLTip')" placement="bottom"><i class="info-icon el-ksd-n-icon-info-circle-filled"></i></el-tooltip></el-dropdown-item> + </el-dropdown-menu> + </el-dropdown> </div> </section> <section class="body"> @@ -173,6 +184,10 @@ import { handleSuccessAsync, handleError, objectClone } from '../../../util' isSecondStorageEnabled: { type: Boolean, default: false + }, + showDDL: { + type: Boolean, + default: false } }, components: { @@ -182,7 +197,8 @@ import { handleSuccessAsync, handleError, objectClone } from '../../../util' ...mapGetters([ 'isAdminRole', 'isProjectAdmin', - 'currentProjectData' + 'currentProjectData', + 'datasourceActions' ]) }, methods: { @@ -330,6 +346,16 @@ export default class DataSourceBar extends Vue { hideLoading (data) { data.isLoading = false } + addDataSource (command) { + switch (command) { + case 'default': + this.importDataSource('selectSource', this.currentProjectData) + break + case 'ddl': + this.$router.push('/studio/ddl') + break + } + } async initTree () { try { this.isSearchIng = false @@ -476,7 +502,7 @@ export default class DataSourceBar extends Vue { !isNotResetDefaultExpandedKeys && this.resetDefaultExpandedKeys() this.filterText = filterText freshTreeOrder(this) - this.selectFirstTable() + // this.selectFirstTable() resolve() }) } @@ -729,12 +755,13 @@ export default class DataSourceBar extends Vue { padding: 24px 16px 16px 16px; font-size: 16px; color: @text-title-color; + display: flex; + justify-content: space-between; } .body { padding: 0px 16px 16px; } .header-text { - float: left; span { line-height: 20px; } @@ -742,7 +769,7 @@ export default class DataSourceBar extends Vue { .icon-btns { position: relative; height: 22px; - top: 2px; + // top: 2px; } .header-icons { float: right; @@ -959,4 +986,7 @@ export default class DataSourceBar extends Vue { left: 0; } } +.info-icon { + color: @text-placeholder-color; +} </style> diff --git a/kystudio/src/components/common/DataSourceBar/locales.js b/kystudio/src/components/common/DataSourceBar/locales.js index 01ca76d98c..6429a88f26 100644 --- a/kystudio/src/components/common/DataSourceBar/locales.js +++ b/kystudio/src/components/common/DataSourceBar/locales.js @@ -19,6 +19,9 @@ export default { databases: 'Database', tables: 'Table', cloudHive: 'Object Storage', - factTable: 'Fact Table' + factTable: 'Fact Table', + importFromDatasource: 'Import from Data Source', + createByDDL: 'DDL Create', + createDDLTip: 'Data Definition Language Create Table' } } diff --git a/kystudio/src/components/layout/layout_left_right_top.vue b/kystudio/src/components/layout/layout_left_right_top.vue index 63dbeff82d..d07f7bfa81 100644 --- a/kystudio/src/components/layout/layout_left_right_top.vue +++ b/kystudio/src/components/layout/layout_left_right_top.vue @@ -329,15 +329,16 @@ export default class LayoutLeftRightTop extends Vue { } } showMenuByRole (menuName) { - let isShowSnapshot = true - let isShowStreamingJob = true - if (menuName === 'snapshot') { - isShowSnapshot = this.$store.state.project.snapshot_manual_management_enabled + switch (menuName) { + case 'snapshot': + return this.availableMenus.includes(menuName.toLowerCase()) && this.$store.state.project.snapshot_manual_management_enabled + case 'streamingjob': + 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' + default: + return this.availableMenus.includes(menuName.toLowerCase()) } - if (menuName === 'streamingjob') { - isShowStreamingJob = this.$store.state.system.streamingEnabled === 'true' - } - return this.availableMenus.includes(menuName.toLowerCase()) && isShowSnapshot && isShowStreamingJob } defaultVal (obj) { if (!obj) { diff --git a/kystudio/src/components/studio/DDL/ddl.vue b/kystudio/src/components/studio/DDL/ddl.vue new file mode 100644 index 0000000000..40dfb12078 --- /dev/null +++ b/kystudio/src/components/studio/DDL/ddl.vue @@ -0,0 +1,377 @@ +<template> + <div class="ddl-container"> + <div class="left-layout"> + <div class="header"> + <span class="title">{{$t('newDDLTable')}}</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> + <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"> + <el-tooltip effect="dark" placement="left"> + <div slot="content">{{$t('runBtnTip')}}<span class="accelerator-key">⌃/⌘ enter</span></div> + <el-button :loading="running" type="primary" icon-button size="big" icon="el-ksd-n-icon-play-filled" @click="runSql"></el-button> + </el-tooltip> + </div> + </div> + </div> + <div :class="['right-layout', {'expand': !!activeType}]"> + <div class="action-btns"> + <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> + </el-badge> + </el-tooltip> + <el-tooltip :content="$t('syntaxRules')" effect="dark" placement="left"> + <el-badge is-dot class="sign-item" :hidden="!ddlError"> + <el-button :class="{'is-active': activeType === 'result'}" text type="primary" icon-button-mini icon="icon el-ksd-n-icon-node-thunder-filled" @click="activeType = 'result'"></el-button> + </el-badge> + </el-tooltip> + </div> + <div class="panel-content-layout"> + <div class="panel-header" v-if="activeType"> + <span class="title">{{activeType === 'database' ? $t('datasourceTable') : $t('syntaxRules')}}</span> + <i class="el-ksd-n-icon-close-L-outlined close-btn" @click="activeType = ''"></i> + </div> + <div class="datasource-layout" v-show="activeType === 'database'"> + <data-source-bar + ref="ddlDataSource" + 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']" + :hide-bar-title="$store.state.config.platform === 'iframe'" + :custom-tree-title="$store.state.config.platform !== 'iframe' ? '' : 'kylinLang.common.dataDirectory'" + @autoComplete="handleAutoComplete" + @click="clickTable"> + </data-source-bar> + </div> + <div class="import-btn" v-if="activeType === 'database'"><el-button @click="importDataSource" type="primary" size="big" icon="el-ksd-n-icon-inport-outlined">{{$t('importDataSource')}}</el-button></div> + <template v-if="activeType === 'result'"> + <div class="feedback-suggestions"> + <div class="suggestion-list"> + <div class="label">{{$t('createDDLSuggestionTitle')}}</div> + <el-alert v-if="errorMsg" class="ksd-mb-16" :title="errorMsg" type="error" show-icon :closable="false"></el-alert> + <div v-if="stacktrace" class="trance-msg">{{stacktrace}}</div> + <div class="item" v-for="(item, index) in ($lang === 'en' ? rules[0] : rules[1])" :key="index">{{index + 1}}. {{item}}</div> + </div> + </div> + </template> + </div> + </div> + </div> + </template> + <script> + import { Component, Vue } from 'vue-property-decorator' + import { mapActions, mapGetters } from 'vuex' + import DataSourceBar from '../../common/DataSourceBar' + import { insightKeyword } from '../../../config' + import { handleSuccessAsync, handleError } from '../../../util' + @Component({ + computed: { + ...mapGetters([ + 'currentSelectedProject', + 'datasourceActions', + 'currentProjectData' + ]) + }, + methods: { + ...mapActions({ + getDDLDescription: 'DDL_DESCRIPTION', + runDDL: 'RUN_DDL' + }) + }, + components: { + DataSourceBar + }, + locales: { + en: { + newDDLTable: 'New DDL Table', + datasourceTable: 'Data Source Table', + syntaxRules: 'Syntax Rules', + createDDLSuggestionTitle: '在 KE 中创建 DDL Table 需要遵循 KE 的语法规则。', + importDataSource: 'Import', + runBtnTip: '执行 ', + runSuccess: 'Dexecute 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.', + goToImport: 'Go to Import' + }, + 'zh-cn': { + newDDLTable: '新的 DDL 表', + datasourceTable: '数据源表', + syntaxRules: '语法规则', + createDDLSuggestionTitle: '在 KE 中创建 DDL Table 需要遵循 KE 的语法规则。', + importDataSource: '导入', + runBtnTip: 'Dexecute ', + runSuccess: '执行成功', + runFailed: '执行失败,请检查后重试', + createViewSuccessAlert: '“Create View” 执行后 DDL Table 创建至 Hive,需从数据源导入后可用。', + goToImport: '立即导入' + } + } + }) + export default class DDL extends Vue { + content = '' + activeType = '' + rules = [] + ddlError = false + errorMsg = '' + stacktrace = '' + running = false + showCreateSuccessAlert = false + setOption (option) { + let editor = this.$refs.ddlEditor.editor + editor.setOptions(Object.assign({ + wrap: 'free', + enableBasicAutocompletion: true, + enableSnippets: true, + enableLiveAutocompletion: true + }, option)) + } + handleAutoComplete (data) { + this.completeData = [...data, ...insightKeyword] + } + clickTable (leaf) { + this.$nextTick(() => { + if (leaf) { + this.insertEditorContent(leaf.label) + } + }) + } + importDataSource () { + this.$refs.ddlDataSource && this.$refs.ddlDataSource.importDataSource('selectSource', this.currentProjectData) + } + insertEditorContent (data) { + const editor = this.$refs.ddlEditor.editor + editor.focus() + editor.insert(data) + this.content = editor.getValue() + } + async runSql () { + try { + this.ddlError = false + this.running = true + const res = await this.runDDL({ + sql: this.content, + project: this.currentSelectedProject + }) + const resultData = await handleSuccessAsync(res) + this.running = false + this.showCreateSuccessAlert = this.content.toLocaleLowerCase().indexOf('create view') > -1 + this.showCreateSuccessAlert && this.insertEditorContent(`\n\n${resultData}`) + this.resetErrorMsg() + this.$message({ type: 'success', message: this.$t('runSuccess') }) + } catch (e) { + const err = e.body + this.ddlError = true + this.errorMsg = err.msg + this.stacktrace = err.stacktrace + this.activeType = 'result' + this.running = false + this.showCreateSuccessAlert = false + this.$message({ type: 'error', message: this.$t('runFailed') }) + // handleError(e) + } + } + resetErrorMsg () { + this.errorMsg = '' + this.stacktrace = '' + } + async getDDLRules () { + try { + const result = await this.getDDLDescription({project: this.currentSelectedProject, page_type: 'hive'}) + const rules = await handleSuccessAsync(result) + this.rules = rules + } catch (e) { + handleError(e) + } + } + created () { + this.getDDLRules() + } + mounted () { + this.setOption() + } + } + </script> + + <style lang="less" scoped> + .ddl-container { + width: 100%; + height: 100%; + display: flex; + .left-layout { + flex: 1; + display: flex; + flex-direction: column; + .editor-content { + flex: 1; + position: relative; + .run-btn { + width: 40px; + height: 38px; + position: absolute; + right: 16px; + bottom: 16px; + } + } + .import-link { + color: #1268FB; + } + } + .right-layout { + width: 46px; + transition: width .5s; + display: flex; + &.expand { + width: 330px; + } + .sign-item { + .is-dot { + right: 7px; + margin-top: 2px; + } + } + .action-btns { + width: 46px; + height: 100%; + display: flex; + flex-direction: column; + align-items: center; + gap: 8px; + border-left: 1px solid #E6EBF4; + padding: 8px 8px; + box-sizing: border-box; + .el-button { + color: #8B99AE; + &.is-active { + background: #ECF0F8 !important; + } + } + } + .feedback-suggestions { + padding: 16px 8px; + box-sizing: border-box; + .suggestion-list { + .label { + font-size: 14px; + font-weight: 400; + color: #8B99AE; + line-height: 22px; + margin-bottom: 16px; + } + .item { + font-size: 14px; + color: #2F374C; + line-height: 22px; + } + .trance-msg { + height: 270px; + overflow: auto; + background: #F8F9FB; + border: 1px solid #E6EBF4; + border-radius: 4px; + margin-bottom: 16px; + padding: 8px 16px; + box-sizing: border-box; + word-break: break-word; + } + } + } + .panel-content-layout { + height: 100%; + width: 284px; + flex: 1; + display: flex; + flex-direction: column; + .panel-header { + height: 60px; + padding: 0 8px; + box-sizing: border-box; + position: relative; + .title { + line-height: 60px; + font-weight: 600; + font-size: 16px; + } + .close-btn { + position: absolute; + line-height: 60px; + right: 25px; + cursor: pointer; + } + } + .datasource-layout { + flex: 1; + height: 0; + } + .data-source-layout { + overflow: hidden; + } + .import-btn { + height: 70px; + padding: 16px; + box-sizing: border-box; + .el-button { + width: 100%; + } + } + } + } + .header { + height: 60px; + display: flex; + align-items: center; + padding: 0 16px; + box-sizing: border-box; + border-bottom: 1px solid #E6EBF4; + .title { + font-weight: 600; + font-size: 16px; + } + } + } + </style> + <style lang="less"> + .ddl-editor { + .ace_content { + width: 100% !important; + } + .ace_print-margin { + visibility: hidden !important; + } + } + .panel-content-layout { + .data-source-bar { + width: 100% !important; + height: 100%; + .body { + width: 100%; + height: 100%; + padding: 0; + .el-tree { + border: 0; + } + } + .el-input__inner { + border: 0; + box-shadow: none; + } + } + } + .sign-item { + .el-badge__content.is-fixed.is-dot { + right: 7px; + margin-top: 2px; + } + } + .accelerator-key { + color: #8B99AE; + } + </style> diff --git a/kystudio/src/components/studio/StudioSource/index.vue b/kystudio/src/components/studio/StudioSource/index.vue index ad9ef9f008..7aa6d0fbf5 100644 --- a/kystudio/src/components/studio/StudioSource/index.vue +++ b/kystudio/src/components/studio/StudioSource/index.vue @@ -6,6 +6,7 @@ <DataSourceBar :ignore-node-types="['column']" ref="datasource-bar" + :showDDL="true" :project-name="currentSelectedProject" :is-show-load-source="true" :is-show-load-table="datasourceActions.includes('loadSource')" diff --git a/kystudio/src/config/index.js b/kystudio/src/config/index.js index 1c9e1da646..b8ecc8af02 100644 --- a/kystudio/src/config/index.js +++ b/kystudio/src/config/index.js @@ -57,7 +57,8 @@ export const menusData = [ children: [ { name: 'source', path: '/studio/source' }, { name: 'modelList', path: '/studio/model' }, - { name: 'snapshot', path: '/studio/snapshot' } + { name: 'snapshot', path: '/studio/snapshot' }, + { name: 'ddl', path: '/studio/ddl' } ] }, { diff --git a/kystudio/src/config/spec.js b/kystudio/src/config/spec.js index 1227a5b5ed..236d4d168e 100644 --- a/kystudio/src/config/spec.js +++ b/kystudio/src/config/spec.js @@ -18,6 +18,7 @@ export default { { "id": "modelDetails", "value": "modeldetails", "title": "Model Details" }, { "id": "modelSubPartitionValues", "value": "modelsubpartitionvalues", "title": "Model SubPartition Values" }, { "id": "snapshot", "value": "snapshot", "title": "Snapshot" }, + { "id": "ddl", "value": "ddl", "title": "DDL" }, { "id": "monitor", "value": "monitor", "title": "Monitor" }, { "id": "job", "value": "job", "title": "Job" }, { "id": "streamingJob", "value": "streamingjob", "title": "streamingJob" }, @@ -76,7 +77,8 @@ export default { { "id": "tableIndexActions" }, { "id": "viewDataSource" }, { "id": "changeBuildType" }, - { "id": "changePartition" } + { "id": "changePartition" }, + { "id": "ddl" } ], "modelActions": [ { "id": "dataLoad" }, @@ -150,12 +152,12 @@ 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,monitor,job,streamingJob]", "value": "dashboard,query,insight,queryHistory,studio,setting,source,model,index,modelEdit,modelDetails,modelSubPartitionValues,snapshot,monitor,job,streamingJob,admin" }, + { "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": "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,monitor,job,streamingJob]", "value": "dashboard,query,insight,queryHistory,studio,setting,source,model,index,modelEdit,modelDetails,modelSubPartitionValues,snapshot,monitor,job,streamingJob,admin" }, - { "key": "systemUser-management-*", "value": "dashboard,query,insight,queryHistory,studio,source,model,index,modelEdit,modelDetails,modelSubPartitionValues,snapshot,monitor,job,streamingJob" }, - { "key": "systemUser-operation-*", "value": "dashboard,query,insight,queryHistory,studio,model,modelDetails,snapshot,index,monitor,job,streamingJob,modelSubPartitionValues" }, - { "key": "systemUser-read-*", "value": "dashboard,query,insight,queryHistory,studio,model,modelDetails,snapshot,index" }, + { "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-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 fa9d97ad4c..22357326e7 100644 --- a/kystudio/src/locale/en.js +++ b/kystudio/src/locale/en.js @@ -68,6 +68,7 @@ exports.default = { jobs: 'Jobs', cubes: 'Cubes', dataSource: 'Data Source', + dataSourceTable: 'Data Source Table', fact: 'Fact Table', limitfact: 'Lookup Table(limited)', lookup: 'Lookup Table', @@ -490,6 +491,7 @@ exports.default = { index: 'Index', modeledit: 'Model Edit', snapshot: 'Snapshot', + ddl: 'DDL', refresh: 'Refresh', systemcapacity: 'Capacity' }, diff --git a/kystudio/src/router/index.js b/kystudio/src/router/index.js index b0b6b3c545..4c75e0a7e7 100644 --- a/kystudio/src/router/index.js +++ b/kystudio/src/router/index.js @@ -80,6 +80,10 @@ let routerOptions = { name: 'Snapshot', path: 'studio/snapshot', component: () => import('../components/studio/snapshot/snapshot.vue') + }, { + name: 'DDL', + path: 'studio/ddl', + component: () => import('../components/studio/DDL/ddl.vue') }, { name: 'Project', path: 'admin/project', diff --git a/kystudio/src/service/datasource.js b/kystudio/src/service/datasource.js index e70b0d67b0..7e00128f44 100644 --- a/kystudio/src/service/datasource.js +++ b/kystudio/src/service/datasource.js @@ -315,5 +315,11 @@ export default { }, exportCSV (data) { return Vue.http.post(apiUrl + 'query/format/csv', data, {emulateJSON: true}) + }, + getDDLDescrition (data) { + return Vue.resource(apiUrl + 'spark_source/ddl/description').get(data) + }, + runDDL (data) { + return Vue.resource(apiUrl + 'spark_source/ddl').save(data) } } diff --git a/kystudio/src/store/datasource.js b/kystudio/src/store/datasource.js index 199d27154d..ac31bd3994 100644 --- a/kystudio/src/store/datasource.js +++ b/kystudio/src/store/datasource.js @@ -394,6 +394,14 @@ export default { }, [types.EXPORT_CSV]: function ({commit}, data) { return api.datasource.exportCSV(data) + }, + // 获取 ddl 规则 + [types.DDL_DESCRIPTION]: function (_, data) { + return api.datasource.getDDLDescrition(data) + }, + // 执行 ddl 语句 + [types.RUN_DDL]: function (_, data) { + return api.datasource.runDDL(data) } } } diff --git a/kystudio/src/store/system.js b/kystudio/src/store/system.js index b662f17c36..7607926d28 100644 --- a/kystudio/src/store/system.js +++ b/kystudio/src/store/system.js @@ -59,7 +59,8 @@ export default { isShowSecondStorage: false, isNonAdminGenQueryDiagPackage: 'true', streamingEnabled: 'false', - storageQuery: 'true' + storageQuery: 'true', + ddlEnabled: 'false' }, mutations: { [types.COLLECT_MESSAGE_DIRECTIVES]: (state, directive) => { @@ -183,6 +184,7 @@ 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'}) resolve(response) }, () => { reject() diff --git a/kystudio/src/store/types.js b/kystudio/src/store/types.js index 29a4f333de..7ce238b2e7 100644 --- a/kystudio/src/store/types.js +++ b/kystudio/src/store/types.js @@ -180,6 +180,9 @@ export const SUBMIT_ACCESS_DATA = 'SUBMIT_ACCESS_DATA' export const EXPORT_CSV = 'EXPORT_CSV' export const LOAD_DATASOURCE_OF_MODEL = 'LOAD_DATASOURCE_OF_MODEL' + +export const DDL_DESCRIPTION = 'DDL_DESCRIPTION' +export const RUN_DDL = 'RUN_DDL' // acl table export const GET_ACL_SET_TABLE = 'GET_ACL_SET_TABLE' export const SAVE_ACL_SET_TABLE = 'SAVE_ACL_SET_TABLE'