diff --git a/paimon-web-ui-new/package.json b/paimon-web-ui-new/package.json
index c5a1f4e30..e3443bbd8 100644
--- a/paimon-web-ui-new/package.json
+++ b/paimon-web-ui-new/package.json
@@ -13,6 +13,7 @@
},
"dependencies": {
"dart-sass": "^1.25.0",
+ "monaco-editor": "^0.43.0",
"pinia": "^2.1.6",
"pinia-plugin-persistedstate": "^3.2.0",
"sass": "^1.66.1",
diff --git a/paimon-web-ui-new/pnpm-lock.yaml b/paimon-web-ui-new/pnpm-lock.yaml
index 05a47af95..17b654a3a 100644
--- a/paimon-web-ui-new/pnpm-lock.yaml
+++ b/paimon-web-ui-new/pnpm-lock.yaml
@@ -23,6 +23,9 @@ dependencies:
dart-sass:
specifier: ^1.25.0
version: 1.25.0
+ monaco-editor:
+ specifier: ^0.43.0
+ version: 0.43.0
pinia:
specifier: ^2.1.6
version: 2.1.6(typescript@5.1.6)(vue@3.3.4)
@@ -2776,6 +2779,10 @@ packages:
ufo: 1.3.0
dev: true
+ /monaco-editor@0.43.0:
+ resolution: {integrity: sha512-cnoqwQi/9fml2Szamv1XbSJieGJ1Dc8tENVMD26Kcfl7xGQWp7OBKMjlwKVGYFJ3/AXJjSOGvcqK7Ry/j9BM1Q==}
+ dev: false
+
/ms@2.1.2:
resolution: {integrity: sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==}
dev: true
diff --git a/paimon-web-ui-new/src/components/monaco-editor/index.tsx b/paimon-web-ui-new/src/components/monaco-editor/index.tsx
new file mode 100644
index 000000000..5bf54afe1
--- /dev/null
+++ b/paimon-web-ui-new/src/components/monaco-editor/index.tsx
@@ -0,0 +1,124 @@
+/* Licensed to the Apache Software Foundation (ASF) under one
+or more contributor license agreements. See the NOTICE file
+distributed with this work for additional information
+regarding copyright ownership. The ASF licenses this file
+to you under the Apache License, Version 2.0 (the
+"License"); you may not use this file except in compliance
+with the License. You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing,
+software distributed under the License is distributed on an
+"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+KIND, either express or implied. See the License for the
+specific language governing permissions and limitations
+under the License. */
+
+import * as monaco from 'monaco-editor'
+import jsonWorker from 'monaco-editor/esm/vs/language/json/json.worker?worker'
+import cssWorker from 'monaco-editor/esm/vs/language/css/css.worker?worker'
+import htmlWorker from 'monaco-editor/esm/vs/language/html/html.worker?worker'
+import tsWorker from 'monaco-editor/esm/vs/language/typescript/ts.worker?worker'
+import EditorWorker from 'monaco-editor/esm/vs/editor/editor.worker?worker'
+import { editorProps } from './type'
+import { useConfigStore } from '@/store/config'
+
+// @ts-ignore: worker
+self.MonacoEnvironment = {
+ getWorker(_: string, label: string) {
+ if (label === 'json') {
+ return new jsonWorker()
+ }
+ if (['css', 'scss', 'less'].includes(label)) {
+ return new cssWorker()
+ }
+ if (['html', 'handlebars', 'razor'].includes(label)) {
+ return new htmlWorker()
+ }
+ if (['typescript', 'javascript'].includes(label)) {
+ return new tsWorker()
+ }
+ return new EditorWorker()
+ }
+}
+
+export default defineComponent({
+ name: 'MonacoEditor',
+ props: editorProps,
+ emits: ['update:modelValue', 'change', 'EditorMounted'],
+ setup(props, { emit }) {
+ const configStore = useConfigStore()
+ const monacoEditorThemeRef = ref(configStore.getCurrentTheme === 'dark' ? 'vs-dark' : 'vs')
+ let editor: monaco.editor.IStandaloneCodeEditor
+ const codeEditBox = ref()
+ const init = () => {
+ monaco.languages.typescript.javascriptDefaults.setDiagnosticsOptions({
+ noSemanticValidation: true,
+ noSyntaxValidation: false
+ })
+ monaco.languages.typescript.javascriptDefaults.setCompilerOptions({
+ target: monaco.languages.typescript.ScriptTarget.ES2020,
+ allowNonTsExtensions: true
+ })
+ editor = monaco.editor.create(codeEditBox.value, {
+ value: props.modelValue,
+ language: props.language,
+ theme: monacoEditorThemeRef.value,
+ ...props.options
+ })
+ editor.onDidChangeModelContent(() => {
+ const value = editor.getValue()
+ emit('update:modelValue', value)
+ emit('change', value)
+ })
+ emit('EditorMounted', editor)
+ }
+ watch(
+ () => props.modelValue,
+ newValue => {
+ if (editor) {
+ const value = editor.getValue()
+ if (newValue !== value) {
+ editor.setValue(newValue)
+ }
+ }
+ }
+ )
+ watch(
+ () => props.options,
+ newValue => {
+ editor.updateOptions(newValue)
+ },
+ { deep: true }
+ )
+ watch(
+ () => props.language,
+ newValue => {
+ monaco.editor.setModelLanguage(editor.getModel()!, newValue)
+ }
+ )
+ watch(
+ () => configStore.getCurrentTheme,
+ () => {
+ editor?.dispose()
+ monacoEditorThemeRef.value = configStore.getCurrentTheme === 'dark' ? 'vs-dark' : 'vs'
+ init()
+ }
+ )
+ onBeforeUnmount(() => {
+ editor.dispose()
+ })
+ onMounted(() => {
+ init()
+ })
+ return { codeEditBox }
+ },
+ render () {
+ return (
+
+ )
+ }
+})
diff --git a/paimon-web-ui-new/src/components/monaco-editor/type.ts b/paimon-web-ui-new/src/components/monaco-editor/type.ts
new file mode 100644
index 000000000..a611096da
--- /dev/null
+++ b/paimon-web-ui-new/src/components/monaco-editor/type.ts
@@ -0,0 +1,79 @@
+/* Licensed to the Apache Software Foundation (ASF) under one
+or more contributor license agreements. See the NOTICE file
+distributed with this work for additional information
+regarding copyright ownership. The ASF licenses this file
+to you under the Apache License, Version 2.0 (the
+"License"); you may not use this file except in compliance
+with the License. You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing,
+software distributed under the License is distributed on an
+"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+KIND, either express or implied. See the License for the
+specific language governing permissions and limitations
+under the License. */
+
+export type Theme = 'vs' | 'vs-dark'
+export type FoldingStrategy = 'auto' | 'indentation'
+export type RenderLineHighlight = 'all' | 'line' | 'none' | 'gutter'
+export interface Options {
+ automaticLayout?: boolean
+ foldingStrategy?: FoldingStrategy
+ renderLineHighlight?: RenderLineHighlight
+ selectOnLineNumbers?: boolean
+ minimap?: {
+ enabled: boolean
+ }
+ readOnly: boolean
+ contextmenu: boolean
+ fontSize?: number
+ scrollBeyondLastLine?: boolean
+ overviewRulerBorder?: boolean
+}
+
+export const editorProps = {
+ modelValue: {
+ type: String as PropType,
+ default: null
+ },
+ width: {
+ type: [String, Number] as PropType,
+ default: '100%'
+ },
+ height: {
+ type: [String, Number] as PropType,
+ default: '100%'
+ },
+ language: {
+ type: String as PropType,
+ default: 'javascript'
+ },
+ theme: {
+ type: String as PropType,
+ validator(value: string): boolean {
+ return ['vs', 'vs-dark'].includes(value)
+ },
+ default: 'vs'
+ },
+ options: {
+ type: Object as PropType,
+ default() {
+ return {
+ automaticLayout: true,
+ foldingStrategy: 'indentation',
+ renderLineHighlight: 'line',
+ selectOnLineNumbers: true,
+ minimap: {
+ enabled: true
+ },
+ readOnly: false,
+ contextmenu: true,
+ fontSize: 16,
+ scrollBeyondLastLine: false,
+ overviewRulerBorder: false
+ }
+ }
+ }
+}
diff --git a/paimon-web-ui-new/src/layouts/content/components/toolbar/index.tsx b/paimon-web-ui-new/src/layouts/content/components/toolbar/index.tsx
index 0925a43da..a436959f4 100644
--- a/paimon-web-ui-new/src/layouts/content/components/toolbar/index.tsx
+++ b/paimon-web-ui-new/src/layouts/content/components/toolbar/index.tsx
@@ -17,7 +17,7 @@ under the License. */
import i18n from '@/locales'
import { useConfigStore } from '@/store/config'
-import { LogoGithub, Moon, SunnyOutline, Language, PersonCircleOutline } from '@vicons/ionicons5'
+import { LogoGithub, Moon, SunnyOutline, Language } from '@vicons/ionicons5'
export default defineComponent({
name: 'ToolBar',
diff --git a/paimon-web-ui-new/src/locales/en/index.ts b/paimon-web-ui-new/src/locales/en/index.ts
index 08e479fc0..db4b7138e 100644
--- a/paimon-web-ui-new/src/locales/en/index.ts
+++ b/paimon-web-ui-new/src/locales/en/index.ts
@@ -17,8 +17,10 @@ under the License. */
import layout from './modules/layout'
import login from './modules/login'
+import playground from './modules/playground'
export default {
login,
- layout
-}
\ No newline at end of file
+ layout,
+ playground
+}
diff --git a/paimon-web-ui-new/src/locales/en/modules/playground.ts b/paimon-web-ui-new/src/locales/en/modules/playground.ts
new file mode 100644
index 000000000..feedda3e8
--- /dev/null
+++ b/paimon-web-ui-new/src/locales/en/modules/playground.ts
@@ -0,0 +1,21 @@
+/* Licensed to the Apache Software Foundation (ASF) under one
+or more contributor license agreements. See the NOTICE file
+distributed with this work for additional information
+regarding copyright ownership. The ASF licenses this file
+to you under the Apache License, Version 2.0 (the
+"License"); you may not use this file except in compliance
+with the License. You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing,
+software distributed under the License is distributed on an
+"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+KIND, either express or implied. See the License for the
+specific language governing permissions and limitations
+under the License. */
+
+export default {
+ select_catalog: 'Select Catalog',
+ search: 'Search'
+}
diff --git a/paimon-web-ui-new/src/locales/zh/index.ts b/paimon-web-ui-new/src/locales/zh/index.ts
index 08e479fc0..db4b7138e 100644
--- a/paimon-web-ui-new/src/locales/zh/index.ts
+++ b/paimon-web-ui-new/src/locales/zh/index.ts
@@ -17,8 +17,10 @@ under the License. */
import layout from './modules/layout'
import login from './modules/login'
+import playground from './modules/playground'
export default {
login,
- layout
-}
\ No newline at end of file
+ layout,
+ playground
+}
diff --git a/paimon-web-ui-new/src/locales/zh/modules/playground.ts b/paimon-web-ui-new/src/locales/zh/modules/playground.ts
new file mode 100644
index 000000000..e9350cb32
--- /dev/null
+++ b/paimon-web-ui-new/src/locales/zh/modules/playground.ts
@@ -0,0 +1,21 @@
+/* Licensed to the Apache Software Foundation (ASF) under one
+or more contributor license agreements. See the NOTICE file
+distributed with this work for additional information
+regarding copyright ownership. The ASF licenses this file
+to you under the Apache License, Version 2.0 (the
+"License"); you may not use this file except in compliance
+with the License. You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing,
+software distributed under the License is distributed on an
+"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+KIND, either express or implied. See the License for the
+specific language governing permissions and limitations
+under the License. */
+
+export default {
+ select_catalog: '选择 Catalog',
+ search: '搜索'
+}
diff --git a/paimon-web-ui-new/src/router/index.ts b/paimon-web-ui-new/src/router/index.ts
index c55aaae0e..e2670e99f 100644
--- a/paimon-web-ui-new/src/router/index.ts
+++ b/paimon-web-ui-new/src/router/index.ts
@@ -15,25 +15,31 @@ KIND, either express or implied. See the License for the
specific language governing permissions and limitations
under the License. */
-import { createRouter, createWebHistory } from 'vue-router'
+import {
+ createRouter,
+ createWebHistory,
+ type RouteLocationNormalized,
+ type NavigationGuardNext
+} from 'vue-router'
+import routes from './routes'
+
const router = createRouter({
history: createWebHistory(import.meta.env.BASE_URL),
- routes: [
- {
- path: '/',
- name: 'homepage',
- // route level code-splitting
- // this generates a separate chunk (About.[hash].js) for this route
- // which is lazy-loaded when the route is visited.
- component: () => import('../layouts/content')
- },
- {
- path: '/login',
- name: 'login',
- component: () => import('../views/login')
- }
- ]
+ routes
})
+/**
+ * Routing to intercept
+ */
+router.beforeEach(
+ async (
+ to: RouteLocationNormalized,
+ from: RouteLocationNormalized,
+ next: NavigationGuardNext
+ ) => {
+ next()
+ }
+)
+
export default router
diff --git a/paimon-web-ui-new/src/router/modules/playground.ts b/paimon-web-ui-new/src/router/modules/playground.ts
new file mode 100644
index 000000000..b8333c1c6
--- /dev/null
+++ b/paimon-web-ui-new/src/router/modules/playground.ts
@@ -0,0 +1,34 @@
+/* Licensed to the Apache Software Foundation (ASF) under one
+or more contributor license agreements. See the NOTICE file
+distributed with this work for additional information
+regarding copyright ownership. The ASF licenses this file
+to you under the Apache License, Version 2.0 (the
+"License"); you may not use this file except in compliance
+with the License. You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing,
+software distributed under the License is distributed on an
+"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+KIND, either express or implied. See the License for the
+specific language governing permissions and limitations
+under the License. */
+
+export default [
+ {
+ path: '/',
+ name: 'homepage',
+ meta: { title: '首页' },
+ redirect: { name: 'playground' },
+ component: () => import('@/layouts/content'),
+ children: [
+ {
+ path: '/playground',
+ name: 'playground',
+ meta: { title: '查询控制台' },
+ component: () => import('@/views/playground')
+ },
+ ]
+ }
+]
diff --git a/paimon-web-ui-new/src/router/routes.ts b/paimon-web-ui-new/src/router/routes.ts
new file mode 100644
index 000000000..15339e49b
--- /dev/null
+++ b/paimon-web-ui-new/src/router/routes.ts
@@ -0,0 +1,42 @@
+/* Licensed to the Apache Software Foundation (ASF) under one
+or more contributor license agreements. See the NOTICE file
+distributed with this work for additional information
+regarding copyright ownership. The ASF licenses this file
+to you under the Apache License, Version 2.0 (the
+"License"); you may not use this file except in compliance
+with the License. You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing,
+software distributed under the License is distributed on an
+"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+KIND, either express or implied. See the License for the
+specific language governing permissions and limitations
+under the License. */
+
+import type { RouteRecordRaw } from 'vue-router'
+import playground_routes from './modules/playground'
+
+/**
+ * Basic page
+ */
+const basePage: RouteRecordRaw[] = [
+ ...playground_routes,
+]
+
+/**
+ * Login page
+ */
+const loginPage: RouteRecordRaw[] = [
+ {
+ path: '/login',
+ name: 'login',
+ component: () => import('../views/login')
+ }
+]
+
+
+const routes: RouteRecordRaw[] = [...basePage, ...loginPage]
+
+export default routes
diff --git a/paimon-web-ui-new/src/store/config/index.ts b/paimon-web-ui-new/src/store/config/index.ts
index ec3e8bf34..dac0a6c9a 100644
--- a/paimon-web-ui-new/src/store/config/index.ts
+++ b/paimon-web-ui-new/src/store/config/index.ts
@@ -24,6 +24,7 @@ export const useConfigStore = defineStore({
theme: 'light',
locale: 'zh'
}),
+ persist: true,
getters: {
getCurrentLocale(): Locale {
return this.locale
@@ -40,4 +41,4 @@ export const useConfigStore = defineStore({
this.theme = theme
}
}
-})
\ No newline at end of file
+})
diff --git a/paimon-web-ui-new/src/views/homepage/index.tsx b/paimon-web-ui-new/src/views/playground/components/catalog/index.module.scss
similarity index 68%
rename from paimon-web-ui-new/src/views/homepage/index.tsx
rename to paimon-web-ui-new/src/views/playground/components/catalog/index.module.scss
index 11292ebec..e32b957e6 100644
--- a/paimon-web-ui-new/src/views/homepage/index.tsx
+++ b/paimon-web-ui-new/src/views/playground/components/catalog/index.module.scss
@@ -15,22 +15,10 @@ KIND, either express or implied. See the License for the
specific language governing permissions and limitations
under the License. */
-import { defineComponent } from 'vue';
+.container {
+ width: 100%;
-export default defineComponent({
- name: 'HomePage',
- setup() {
- const handleRequest = () => {}
-
- return { handleRequest }
- },
- render() {
- return (
-
- );
- },
-});
+ .select-catalog {
+ padding-bottom: 10px;
+ }
+}
diff --git a/paimon-web-ui-new/src/views/playground/components/catalog/index.tsx b/paimon-web-ui-new/src/views/playground/components/catalog/index.tsx
new file mode 100644
index 000000000..ea44e8c56
--- /dev/null
+++ b/paimon-web-ui-new/src/views/playground/components/catalog/index.tsx
@@ -0,0 +1,88 @@
+/* Licensed to the Apache Software Foundation (ASF) under one
+or more contributor license agreements. See the NOTICE file
+distributed with this work for additional information
+regarding copyright ownership. The ASF licenses this file
+to you under the Apache License, Version 2.0 (the
+"License"); you may not use this file except in compliance
+with the License. You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing,
+software distributed under the License is distributed on an
+"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+KIND, either express or implied. See the License for the
+specific language governing permissions and limitations
+under the License. */
+
+import i18n from "@/locales"
+import type { TreeOption } from "naive-ui";
+import styles from './index.module.scss'
+
+export default defineComponent({
+ name: 'CataLogPage',
+ setup() {
+ const selectedValue= ref(null)
+
+ const options= [
+ {
+ label: 'catalog1',
+ value: 'catalog1'
+ },
+ {
+ label: 'catalog2',
+ value: 'catalog2'
+ }
+ ]
+
+ const searchVal = ref('')
+
+ const treeData: TreeOption[] = [
+ {
+ label: 'paimon',
+ key: 'paimon',
+ children: [
+ {
+ label: 'paimon-table-01',
+ key: 'paimon-table-01',
+ children: [
+ { label: 'id', key: 'id' },
+ { label: 'name', key: 'name' }
+ ]
+ },
+ {
+ label: 'paimon-table-02',
+ key: 'paimon-table-02',
+ children: [
+ { label: 'Osaka', key: 'Osaka' },
+ ]
+ }
+ ]
+ }
+ ]
+
+ return { selectedValue, options, searchVal, treeData }
+ },
+ render() {
+ return (
+
+ );
+ },
+});
diff --git a/paimon-web-ui-new/src/views/playground/index.module.scss b/paimon-web-ui-new/src/views/playground/index.module.scss
new file mode 100644
index 000000000..839bb211e
--- /dev/null
+++ b/paimon-web-ui-new/src/views/playground/index.module.scss
@@ -0,0 +1,46 @@
+/* Licensed to the Apache Software Foundation (ASF) under one
+or more contributor license agreements. See the NOTICE file
+distributed with this work for additional information
+regarding copyright ownership. The ASF licenses this file
+to you under the Apache License, Version 2.0 (the
+"License"); you may not use this file except in compliance
+with the License. You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing,
+software distributed under the License is distributed on an
+"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+KIND, either express or implied. See the License for the
+specific language governing permissions and limitations
+under the License. */
+
+.container {
+ height: 100%;
+ width: 100%;
+
+ :global {
+ .n-tabs {
+ height: 100%;
+ }
+ }
+
+ .content {
+ display: flex;
+ height: 100%;
+
+ .catalog {
+ width: 350px;
+ height: 100%;
+ padding: 10px;
+ box-sizing: border-box;
+ }
+
+ .editor {
+ height: 100%;
+ flex: 1;
+ padding: 10px;
+ box-sizing: border-box;
+ }
+ }
+}
diff --git a/paimon-web-ui-new/src/views/playground/index.tsx b/paimon-web-ui-new/src/views/playground/index.tsx
new file mode 100644
index 000000000..448b0de6e
--- /dev/null
+++ b/paimon-web-ui-new/src/views/playground/index.tsx
@@ -0,0 +1,101 @@
+/* Licensed to the Apache Software Foundation (ASF) under one
+or more contributor license agreements. See the NOTICE file
+distributed with this work for additional information
+regarding copyright ownership. The ASF licenses this file
+to you under the Apache License, Version 2.0 (the
+"License"); you may not use this file except in compliance
+with the License. You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing,
+software distributed under the License is distributed on an
+"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+KIND, either express or implied. See the License for the
+specific language governing permissions and limitations
+under the License. */
+
+import styles from './index.module.scss';
+import type { TabsProps } from 'naive-ui';
+import { Layers, CodeSlashSharp, SyncCircleOutline } from '@vicons/ionicons5';
+import CataLog from './components/catalog';
+import * as monaco from 'monaco-editor'
+import MonacoEditor from '@/components/monaco-editor';
+
+
+export default defineComponent({
+ name: 'PlaygroundPage',
+ setup() {
+ const type = ref('bar')
+
+ const content = ref('')
+ const language = ref('javascript')
+ const editorMounted = (editor: monaco.editor.IStandaloneCodeEditor) => {
+ console.log('Loaded editor instance.', editor)
+ }
+
+ return {
+ type,
+ content,
+ language,
+ editorMounted
+ }
+ },
+ render() {
+ return (
+
+
+ (
+
+
+
+ )
+ }}
+ >
+
+
+ (
+
+
+
+ )
+ }}
+ >
+ Saved Queries
+
+ (
+
+
+
+ )
+ }}
+ >
+ History
+
+
+
+ );
+ },
+});