Skip to content

Commit

Permalink
feat: add extension
Browse files Browse the repository at this point in the history
  • Loading branch information
invisal committed Apr 16, 2024
1 parent b52e684 commit 1b1a310
Show file tree
Hide file tree
Showing 27 changed files with 152 additions and 155 deletions.
4 changes: 0 additions & 4 deletions gui/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -33,8 +33,6 @@
"react-dom": "^18.2.0"
},
"dependencies": {
"@blocknote/core": "^0.12.1",
"@blocknote/react": "^0.12.2",
"@codemirror/commands": "^6.3.3",
"@codemirror/lang-sql": "^6.5.5",
"@codemirror/view": "^6.26.3",
Expand Down Expand Up @@ -65,8 +63,6 @@
"@radix-ui/react-toggle": "^1.0.3",
"@radix-ui/react-toggle-group": "^1.0.4",
"@radix-ui/react-tooltip": "^1.0.7",
"@tiptap/core": "^2.3.0",
"@tiptap/react": "^2.3.0",
"@uiw/codemirror-extensions-langs": "^4.21.24",
"@uiw/codemirror-themes": "^4.21.21",
"@uiw/react-codemirror": "^4.21.21",
Expand Down
5 changes: 1 addition & 4 deletions gui/src/components/main-connection.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@ import { useDatabaseDriver } from "@gui/contexts/driver-provider";
import DatabaseGui from "./database-gui";
import { useConfig } from "@gui/contexts/config-provider";
import { AutoCompleteProvider } from "@gui/contexts/auto-complete-provider";
import { BlockEditorProvider } from "@gui/contexts/block-editor-provider";
import InternalPubSub from "@gui/lib/internal-pubsub";
import { SchemaProvider } from "@gui/contexts/schema-provider";

Expand All @@ -21,9 +20,7 @@ function MainConnection() {

return (
<SchemaProvider>
<BlockEditorProvider>
<DatabaseGui />
</BlockEditorProvider>
<DatabaseGui />
</SchemaProvider>
);
}
Expand Down
64 changes: 17 additions & 47 deletions gui/src/components/query-result-table.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,10 @@ import {
exportRowsToSqlInsert,
} from "@gui/lib/export-helper";
import { KEY_BINDING } from "@gui/lib/key-matcher";
import { openContextMenuFromEvent } from "@gui/messages/open-context-menu";
import {
StudioContextMenuItem,
openContextMenuFromEvent,
} from "@gui/messages/open-context-menu";
import {
LucideChevronDown,
LucidePin,
Expand All @@ -26,7 +29,6 @@ import {
DatabaseValue,
TableColumnDataType,
} from "@gui/drivers/base-driver";
import { useBlockEditor } from "@gui/contexts/block-editor-provider";
import parseSafeJson from "@gui/lib/json-safe";
import {
DropdownMenu,
Expand All @@ -35,10 +37,9 @@ import {
DropdownMenuItem,
DropdownMenuSeparator,
} from "./ui/dropdown-menu";
import { triggerSelectFiles, uploadFile } from "@gui/lib/file-upload";
import { toast } from "sonner";
import BigNumberCell from "./table-cell/BigNumberCell";
import { useDatabaseDriver } from "@gui/contexts/driver-provider";
import { useConfig } from "@gui/contexts/config-provider";

interface ResultTableProps {
data: OptimizeTableState;
Expand Down Expand Up @@ -96,8 +97,8 @@ export default function ResultTable({
onSortColumnChange,
}: ResultTableProps) {
const [stickyHeaderIndex, setStickHeaderIndex] = useState<number>();
const { openBlockEditor } = useBlockEditor();
const { databaseDriver } = useDatabaseDriver();
const { extensions } = useConfig();

const renderHeader = useCallback(
(header: OptimizeTableHeaderWithIndexProps) => {
Expand Down Expand Up @@ -260,14 +261,15 @@ export default function ResultTable({
}
}

function getFocusValue() {
const focusCell = state.getFocus();
if (focusCell) {
return state.getValue(focusCell.y, focusCell.x);
}

return undefined;
}
const extensionMenu = (extensions ?? []).reduce<StudioContextMenuItem[]>(
(menu, ext) => {
if (ext.contextMenu) {
return [...menu, ...ext.contextMenu(state)];
}
return menu;
},
[]
);

openContextMenuFromEvent([
{
Expand Down Expand Up @@ -313,39 +315,7 @@ export default function ResultTable({
},
],
},
{
title: "Edit with Block Editor",
onClick: () => {
openBlockEditor({
initialContent: getFocusValue() as string,
onSave: setFocusValue,
});
},
},

{
title: "Upload File",
onClick: async () => {
const files = await triggerSelectFiles();

if (files.error) return toast.error(files.error.message);

const file = files.value[0];
if (!file) return;

const toastId = toast.loading("Uploading file...");
const { data, error } = await uploadFile(file);
if (error)
return toast.error("Upload failed!", {
id: toastId,
description: error.message,
});

setFocusValue(data.url);
return toast.success("File uploaded!", { id: toastId });
},
},

...extensionMenu,
{
separator: true,
},
Expand Down Expand Up @@ -418,7 +388,7 @@ export default function ResultTable({
},
])(event);
},
[data, tableName, copyCallback, pasteCallback, openBlockEditor]
[data, tableName, copyCallback, pasteCallback, extensions]
);

const onKeyDown = useCallback(
Expand Down
79 changes: 12 additions & 67 deletions gui/src/components/table-cell/createEditableCell.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
import { useState, useEffect, useCallback, useRef } from "react";
import GenericCell from "./GenericCell";
import { DatabaseValue } from "@gui/drivers/base-driver";
import { useBlockEditor } from "@gui/contexts/block-editor-provider";
import OptimizeTableState from "../table-optimized/OptimizeTableState";

export interface TableEditableCell<T = unknown> {
Expand Down Expand Up @@ -92,45 +91,6 @@ function InputCellEditor({
);
}

function BlockEditCellEditor({
value,
discardChange,
applyChange,
onChange,
}: Readonly<{
align?: "left" | "right";
applyChange: (v: DatabaseValue<string>) => void;
discardChange: () => void;
value: DatabaseValue<string>;
onChange: (v: string) => void;
}>) {
const { openBlockEditor, closeBlockEditor } = useBlockEditor();

useEffect(() => {
openBlockEditor({
initialContent: value ?? "",
onSave: (v) => {
onChange(v);
applyChange(v);
},
onCancel: discardChange,
});

return () => {
closeBlockEditor();
};
}, [
value,
openBlockEditor,
closeBlockEditor,
applyChange,
discardChange,
onChange,
]);

return null;
}

export default function createEditableCell<T = unknown>({
toString,
toValue,
Expand All @@ -143,7 +103,6 @@ export default function createEditableCell<T = unknown>({
onChange,
state,
editMode,
editor,
}: TableEditableCell<T>) {
const [editValue, setEditValue] = useState<DatabaseValue<string>>(
toString(value)
Expand Down Expand Up @@ -177,32 +136,18 @@ export default function createEditableCell<T = unknown>({
.join(" ");

if (editMode) {
if (editor === "blocknote") {
return (
<div className={className}>
<BlockEditCellEditor
align={align}
applyChange={applyChange}
discardChange={discardChange}
onChange={setEditValue}
value={editValue}
/>
</div>
);
} else {
return (
<div className={className}>
<InputCellEditor
state={state}
align={align}
applyChange={applyChange}
discardChange={discardChange}
onChange={setEditValue}
value={editValue}
/>
</div>
);
}
return (
<div className={className}>
<InputCellEditor
state={state}
align={align}
applyChange={applyChange}
discardChange={discardChange}
onChange={setEditValue}
value={editValue}
/>
</div>
);
}

return (
Expand Down
16 changes: 16 additions & 0 deletions gui/src/components/table-optimized/OptimizeTableState.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -317,6 +317,22 @@ export default class OptimizeTableState {
: null;
}

getFocusValue(): unknown {
const focusCell = this.getFocus();
if (focusCell) {
return this.getValue(focusCell.y, focusCell.x);
}

return undefined;
}

setFocusValue(newValue: unknown) {
const focusCell = this.getFocus();
if (focusCell) {
this.changeValue(focusCell.y, focusCell.x, newValue);
}
}

hasFocus(y: number, x: number): boolean {
if (!this.focus) return false;
return this.focus[0] === y && this.focus[1] === x;
Expand Down
7 changes: 5 additions & 2 deletions gui/src/contexts/config-provider.tsx
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import { StudioExtension } from "@gui/extension";
import type { PropsWithChildren, ReactElement } from "react";
import { createContext, useContext, useMemo } from "react";

Expand All @@ -6,6 +7,7 @@ interface ConfigContextProps {
name: string;
onBack: () => void;
sideBarFooterComponent?: ReactElement;
extensions?: StudioExtension[];
}

const ConfigContext = createContext<ConfigContextProps>({
Expand All @@ -25,11 +27,12 @@ export function ConfigProvider({
color,
name,
onBack,
extensions,
sideBarFooterComponent,
}: PropsWithChildren<ConfigContextProps>) {
const memo = useMemo(
() => ({ color, name, onBack, sideBarFooterComponent }),
[name, color, onBack, sideBarFooterComponent]
() => ({ color, name, onBack, sideBarFooterComponent, extensions }),
[name, color, onBack, sideBarFooterComponent, extensions]
);

return (
Expand Down
6 changes: 6 additions & 0 deletions gui/src/extension.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
import OptimizeTableState from "./components/table-optimized/OptimizeTableState";
import { StudioContextMenuItem } from "./messages/open-context-menu";

export interface StudioExtension {
contextMenu?: (state: OptimizeTableState) => StudioContextMenuItem[];
}
1 change: 1 addition & 0 deletions gui/src/index.tsx
Original file line number Diff line number Diff line change
@@ -1 +1,2 @@
export { Studio } from "./studio";
export type { StudioExtension } from "./extension";
6 changes: 4 additions & 2 deletions gui/src/messages/open-context-menu.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { MessageChannelName } from "./const";
import type { LucideIcon } from "lucide-react";

export type OpenContextMenuList = Array<{
export interface StudioContextMenuItem {
type?: "check";
checked?: boolean;
title?: string | JSX.Element;
Expand All @@ -13,7 +13,9 @@ export type OpenContextMenuList = Array<{
sub?: OpenContextMenuList;
subWidth?: number;
icon?: LucideIcon;
}>;
}

export type OpenContextMenuList = Array<StudioContextMenuItem>;

export interface OpenContextMenuOptions {
contextMenu: OpenContextMenuList;
Expand Down
5 changes: 5 additions & 0 deletions gui/src/studio.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import ThemeProvider from "./contexts/theme-provider";
import type { BaseDriver } from "./drivers/base-driver";
import { CollaborationDriver } from "./drivers/collaboration-driver";
import { ReactElement } from "react";
import { StudioExtension } from "./extension";

interface StudioProps {
driver: BaseDriver;
Expand All @@ -19,6 +20,8 @@ interface StudioProps {

theme?: "dark" | "light";
onThemeChange?: (theme: "dark" | "light") => void;

extensions?: StudioExtension[];
}

export function Studio({
Expand All @@ -28,13 +31,15 @@ export function Studio({
collaboration,
name,
color,
extensions,
sideBarFooterComponent,
onBack,
}: Readonly<StudioProps>) {
return (
<ThemeProvider theme={theme ?? "light"} onChange={onThemeChange}>
<DriverProvider driver={driver} collaborationDriver={collaboration}>
<ConfigProvider
extensions={extensions}
name={name}
color={color}
onBack={onBack}
Expand Down
2 changes: 1 addition & 1 deletion gui/tsconfig.json
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,6 @@
"*.js",
"*.ts",
"jest.config.cjs"
],
, "../studio/src/components/file-upload.ts" ],
"exclude": ["node_modules", "dist"]
}
Loading

0 comments on commit 1b1a310

Please sign in to comment.