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

nicholasjiang pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/paimon-webui.git


The following commit(s) were added to refs/heads/main by this push:
     new 332ed2fd [Improvement] Optimize query page style (#315)
332ed2fd is described below

commit 332ed2fd2cd9121033463f59e1b41ab843742be2
Author: s7monk <[email protected]>
AuthorDate: Fri Jun 7 11:17:45 2024 +0800

    [Improvement] Optimize query page style (#315)
---
 .../console/components/table/index.module.scss     |   2 +-
 .../components/console/components/table/index.tsx  |  86 ++++++++++++++++--
 .../components/query/components/console/index.tsx  |  29 +++++-
 .../playground/components/query/index.module.scss  |  53 +++++++++--
 .../views/playground/components/query/index.tsx    | 101 +++++++++++++--------
 5 files changed, 212 insertions(+), 59 deletions(-)

diff --git 
a/paimon-web-ui/src/views/playground/components/query/components/console/components/table/index.module.scss
 
b/paimon-web-ui/src/views/playground/components/query/components/console/components/table/index.module.scss
index 87820735..c7c41421 100644
--- 
a/paimon-web-ui/src/views/playground/components/query/components/console/components/table/index.module.scss
+++ 
b/paimon-web-ui/src/views/playground/components/query/components/console/components/table/index.module.scss
@@ -24,4 +24,4 @@ under the License. */
   .table {
     padding-left: 20px;
   }
-}
\ No newline at end of file
+}
diff --git 
a/paimon-web-ui/src/views/playground/components/query/components/console/components/table/index.tsx
 
b/paimon-web-ui/src/views/playground/components/query/components/console/components/table/index.tsx
index d400f58e..592a71ff 100644
--- 
a/paimon-web-ui/src/views/playground/components/query/components/console/components/table/index.tsx
+++ 
b/paimon-web-ui/src/views/playground/components/query/components/console/components/table/index.tsx
@@ -22,18 +22,27 @@ import { useJobStore } from '@/store/job'
 
 export default defineComponent({
   name: 'TableResult',
-  setup() {
+  props: {
+    maxHeight: {
+      type: Number as PropType<number>,
+      default: 150,
+    },
+  },
+  setup(props) {
     const { t } = useLocaleHooks()
     const message = useMessage()
     const jobStore = useJobStore()
-
+    const scrollX = ref('100%')
+    const tableContainer = ref<HTMLElement | null>(null)
     const tableRef = ref<DataTableInst | null>(null)
+    const maxTableHeight = ref(0)
 
     interface TableColumn {
       title: string
       key: string
       fixed?: string
       width?: number
+      originalWidth?: number
       render?: (row: any, index: number) => string | number | JSX.Element
     }
 
@@ -59,12 +68,19 @@ export default defineComponent({
         render: (_, index) => `${index + 1}`,
       }
 
-      const dynamicColumns = Object.keys(sampleObject).map(key => ({
-        title: key,
-        key,
-        resizable: true,
-        sortable: true,
-      }))
+      const dynamicColumns = Object.keys(sampleObject).map((key) => {
+        const maxContentWidth = Math.max(...data.value.map(item => 
item[key]?.toString().length || 0))
+        const maxTitleWidth = key.length * 10
+        const originalWidth = Math.max(100, maxContentWidth * 10, 
maxTitleWidth)
+        return {
+          title: key,
+          key,
+          width: originalWidth,
+          originalWidth,
+          resizable: true,
+          sortable: true,
+        }
+      })
 
       return [indexColumn, ...dynamicColumns]
     }
@@ -83,26 +99,76 @@ export default defineComponent({
       }
     })
 
+    const updateTableWidth = () => {
+      if (tableContainer.value) {
+        const totalColumnWidth = columns.value.reduce((acc, col) => acc + 
(col.originalWidth || 100), 0)
+        if (totalColumnWidth > tableContainer.value.clientWidth) {
+          scrollX.value = `${totalColumnWidth}px`
+          columns.value.forEach((col) => {
+            if (col.originalWidth !== undefined)
+              col.width = col.originalWidth
+          })
+        }
+        else {
+          scrollX.value = ''
+          columns.value.forEach((col) => {
+            col.width = undefined
+          })
+        }
+      }
+    }
+
+    watchEffect(updateTableWidth)
+
+    watch(data, async (newData) => {
+      if (newData && newData.length > 0) {
+        await nextTick()
+        if (tableContainer.value) {
+          const headerElement = 
tableContainer.value.querySelector('.n-data-table-base-table-header')
+          if (headerElement) {
+            const headerHeight = headerElement.clientHeight
+            maxTableHeight.value = Math.max(0, props.maxHeight - headerHeight)
+          }
+        }
+      }
+    }, { immediate: true })
+
+    onMounted(() => {
+      nextTick(() => {
+        updateTableWidth()
+        window.addEventListener('resize', updateTableWidth)
+      })
+    })
+
     onUnmounted(() => {
       mittBus.off('triggerDownloadCsv')
       mittBus.off('triggerCopyData')
+      window.removeEventListener('resize', updateTableWidth)
     })
 
     return {
       columns,
       data,
       tableRef,
+      tableContainer,
+      scrollX,
+      maxHeight: props.maxHeight,
+      maxTableHeight,
     }
   },
   render() {
     return (
-      <div>
+      <div
+        ref="tableContainer"
+        style={{ height: `${this.maxHeight}px` }}
+      >
         <n-data-table
           ref={(el: any) => { this.tableRef = el }}
           class={styles.table}
           columns={this.columns}
           data={this.data}
-          max-height={90}
+          max-height={`${this.maxTableHeight}px`}
+          scroll-x={this.scrollX || undefined}
           v-slots={{
             empty: () => '',
           }}
diff --git 
a/paimon-web-ui/src/views/playground/components/query/components/console/index.tsx
 
b/paimon-web-ui/src/views/playground/components/query/components/console/index.tsx
index 23c23ab5..b9436070 100644
--- 
a/paimon-web-ui/src/views/playground/components/query/components/console/index.tsx
+++ 
b/paimon-web-ui/src/views/playground/components/query/components/console/index.tsx
@@ -16,6 +16,7 @@ specific language governing permissions and limitations
 under the License. */
 
 import { CloseSharp, KeyboardDoubleArrowDownSharp, KeyboardDoubleArrowUpSharp 
} from '@vicons/material'
+import { throttle } from 'lodash'
 import TableActionBar from './components/controls'
 import TableResult from './components/table'
 import styles from './index.module.scss'
@@ -25,6 +26,8 @@ export default defineComponent({
   emits: ['ConsoleUp', 'ConsoleDown', 'ConsoleClose'],
   setup(props, { emit }) {
     const { t } = useLocaleHooks()
+    const editorConsoleRef = ref<HTMLElement | null>(null)
+    const adjustedHeight = ref(0)
 
     const handleUp = () => {
       emit('ConsoleUp', 'up')
@@ -38,16 +41,38 @@ export default defineComponent({
       emit('ConsoleClose', 'close')
     }
 
+    const handleResize = throttle((entries) => {
+      for (const entry of entries) {
+        const { height } = entry.contentRect
+        adjustedHeight.value = height - 106
+      }
+    }, 100)
+
+    let resizeObserver: ResizeObserver
+    onMounted(() => {
+      if (editorConsoleRef.value) {
+        resizeObserver = new ResizeObserver(handleResize)
+        resizeObserver.observe(editorConsoleRef.value)
+      }
+    })
+
+    onUnmounted(() => {
+      if (editorConsoleRef.value)
+        resizeObserver.unobserve(editorConsoleRef.value)
+    })
+
     return {
       t,
       handleUp,
       handleDown,
       handleClose,
+      editorConsoleRef,
+      adjustedHeight,
     }
   },
   render() {
     return (
-      <div class={styles['editor-console']}>
+      <div class={styles['editor-console']} ref="editorConsoleRef">
         <n-tabs
           type="line"
           size="large"
@@ -60,7 +85,7 @@ export default defineComponent({
           </n-tab-pane>
           <n-tab-pane name="result" tab={this.t('playground.result')}>
             <TableActionBar />
-            <TableResult />
+            <TableResult maxHeight={this.adjustedHeight} />
           </n-tab-pane>
         </n-tabs>
         <div class={styles.operations}>
diff --git 
a/paimon-web-ui/src/views/playground/components/query/index.module.scss 
b/paimon-web-ui/src/views/playground/components/query/index.module.scss
index 0a807a10..cbda480c 100644
--- a/paimon-web-ui/src/views/playground/components/query/index.module.scss
+++ b/paimon-web-ui/src/views/playground/components/query/index.module.scss
@@ -21,17 +21,40 @@ under the License. */
   height: 100%;
 
   .menu-tree {
-    width: 20%;
+    width: 100%;
     height: 100%;
   }
 
+  .split {
+    position: relative;
+    width: 0;
+    height: 100%;
+    flex: none;
+    cursor: col-resize;
+
+    &::after {
+      content: '';
+      position: absolute;
+      top: 0;
+      right: -5px;
+      bottom: 0;
+      left: -5px;
+      background: transparent;
+      z-index: 1;
+    }
+  }
+
   .editor-area {
-    width: 80%;
+    display: flex;
+    flex: 1;
     height: 100%;
+    flex-direction: column;
 
     :global {
       .n-card {
         height: 100%;
+        display: flex;
+        flex-direction: column;
       }
     }
 
@@ -46,13 +69,31 @@ under the License. */
     }
   
     .editor {
-      height: 60%;
-      overflow-y: scroll;
+      height: 100%;
+      flex: 1;
     }
 
     .console {
-      height: 40%;
-      overflow-y: scroll;
+      height: 100%;
+      flex: 1;
+    }
+
+    .console-splitter {
+      position: relative;
+      height: 0;
+      background: transparent;
+      cursor: ns-resize;
+
+      &::after {
+        content: '';
+        position: absolute;
+        top: -5px;
+        right: 0;
+        bottom: -5px;
+        left: 0;
+        background: transparent;
+        z-index: 1;
+      }
     }
   }
 }
diff --git a/paimon-web-ui/src/views/playground/components/query/index.tsx 
b/paimon-web-ui/src/views/playground/components/query/index.tsx
index 34a20196..0b0c0172 100644
--- a/paimon-web-ui/src/views/playground/components/query/index.tsx
+++ b/paimon-web-ui/src/views/playground/components/query/index.tsx
@@ -168,47 +168,68 @@ export default defineComponent({
   render() {
     return (
       <div class={styles.query}>
-        <div class={styles['menu-tree']}>
-          <MenuTree ref="menuTreeRef" />
-        </div>
-        <div class={styles['editor-area']}>
-          <n-card class={styles.card} content-style="padding: 5px 
18px;display: flex;flex-direction: column;">
-            <div class={styles.tabs}>
-              <EditorTabs />
-            </div>
-            <div class={styles.debugger}>
-              <EditorDebugger tabData={this.tabData} 
onHandleFormat={this.handleFormat} onHandleSave={this.editorSave} />
-            </div>
-            <div class={styles.editor} style={`height: 
${this.consoleHeightType === 'up' ? '20%' : '60%'}`}>
-              {
-                this.tabData.panelsList?.length > 0
-                && (
-                  <n-card content-style="padding: 0;">
-                    <MonacoEditor
-                      v-model={this.tabData.panelsList.find((item: any) => 
item.key === this.tabData.chooseTab).content}
-                      language={this.language}
-                      onEditorMounted={this.editorMounted}
-                      onEditorSave={this.editorSave}
-                      onChange={this.handleContentChange}
-                    />
-                  </n-card>
-                )
-              }
-            </div>
-            { this.showConsole && (
-              <div class={styles.console} style={`height: 
${this.consoleHeightType === 'up' ? '80%' : '40%'}`}>
-                {
-                  this.tabData.panelsList?.length > 0
-                  && (
-                    <n-card content-style="padding: 0;">
-                      <EditorConsole onConsoleDown={this.handleConsoleDown} 
onConsoleUp={this.handleConsoleUp} onConsoleClose={this.handleConsoleClose} />
-                    </n-card>
-                  )
-                }
+        <n-split direction="horizontal" max={0.35} min={0.16} 
resize-trigger-size={0} default-size={0.20}>
+          {{
+            '1': () => (
+              <div class={styles['menu-tree']}>
+                <MenuTree ref="menuTreeRef" />
               </div>
-            )}
-          </n-card>
-        </div>
+            ),
+            '2': () => (
+              <div class={styles['editor-area']}>
+                <n-card class={styles.card} content-style="padding: 5px 
18px;display: flex;flex-direction: column;">
+                  <div class={styles.tabs}>
+                    <EditorTabs />
+                  </div>
+                  <div class={styles.debugger}>
+                    <EditorDebugger tabData={this.tabData} 
onHandleFormat={this.handleFormat} onHandleSave={this.editorSave} />
+                  </div>
+                  <n-split direction="vertical" max={0.60} min={0.00} 
resize-trigger-size={0} default-size={0.6}>
+                    {{
+                      '1': () => (
+                        <div class={styles.editor}>
+                          {
+                            this.tabData.panelsList?.length > 0
+                            && (
+                              <n-card content-style="padding: 0;">
+                                <MonacoEditor
+                                  v-model={this.tabData.panelsList.find((item: 
any) => item.key === this.tabData.chooseTab).content}
+                                  language={this.language}
+                                  onEditorMounted={this.editorMounted}
+                                  onEditorSave={this.editorSave}
+                                  onChange={this.handleContentChange}
+                                />
+                              </n-card>
+                            )
+                          }
+                        </div>
+                      ),
+                      '2': () => (this.showConsole && (
+                        <div class={styles.console}>
+                          {
+                              this.tabData.panelsList?.length > 0
+                              && (
+                                <n-card content-style="padding: 0;">
+                                  <EditorConsole 
onConsoleDown={this.handleConsoleDown} onConsoleUp={this.handleConsoleUp} 
onConsoleClose={this.handleConsoleClose} />
+                                </n-card>
+                              )
+                            }
+                        </div>
+                      )
+                      ),
+                      'resize-trigger': () => (
+                        <div class={styles['console-splitter']} />
+                      ),
+                    }}
+                  </n-split>
+                </n-card>
+              </div>
+            ),
+            'resize-trigger': () => (
+              <div class={styles.split} />
+            ),
+          }}
+        </n-split>
       </div>
     )
   },

Reply via email to