From 65f2100f50aa6f3313ad64afe52cf429401ef5d1 Mon Sep 17 00:00:00 2001 From: steven Date: Tue, 28 Mar 2023 16:43:15 +0800 Subject: [PATCH] feat: use drawer instead of modal for sql query --- components/CodeBlock.tsx | 71 ++- ...cuteStatementModal.tsx => QueryDrawer.tsx} | 45 +- package.json | 5 + pages/index.tsx | 2 + pnpm-lock.yaml | 434 ++++++++++++++++-- store/index.ts | 1 + store/layout.ts | 2 +- store/query.ts | 31 ++ 8 files changed, 503 insertions(+), 88 deletions(-) rename components/{ExecuteStatementModal.tsx => QueryDrawer.tsx} (63%) create mode 100644 store/query.ts diff --git a/components/CodeBlock.tsx b/components/CodeBlock.tsx index b16b999..67a4c4a 100644 --- a/components/CodeBlock.tsx +++ b/components/CodeBlock.tsx @@ -1,11 +1,8 @@ -import { useState } from "react"; -import { createPortal } from "react-dom"; import { toast } from "react-hot-toast"; import { Prism as SyntaxHighlighter } from "react-syntax-highlighter"; import { oneDark } from "react-syntax-highlighter/dist/cjs/styles/prism"; -import { useConnectionStore } from "@/store"; +import { useConnectionStore, useQueryStore } from "@/store"; import Icon from "./Icon"; -import ExecuteStatementModal from "./ExecuteStatementModal"; interface Props { language: string; @@ -19,7 +16,7 @@ const checkStatementIsSelect = (statement: string) => { export const CodeBlock = (props: Props) => { const { language, value } = props; const connectionStore = useConnectionStore(); - const [showExecuteQueryModal, setShowExecuteQueryModal] = useState(false); + const queryStore = useQueryStore(); const currentConnectionCtx = connectionStore.currentConnectionCtx; // Only show execute button in the following situations: // * SQL code, and it is a SELECT statement; @@ -37,44 +34,44 @@ export const CodeBlock = (props: Props) => { }); }; + const handleExecuteQuery = () => { + if (!currentConnectionCtx) { + toast.error("Please select a connection first"); + return; + } + + queryStore.setContext({ + connection: currentConnectionCtx.connection, + database: currentConnectionCtx.database, + statement: value, + }); + queryStore.toggleDrawer(true); + }; + return ( - <> -
-
- {language} -
+
+
+ {language} +
+ + {showExecuteButton && ( - {showExecuteButton && ( - - )} -
+ )}
- - {value} -
- - {showExecuteQueryModal && - showExecuteButton && - createPortal( - setShowExecuteQueryModal(false)} - />, - document.body - )} - + + {value} + +
); }; diff --git a/components/ExecuteStatementModal.tsx b/components/QueryDrawer.tsx similarity index 63% rename from components/ExecuteStatementModal.tsx rename to components/QueryDrawer.tsx index d08bb63..11a1bbe 100644 --- a/components/ExecuteStatementModal.tsx +++ b/components/QueryDrawer.tsx @@ -1,23 +1,18 @@ +import { Drawer } from "@mui/material"; import { head } from "lodash-es"; import { useEffect, useState } from "react"; import DataTable from "react-data-table-component"; import { toast } from "react-hot-toast"; -import { Connection } from "@/types"; +import { useQueryStore } from "@/store"; import Icon from "./Icon"; -interface Props { - connection: Connection; - databaseName: string; - statement: string; - close: () => void; -} - type RawQueryResult = { [key: string]: any; }; -const ExecuteStatementModal = (props: Props) => { - const { close, connection, databaseName, statement } = props; +const QueryDrawer = () => { + const queryStore = useQueryStore(); + const context = queryStore.context; const [rawResults, setRawResults] = useState([]); const [isLoading, setIsLoading] = useState(true); const columns = Object.keys(head(rawResults) || {}).map((key) => { @@ -28,6 +23,16 @@ const ExecuteStatementModal = (props: Props) => { }); useEffect(() => { + if (!context) { + toast.error("No execution context found."); + setIsLoading(false); + setRawResults([]); + return; + } + + setIsLoading(true); + setRawResults([]); + const { connection, database, statement } = context; const executeStatement = async () => { try { const response = await fetch("/api/connection/execute", { @@ -37,7 +42,7 @@ const ExecuteStatementModal = (props: Props) => { }, body: JSON.stringify({ connection, - db: databaseName, + db: database?.name, statement, }), }); @@ -51,15 +56,17 @@ const ExecuteStatementModal = (props: Props) => { }; executeStatement(); - }, []); + }, [context]); + + const close = () => queryStore.toggleDrawer(false); return ( -
-
-

Execute query

- +

Execute query

{isLoading ? (
@@ -69,13 +76,13 @@ const ExecuteStatementModal = (props: Props) => {
No data return.
) : (
- +
)}
-
+ ); }; -export default ExecuteStatementModal; +export default QueryDrawer; diff --git a/package.json b/package.json index 62da092..564308e 100644 --- a/package.json +++ b/package.json @@ -7,6 +7,10 @@ "start": "next start" }, "dependencies": { + "@emotion/react": "^11.10.6", + "@emotion/styled": "^11.10.6", + "@mui/material": "^5.11.14", + "@mui/styled-engine-sc": "^5.11.11", "@vercel/analytics": "^0.1.11", "axios": "^1.3.4", "csstype": "^3.1.1", @@ -21,6 +25,7 @@ "react-dom": "^18.2.0", "react-hot-toast": "^2.4.0", "react-icons": "^4.8.0", + "react-is": "^18.2.0", "react-loader-spinner": "^5.3.4", "react-markdown": "^8.0.6", "react-textarea-autosize": "^8.4.0", diff --git a/pages/index.tsx b/pages/index.tsx index 16b52c4..4e2bf31 100644 --- a/pages/index.tsx +++ b/pages/index.tsx @@ -3,6 +3,7 @@ import Head from "next/head"; import dynamic from "next/dynamic"; import React, { useEffect } from "react"; import { ResponsiveWidth, useLayoutStore } from "@/store"; +import QueryDrawer from "@/components/QueryDrawer"; // Use dynamic import to avoid page hydrated. // reference: https://github.com/pmndrs/zustand/issues/1145#issuecomment-1316431268 @@ -51,6 +52,7 @@ const ChatPage: NextPage = () => { /> +
); diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index ae99ec9..d021451 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -1,6 +1,10 @@ lockfileVersion: 5.4 specifiers: + '@emotion/react': ^11.10.6 + '@emotion/styled': ^11.10.6 + '@mui/material': ^5.11.14 + '@mui/styled-engine-sc': ^5.11.11 '@tailwindcss/typography': ^0.5.9 '@types/lodash-es': ^4.17.7 '@types/node': ^18.11.18 @@ -29,6 +33,7 @@ specifiers: react-dom: ^18.2.0 react-hot-toast: ^2.4.0 react-icons: ^4.8.0 + react-is: ^18.2.0 react-loader-spinner: ^5.3.4 react-markdown: ^8.0.6 react-syntax-highlighter: ^15.5.0 @@ -41,6 +46,10 @@ specifiers: zustand: ^4.3.6 dependencies: + '@emotion/react': 11.10.6_pmekkgnqduwlme35zpnqhenc34 + '@emotion/styled': 11.10.6_oouaibmszuch5k64ms7uxp2aia + '@mui/material': 5.11.14_xqeqsl5kvjjtyxwyi3jhw3yuli + '@mui/styled-engine-sc': 5.11.11_styled-components@5.3.9 '@vercel/analytics': 0.1.11_react@18.2.0 axios: 1.3.4 csstype: 3.1.1 @@ -55,11 +64,12 @@ dependencies: react-dom: 18.2.0_react@18.2.0 react-hot-toast: 2.4.0_owo25xnefcwdq3zjgtohz6dbju react-icons: 4.8.0_react@18.2.0 + react-is: 18.2.0 react-loader-spinner: 5.3.4_biqbaboplfbrettd7655fr4n2y react-markdown: 8.0.6_pmekkgnqduwlme35zpnqhenc34 react-textarea-autosize: 8.4.0_pmekkgnqduwlme35zpnqhenc34 remark-gfm: 3.0.1 - styled-components: 5.3.9_biqbaboplfbrettd7655fr4n2y + styled-components: 5.3.9_7i5myeigehqah43i5u7wbekgba uuid: 9.0.0 zustand: 4.3.6_react@18.2.0 @@ -211,6 +221,36 @@ packages: to-fast-properties: 2.0.0 dev: false + /@emotion/babel-plugin/11.10.6: + resolution: {integrity: sha512-p2dAqtVrkhSa7xz1u/m9eHYdLi+en8NowrmXeF/dKtJpU8lCWli8RUAati7NcSl0afsBott48pdnANuD0wh9QQ==} + dependencies: + '@babel/helper-module-imports': 7.18.6 + '@babel/runtime': 7.21.0 + '@emotion/hash': 0.9.0 + '@emotion/memoize': 0.8.0 + '@emotion/serialize': 1.1.1 + babel-plugin-macros: 3.1.0 + convert-source-map: 1.9.0 + escape-string-regexp: 4.0.0 + find-root: 1.1.0 + source-map: 0.5.7 + stylis: 4.1.3 + dev: false + + /@emotion/cache/11.10.5: + resolution: {integrity: sha512-dGYHWyzTdmK+f2+EnIGBpkz1lKc4Zbj2KHd4cX3Wi8/OWr5pKslNjc3yABKH4adRGCvSX4VDC0i04mrrq0aiRA==} + dependencies: + '@emotion/memoize': 0.8.0 + '@emotion/sheet': 1.2.1 + '@emotion/utils': 1.2.0 + '@emotion/weak-memoize': 0.3.0 + stylis: 4.1.3 + dev: false + + /@emotion/hash/0.9.0: + resolution: {integrity: sha512-14FtKiHhy2QoPIzdTcvh//8OyBlknNs2nXRwIhG904opCby3l+9Xaf/wuPvICBF0rc1ZCNBd3nKe9cd2mecVkQ==} + dev: false + /@emotion/is-prop-valid/1.2.0: resolution: {integrity: sha512-3aDpDprjM0AwaxGE09bOPkNxHpBd+kA6jty3RnaEXdweX1DF1U3VQpPYb0g1IStAuK7SVQ1cy+bNBBKp4W3Fjg==} dependencies: @@ -221,6 +261,62 @@ packages: resolution: {integrity: sha512-G/YwXTkv7Den9mXDO7AhLWkE3q+I92B+VqAE+dYG4NGPaHZGvt3G8Q0p9vmE+sq7rTGphUbAvmQ9YpbfMQGGlA==} dev: false + /@emotion/react/11.10.6_pmekkgnqduwlme35zpnqhenc34: + resolution: {integrity: sha512-6HT8jBmcSkfzO7mc+N1L9uwvOnlcGoix8Zn7srt+9ga0MjREo6lRpuVX0kzo6Jp6oTqDhREOFsygN6Ew4fEQbw==} + peerDependencies: + '@types/react': '*' + react: '>=16.8.0' + peerDependenciesMeta: + '@types/react': + optional: true + dependencies: + '@babel/runtime': 7.21.0 + '@emotion/babel-plugin': 11.10.6 + '@emotion/cache': 11.10.5 + '@emotion/serialize': 1.1.1 + '@emotion/use-insertion-effect-with-fallbacks': 1.0.0_react@18.2.0 + '@emotion/utils': 1.2.0 + '@emotion/weak-memoize': 0.3.0 + '@types/react': 18.0.28 + hoist-non-react-statics: 3.3.2 + react: 18.2.0 + dev: false + + /@emotion/serialize/1.1.1: + resolution: {integrity: sha512-Zl/0LFggN7+L1liljxXdsVSVlg6E/Z/olVWpfxUTxOAmi8NU7YoeWeLfi1RmnB2TATHoaWwIBRoL+FvAJiTUQA==} + dependencies: + '@emotion/hash': 0.9.0 + '@emotion/memoize': 0.8.0 + '@emotion/unitless': 0.8.0 + '@emotion/utils': 1.2.0 + csstype: 3.1.1 + dev: false + + /@emotion/sheet/1.2.1: + resolution: {integrity: sha512-zxRBwl93sHMsOj4zs+OslQKg/uhF38MB+OMKoCrVuS0nyTkqnau+BM3WGEoOptg9Oz45T/aIGs1qbVAsEFo3nA==} + dev: false + + /@emotion/styled/11.10.6_oouaibmszuch5k64ms7uxp2aia: + resolution: {integrity: sha512-OXtBzOmDSJo5Q0AFemHCfl+bUueT8BIcPSxu0EGTpGk6DmI5dnhSzQANm1e1ze0YZL7TDyAyy6s/b/zmGOS3Og==} + peerDependencies: + '@emotion/react': ^11.0.0-rc.0 + '@types/react': '*' + react: '>=16.8.0' + peerDependenciesMeta: + '@types/react': + optional: true + dependencies: + '@babel/runtime': 7.21.0 + '@emotion/babel-plugin': 11.10.6 + '@emotion/is-prop-valid': 1.2.0 + '@emotion/react': 11.10.6_pmekkgnqduwlme35zpnqhenc34 + '@emotion/serialize': 1.1.1 + '@emotion/use-insertion-effect-with-fallbacks': 1.0.0_react@18.2.0 + '@emotion/utils': 1.2.0 + '@types/react': 18.0.28 + react: 18.2.0 + dev: false + /@emotion/stylis/0.8.5: resolution: {integrity: sha512-h6KtPihKFn3T9fuIrwvXXUOwlx3rfUvfZIcP5a6rh8Y7zjE3O06hT5Ss4S/YI1AYhuZ1kjaE/5EaOOI2NqSylQ==} dev: false @@ -229,6 +325,26 @@ packages: resolution: {integrity: sha512-OWORNpfjMsSSUBVrRBVGECkhWcULOAJz9ZW8uK9qgxD+87M7jHRcvh/A96XXNhXTLmKcoYSQtBEX7lHMO7YRwg==} dev: false + /@emotion/unitless/0.8.0: + resolution: {integrity: sha512-VINS5vEYAscRl2ZUDiT3uMPlrFQupiKgHz5AA4bCH1miKBg4qtwkim1qPmJj/4WG6TreYMY111rEFsjupcOKHw==} + dev: false + + /@emotion/use-insertion-effect-with-fallbacks/1.0.0_react@18.2.0: + resolution: {integrity: sha512-1eEgUGmkaljiBnRMTdksDV1W4kUnmwgp7X9G8B++9GYwl1lUdqSndSriIrTJ0N7LQaoauY9JJ2yhiOYK5+NI4A==} + peerDependencies: + react: '>=16.8.0' + dependencies: + react: 18.2.0 + dev: false + + /@emotion/utils/1.2.0: + resolution: {integrity: sha512-sn3WH53Kzpw8oQ5mgMmIzzyAaH2ZqFEbozVVBSYp538E06OSE6ytOp7pRAjNQR+Q/orwqdQYJSe2m3hCOeznkw==} + dev: false + + /@emotion/weak-memoize/0.3.0: + resolution: {integrity: sha512-AHPmaAx+RYfZz0eYu6Gviiagpmiyw98ySSlQvCUhVGDRtDFe4DBS0x1bSjdF3gqUDYOczB+yYvBTtEylYSdRhg==} + dev: false + /@eslint/eslintrc/1.4.1: resolution: {integrity: sha512-XXrH9Uarn0stsyldqDYq8r++mROmWRI1xKMXa640Bb//SY1+ECYX6VzT6Lcx5frD0V30XieqJ0oX9I2Xj5aoMA==} engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} @@ -291,6 +407,179 @@ packages: '@jridgewell/sourcemap-codec': 1.4.14 dev: false + /@mui/base/5.0.0-alpha.122_zula6vjvt3wdocc4mwcxqa6nzi: + resolution: {integrity: sha512-IgZEFQyHa39J1+Q3tekVdhPuUm1fr3icddaNLmiAIeYTVXmR7KR5FhBAIL0P+4shlPq0liUPGlXryoTm0iCeFg==} + engines: {node: '>=12.0.0'} + peerDependencies: + '@types/react': ^17.0.0 || ^18.0.0 + react: ^17.0.0 || ^18.0.0 + react-dom: ^17.0.0 || ^18.0.0 + peerDependenciesMeta: + '@types/react': + optional: true + dependencies: + '@babel/runtime': 7.21.0 + '@emotion/is-prop-valid': 1.2.0 + '@mui/types': 7.2.3_@types+react@18.0.28 + '@mui/utils': 5.11.13_react@18.2.0 + '@popperjs/core': 2.11.7 + '@types/react': 18.0.28 + clsx: 1.2.1 + prop-types: 15.8.1 + react: 18.2.0 + react-dom: 18.2.0_react@18.2.0 + react-is: 18.2.0 + dev: false + + /@mui/core-downloads-tracker/5.11.14: + resolution: {integrity: sha512-rfc08z6+3Fif+Gopx2/qmk+MEQlwYeA+gOcSK048BHkTty/ol/boHuVeL2BNC/cf9OVRjJLYHtVb/DeW791LSQ==} + dev: false + + /@mui/material/5.11.14_xqeqsl5kvjjtyxwyi3jhw3yuli: + resolution: {integrity: sha512-uoiUyybmo+M+nYARBygmbXgX6s/hH0NKD56LCAv9XvmdGVoXhEGjOvxI5/Bng6FS3NNybnA8V+rgZW1Z/9OJtA==} + engines: {node: '>=12.0.0'} + peerDependencies: + '@emotion/react': ^11.5.0 + '@emotion/styled': ^11.3.0 + '@types/react': ^17.0.0 || ^18.0.0 + react: ^17.0.0 || ^18.0.0 + react-dom: ^17.0.0 || ^18.0.0 + peerDependenciesMeta: + '@emotion/react': + optional: true + '@emotion/styled': + optional: true + '@types/react': + optional: true + dependencies: + '@babel/runtime': 7.21.0 + '@emotion/react': 11.10.6_pmekkgnqduwlme35zpnqhenc34 + '@emotion/styled': 11.10.6_oouaibmszuch5k64ms7uxp2aia + '@mui/base': 5.0.0-alpha.122_zula6vjvt3wdocc4mwcxqa6nzi + '@mui/core-downloads-tracker': 5.11.14 + '@mui/system': 5.11.14_d2lgyfpecxdc2bsiwyag5wf7ti + '@mui/types': 7.2.3_@types+react@18.0.28 + '@mui/utils': 5.11.13_react@18.2.0 + '@types/react': 18.0.28 + '@types/react-transition-group': 4.4.5 + clsx: 1.2.1 + csstype: 3.1.1 + prop-types: 15.8.1 + react: 18.2.0 + react-dom: 18.2.0_react@18.2.0 + react-is: 18.2.0 + react-transition-group: 4.4.5_biqbaboplfbrettd7655fr4n2y + dev: false + + /@mui/private-theming/5.11.13_pmekkgnqduwlme35zpnqhenc34: + resolution: {integrity: sha512-PJnYNKzW5LIx3R+Zsp6WZVPs6w5sEKJ7mgLNnUXuYB1zo5aX71FVLtV7geyPXRcaN2tsoRNK7h444ED0t7cIjA==} + engines: {node: '>=12.0.0'} + peerDependencies: + '@types/react': ^17.0.0 || ^18.0.0 + react: ^17.0.0 || ^18.0.0 + peerDependenciesMeta: + '@types/react': + optional: true + dependencies: + '@babel/runtime': 7.21.0 + '@mui/utils': 5.11.13_react@18.2.0 + '@types/react': 18.0.28 + prop-types: 15.8.1 + react: 18.2.0 + dev: false + + /@mui/styled-engine-sc/5.11.11_styled-components@5.3.9: + resolution: {integrity: sha512-6+HsfcKHlhjQklDoEup7Itl+Xgn+BCsqEpIdIIhlxED4YlOZ38xghxIKrx78XFZznTorbhAspUgDDKIaB5vDMg==} + engines: {node: '>=12.0.0'} + peerDependencies: + '@types/styled-components': ^5.1.14 + styled-components: ^5.3.1 + peerDependenciesMeta: + '@types/styled-components': + optional: true + dependencies: + '@babel/runtime': 7.21.0 + prop-types: 15.8.1 + styled-components: 5.3.9_7i5myeigehqah43i5u7wbekgba + dev: false + + /@mui/styled-engine/5.11.11_xqp3pgpqjlfxxa3zxu4zoc4fba: + resolution: {integrity: sha512-wV0UgW4lN5FkDBXefN8eTYeuE9sjyQdg5h94vtwZCUamGQEzmCOtir4AakgmbWMy0x8OLjdEUESn9wnf5J9MOg==} + engines: {node: '>=12.0.0'} + peerDependencies: + '@emotion/react': ^11.4.1 + '@emotion/styled': ^11.3.0 + react: ^17.0.0 || ^18.0.0 + peerDependenciesMeta: + '@emotion/react': + optional: true + '@emotion/styled': + optional: true + dependencies: + '@babel/runtime': 7.21.0 + '@emotion/cache': 11.10.5 + '@emotion/react': 11.10.6_pmekkgnqduwlme35zpnqhenc34 + '@emotion/styled': 11.10.6_oouaibmszuch5k64ms7uxp2aia + csstype: 3.1.1 + prop-types: 15.8.1 + react: 18.2.0 + dev: false + + /@mui/system/5.11.14_d2lgyfpecxdc2bsiwyag5wf7ti: + resolution: {integrity: sha512-/MBv5dUoijJNEKEGi5tppIszGN0o2uejmeISi5vl0CLcaQsI1cd+uBgK+JYUP1VWvI/MtkWRLVSWtF2FWhu5Nw==} + engines: {node: '>=12.0.0'} + peerDependencies: + '@emotion/react': ^11.5.0 + '@emotion/styled': ^11.3.0 + '@types/react': ^17.0.0 || ^18.0.0 + react: ^17.0.0 || ^18.0.0 + peerDependenciesMeta: + '@emotion/react': + optional: true + '@emotion/styled': + optional: true + '@types/react': + optional: true + dependencies: + '@babel/runtime': 7.21.0 + '@emotion/react': 11.10.6_pmekkgnqduwlme35zpnqhenc34 + '@emotion/styled': 11.10.6_oouaibmszuch5k64ms7uxp2aia + '@mui/private-theming': 5.11.13_pmekkgnqduwlme35zpnqhenc34 + '@mui/styled-engine': 5.11.11_xqp3pgpqjlfxxa3zxu4zoc4fba + '@mui/types': 7.2.3_@types+react@18.0.28 + '@mui/utils': 5.11.13_react@18.2.0 + '@types/react': 18.0.28 + clsx: 1.2.1 + csstype: 3.1.1 + prop-types: 15.8.1 + react: 18.2.0 + dev: false + + /@mui/types/7.2.3_@types+react@18.0.28: + resolution: {integrity: sha512-tZ+CQggbe9Ol7e/Fs5RcKwg/woU+o8DCtOnccX6KmbBc7YrfqMYEYuaIcXHuhpT880QwNkZZ3wQwvtlDFA2yOw==} + peerDependencies: + '@types/react': '*' + peerDependenciesMeta: + '@types/react': + optional: true + dependencies: + '@types/react': 18.0.28 + dev: false + + /@mui/utils/5.11.13_react@18.2.0: + resolution: {integrity: sha512-5ltA58MM9euOuUcnvwFJqpLdEugc9XFsRR8Gt4zZNb31XzMfSKJPR4eumulyhsOTK1rWf7K4D63NKFPfX0AxqA==} + engines: {node: '>=12.0.0'} + peerDependencies: + react: ^17.0.0 || ^18.0.0 + dependencies: + '@babel/runtime': 7.21.0 + '@types/prop-types': 15.7.5 + '@types/react-is': 17.0.3 + prop-types: 15.8.1 + react: 18.2.0 + react-is: 18.2.0 + dev: false + /@next/env/13.2.4: resolution: {integrity: sha512-+Mq3TtpkeeKFZanPturjcXt+KHfKYnLlX6jMLyCrmpq6OOs4i1GqBOAauSkii9QeKCMTYzGppar21JU57b/GEA==} dev: false @@ -436,6 +725,10 @@ packages: '@nodelib/fs.scandir': 2.1.5 fastq: 1.15.0 + /@popperjs/core/2.11.7: + resolution: {integrity: sha512-Cr4OjIkipTtcXKjAsm8agyleBuDHvxzeBoa1v543lbv1YaIwQjESsVcmjiWiPEbC1FIeHOG/Op9kdCmAmiS3Kw==} + dev: false + /@rushstack/eslint-patch/1.2.0: resolution: {integrity: sha512-sXo/qW2/pAcmT43VoRKOJbDOfV3cYpq3szSVfIThQXNt+E4DfKj361vaAt3c88U5tPUxzEswam7GW48PJqtKAg==} dev: true @@ -497,6 +790,10 @@ packages: resolution: {integrity: sha512-p6ua9zBxz5otCmbpb5D3U4B5Nanw6Pk3PPyX05xnxbB/fRv71N7CPmORg7uAD5P70T0xmx1pzAx/FUfa5X+3cw==} dev: true + /@types/parse-json/4.0.0: + resolution: {integrity: sha512-//oorEZjL6sbPcKUaCdIGlIUeH26mgzimjBB77G6XRgnDl/L5wOnpyBGRe/Mmf5CVW3PwEBE1NjiMZ/ssFh4wA==} + dev: false + /@types/pg/8.6.6: resolution: {integrity: sha512-O2xNmXebtwVekJDD+02udOncjVcMZQuTEQEMpKJ0ZRf5E7/9JJX3izhKUcUifBkyKpljyUM6BTgy2trmviKlpw==} dependencies: @@ -514,12 +811,24 @@ packages: '@types/react': 18.0.28 dev: true + /@types/react-is/17.0.3: + resolution: {integrity: sha512-aBTIWg1emtu95bLTLx0cpkxwGW3ueZv71nE2YFBpL8k/z5czEW8yYpOo8Dp+UUAFAtKwNaOsh/ioSeQnWlZcfw==} + dependencies: + '@types/react': 18.0.28 + dev: false + /@types/react-syntax-highlighter/15.5.6: resolution: {integrity: sha512-i7wFuLbIAFlabTeD2I1cLjEOrG/xdMa/rpx2zwzAoGHuXJDhSqp9BSfDlMHSh9JSuNfxHk9eEmMX6D55GiyjGg==} dependencies: '@types/react': 18.0.28 dev: true + /@types/react-transition-group/4.4.5: + resolution: {integrity: sha512-juKD/eiSM3/xZYzjuzH6ZwpP+/lejltmiS3QEzV/vmb/Q8+HfDmxu+Baga8UEMGBqV88Nbg4l2hY/K2DkyaLLA==} + dependencies: + '@types/react': 18.0.28 + dev: false + /@types/react/18.0.28: resolution: {integrity: sha512-RD0ivG1kEztNBdoAK7lekI9M+azSnitIn85h4iOiaLjaTrMjzslhaqCGaI4IyCJ1RljWiLCEu4jyrLLgqxBTew==} dependencies: @@ -787,6 +1096,15 @@ packages: deep-equal: 2.2.0 dev: true + /babel-plugin-macros/3.1.0: + resolution: {integrity: sha512-Cg7TFGpIr01vOQNODXOOaGz2NpCU5gl8x1qJFbb6hbZxR7XrcE2vtbAsTAbJ7/xwJtUuJEw8K8Zr/AE0LHlesg==} + engines: {node: '>=10', npm: '>=6'} + dependencies: + '@babel/runtime': 7.21.0 + cosmiconfig: 7.1.0 + resolve: 1.22.1 + dev: false + /babel-plugin-styled-components/2.0.7_styled-components@5.3.9: resolution: {integrity: sha512-i7YhvPgVqRKfoQ66toiZ06jPNA3p6ierpfUuEWxNF+fV27Uv5gxBkf8KZLHUCc1nFA9j6+80pYoIpqCeyW3/bA==} peerDependencies: @@ -797,7 +1115,7 @@ packages: babel-plugin-syntax-jsx: 6.18.0 lodash: 4.17.21 picomatch: 2.3.1 - styled-components: 5.3.9_biqbaboplfbrettd7655fr4n2y + styled-components: 5.3.9_7i5myeigehqah43i5u7wbekgba dev: false /babel-plugin-syntax-jsx/6.18.0: @@ -854,7 +1172,6 @@ packages: /callsites/3.1.0: resolution: {integrity: sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==} engines: {node: '>=6'} - dev: true /camelcase-css/2.0.1: resolution: {integrity: sha512-QOSvevhslijgYwRx6Rv7zKdMF8lbRmx+uQGx2+vDc+KI/eBnsy9kit5aj23AgGu3pa4t9AgwbnXWqS+iOY+2aA==} @@ -922,6 +1239,11 @@ packages: resolution: {integrity: sha512-IV3Ou0jSMzZrd3pZ48nLkT9DA7Ag1pnPzaiQhpW7c3RbcqqzvzzVu+L8gfqMp/8IM2MQtSiqaCxrrcfu8I8rMA==} dev: false + /clsx/1.2.1: + resolution: {integrity: sha512-EcR6r5a8bj6pu3ycsa/E/cKVGuTgZJZdsyUYHOksG/UHIiKfjxzRxYJpyVBwYaQeOvghal9fcc4PidlgzugAQg==} + engines: {node: '>=6'} + dev: false + /color-convert/1.9.3: resolution: {integrity: sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==} dependencies: @@ -975,6 +1297,21 @@ packages: resolution: {integrity: sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==} dev: true + /convert-source-map/1.9.0: + resolution: {integrity: sha512-ASFBup0Mz1uyiIjANan1jzLQami9z1PoYSZCiiYW2FczPbenXc45FZdBZLzOT+r6+iciuEModtmCti+hjaAk0A==} + dev: false + + /cosmiconfig/7.1.0: + resolution: {integrity: sha512-AdmX6xUzdNASswsFtmwSt7Vj8po9IuqXm0UXz7QKPuEUmPB4XyjGfaAr2PSuELMwkRMVH1EpIkX5bTZGRB3eCA==} + engines: {node: '>=10'} + dependencies: + '@types/parse-json': 4.0.0 + import-fresh: 3.3.0 + parse-json: 5.2.0 + path-type: 4.0.0 + yaml: 1.10.2 + dev: false + /cross-spawn/7.0.3: resolution: {integrity: sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==} engines: {node: '>= 8'} @@ -1175,6 +1512,13 @@ packages: esutils: 2.0.3 dev: true + /dom-helpers/5.2.1: + resolution: {integrity: sha512-nRCa7CK3VTrM2NmGkIy4cbK7IZlgBE/PYMn55rrXefr5xXDP0LdtfPnblFDoVdcAfslJ7or6iqAUnx0CCGIWQA==} + dependencies: + '@babel/runtime': 7.21.0 + csstype: 3.1.1 + dev: false + /electron-to-chromium/1.4.330: resolution: {integrity: sha512-PqyefhybrVdjAJ45HaPLtuVaehiSw7C3ya0aad+rvmV53IVyXmYRk3pwIOb2TxTDTnmgQdn46NjMMaysx79/6Q==} @@ -1182,6 +1526,12 @@ packages: resolution: {integrity: sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==} dev: true + /error-ex/1.3.2: + resolution: {integrity: sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==} + dependencies: + is-arrayish: 0.2.1 + dev: false + /es-abstract/1.21.2: resolution: {integrity: sha512-y/B5POM2iBnIxCiernH1G7rC9qQoM77lLIMQLuob0zhp8C56Po81+2Nj0WFKnd0pNReDTnkYryc+zhOzpEIROg==} engines: {node: '>= 0.4'} @@ -1272,7 +1622,6 @@ packages: /escape-string-regexp/4.0.0: resolution: {integrity: sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==} engines: {node: '>=10'} - dev: true /escape-string-regexp/5.0.0: resolution: {integrity: sha512-/veY75JbMK4j1yjvuUxuVsiS/hr/4iHs9FTT6cgTexxdE0Ly/glccBAkloH/DofkjRbZU3bnoj38mOmhkZ0lHw==} @@ -1617,6 +1966,10 @@ packages: dependencies: to-regex-range: 5.0.1 + /find-root/1.1.0: + resolution: {integrity: sha512-NKfW6bec6GfKc0SGx1e07QZY9PE99u0Bft/0rzSD5k3sO/vwkVUpDUKVm5Gpp5Ue3YfShPFTX2070tDs5kB9Ng==} + dev: false + /flat-cache/3.0.4: resolution: {integrity: sha512-dm9s5Pw7Jc0GvMYbshN6zchCA9RgQlzzEZX3vylR9IqFfS8XciblUXOKfW6SiuJ0e13eDYZoZV5wdrev7P3Nwg==} engines: {node: ^10.12.0 || >=12.0.0} @@ -1889,7 +2242,6 @@ packages: dependencies: parent-module: 1.0.1 resolve-from: 4.0.0 - dev: true /imurmurhash/0.1.4: resolution: {integrity: sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==} @@ -1947,6 +2299,10 @@ packages: is-typed-array: 1.1.10 dev: true + /is-arrayish/0.2.1: + resolution: {integrity: sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg==} + dev: false + /is-arrayish/0.3.2: resolution: {integrity: sha512-eVRqCvVlZbuw3GrM63ovNSNAeA1K16kaR/LRY/92w0zxQ5/1YzwblUX652i4Xs9RwAGjW9d9y6X88t8OaAJfWQ==} dev: false @@ -2124,6 +2480,10 @@ packages: hasBin: true dev: false + /json-parse-even-better-errors/2.3.1: + resolution: {integrity: sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==} + dev: false + /json-schema-traverse/0.4.1: resolution: {integrity: sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==} dev: true @@ -2174,6 +2534,10 @@ packages: resolution: {integrity: sha512-utWOt/GHzuUxnLKxB6dk81RoOeoNeHgbrXiuGk4yyF5qlRz+iIVWu56E2fqGHFrXz0QNUhLB/8nKqvRH66JKGQ==} engines: {node: '>=10'} + /lines-and-columns/1.2.4: + resolution: {integrity: sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==} + dev: false + /lodash-es/4.17.21: resolution: {integrity: sha512-mKnC+QJ9pWVzv+C4/U3rRsHapFfHvQFoFB92e52xeyGMcX6/OlIl78je1u8vePzYZSkkogMPJ2yjxxsb89cxyw==} dev: false @@ -2839,7 +3203,6 @@ packages: engines: {node: '>=6'} dependencies: callsites: 3.1.0 - dev: true /parse-entities/2.0.0: resolution: {integrity: sha512-kkywGpCcRYhqQIchaWqZ875wzpS/bMKhz5HnN3p7wveJTkTtyAB/AlnS0f8DFSqYW1T82t6yEAkEcB+A1I3MbQ==} @@ -2852,6 +3215,16 @@ packages: is-hexadecimal: 1.0.4 dev: true + /parse-json/5.2.0: + resolution: {integrity: sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==} + engines: {node: '>=8'} + dependencies: + '@babel/code-frame': 7.18.6 + error-ex: 1.3.2 + json-parse-even-better-errors: 2.3.1 + lines-and-columns: 1.2.4 + dev: false + /path-is-absolute/1.0.1: resolution: {integrity: sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==} engines: {node: '>=0.10.0'} @@ -2868,7 +3241,6 @@ packages: /path-type/4.0.0: resolution: {integrity: sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==} engines: {node: '>=8'} - dev: true /pg-connection-string/2.5.0: resolution: {integrity: sha512-r5o/V/ORTA6TmUnyWZR9nCj1klXCO2CEKNRlVuJptZe85QuhFayC7WeMic7ndayT5IRIR0S0xFxFi2ousartlQ==} @@ -3095,7 +3467,7 @@ packages: dependencies: deepmerge: 4.3.1 react: 18.2.0 - styled-components: 5.3.9_biqbaboplfbrettd7655fr4n2y + styled-components: 5.3.9_7i5myeigehqah43i5u7wbekgba dev: false /react-dom/18.2.0_react@18.2.0: @@ -3204,6 +3576,20 @@ packages: - '@types/react' dev: false + /react-transition-group/4.4.5_biqbaboplfbrettd7655fr4n2y: + resolution: {integrity: sha512-pZcd1MCJoiKiBR2NRxeCRg13uCXbydPnmB4EOeRrY7480qNWO8IIgQG6zlDkm6uRMsURXPuKq0GWtiM59a5Q6g==} + peerDependencies: + react: '>=16.6.0' + react-dom: '>=16.6.0' + dependencies: + '@babel/runtime': 7.21.0 + dom-helpers: 5.2.1 + loose-envify: 1.4.0 + prop-types: 15.8.1 + react: 18.2.0 + react-dom: 18.2.0_react@18.2.0 + dev: false + /react/18.2.0: resolution: {integrity: sha512-/3IjMdb2L9QbBdWiW5e3P2/npwMBaU9mHCSCUzNln0ZCYbcfTsGbTJrU/kGemdH2IWmB2ioZ+zkxtmq6g09fGQ==} engines: {node: '>=0.10.0'} @@ -3279,7 +3665,6 @@ packages: /resolve-from/4.0.0: resolution: {integrity: sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==} engines: {node: '>=4'} - dev: true /resolve/1.22.1: resolution: {integrity: sha512-nBpuuYuY5jFsli/JIs1oldw6fOQCBioohqWZg/2hiaOybXOft4lonv85uDOKXdf8rhyK159cxU5cDcK/NKk8zw==} @@ -3395,6 +3780,11 @@ packages: resolution: {integrity: sha512-R0XvVJ9WusLiqTCEiGCmICCMplcCkIwwR11mOSD9CR5u+IXYdiseeEuXCVAjS54zqwkLcPNnmU4OeJ6tUrWhDw==} engines: {node: '>=0.10.0'} + /source-map/0.5.7: + resolution: {integrity: sha512-LbrmJOMUSdEVxIKvdcJzQC+nQhe8FUZQTXQy6+I75skNgn3OoQ0DZA8YnFa7gp8tqtL3KPf1kmo0R5DoApeSGQ==} + engines: {node: '>=0.10.0'} + dev: false + /space-separated-tokens/1.1.5: resolution: {integrity: sha512-q/JSVd1Lptzhf5bkYm4ob4iWPjx0KiRe3sRFBNrVqbJkFaBm5vbbowy1mymoPNLRa52+oadOhJ+K49wsSeSjTA==} dev: true @@ -3504,28 +3894,6 @@ packages: supports-color: 5.5.0 dev: false - /styled-components/5.3.9_biqbaboplfbrettd7655fr4n2y: - resolution: {integrity: sha512-Aj3kb13B75DQBo2oRwRa/APdB5rSmwUfN5exyarpX+x/tlM/rwZA2vVk2vQgVSP6WKaZJHWwiFrzgHt+CLtB4A==} - engines: {node: '>=10'} - peerDependencies: - react: '>= 16.8.0' - react-dom: '>= 16.8.0' - react-is: '>= 16.8.0' - dependencies: - '@babel/helper-module-imports': 7.18.6 - '@babel/traverse': 7.21.3_supports-color@5.5.0 - '@emotion/is-prop-valid': 1.2.0 - '@emotion/stylis': 0.8.5 - '@emotion/unitless': 0.7.5 - babel-plugin-styled-components: 2.0.7_styled-components@5.3.9 - css-to-react-native: 3.2.0 - hoist-non-react-statics: 3.3.2 - react: 18.2.0 - react-dom: 18.2.0_react@18.2.0 - shallowequal: 1.1.0 - supports-color: 5.5.0 - dev: false - /styled-jsx/5.1.1_react@18.2.0: resolution: {integrity: sha512-pW7uC1l4mBZ8ugbiZrcIsiIvVx1UmTfw7UkC3Um2tmfUq9Bhk8IiyEIPl6F8agHgjzku6j0xQEZbfA5uSgSaCw==} engines: {node: '>= 12.0.0'} @@ -3547,6 +3915,10 @@ packages: resolution: {integrity: sha512-IjLxzM20RMwAsx8M1QoRlCG/Kmq8lKzCGyospjtSXt/BTIIcvgTonaxQAsKnBrsZNwhpHzO9ADx5te0h76ILVg==} dev: false + /stylis/4.1.3: + resolution: {integrity: sha512-GP6WDNWf+o403jrEp9c5jibKavrtLW+/qYGhFxFrG8maXhwTBI7gLLhiBb0o7uFccWN+EOS9aMO6cGHWAO07OA==} + dev: false + /supports-color/5.5.0: resolution: {integrity: sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==} engines: {node: '>=4'} diff --git a/store/index.ts b/store/index.ts index d9a4117..e3cfd45 100644 --- a/store/index.ts +++ b/store/index.ts @@ -4,3 +4,4 @@ export * from "./connection"; export * from "./chat"; export * from "./message"; export * from "./layout"; +export * from "./query"; diff --git a/store/layout.ts b/store/layout.ts index 6355ad8..675905f 100644 --- a/store/layout.ts +++ b/store/layout.ts @@ -12,7 +12,7 @@ interface LayoutState { toggleSidebar: (show?: boolean) => void; } -export const useLayoutStore = create()((set, get) => ({ +export const useLayoutStore = create()((set) => ({ showSidebar: true, toggleSidebar: (show) => { if (isUndefined(show)) { diff --git a/store/query.ts b/store/query.ts new file mode 100644 index 0000000..ac66270 --- /dev/null +++ b/store/query.ts @@ -0,0 +1,31 @@ +import { create } from "zustand"; +import { Connection, Database } from "@/types"; + +interface ExecuteQueryContext { + connection: Connection; + database?: Database; + statement: string; +} + +interface QueryState { + context?: ExecuteQueryContext; + showDrawer: boolean; + toggleDrawer: (show?: boolean) => void; + setContext: (context: ExecuteQueryContext | undefined) => void; +} + +export const useQueryStore = create()((set) => ({ + showDrawer: false, + toggleDrawer: (show) => { + set((state) => ({ + ...state, + showDrawer: show ?? !state.showDrawer, + })); + }, + setContext: (context) => { + set((state) => ({ + ...state, + context, + })); + }, +}));