Skip to content

Commit

Permalink
add commit and discard keybinding (#161)
Browse files Browse the repository at this point in the history
  • Loading branch information
invisal authored Sep 17, 2024
1 parent e570d68 commit d35c53f
Show file tree
Hide file tree
Showing 4 changed files with 118 additions and 35 deletions.
67 changes: 39 additions & 28 deletions src/components/gui/tabs/table-data-tab.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@ import {
LucideArrowRight,
LucideDelete,
LucideFilter,
LucideLoader,
LucidePlus,
LucideRefreshCcw,
LucideSaveAll,
Expand Down Expand Up @@ -38,6 +37,9 @@ import ResultStats from "../result-stat";
import isEmptyResultStats from "@/components/lib/empty-stats";
import useTableResultColumnFilter from "../table-result/filter-column";
import { AlertDialogTitle } from "@radix-ui/react-alert-dialog";
import { useCurrentTab } from "../windows-tab";
import { KEY_BINDING } from "@/lib/key-matcher";
import { Toolbar, ToolbarButton } from "../toolbar";

interface TableDataContentProps {
tableName: string;
Expand Down Expand Up @@ -169,6 +171,28 @@ export default function TableDataWindow({
}
}, [data]);

const { isActiveTab } = useCurrentTab();

useEffect(() => {
if (isActiveTab) {
const handleGlobalKeyBinding = (e: KeyboardEvent) => {
if (KEY_BINDING.commit.match(e)) {
onCommit();
e.preventDefault();
e.stopPropagation();
} else if (KEY_BINDING.discard.match(e)) {
onDiscard();
e.preventDefault();
e.stopPropagation();
}
};

document.addEventListener("keydown", handleGlobalKeyBinding);
return () =>
document.removeEventListener("keydown", handleGlobalKeyBinding);
}
}, [isActiveTab, onCommit, onDiscard]);

return (
<div className="flex flex-col overflow-hidden w-full h-full">
{executeError && (
Expand All @@ -185,37 +209,24 @@ export default function TableDataWindow({
</AlertDialog>
)}
<div className="shrink-0 grow-0">
<div className="flex p-1 gap-1">
<Button
variant={"ghost"}
size={"sm"}
<Toolbar>
<ToolbarButton
text="Commit"
icon={<LucideSaveAll className="w-4 h-4 mr-2" />}
tooltip={`Commit your changes (${KEY_BINDING.commit.toString()})`}
disabled={!changeNumber || isExecuting}
loading={isExecuting}
onClick={onCommit}
>
{isExecuting ? (
<LucideLoader className="w-4 h-4 animate-spin mr-2" />
) : (
<LucideSaveAll className="w-4 h-4 mr-2 text-green-600" />
)}
Commit
{!!changeNumber && (
<span
className="ml-2 bg-red-500 text-white leading-5 w-5 h-5 rounded-full"
style={{ fontSize: 9 }}
>
{changeNumber}
</span>
)}
</Button>
badge={changeNumber ? changeNumber.toString() : ""}
/>

<Button
variant={"ghost"}
size={"sm"}
<ToolbarButton
text="Discard Change"
tooltip={`Dicard all changes (${KEY_BINDING.discard.toString()})`}
destructive
disabled={!changeNumber}
onClick={onDiscard}
>
<span className="text-red-500">Discard Change</span>
</Button>
/>

<div className="mx-1">
<Separator orientation="vertical" />
Expand Down Expand Up @@ -337,7 +348,7 @@ export default function TableDataWindow({
}}
/>
</Button>
</div>
</Toolbar>
<Separator />
</div>
<div className="grow overflow-hidden relative">
Expand Down
58 changes: 58 additions & 0 deletions src/components/gui/toolbar.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
import { PropsWithChildren, ReactElement } from "react";
import { Button } from "../ui/button";
import { LucideLoader } from "lucide-react";
import { Tooltip, TooltipContent, TooltipTrigger } from "../ui/tooltip";

export function Toolbar({ children }: PropsWithChildren) {
return <div className="flex p-1 gap-1">{children}</div>;
}

export function ToolbarButton({
disabled,
loading,
icon,
onClick,
badge,
text,
tooltip,
destructive,
}: {
icon?: ReactElement;
disabled?: boolean;
loading?: boolean;
badge?: string;
text: string;
onClick?: () => void;
tooltip?: ReactElement | string;
destructive?: boolean;
}) {
const buttonContent = (
<Button variant={"ghost"} size={"sm"} disabled={disabled} onClick={onClick}>
{loading ? <LucideLoader className="w-4 h-4 animate-spin mr-2" /> : icon}

{destructive ? <span className="text-red-500">{text}</span> : text}

{badge && (
<span
className={
"ml-2 bg-red-500 text-white leading-5 w-5 h-5 rounded-full"
}
style={{ fontSize: 9 }}
>
{badge}
</span>
)}
</Button>
);

if (tooltip) {
return (
<Tooltip>
<TooltipTrigger>{buttonContent}</TooltipTrigger>
<TooltipContent>{tooltip}</TooltipContent>
</Tooltip>
);
}

return buttonContent;
}
26 changes: 19 additions & 7 deletions src/components/gui/windows-tab.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -53,10 +53,18 @@ const WindowTabsContext = createContext<{
},
});

const CurrentWindowTab = createContext<{ isActiveTab: boolean }>({
isActiveTab: false,
});

export function useTabsContext() {
return useContext(WindowTabsContext);
}

export function useCurrentTab() {
return useContext(CurrentWindowTab);
}

export default function WindowTabs({
menu,
tabs,
Expand Down Expand Up @@ -200,15 +208,19 @@ export default function WindowTabs({
</div>
<div className="grow relative">
{tabs.map((tab, tabIndex) => (
<div
className="absolute left-0 right-0 top-0 bottom-0"
style={{
visibility: tabIndex === selected ? "inherit" : "hidden",
}}
<CurrentWindowTab.Provider
key={tab.key}
value={{ isActiveTab: tabIndex === selected }}
>
{tab.component}
</div>
<div
className="absolute left-0 right-0 top-0 bottom-0"
style={{
visibility: tabIndex === selected ? "inherit" : "hidden",
}}
>
{tab.component}
</div>
</CurrentWindowTab.Provider>
))}
</div>
</div>
Expand Down
2 changes: 2 additions & 0 deletions src/lib/key-matcher.ts
Original file line number Diff line number Diff line change
Expand Up @@ -77,4 +77,6 @@ export const KEY_BINDING = {
copy: new KeyMatcher({ ctrl: true, key: "c" }),
paste: new KeyMatcher({ ctrl: true, key: "v" }),
format: new KeyMatcher({ ctrl: true, shift: true, key: "i" }),
commit: new KeyMatcher({ ctrl: true, key: "s" }),
discard: new KeyMatcher({ ctrl: true, shift: true, key: "Delete" }),
};

0 comments on commit d35c53f

Please sign in to comment.