Skip to content

Commit

Permalink
feat: sql dialog ✨ (#64)
Browse files Browse the repository at this point in the history
* feat: sql dialog mvp & use events for dialogs state ✨

* feat: majority of sql dialog logic ✨

* feat: resizable panels in sql dialog ✨

* chore: add changeset 🔖
  • Loading branch information
kareemmahlees authored Jun 3, 2024
1 parent 76f29e9 commit b88d833
Show file tree
Hide file tree
Showing 22 changed files with 422 additions and 81 deletions.
5 changes: 5 additions & 0 deletions .changeset/clever-pillows-tickle.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@tablex/core": patch
---

SQL dialog for in-app queries
11 changes: 9 additions & 2 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -17,12 +17,19 @@ jobs:
matrix:
include:
- platform: "macos-latest" # for Arm based macs (M1 and above).
target: "aarch64-apple-darwin"
args: "--target aarch64-apple-darwin"
- platform: "macos-latest" # for Intel based macs.

- platform: "macos-13" # for Intel based macs.
target: "x86_64-apple-darwin"
args: "--target x86_64-apple-darwin"

- platform: "ubuntu-22.04"
target: ""
args: ""

- platform: "windows-latest"
target: ""
args: ""

runs-on: ${{ matrix.platform }}
Expand Down Expand Up @@ -51,7 +58,7 @@ jobs:
- name: Install Rust stable
uses: dtolnay/rust-toolchain@stable
with:
targets: ${{ matrix.platform == 'macos-latest' && 'aarch64-apple-darwin,x86_64-apple-darwin' || '' }}
targets: ${{ matrix.target }}

- name: Rust cache
uses: swatinem/rust-cache@v2
Expand Down
2 changes: 2 additions & 0 deletions apps/core/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
},
"dependencies": {
"@hookform/resolvers": "^3.3.2",
"@monaco-editor/react": "^4.6.0",
"@radix-ui/react-checkbox": "^1.0.4",
"@radix-ui/react-context-menu": "^2.1.5",
"@radix-ui/react-dialog": "^1.0.5",
Expand Down Expand Up @@ -40,6 +41,7 @@
"react-dom": "^18.2.0",
"react-hook-form": "^7.49.2",
"react-hot-toast": "^2.4.1",
"react-resizable-panels": "^2.0.19",
"tailwind-merge": "^2.2.1",
"tailwindcss-animate": "^1.0.7",
"zod": "^3.22.4"
Expand Down
5 changes: 3 additions & 2 deletions apps/core/src-tauri/src/connection.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,10 @@ use tauri_plugin_shell::ShellExt;
use tauri_specta::Event;
use tx_handlers::{mysql::MySQLHandler, postgres::PostgresHandler, sqlite::SQLiteHandler};
use tx_lib::{
events::ConnectionsChanged,
fs::{delete_from_connections_file, read_from_connections_file, write_into_connections_file},
handler::Handler,
types::{ConnConfig, ConnectionsChangedEvent, Drivers},
types::{ConnConfig, Drivers},
};

#[tauri::command]
Expand Down Expand Up @@ -47,7 +48,7 @@ pub fn create_connection_record(
pub fn delete_connection_record(app: tauri::AppHandle, conn_id: String) -> Result<String, String> {
let mut connections_file_path = get_connections_file_path(&app)?;
delete_from_connections_file(&mut connections_file_path, conn_id)?;
ConnectionsChangedEvent.emit(&app).unwrap();
ConnectionsChanged.emit(&app).unwrap();
Ok(String::from("Successfully deleted connection"))
}

Expand Down
17 changes: 12 additions & 5 deletions apps/core/src-tauri/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,11 +14,13 @@ use connection::{
};
use row::{create_row, delete_rows, get_fk_relations, get_paginated_rows, update_row};
use specta::ts::{BigIntExportBehavior, ExportConfig};
use table::{get_columns_props, get_tables};
use table::{execute_raw_query, get_columns_props, get_tables};
use tauri::async_runtime::Mutex;
use tauri::{Manager, Window, WindowEvent};
use tauri_specta::{collect_commands, collect_events};
use tx_lib::types::{ConnectionsChangedEvent, TableContentsChangedEvent};
use tx_lib::events::{
CommandPaletteOpen, ConnectionsChanged, MetaXDialogOpen, SQLDialogOpen, TableContentsChanged,
};

#[tauri::command]
#[specta::specta]
Expand Down Expand Up @@ -47,6 +49,7 @@ fn main() {
get_connections,
get_connection_details,
get_tables,
execute_raw_query,
get_paginated_rows,
delete_rows,
get_columns_props,
Expand All @@ -55,9 +58,13 @@ fn main() {
get_fk_relations
])
.events(collect_events![
ConnectionsChangedEvent,
TableContentsChangedEvent
]);
ConnectionsChanged,
TableContentsChanged,
CommandPaletteOpen,
MetaXDialogOpen,
SQLDialogOpen
])
.header("// @ts-nocheck\n");

#[cfg(debug_assertions)]
let builder = builder.path("../src/bindings.ts");
Expand Down
8 changes: 4 additions & 4 deletions apps/core/src-tauri/src/row.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ use serde_json::Value as JsonValue;
use std::collections::HashMap;
use tauri::{async_runtime::Mutex, AppHandle, State};
use tauri_specta::Event;
use tx_lib::types::TableContentsChangedEvent;
use tx_lib::events::TableContentsChanged;
use tx_lib::types::{FKRows, PaginatedRows};

#[tauri::command]
Expand Down Expand Up @@ -52,7 +52,7 @@ pub async fn delete_rows(
.delete_rows(pool, pk_col_name, table_name, params)
.await;
if result.is_ok() {
TableContentsChangedEvent.emit(&app).unwrap()
TableContentsChanged.emit(&app).unwrap()
}
result
}
Expand Down Expand Up @@ -86,7 +86,7 @@ pub async fn create_row(

let result = handler.create_row(pool, table_name, columns, values).await;
if result.is_ok() {
TableContentsChangedEvent.emit(&app).unwrap();
TableContentsChanged.emit(&app).unwrap();
}
result
}
Expand Down Expand Up @@ -118,7 +118,7 @@ pub async fn update_row(
.update_row(pool, table_name, set_condition, pk_col_name, pk_col_value)
.await;
if result.is_ok() {
TableContentsChangedEvent.emit(&app).unwrap();
TableContentsChanged.emit(&app).unwrap();
}
result
}
Expand Down
16 changes: 16 additions & 0 deletions apps/core/src-tauri/src/table.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
use crate::state::SharedState;
use serde_json::{Map, Value};
use sqlx::Row;
use tauri::{async_runtime::Mutex, State};
use tx_lib::types::ColumnProps;
Expand Down Expand Up @@ -35,3 +36,18 @@ pub async fn get_columns_props(

Ok(cols_defs)
}

#[tauri::command]
#[specta::specta]
pub async fn execute_raw_query(
state: State<'_, Mutex<SharedState>>,
query: String,
) -> Result<Vec<Map<String, Value>>, String> {
let state = state.lock().await;
let pool = state.pool.as_ref().unwrap();
let handler = state.handler.as_ref().unwrap();

let result = handler.execute_raw_query(pool, query).await?;

Ok(result)
}
30 changes: 24 additions & 6 deletions apps/core/src/bindings.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
// @ts-nocheck
// This file was generated by [tauri-specta](https:/oscartbeaumont/tauri-specta). Do not edit this file manually.

export const commands = {
Expand Down Expand Up @@ -68,6 +69,14 @@ try {
else return { status: "error", error: e as any };
}
},
async executeRawQuery(query: string) : Promise<Result<{ [key in string]: JsonValue }[], string>> {
try {
return { status: "ok", data: await TAURI_INVOKE("execute_raw_query", { query }) };
} catch (e) {
if(e instanceof Error) throw e;
else return { status: "error", error: e as any };
}
},
async getPaginatedRows(tableName: string, pageIndex: number, pageSize: number) : Promise<Result<PaginatedRows, string>> {
try {
return { status: "ok", data: await TAURI_INVOKE("get_paginated_rows", { tableName, pageIndex, pageSize }) };
Expand Down Expand Up @@ -119,29 +128,38 @@ try {
}

export const events = __makeEvents__<{
connectionsChangedEvent: ConnectionsChangedEvent,
tableContentsChangedEvent: TableContentsChangedEvent
connectionsChanged: ConnectionsChanged,
tableContentsChanged: TableContentsChanged,
commandPaletteOpen: CommandPaletteOpen,
metaXDialogOpen: MetaXDialogOpen,
sqlDialogOpen: SQLDialogOpen
}>({
connectionsChangedEvent: "connections-changed-event",
tableContentsChangedEvent: "table-contents-changed-event"
connectionsChanged: "connections-changed",
tableContentsChanged: "table-contents-changed",
commandPaletteOpen: "command-palette-open",
metaXDialogOpen: "meta-x-dialog-open",
sqlDialogOpen: "sql-dialog-open"
})

/** user-defined types **/

export type ColumnProps = { columnName: string; type: string; isNullable: boolean; defaultValue: JsonValue; isPK: boolean; hasFkRelations: boolean }
export type CommandPaletteOpen = null
/**
* Connection Config Stored inside `connections.json` file
*/
export type ConnConfig = { driver: Drivers; connString: string; connName: string }
export type ConnectionsChangedEvent = null
export type ConnectionsChanged = null
/**
* Supported drivers, stored inside connection config in `connections.json`.
*/
export type Drivers = "sqlite" | "postgresql" | "mysql"
export type FKRows = { tableName: string; rows: { [key in string]: JsonValue }[] }
export type JsonValue = null | boolean | number | string | JsonValue[] | { [key in string]: JsonValue }
export type MetaXDialogOpen = null
export type PaginatedRows = { data: { [key in string]: JsonValue }[]; pageCount: number }
export type TableContentsChangedEvent = null
export type SQLDialogOpen = null
export type TableContentsChanged = null

/** tauri-specta globals **/

Expand Down
3 changes: 2 additions & 1 deletion apps/core/src/components/ui/command.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -117,7 +117,7 @@ const CommandItem = React.forwardRef<
<CommandPrimitive.Item
ref={ref}
className={cn(
"aria-selected:bg-accent aria-selected:text-accent-foreground relative flex cursor-default select-none items-center rounded-sm px-2 py-1.5 text-sm outline-none data-[disabled]:pointer-events-none data-[disabled]:opacity-50",
"aria-selected:bg-accent aria-selected:text-accent-foreground relative flex cursor-default select-none items-center rounded-sm px-2 py-1.5 text-sm outline-none data-[disabled]:pointer-events-none data-[disabled]:opacity-50 gap-x-2",
className
)}
{...props}
Expand Down Expand Up @@ -153,3 +153,4 @@ export {
CommandSeparator,
CommandShortcut
}

46 changes: 46 additions & 0 deletions apps/core/src/components/ui/resizable.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
"use client"

import { GripVertical } from "lucide-react"
import * as ResizablePrimitive from "react-resizable-panels"

import { cn } from "@tablex/lib/utils"

const ResizablePanelGroup = ({
className,
...props
}: React.ComponentProps<typeof ResizablePrimitive.PanelGroup>) => (
<ResizablePrimitive.PanelGroup
className={cn(
"flex h-full w-full data-[panel-group-direction=vertical]:flex-col",
className
)}
{...props}
/>
)

const ResizablePanel = ResizablePrimitive.Panel

const ResizableHandle = ({
withHandle,
className,
...props
}: React.ComponentProps<typeof ResizablePrimitive.PanelResizeHandle> & {
withHandle?: boolean
}) => (
<ResizablePrimitive.PanelResizeHandle
className={cn(
"relative flex w-px items-center justify-center bg-border after:absolute after:inset-y-0 after:left-1/2 after:w-1 after:-translate-x-1/2 focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring focus-visible:ring-offset-1 data-[panel-group-direction=vertical]:h-px data-[panel-group-direction=vertical]:w-full data-[panel-group-direction=vertical]:after:left-0 data-[panel-group-direction=vertical]:after:h-1 data-[panel-group-direction=vertical]:after:w-full data-[panel-group-direction=vertical]:after:-translate-y-1/2 data-[panel-group-direction=vertical]:after:translate-x-0 [&[data-panel-group-direction=vertical]>div]:rotate-90",
className
)}
{...props}
>
{withHandle && (
<div className="z-10 flex h-4 w-3 items-center justify-center rounded-sm border bg-border">
<GripVertical className="h-2.5 w-2.5" />
</div>
)}
</ResizablePrimitive.PanelResizeHandle>
)

export { ResizableHandle, ResizablePanel, ResizablePanelGroup }

10 changes: 3 additions & 7 deletions apps/core/src/routes/dashboard/_layout.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ import toast from "react-hot-toast"
import { z } from "zod"
import AddRowBtn from "../../components/sheets/create-row-sheet"
import CommandPalette from "./_layout/-components/command-palette"
import APIDocsDialog from "./_layout/-components/metax-dialog"
import MetaXDialog from "./_layout/-components/metax-dialog"

const dashboardConnectionSchema = z.object({
connectionName: z.string().optional(),
Expand Down Expand Up @@ -42,7 +42,6 @@ function DashboardLayout() {
const deps = Route.useLoaderDeps()
const data = Route.useLoaderData()
const [tables, setTables] = useState<string[]>(data!.tables)
const [isDialogOpen, setIsDialogOpen] = useState(false)

let timeout: NodeJS.Timeout
const handleKeyUp = (e: KeyboardEvent<HTMLInputElement>) => {
Expand Down Expand Up @@ -119,11 +118,8 @@ function DashboardLayout() {
</aside>
{deps.tableName && <AddRowBtn tableName={deps.tableName} />}
{tables.length > 0 && <Outlet />}
<CommandPalette setIsDialogOpen={setIsDialogOpen} />
<APIDocsDialog
isDialogOpen={isDialogOpen}
setIsDialogOpen={setIsDialogOpen}
/>
<CommandPalette />
<MetaXDialog />
</main>
)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@ const DataTable = <TData, TValue>({
} = useSetupReactTable({ columns, tableName })
const queryClient = useQueryClient()

events.tableContentsChangedEvent.listen(() => {
events.tableContentsChanged.listen(() => {
queryClient.invalidateQueries({ queryKey: ["table_rows"] })
})

Expand Down
Loading

0 comments on commit b88d833

Please sign in to comment.