diff --git a/api/package.json b/api/package.json index a8029b85..719ddbbd 100644 --- a/api/package.json +++ b/api/package.json @@ -9,6 +9,7 @@ "cross-env": "^6.0.3", "eslint": "^6.8.0", "express": "^4.17.1", + "fs-extra": "^8.1.0", "mssql": "^6.0.1", "mysql": "^2.17.1", "pg": "^7.17.0" diff --git a/api/src/connection.js b/api/src/connection.js index 05b7684a..ea21a364 100644 --- a/api/src/connection.js +++ b/api/src/connection.js @@ -1,23 +1,36 @@ +const os = require('os'); +const path = require('path'); +const fs = require('fs-extra'); const express = require('express'); const router = express.Router(); const { fork } = require('child_process'); +const _ = require('lodash'); + +function datadir() { + return path.join(os.homedir(), 'dbgate-data'); +} router.post('/test', async (req, res) => { const subprocess = fork(`${__dirname}/connectProcess.js`); subprocess.send(req.body); subprocess.on('message', resp => res.json(resp)); +}); - // const { server, port, user, password } = req.body; - // let pool; - // try { - // pool = await mssql.connect({ server, port, user, password }); - // const resp = await pool.request().query('SELECT @@VERSION AS version'); - // const { version } = resp.recordset[0]; - // res.json({ version }); - // } catch (e) { - // res.json({ error: e.message }); - // } - // if (pool) await pool.close(); +router.post('/save', async (req, res) => { + await fs.mkdir(datadir()); + const fileName = `${new Date().getTime()}.con`; + await fs.writeFile(path.join(datadir(), fileName), JSON.stringify(req.body)); + res.json({ fileName }); +}); + +router.get('/list', async (req, res) => { + const files = await fs.readdir(datadir()); + + res + .json( + await Promise.all(files.filter(x => x.endsWith('.con')).map(x => fs.readFile(path.join(datadir(), x), 'utf-8'))) + ) + .map(x => _.omit(JSON.parse(x), 'password')); }); module.exports = router; diff --git a/api/yarn.lock b/api/yarn.lock index e50c0c8b..dfb39cb9 100644 --- a/api/yarn.lock +++ b/api/yarn.lock @@ -919,6 +919,15 @@ fresh@0.5.2: resolved "https://registry.yarnpkg.com/fresh/-/fresh-0.5.2.tgz#3d8cadd90d976569fa835ab1f8e4b23a105605a7" integrity sha1-PYyt2Q2XZWn6g1qx+OSyOhBWBac= +fs-extra@^8.1.0: + version "8.1.0" + resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-8.1.0.tgz#49d43c45a88cd9677668cb7be1b46efdb8d2e1c0" + integrity sha512-yhlQgA6mnOJUKOsRUFsgJdQCvkKhcz8tlZG5HBQfReYZy46OwLcY+Zia0mtdHsOo9y/hP+CxMN0TU9QxoOtG4g== + dependencies: + graceful-fs "^4.2.0" + jsonfile "^4.0.0" + universalify "^0.1.0" + fs.realpath@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/fs.realpath/-/fs.realpath-1.0.0.tgz#1504ad2523158caa40db4a2787cb01411994ea4f" @@ -996,7 +1005,7 @@ got@^6.7.1: unzip-response "^2.0.1" url-parse-lax "^1.0.0" -graceful-fs@^4.1.11, graceful-fs@^4.1.2: +graceful-fs@^4.1.11, graceful-fs@^4.1.2, graceful-fs@^4.1.6, graceful-fs@^4.2.0: version "4.2.3" resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.3.tgz#4a12ff1b60376ef09862c2093edd908328be8423" integrity sha512-a30VEBm4PEdx1dRB7MFK7BejejvCvBronbLjht+sHuGYj8PHs7M/5Z+rt5lw551vZ7yfTCj4Vuyy3mSJytDWRQ== @@ -1293,6 +1302,13 @@ json-stringify-safe@~5.0.1: resolved "https://registry.yarnpkg.com/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz#1296a2d58fd45f19a0f6ce01d65701e2c735b6eb" integrity sha1-Epai1Y/UXxmg9s4B1lcB4sc1tus= +jsonfile@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/jsonfile/-/jsonfile-4.0.0.tgz#8771aae0799b64076b76640fca058f9c10e33ecb" + integrity sha1-h3Gq4HmbZAdrdmQPygWPnBDjPss= + optionalDependencies: + graceful-fs "^4.1.6" + jsprim@^1.2.2: version "1.4.1" resolved "https://registry.yarnpkg.com/jsprim/-/jsprim-1.4.1.tgz#313e66bc1e5cc06e438bc1b7499c2e5c56acb6a2" @@ -2302,6 +2318,11 @@ unique-string@^1.0.0: dependencies: crypto-random-string "^1.0.0" +universalify@^0.1.0: + version "0.1.2" + resolved "https://registry.yarnpkg.com/universalify/-/universalify-0.1.2.tgz#b646f69be3942dabcecc9d6639c80dc105efaa66" + integrity sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg== + unpipe@1.0.0, unpipe@~1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/unpipe/-/unpipe-1.0.0.tgz#b2bf4ee8514aae6165b4817829d21b2ef49904ec" diff --git a/web/src/modals/ConnectionModal.js b/web/src/modals/ConnectionModal.js index b5f81d06..9cd041ab 100644 --- a/web/src/modals/ConnectionModal.js +++ b/web/src/modals/ConnectionModal.js @@ -1,7 +1,7 @@ import React from 'react'; import axios from 'axios'; import ModalBase from './ModalBase'; -import { FormRow, FormLabel, FormValue, FormTextField, FormSelectField, FormSubmit } from '../utility/forms'; +import { FormRow, FormButton, FormTextField, FormSelectField, FormSubmit } from '../utility/forms'; import { TextField } from '../utility/inputs'; import { Formik, Form } from 'formik'; // import FormikForm from '../utility/FormikForm'; @@ -9,7 +9,7 @@ import { Formik, Form } from 'formik'; export default function ConnectionModal({ modalState }) { const [sqlConnectResult, setSqlConnectResult] = React.useState('Not connected'); - const handleSubmit = async values => { + const handleTest = async values => { const resp = await axios.post('http://localhost:3000/connection/test', values); console.log('resp.data', resp.data); const { error, version } = resp.data; @@ -18,6 +18,13 @@ export default function ConnectionModal({ modalState }) { // modalState.close(); }; + + const handleSubmit = async values => { + const resp = await axios.post('http://localhost:3000/connection/save', values); + console.log('resp.data', resp.data); + + // modalState.close(); + }; return (

Add connection

@@ -34,7 +41,10 @@ export default function ConnectionModal({ modalState }) { - + + + +
Connect result: {sqlConnectResult}
diff --git a/web/src/utility/forms.js b/web/src/utility/forms.js index b27b9577..5c5da280 100644 --- a/web/src/utility/forms.js +++ b/web/src/utility/forms.js @@ -1,7 +1,7 @@ import React from 'react'; import styled from 'styled-components'; import { TextField, SelectField } from './inputs'; -import { Field } from 'formik'; +import { Field, useFormikContext } from 'formik'; export const FormRow = styled.div` display: flex; @@ -40,9 +40,10 @@ export function FormSelectField({ label, children, ...other }) { } export function FormSubmit({ text }) { - return ( - - - - ); + return ; +} + +export function FormButton({ text, onClick, ...other }) { + const { values } = useFormikContext(); + return onClick(values)} {...other} />; }