Skip to content

Commit

Permalink
mvp ui
Browse files Browse the repository at this point in the history
  • Loading branch information
tamjidrahman committed Nov 12, 2024
1 parent eedf90e commit 1b3fc33
Show file tree
Hide file tree
Showing 8 changed files with 692 additions and 137 deletions.
24 changes: 12 additions & 12 deletions eslint.config.js
Original file line number Diff line number Diff line change
@@ -1,28 +1,28 @@
import js from '@eslint/js'
import globals from 'globals'
import reactHooks from 'eslint-plugin-react-hooks'
import reactRefresh from 'eslint-plugin-react-refresh'
import tseslint from 'typescript-eslint'
import js from "@eslint/js";
import globals from "globals";
import reactHooks from "eslint-plugin-react-hooks";
import reactRefresh from "eslint-plugin-react-refresh";
import tseslint from "typescript-eslint";

export default tseslint.config(
{ ignores: ['dist'] },
{ ignores: ["dist"] },
{
extends: [js.configs.recommended, ...tseslint.configs.recommended],
files: ['**/*.{ts,tsx}'],
files: ["**/*.{ts,tsx}"],
languageOptions: {
ecmaVersion: 2020,
globals: globals.browser,
},
plugins: {
'react-hooks': reactHooks,
'react-refresh': reactRefresh,
"react-hooks": reactHooks,
"react-refresh": reactRefresh,
},
rules: {
...reactHooks.configs.recommended.rules,
'react-refresh/only-export-components': [
'warn',
"react-refresh/only-export-components": [
"warn",
{ allowConstantExport: true },
],
},
},
)
);
3 changes: 3 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,10 @@
"preview": "vite preview"
},
"dependencies": {
"@codemirror/lang-sql": "^6.8.0",
"@duckdb/duckdb-wasm": "^1.29.0",
"@uiw/react-codemirror": "^4.23.6",
"code-mirror": "^3.22.0",
"react": "^18.3.1",
"react-dom": "^18.3.1"
},
Expand Down
36 changes: 0 additions & 36 deletions src/App.css
Original file line number Diff line number Diff line change
Expand Up @@ -4,39 +4,3 @@
padding: 2rem;
text-align: center;
}

.logo {
height: 6em;
padding: 1.5em;
will-change: filter;
transition: filter 300ms;
}
.logo:hover {
filter: drop-shadow(0 0 2em #646cffaa);
}
.logo.react:hover {
filter: drop-shadow(0 0 2em #61dafbaa);
}

@keyframes logo-spin {
from {
transform: rotate(0deg);
}
to {
transform: rotate(360deg);
}
}

@media (prefers-reduced-motion: no-preference) {
a:nth-of-type(2) .logo {
animation: logo-spin infinite 20s linear;
}
}

.card {
padding: 2em;
}

.read-the-docs {
color: #888;
}
148 changes: 93 additions & 55 deletions src/App.tsx
Original file line number Diff line number Diff line change
@@ -1,89 +1,127 @@
import {
AsyncDuckDB,
AsyncDuckDBConnection,
} from '@duckdb/duckdb-wasm'
import { useEffect, useState } from 'react'
import { initializeDuckDB, cleanUpDuckDB } from './duckdb'
import './App.css'
import { AsyncDuckDB, AsyncDuckDBConnection } from "@duckdb/duckdb-wasm";
import { useEffect, useState } from "react";
import { initializeDuckDB, cleanUpDuckDB } from "./duckdb";
import SQLEditor from "./SQLEditor.tsx";
import "./App.css";
import ResultTable from "./ResultTable.tsx";

function useDuckDBConnection() {
const [db, setDb] = useState<AsyncDuckDB | null>(null)
const [conn, setConn] = useState<AsyncDuckDBConnection | null>(null)
const [db, setDb] = useState<AsyncDuckDB | null>(null);
const [conn, setConn] = useState<AsyncDuckDBConnection | null>(null);

useEffect(() => {
let cleanUpFn = () => {}
let cleanUpFn = () => {};

initializeDuckDB().then(async (duck) => {
cleanUpFn = () => {
setDb(null)
setConn(null)
cleanUpDuckDB(duck.conn)
}
setDb(null);
setConn(null);
cleanUpDuckDB(duck.conn);
};

setDb(duck.db)
setConn(duck.conn)
})
setDb(duck.db);
setConn(duck.conn);
});

return () => cleanUpFn?.()
}, [])
return () => cleanUpFn?.();
}, []);

return { db, conn }
return { db, conn };
}

const FRIENDS = [
'Tamjid',
'Vinesh',
'Samarth',
'Andrew',
'Evan',
'David',
'Joni',
'Keegan',
'Lauren',
'Nancy',
'Shoji',
'James',
'Laura',
]
"Tamjid",
"Vinesh",
"Samarth",
"Andrew",
"Evan",
"David",
"Joni",
"Keegan",
"Lauren",
"Nancy",
"Shoji",
"James",
"Laura",
];

async function insertFriends(conn: AsyncDuckDBConnection) {
const name = FRIENDS[Math.floor(Math.random() * FRIENDS.length)]
const score = Math.ceil(Math.random() * 100)
await conn.query(`INSERT INTO friends VALUES ('${name}', ${score})`)
console.log(`🦆 Inserted ('${name}', ${score}) into table [friends].`)
const name = FRIENDS[Math.floor(Math.random() * FRIENDS.length)];
const score = Math.ceil(Math.random() * 100);
await conn.query(`INSERT INTO friends VALUES ('${name}', ${score})`);
console.log(`🦆 Inserted ('${name}', ${score}) into table [friends].`);
}

async function getFriends(conn: AsyncDuckDBConnection) {
const result = await conn.query(`SELECT * FROM friends`)
const friends = result.toArray().map((row) => row.toJSON())
console.log({ friends })
async function setUpDatabase(conn: AsyncDuckDBConnection) {
const query = `CREATE TABLE IF NOT EXISTS friends (name VARCHAR(255) NOT NULL, score INTEGER NOT NULL)`;
await conn.query(query);
await insertFriends(conn);
}

async function setUpDatabase(conn: AsyncDuckDBConnection) {
const query = `CREATE TABLE IF NOT EXISTS friends (name VARCHAR(255) NOT NULL, score INTEGER NOT NULL)`
await conn.query(query)
await insertFriends(conn)
function transpileToZQL(sql: string) {
return `transpileToZQL(${sql})`;
}

function transpileFromZQL(sql: string) {
return `transpileFromZQL(${sql})`;
}

async function runSQL(conn: AsyncDuckDBConnection, sql: string) {
console.log(`🦆 Running SQL: ${sql}`);
const result = await conn.query(sql);
return result.toArray().map((row) => row.toJSON());
}

function App() {
const { db, conn } = useDuckDBConnection()
const { db, conn } = useDuckDBConnection();

useEffect(() => {
if (db == null || conn == null) {
return
return;
}

setUpDatabase(conn)
}, [db, conn])
setUpDatabase(conn);
}, [db, conn]);

const [inputSQL, setInputSQL] = useState<string>("");
const [outputSQL, setOutputSQL] = useState<string>("");
const [sqlResult, setSqlResult] = useState<any[] | null>(null);

const handleRunSQL = async () => {
if (conn) {
const result = await runSQL(conn, inputSQL);
setSqlResult(result);
}
};
return (
<>
<h1>Web DuckDB</h1>
<h1>zql</h1>
<p>The future is quack.</p>
<button onClick={() => conn && insertFriends(conn)}>Insert</button>
<button onClick={() => conn && getFriends(conn)}>Query</button>
<div style={{ display: "flex", justifyContent: "space-between" }}>
<div style={{ width: "48%" }}>
<SQLEditor
value={inputSQL}
onChange={(v) => {
setInputSQL(v);
setOutputSQL(transpileToZQL(v));
}}
/>
<button onClick={handleRunSQL}>Run</button>
</div>
<div style={{ width: "48%" }}>
<SQLEditor
value={outputSQL}
onChange={(v) => {
setOutputSQL(v);
setInputSQL(transpileFromZQL(v));
}}
/>
</div>
</div>

{sqlResult && <ResultTable result={sqlResult} />}
</>
)
);
}

export default App
export default App;
21 changes: 21 additions & 0 deletions src/ResultTable.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
import React from "react";

interface ResultTableProps {
result: any[] | null;
}

const ResultTable: React.FC<ResultTableProps> = ({ result }) => {
console.log("result", result);
if (!result || result.length === 0) {
return null;
}

return (
<div style={{ marginTop: "20px" }}>
<h2>SQL Result:</h2>
<div>{result}</div>
</div>
);
};

export default ResultTable;
24 changes: 24 additions & 0 deletions src/SQLEditor.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
import React from "react";
import CodeMirror from "@uiw/react-codemirror";
import { sql } from "@codemirror/lang-sql";

const SQLEditor: React.FC<{
value: string;
onChange: (value: string) => void;
}> = ({ value, onChange }) => {
return (
<div style={{ width: "500px", maxWidth: "800px", margin: "0 auto" }}>
<CodeMirror
value={value}
height="300px"
extensions={[sql()]}
onChange={onChange}
theme="dark"
placeholder="Enter your SQL code here..."
style={{ textAlign: "left" }}
/>
</div>
);
};

export default SQLEditor;
32 changes: 0 additions & 32 deletions src/index.css
Original file line number Diff line number Diff line change
Expand Up @@ -34,35 +34,3 @@ h1 {
font-size: 3.2em;
line-height: 1.1;
}

button {
border-radius: 8px;
border: 1px solid transparent;
padding: 0.6em 1.2em;
font-size: 1em;
font-weight: 500;
font-family: inherit;
background-color: #1a1a1a;
cursor: pointer;
transition: border-color 0.25s;
}
button:hover {
border-color: #646cff;
}
button:focus,
button:focus-visible {
outline: 4px auto -webkit-focus-ring-color;
}

@media (prefers-color-scheme: light) {
:root {
color: #213547;
background-color: #ffffff;
}
a:hover {
color: #747bff;
}
button {
background-color: #f9f9f9;
}
}
Loading

0 comments on commit 1b3fc33

Please sign in to comment.