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 @@ + + + + + + +