diff --git a/LICENSE-binary b/LICENSE-binary
index b449a8344d9..748842a6191 100644
--- a/LICENSE-binary
+++ b/LICENSE-binary
@@ -374,12 +374,16 @@ is auto-generated by `pnpm licenses list --prod`.
├────────────────────────────────────┼──────────────┤
│ typescript │ Apache-2.0 │
├────────────────────────────────────┼──────────────┤
+│ moo │ BSD-3-Clause │
+├────────────────────────────────────┼──────────────┤
│ normalize-wheel-es │ BSD-3-Clause │
├────────────────────────────────────┼──────────────┤
│ source-map │ BSD-3-Clause │
├────────────────────────────────────┼──────────────┤
│ source-map-js │ BSD-3-Clause │
├────────────────────────────────────┼──────────────┤
+│ railroad-diagrams │ CC0-1.0 │
+├────────────────────────────────────┼──────────────┤
│ picocolors │ ISC │
├────────────────────────────────────┼──────────────┤
│ @babel/helper-string-parser │ MIT │
@@ -452,6 +456,8 @@ is auto-generated by `pnpm licenses list --prod`.
├────────────────────────────────────┼──────────────┤
│ combined-stream │ MIT │
├────────────────────────────────────┼──────────────┤
+│ commander │ MIT │
+├────────────────────────────────────┼──────────────┤
│ csstype │ MIT │
├────────────────────────────────────┼──────────────┤
│ date-fns │ MIT │
@@ -460,6 +466,8 @@ is auto-generated by `pnpm licenses list --prod`.
├────────────────────────────────────┼──────────────┤
│ delayed-stream │ MIT │
├────────────────────────────────────┼──────────────┤
+│ discontinuous-range │ MIT │
+├────────────────────────────────────┼──────────────┤
│ element-plus │ MIT │
├────────────────────────────────────┼──────────────┤
│ escape-html │ MIT │
@@ -470,6 +478,8 @@ is auto-generated by `pnpm licenses list --prod`.
├────────────────────────────────────┼──────────────┤
│ form-data │ MIT │
├────────────────────────────────────┼──────────────┤
+│ get-stdin │ MIT │
+├────────────────────────────────────┼──────────────┤
│ lodash │ MIT │
├────────────────────────────────────┼──────────────┤
│ lodash-es │ MIT │
@@ -484,16 +494,26 @@ is auto-generated by `pnpm licenses list --prod`.
├────────────────────────────────────┼──────────────┤
│ mime-types │ MIT │
├────────────────────────────────────┼──────────────┤
+│ monaco-editor │ MIT │
+├────────────────────────────────────┼──────────────┤
│ nanoid │ MIT │
├────────────────────────────────────┼──────────────┤
+│ nearley │ MIT │
+├────────────────────────────────────┼──────────────┤
│ pinia │ MIT │
├────────────────────────────────────┼──────────────┤
│ pinia-plugin-persistedstate │ MIT │
├────────────────────────────────────┼──────────────┤
│ postcss │ MIT │
├────────────────────────────────────┼──────────────┤
+│ randexp │ MIT │
+├────────────────────────────────────┼──────────────┤
+│ ret │ MIT │
+├────────────────────────────────────┼──────────────┤
│ sourcemap-codec │ MIT │
├────────────────────────────────────┼──────────────┤
+│ sql-formatter │ MIT │
+├────────────────────────────────────┼──────────────┤
│ to-fast-properties │ MIT │
├────────────────────────────────────┼──────────────┤
│ vue │ MIT │
@@ -503,4 +523,6 @@ is auto-generated by `pnpm licenses list --prod`.
│ vue-i18n │ MIT │
├────────────────────────────────────┼──────────────┤
│ vue-router │ MIT │
+├────────────────────────────────────┼──────────────┤
+│ argparse │ Python-2.0 │
└────────────────────────────────────┴──────────────┘
diff --git a/kyuubi-server/web-ui/package.json b/kyuubi-server/web-ui/package.json
index f31b836dcb8..239c6270623 100644
--- a/kyuubi-server/web-ui/package.json
+++ b/kyuubi-server/web-ui/package.json
@@ -19,8 +19,10 @@
"axios": "^0.27.2",
"date-fns": "^2.29.3",
"element-plus": "^2.2.12",
+ "monaco-editor": "^0.44.0",
"pinia": "^2.0.18",
"pinia-plugin-persistedstate": "^2.1.1",
+ "sql-formatter": "^13.0.1",
"swagger-ui-dist": "^4.9.1",
"vue": "^3.2.37",
"vue-i18n": "^9.2.2",
diff --git a/kyuubi-server/web-ui/pnpm-lock.yaml b/kyuubi-server/web-ui/pnpm-lock.yaml
index ffed6c6bd4c..a83d162ab6c 100644
--- a/kyuubi-server/web-ui/pnpm-lock.yaml
+++ b/kyuubi-server/web-ui/pnpm-lock.yaml
@@ -1,9 +1,5 @@
lockfileVersion: '6.0'
-settings:
- autoInstallPeers: true
- excludeLinksFromLockfile: false
-
dependencies:
'@element-plus/icons-vue':
specifier: ^2.0.9
@@ -17,12 +13,18 @@ dependencies:
element-plus:
specifier: ^2.2.12
version: 2.2.13(vue@3.2.37)
+ monaco-editor:
+ specifier: ^0.44.0
+ version: 0.44.0
pinia:
specifier: ^2.0.18
version: 2.0.18(typescript@4.7.4)(vue@3.2.37)
pinia-plugin-persistedstate:
specifier: ^2.1.1
version: 2.1.1(pinia@2.0.18)
+ sql-formatter:
+ specifier: ^13.0.1
+ version: 13.0.1
swagger-ui-dist:
specifier: ^4.9.1
version: 4.19.1
@@ -1019,7 +1021,6 @@ packages:
/argparse@2.0.1:
resolution: {integrity: sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==}
- dev: true
/array-union@2.1.0:
resolution: {integrity: sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==}
@@ -1148,6 +1149,10 @@ packages:
dependencies:
delayed-stream: 1.0.0
+ /commander@2.20.3:
+ resolution: {integrity: sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==}
+ dev: false
+
/concat-map@0.0.1:
resolution: {integrity: sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==}
dev: true
@@ -1268,6 +1273,10 @@ packages:
path-type: 4.0.0
dev: true
+ /discontinuous-range@1.0.0:
+ resolution: {integrity: sha512-c68LpLbO+7kP/b1Hr1qs8/BJ09F5khZGTxqxZuhzxpmwJKOgRFHJWIb9/KmqnqHhLdO55aOxFH/EGBvUQbL/RQ==}
+ dev: false
+
/doctrine@3.0.0:
resolution: {integrity: sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==}
engines: {node: '>=6.0.0'}
@@ -1648,6 +1657,11 @@ packages:
resolution: {integrity: sha512-Hm0ixYtaSZ/V7C8FJrtZIuBBI+iSgL+1Aq82zSu8VQNB4S3Gk8e7Qs3VwBDJAhmRZcFqkl3tQu36g/Foh5I5ig==}
dev: true
+ /get-stdin@8.0.0:
+ resolution: {integrity: sha512-sY22aA6xchAzprjyqmSEQv4UbAAzRN0L2dQB0NlN5acTTK9Don6nhoc3eAbUnpZiCANAMfd/+40kVdKfFygohg==}
+ engines: {node: '>=10'}
+ dev: false
+
/glob-parent@5.1.2:
resolution: {integrity: sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==}
engines: {node: '>= 6'}
@@ -2055,6 +2069,14 @@ packages:
ufo: 1.1.2
dev: true
+ /monaco-editor@0.44.0:
+ resolution: {integrity: sha512-5SmjNStN6bSuSE5WPT2ZV+iYn1/yI9sd4Igtk23ChvqB7kDk9lZbB9F5frsuvpB+2njdIeGGFf2G4gbE6rCC9Q==}
+ dev: false
+
+ /moo@0.5.2:
+ resolution: {integrity: sha512-iSAJLHYKnX41mKcJKjqvnAN9sf0LMDTXDEvFv+ffuRR9a1MIuXLjMNL6EsnDHSkKLTWNqQQ5uo61P4EbU4NU+Q==}
+ dev: false
+
/ms@2.1.2:
resolution: {integrity: sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==}
dev: true
@@ -2068,6 +2090,16 @@ packages:
resolution: {integrity: sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==}
dev: true
+ /nearley@2.20.1:
+ resolution: {integrity: sha512-+Mc8UaAebFzgV+KpI5n7DasuuQCHA89dmwm7JXw3TV43ukfNQ9DnBH3Mdb2g/I4Fdxc26pwimBWvjIw0UAILSQ==}
+ hasBin: true
+ dependencies:
+ commander: 2.20.3
+ moo: 0.5.2
+ railroad-diagrams: 1.0.0
+ randexp: 0.4.6
+ dev: false
+
/normalize-path@3.0.0:
resolution: {integrity: sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==}
engines: {node: '>=0.10.0'}
@@ -2293,6 +2325,18 @@ packages:
resolution: {integrity: sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==}
dev: true
+ /railroad-diagrams@1.0.0:
+ resolution: {integrity: sha512-cz93DjNeLY0idrCNOH6PviZGRN9GJhsdm9hpn1YCS879fj4W+x5IFJhhkRZcwVgMmFF7R82UA/7Oh+R8lLZg6A==}
+ dev: false
+
+ /randexp@0.4.6:
+ resolution: {integrity: sha512-80WNmd9DA0tmZrw9qQa62GPPWfuXJknrmVmLcxvq4uZBdYqb1wYoKTmnlGUchvVWe0XiLupYkBoXVOxz3C8DYQ==}
+ engines: {node: '>=0.12'}
+ dependencies:
+ discontinuous-range: 1.0.0
+ ret: 0.1.15
+ dev: false
+
/react-is@17.0.2:
resolution: {integrity: sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w==}
dev: true
@@ -2327,6 +2371,11 @@ packages:
supports-preserve-symlinks-flag: 1.0.0
dev: true
+ /ret@0.1.15:
+ resolution: {integrity: sha512-TTlYpa+OL+vMMNG24xSlQGEJ3B/RzEfUlLct7b5G/ytav+wPrplCpVMFuwzXbkecJrb6IYo1iFb0S9v37754mg==}
+ engines: {node: '>=0.12'}
+ dev: false
+
/reusify@1.0.4:
resolution: {integrity: sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==}
engines: {iojs: '>=1.0.0', node: '>=0.10.0'}
@@ -2423,6 +2472,15 @@ packages:
/sourcemap-codec@1.4.8:
resolution: {integrity: sha512-9NykojV5Uih4lgo5So5dtw+f0JgJX30KCNI8gwhz2J9A15wD0Ml6tjHKwf6fTSa6fAdVBdZeNOs9eJ71qCk8vA==}
+ /sql-formatter@13.0.1:
+ resolution: {integrity: sha512-/tM0H1O2kto6DKv1YuaZa75PMr1J9vTHj5aMu3GF0coKskWUNNcHCvtE1YBHpoFEuKnGUqxAwEpeAH+BAcZcEQ==}
+ hasBin: true
+ dependencies:
+ argparse: 2.0.1
+ get-stdin: 8.0.0
+ nearley: 2.20.1
+ dev: false
+
/stackback@0.0.2:
resolution: {integrity: sha512-1XMJE5fQo1jGH6Y/7ebnwPOBEkIEnT4QF32d5R1+VXdXveM0IBMJt8zfaxX1P3QhVwrYe+576+jkANtSS2mBbw==}
dev: true
@@ -2911,3 +2969,7 @@ packages:
resolution: {integrity: sha512-9bnSc/HEW2uRy67wc+T8UwauLuPJVn28jb+GtJY16iiKWyvmYJRXVT4UamsAEGQfPohgr2q4Tq0sQbQlxTfi1g==}
engines: {node: '>=12.20'}
dev: true
+
+settings:
+ autoInstallPeers: true
+ excludeLinksFromLockfile: false
diff --git a/kyuubi-server/web-ui/src/components/monaco-editor/index.vue b/kyuubi-server/web-ui/src/components/monaco-editor/index.vue
new file mode 100644
index 00000000000..4c387172a1a
--- /dev/null
+++ b/kyuubi-server/web-ui/src/components/monaco-editor/index.vue
@@ -0,0 +1,149 @@
+
+
+
+
+
+
+
diff --git a/kyuubi-server/web-ui/src/components/monaco-editor/type.ts b/kyuubi-server/web-ui/src/components/monaco-editor/type.ts
new file mode 100644
index 00000000000..80400565eb0
--- /dev/null
+++ b/kyuubi-server/web-ui/src/components/monaco-editor/type.ts
@@ -0,0 +1,81 @@
+/*
+ * 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 { PropType } from 'vue'
+
+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: 'sql'
+ },
+ 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: false
+ },
+ readOnly: false,
+ contextmenu: true,
+ fontSize: 16,
+ scrollBeyondLastLine: true,
+ overviewRulerBorder: false
+ }
+ }
+ }
+}
diff --git a/kyuubi-server/web-ui/src/layout/components/aside/types.ts b/kyuubi-server/web-ui/src/layout/components/aside/types.ts
index 728ee326d71..a7e495e187c 100644
--- a/kyuubi-server/web-ui/src/layout/components/aside/types.ts
+++ b/kyuubi-server/web-ui/src/layout/components/aside/types.ts
@@ -94,5 +94,10 @@ export const MENUS = [
label: 'Contact Us',
icon: 'PhoneFilled',
router: '/contact'
+ },
+ {
+ label: 'SQL Lab',
+ icon: 'Cpu',
+ router: '/lab'
}
]
diff --git a/kyuubi-server/web-ui/src/pinia/editor/index.ts b/kyuubi-server/web-ui/src/pinia/editor/index.ts
new file mode 100644
index 00000000000..8902d172c05
--- /dev/null
+++ b/kyuubi-server/web-ui/src/pinia/editor/index.ts
@@ -0,0 +1,37 @@
+/*
+ * 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 { defineStore } from 'pinia'
+import { Theme } from './type'
+
+export const useEditorStore = defineStore({
+ id: 'editor',
+ state: (): { theme: Theme } => ({
+ theme: 'light'
+ }),
+ persist: true,
+ getters: {
+ getCurrentTheme(): Theme {
+ return this.theme
+ }
+ },
+ actions: {
+ setCurrentTheme(theme: Theme): void {
+ this.theme = theme
+ }
+ }
+})
diff --git a/kyuubi-server/web-ui/src/pinia/editor/type.ts b/kyuubi-server/web-ui/src/pinia/editor/type.ts
new file mode 100644
index 00000000000..4155d60e0f5
--- /dev/null
+++ b/kyuubi-server/web-ui/src/pinia/editor/type.ts
@@ -0,0 +1,18 @@
+/*
+ * 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 = 'dark' | 'light'
diff --git a/kyuubi-server/web-ui/src/router/index.ts b/kyuubi-server/web-ui/src/router/index.ts
index 42371566101..c59c5f28c7b 100644
--- a/kyuubi-server/web-ui/src/router/index.ts
+++ b/kyuubi-server/web-ui/src/router/index.ts
@@ -23,6 +23,7 @@ import contactRoutes from './contact'
import managementRoutes from './management'
import detailRoutes from './detail'
import swaggerRoutes from './swagger'
+import labRoutes from './lab'
const routes = [
{
@@ -44,7 +45,8 @@ const routes = [
...managementRoutes,
...detailRoutes,
...swaggerRoutes,
- ...contactRoutes
+ ...contactRoutes,
+ ...labRoutes
]
}
]
diff --git a/kyuubi-server/web-ui/src/router/lab/index.ts b/kyuubi-server/web-ui/src/router/lab/index.ts
new file mode 100644
index 00000000000..d78838079bf
--- /dev/null
+++ b/kyuubi-server/web-ui/src/router/lab/index.ts
@@ -0,0 +1,26 @@
+/*
+ * 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.
+ */
+
+const routes = [
+ {
+ path: '/lab',
+ name: 'lab',
+ component: () => import('@/views/lab/index.vue')
+ }
+]
+
+export default routes
diff --git a/kyuubi-server/web-ui/src/views/lab/index.vue b/kyuubi-server/web-ui/src/views/lab/index.vue
new file mode 100644
index 00000000000..26ecfac0d87
--- /dev/null
+++ b/kyuubi-server/web-ui/src/views/lab/index.vue
@@ -0,0 +1,64 @@
+
+
+
+
+
+
+
+
+
+
+