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 334b8b2ca4b588bbc820b1a3cefb19cd286a4bf5
Author: Qian Xia <lauraxiaq...@gmail.com>
AuthorDate: Thu Jul 13 15:15:13 2023 +0800

    KYLIN-5624 agg index / table index text recognize
---
 .../RecognizeAggregateModal.vue                    | 29 ++++++++----
 .../common/RecognizeAggregateModal/handler.js      | 13 +++++-
 .../StudioModel/ModelList/AggregateModal/index.vue | 54 +++++++++++++++++++---
 .../studio/StudioModel/TableIndexEdit/locales.js   |  1 +
 .../StudioModel/TableIndexEdit/tableindex_edit.vue | 19 ++++++++
 5 files changed, 97 insertions(+), 19 deletions(-)

diff --git 
a/kystudio/src/components/common/RecognizeAggregateModal/RecognizeAggregateModal.vue
 
b/kystudio/src/components/common/RecognizeAggregateModal/RecognizeAggregateModal.vue
index 554e73a2cf..43b6dddd6b 100644
--- 
a/kystudio/src/components/common/RecognizeAggregateModal/RecognizeAggregateModal.vue
+++ 
b/kystudio/src/components/common/RecognizeAggregateModal/RecognizeAggregateModal.vue
@@ -90,6 +90,9 @@
   import { collectErrorsInEditor, refreshEditor, scrollToLineAndHighlight, 
updatePlaceHolder, ERROR_TYPE } from './handler'
   import { AGGREGATE_TYPE } from '../../../config'
   vuex.registerModule(['modals', 'RecognizeAggregateModal'], store)
+
+  const TABLE_INDEX = 'TABLE_INDEX'
+
   @Component({
     components: {
       AceEditor,
@@ -115,7 +118,8 @@
         'hierarchies',
         'hierarchyItems',
         'joints',
-        'jointItems'
+        'jointItems',
+        'tableIndexCols'
       ])
     },
     methods: {
@@ -149,7 +153,11 @@
     }
     get errorCount () {
       const { errorInEditor } = this
-      return errorInEditor.filter(line => [ERROR_TYPE.COLUMN_NOT_IN_MODEL, 
ERROR_TYPE.COLUMN_NOT_IN_INCLUDES].includes(line.type)).length
+      return errorInEditor.filter(line => [
+        ERROR_TYPE.COLUMN_NOT_IN_MODEL,
+        ERROR_TYPE.COLUMN_NOT_IN_INCLUDES,
+        ERROR_TYPE.COLUMN_USED_IN_OTHER
+      ].includes(line.type)).length
     }
     get repeatCount () {
       const { errorInEditor } = this
@@ -176,12 +184,13 @@
       return selectedDimensionCount && !isSelectAll
     }
     isColumnUsedInCurrent (column) {
-      const { type, includes, mandatories, hierarchyItems, jointItems } = this
+      const { type, includes, mandatories, hierarchyItems, jointItems, 
tableIndexCols } = this
       switch (type) {
         case AGGREGATE_TYPE.INCLUDE: return includes.includes(column)
         case AGGREGATE_TYPE.MANDATORY: return mandatories.includes(column)
         case AGGREGATE_TYPE.HIERARCHY: return hierarchyItems.includes(column)
         case AGGREGATE_TYPE.JOINT: return jointItems.includes(column)
+        case TABLE_INDEX: return tableIndexCols.includes(column)
         default: return false
       }
     }
@@ -223,6 +232,8 @@
           return this.$t('columnNotInIncludes', { column })
         case ERROR_TYPE.COLUMN_DUPLICATE:
           return this.$t('columnDuplicate', { column })
+        case ERROR_TYPE.COLUMN_USED_IN_OTHER:
+          return this.$t('columnUsedInOther', { column })
         default: return 'Unknow Error'
       }
     }
@@ -262,14 +273,12 @@
               {this.$t('inputPlaceholder1')}
               <el-tooltip
                 popperClass="recognize-aggregate-placeholder-tooltip"
-                content={(
-                  <ul>
-                    <li>{this.$t('inputPlaceholderTooltip1')}</li>
-                    <li>{this.$t('inputPlaceholderTooltip2')}</li>
-                  </ul>
-                )}
                 placement="top"
               >
+                <ul slot="content">
+                  <li>{this.$t('inputPlaceholderTooltip1')}</li>
+                  <li>{this.$t('inputPlaceholderTooltip2')}</li>
+                </ul>
                 <span 
class="how-to-use">{this.$t('inputPlaceholderTooltipTrigger')}</span>
               </el-tooltip>
             </div>
@@ -323,7 +332,7 @@
         if (columnText) {
           const dimension = modelDimensions.find(d => d.column === columnText)
           if (dimension) {
-            if (type !== AGGREGATE_TYPE.INCLUDE && 
!this.isColumnInIncludes(dimension.column)) {
+            if (![AGGREGATE_TYPE.INCLUDE, TABLE_INDEX].includes(type) && 
!this.isColumnInIncludes(dimension.column)) {
               this.setNotInIncludesError(dimension.column)
             } else if (!this.isColumnUsedInOther(dimension.column)) {
               const duplicate = dimensions.some(d => d.value === 
dimension.column)
diff --git a/kystudio/src/components/common/RecognizeAggregateModal/handler.js 
b/kystudio/src/components/common/RecognizeAggregateModal/handler.js
index f8cdc0d6e8..db4eb83cf2 100644
--- a/kystudio/src/components/common/RecognizeAggregateModal/handler.js
+++ b/kystudio/src/components/common/RecognizeAggregateModal/handler.js
@@ -8,7 +8,8 @@ const dom = acequire('ace/lib/dom')
 export const ERROR_TYPE = {
   COLUMN_NOT_IN_MODEL: 'columnNotInModel',
   COLUMN_NOT_IN_INCLUDES: 'columnNotInIncludes',
-  COLUMN_DUPLICATE: 'columnDuplicate'
+  COLUMN_DUPLICATE: 'columnDuplicate',
+  COLUMN_USED_IN_OTHER: 'columnUsedInOther'
 }
 
 export function $updatePlaceholder (editor, renderPlaceholder) {
@@ -83,7 +84,7 @@ export function searchColumnInEditor (editor, column) {
 }
 
 export function collectErrorsInEditor (errors, editor) {
-  const { notInModel, duplicate, notInIncludes } = errors
+  const { notInModel, duplicate, notInIncludes, usedInOthers } = errors
 
   let errorInEditor = []
   let errorLines = []
@@ -112,6 +113,14 @@ export function collectErrorsInEditor (errors, editor) {
     })]
   }
 
+  for (const column of usedInOthers) {
+    const usedInOtherRanges = searchColumnInEditor(editor, column)
+    errorInEditor = [...errorInEditor, ...usedInOtherRanges.map(r => {
+      errorLines.push(r.start.row)
+      return { row: r.start.row, column, type: ERROR_TYPE.COLUMN_USED_IN_OTHER 
}
+    })]
+  }
+
   errorLines = errorLines.sort()
 
   return { errorInEditor, errorLines }
diff --git 
a/kystudio/src/components/studio/StudioModel/ModelList/AggregateModal/index.vue 
b/kystudio/src/components/studio/StudioModel/ModelList/AggregateModal/index.vue
index 7ad21f77b9..a53beaa4f0 100644
--- 
a/kystudio/src/components/studio/StudioModel/ModelList/AggregateModal/index.vue
+++ 
b/kystudio/src/components/studio/StudioModel/ModelList/AggregateModal/index.vue
@@ -191,6 +191,14 @@
                             <common-tip placement="right" 
:content="$t('hierarchyDesc')">
                               <i class="el-ksd-icon-more_info_16"></i>
                             </common-tip>
+                            <span class="row ksd-fright ky-no-br-space">
+                              <el-button
+                                plain class="ksd-ml-10" size="mini"
+                                
@click="handleHierarchyRecognize(AGGREGATE_TYPE.HIERARCHY, aggregateIdx)"
+                              >
+                                {{$t('textRecognition')}}
+                              </el-button>
+                            </span>
                           </h2>
                           <div class="list"
                             v-for="(hierarchy, hierarchyRowIdx) in 
aggregate.hierarchyArray"
@@ -229,6 +237,14 @@
                             <common-tip placement="right" 
:content="$t('jointDesc')">
                               <i class="el-ksd-icon-more_info_16"></i>
                             </common-tip>
+                            <span class="row ksd-fright ky-no-br-space">
+                              <el-button
+                                plain class="ksd-ml-10" size="mini"
+                                
@click="handleJointRecognize(AGGREGATE_TYPE.JOINT, aggregateIdx)"
+                              >
+                                {{$t('textRecognition')}}
+                              </el-button>
+                            </span>
                           </h2>
                           <div class="list"
                             v-for="(joint, jointRowIdx) in 
aggregate.jointArray"
@@ -1033,11 +1049,11 @@ export default class AggregateModal extends Vue {
       this.aggregateStyle = []
     })
   }
-  handleAddDimensionRow (path, id) {
+  handleAddDimensionRow (path, id, items = []) {
     const rootKey = path.split('.')[0]
     const dimensionRows = get(this.form, path)
     const newId = dimensionRows.length
-    const newDimensionRow = { id: newId, items: [] }
+    const newDimensionRow = { id: newId, items }
     this.setModalForm({[rootKey]: push(this.form, path, 
newDimensionRow)[rootKey]})
     this.isWaitingCheckCuboids[id] = true
     this.isWaitingCheckAllCuboids = true
@@ -1126,22 +1142,46 @@ export default class AggregateModal extends Vue {
       }
     })
   }
-  async handleIncludesRecognize (type, aggregateIdx, groupIdx = 0) {
+  async handleIncludesRecognize (type, aggregateIdx) {
     const { model, form } = this
     const { aggregateArray = [] } = form
     const aggregate = aggregateArray[aggregateIdx]
-    const selectedColumns = await this.callRecognizeAggregateModal({ type, 
model, aggregate, groupIdx })
+    const selectedColumns = await this.callRecognizeAggregateModal({ type, 
model, aggregate })
     const value = [...aggregate.includes, ...selectedColumns]
     this.handleInput(`aggregateArray.${aggregateIdx}.includes`, value, 
aggregate.id)
   }
-  async handleMandatoryRecognize (type, aggregateIdx, groupIdx = 0) {
+  async handleMandatoryRecognize (type, aggregateIdx) {
     const { model, form } = this
     const { aggregateArray = [] } = form
     const aggregate = aggregateArray[aggregateIdx]
-    const selectedColumns = await this.callRecognizeAggregateModal({ type, 
model, aggregate, groupIdx })
+    const selectedColumns = await this.callRecognizeAggregateModal({ type, 
model, aggregate })
     const value = [...aggregate.mandatory, ...selectedColumns]
     this.handleInput(`aggregateArray.${aggregateIdx}.mandatory`, value, 
aggregate.id)
   }
+  async handleHierarchyRecognize (type, aggregateIdx) {
+    const { model, form } = this
+    const { aggregateArray = [] } = form
+    const aggregate = aggregateArray[aggregateIdx]
+    const value = await this.callRecognizeAggregateModal({ type, model, 
aggregate })
+    const emptyArrayIdx = aggregate.hierarchyArray.findIndex(array => 
array.items.length === 0)
+    if (emptyArrayIdx !== -1) {
+      
this.handleInput(`aggregateArray.${aggregateIdx}.hierarchyArray.${emptyArrayIdx}.items`,
 value, aggregate.id)
+    } else {
+      
this.handleAddDimensionRow(`aggregateArray.${aggregateIdx}.hierarchyArray`, 
aggregate.id, value)
+    }
+  }
+  async handleJointRecognize (type, aggregateIdx) {
+    const { model, form } = this
+    const { aggregateArray = [] } = form
+    const aggregate = aggregateArray[aggregateIdx]
+    const value = await this.callRecognizeAggregateModal({ type, model, 
aggregate })
+    const emptyArrayIdx = aggregate.jointArray.findIndex(array => 
array.items.length === 0)
+    if (emptyArrayIdx !== -1) {
+      
this.handleInput(`aggregateArray.${aggregateIdx}.jointArray.${emptyArrayIdx}.items`,
 value, aggregate.id)
+    } else {
+      this.handleAddDimensionRow(`aggregateArray.${aggregateIdx}.jointArray`, 
aggregate.id, value)
+    }
+  }
   handleRemoveAllIncludes (aggregateIdx, titleId, id) {
     kylinConfirm(this.$t('clearAllAggregateTip', {aggId: titleId}), {type: 
'warning'}, this.$t('clearAggregateTitle')).then(() => {
       const { aggregateArray = [] } = this.form
@@ -2210,7 +2250,7 @@ export default class AggregateModal extends Vue {
     position: absolute;
     right: 6px;
     top: 0;
-    transform: translateY(2px);
+    transform: translateY(12px);
     .is-text {
       font-size: 24px;
       border: 0;
diff --git 
a/kystudio/src/components/studio/StudioModel/TableIndexEdit/locales.js 
b/kystudio/src/components/studio/StudioModel/TableIndexEdit/locales.js
index 031267a13a..45109240d4 100644
--- a/kystudio/src/components/studio/StudioModel/TableIndexEdit/locales.js
+++ b/kystudio/src/components/studio/StudioModel/TableIndexEdit/locales.js
@@ -29,6 +29,7 @@ export default {
     indexTimeRange: 'Index’s Time Range',
     indexTimeRangeTips: 'The data range that the indexes will be built in. 
With "Batch and Streaming" selected, there will be generated batch indexes and 
streaming indexes with same content respectively. ',
     noIndexRangeByHybrid: 'Select index’s data range to display available 
columns.',
+    textRecognition: 'Text Recognition',
     refuseAddIndexTip: 'Can\'t add streaming indexes. Please stop the 
streaming job and then delete all the streaming segments.'
   }
 }
diff --git 
a/kystudio/src/components/studio/StudioModel/TableIndexEdit/tableindex_edit.vue 
b/kystudio/src/components/studio/StudioModel/TableIndexEdit/tableindex_edit.vue
index c34a90dcc0..946ac5ee48 100644
--- 
a/kystudio/src/components/studio/StudioModel/TableIndexEdit/tableindex_edit.vue
+++ 
b/kystudio/src/components/studio/StudioModel/TableIndexEdit/tableindex_edit.vue
@@ -29,6 +29,9 @@
           </el-alert>
           <template v-if="modelInstance.model_type !== 'HYBRID' || 
modelInstance.model_type === 'HYBRID' && tableIndexMeta.index_range">
             <p class="anit-table-tips" 
v-if="hasManyToManyAndAntiTable">{{$t('manyToManyAntiTableTip')}}</p>
+            <el-button plain class="ksd-ml-10" size="mini" 
@click="handleTableIndexRecognize">
+              {{$t('textRecognition')}}
+            </el-button>
             <el-input v-model="searchColumn" size="medium" 
prefix-icon="el-ksd-icon-search_22" style="width:200px" 
:placeholder="$t('filterByColumns')"></el-input>
           </template>
         </div>
@@ -118,6 +121,9 @@
         hideModal: types.HIDE_MODAL,
         setModalForm: types.SET_MODAL_FORM,
         resetModalForm: types.RESET_MODAL_FORM
+      }),
+      ...mapActions('RecognizeAggregateModal', {
+        callRecognizeAggregateModal: types.CALL_MODAL
       })
     },
     locales
@@ -349,6 +355,19 @@
         this.$message({message: tipMsg, type: 'success'})
       }
     }
+    async handleTableIndexRecognize () {
+      const selectedColumns = await this.callRecognizeAggregateModal({
+        type: 'TABLE_INDEX',
+        allColumns: this.allColumns,
+        model: this.modelInstance
+      })
+      this.allColumns.forEach((col) => {
+        if (selectedColumns.includes(col.fullName)) {
+          col.isUsed = true
+        }
+      })
+      this.selectTableIndex()
+    }
     confirmSubmit (isLoadData) {
       this.isLoadDataLoading = isLoadData
       this.btnLoading = true

Reply via email to