aboutsummaryrefslogtreecommitdiffstats
path: root/ui/src
diff options
context:
space:
mode:
authorEllie Huxtable <ellie@atuin.sh>2024-07-25 23:31:38 +0100
committerGitHub <noreply@github.com>2024-07-25 23:31:38 +0100
commitc32bbcc7edc2cf99da52b1407c90238bc781a804 (patch)
tree4a8b307f69fb444f5c8c15a65e6f89170d9d4bbf /ui/src
parentfeat(gui): allow interacting with the embedded terminal (#2312) (diff)
downloadatuin-c32bbcc7edc2cf99da52b1407c90238bc781a804.zip
feat(gui): directory block, re-org of some code (#2314)
Diffstat (limited to 'ui/src')
-rw-r--r--ui/src/App.css2
-rw-r--r--ui/src/components/runbooks/List.tsx3
-rw-r--r--ui/src/components/runbooks/editor/Editor.tsx33
-rw-r--r--ui/src/components/runbooks/editor/blocks/Directory/index.tsx65
-rw-r--r--ui/src/components/runbooks/editor/blocks/Run/extensions.ts (renamed from ui/src/components/runbooks/editor/blocks/RunBlock/extensions.ts)0
-rw-r--r--ui/src/components/runbooks/editor/blocks/Run/index.css (renamed from ui/src/components/runbooks/editor/blocks/RunBlock/index.css)0
-rw-r--r--ui/src/components/runbooks/editor/blocks/Run/index.tsx (renamed from ui/src/components/runbooks/editor/blocks/RunBlock/index.tsx)25
-rw-r--r--ui/src/components/runbooks/editor/blocks/Run/terminal.tsx (renamed from ui/src/components/runbooks/editor/blocks/RunBlock/terminal.tsx)0
-rw-r--r--ui/src/pages/History.tsx19
-rw-r--r--ui/src/pages/Runbooks.tsx9
10 files changed, 134 insertions, 22 deletions
diff --git a/ui/src/App.css b/ui/src/App.css
index cf6d3123..29ca80f1 100644
--- a/ui/src/App.css
+++ b/ui/src/App.css
@@ -19,7 +19,7 @@ html {
}
.history-list {
- height: calc(100vh - 150px - 64px);
+ height: calc(100dvh - 4rem - 2rem);
}
.history-item {
diff --git a/ui/src/components/runbooks/List.tsx b/ui/src/components/runbooks/List.tsx
index d4591e6f..42da3885 100644
--- a/ui/src/components/runbooks/List.tsx
+++ b/ui/src/components/runbooks/List.tsx
@@ -109,8 +109,7 @@ const NoteSidebar = () => {
onPress={async () => {
await Runbook.delete(runbook.id);
- if (runbook.id == currentRunbook)
- setCurrentRunbook(null);
+ if (runbook.id == currentRunbook) setCurrentRunbook("");
refreshRunbooks();
}}
diff --git a/ui/src/components/runbooks/editor/Editor.tsx b/ui/src/components/runbooks/editor/Editor.tsx
index bbf594d8..6b0522f5 100644
--- a/ui/src/components/runbooks/editor/Editor.tsx
+++ b/ui/src/components/runbooks/editor/Editor.tsx
@@ -36,10 +36,12 @@ import { BlockNoteView } from "@blocknote/mantine";
import "@blocknote/core/fonts/inter.css";
import "@blocknote/mantine/style.css";
-import { Code } from "lucide-react";
+import { CodeIcon, FolderOpenIcon } from "lucide-react";
import { useDebounceCallback } from "usehooks-ts";
-import RunBlock from "@/components/runbooks/editor/blocks/RunBlock";
+import Run from "@/components/runbooks/editor/blocks/Run";
+import Directory from "@/components/runbooks/editor/blocks/Directory";
+
import { DeleteBlock } from "@/components/runbooks/editor/ui/DeleteBlockButton";
import { AtuinState, useStore } from "@/state/store";
import Runbook from "@/state/runbooks/runbook";
@@ -52,21 +54,34 @@ const schema = BlockNoteSchema.create({
...defaultBlockSpecs,
// Adds the code block.
- run: RunBlock,
+ run: Run,
+ directory: Directory,
},
});
// Slash menu item to insert an Alert block
const insertRun = (editor: typeof schema.BlockNoteEditor) => ({
- title: "Code block",
+ title: "Code",
onItemClick: () => {
insertOrUpdateBlock(editor, {
type: "run",
});
},
- icon: <Code size={18} />,
+ icon: <CodeIcon size={18} />,
aliases: ["code", "run"],
- group: "Code",
+ group: "Execute",
+});
+
+const insertDirectory = (editor: typeof schema.BlockNoteEditor) => ({
+ title: "Directory",
+ onItemClick: () => {
+ insertOrUpdateBlock(editor, {
+ type: "directory",
+ });
+ },
+ icon: <FolderOpenIcon size={18} />,
+ aliases: ["directory", "dir", "folder"],
+ group: "Execute",
});
export default function Editor() {
@@ -161,7 +176,11 @@ export default function Editor() {
triggerCharacter={"/"}
getItems={async (query: any) =>
filterSuggestionItems(
- [...getDefaultReactSlashMenuItems(editor), insertRun(editor)],
+ [
+ ...getDefaultReactSlashMenuItems(editor),
+ insertRun(editor),
+ insertDirectory(editor),
+ ],
query,
)
}
diff --git a/ui/src/components/runbooks/editor/blocks/Directory/index.tsx b/ui/src/components/runbooks/editor/blocks/Directory/index.tsx
new file mode 100644
index 00000000..38e974ff
--- /dev/null
+++ b/ui/src/components/runbooks/editor/blocks/Directory/index.tsx
@@ -0,0 +1,65 @@
+import { useState } from "react";
+import { Input, Tooltip } from "@nextui-org/react";
+import { FolderInputIcon, HelpCircleIcon } from "lucide-react";
+
+// @ts-ignore
+import { createReactBlockSpec } from "@blocknote/react";
+
+interface DirectoryProps {
+ path: string;
+ onInputChange: (string) => void;
+}
+
+const Directory = ({ path, onInputChange }: DirectoryProps) => {
+ const [value, setValue] = useState(path);
+
+ return (
+ <div className="w-full !max-w-full !outline-none overflow-none">
+ <Tooltip
+ content="Change working directory for all subsequent code blocks"
+ delay={1000}
+ >
+ <Input
+ label="Directory"
+ placeholder="~"
+ labelPlacement="outside"
+ value={value}
+ autoComplete="off"
+ autoCapitalize="off"
+ autoCorrect="off"
+ spellCheck="false"
+ onValueChange={(val) => {
+ setValue(val);
+ onInputChange(val);
+ }}
+ startContent={<FolderInputIcon />}
+ />
+ </Tooltip>
+ </div>
+ );
+};
+
+export default createReactBlockSpec(
+ {
+ type: "directory",
+ propSchema: {
+ path: { default: "" },
+ },
+ content: "none",
+ },
+ {
+ // @ts-ignore
+ render: ({ block, editor, code, type }) => {
+ const onInputChange = (val: string) => {
+ editor.updateBlock(block, {
+ // @ts-ignore
+ props: { ...block.props, path: val },
+ });
+ };
+
+ return (
+ <Directory path={block.props.path} onInputChange={onInputChange} />
+ );
+ },
+ },
+);
diff --git a/ui/src/components/runbooks/editor/blocks/RunBlock/extensions.ts b/ui/src/components/runbooks/editor/blocks/Run/extensions.ts
index 76fc4343..76fc4343 100644
--- a/ui/src/components/runbooks/editor/blocks/RunBlock/extensions.ts
+++ b/ui/src/components/runbooks/editor/blocks/Run/extensions.ts
diff --git a/ui/src/components/runbooks/editor/blocks/RunBlock/index.css b/ui/src/components/runbooks/editor/blocks/Run/index.css
index e854c03b..e854c03b 100644
--- a/ui/src/components/runbooks/editor/blocks/RunBlock/index.css
+++ b/ui/src/components/runbooks/editor/blocks/Run/index.css
diff --git a/ui/src/components/runbooks/editor/blocks/RunBlock/index.tsx b/ui/src/components/runbooks/editor/blocks/Run/index.tsx
index 25faa211..e0989f47 100644
--- a/ui/src/components/runbooks/editor/blocks/RunBlock/index.tsx
+++ b/ui/src/components/runbooks/editor/blocks/Run/index.tsx
@@ -1,5 +1,6 @@
// @ts-ignore
import { createReactBlockSpec } from "@blocknote/react";
+
import "./index.css";
import CodeMirror from "@uiw/react-codemirror";
@@ -26,8 +27,25 @@ interface RunBlockProps {
type: string;
pty: string;
isEditable: boolean;
+ editor: any;
}
+const findFirstParentOfType = (editor: any, id: string, type: string): any => {
+ // TODO: the types for blocknote aren't working. Now I'm doing this sort of shit,
+ // really need to fix that.
+ const document = editor.document;
+ var lastOfType = null;
+
+ // Iterate through ALL of the blocks.
+ for (let i = 0; i < document.length; i++) {
+ if (document[i].id == id) return lastOfType;
+
+ if (document[i].type == type) lastOfType = document[i];
+ }
+
+ return lastOfType;
+};
+
const RunBlock = ({
onChange,
id,
@@ -36,6 +54,7 @@ const RunBlock = ({
onRun,
onStop,
pty,
+ editor,
}: RunBlockProps) => {
const [value, setValue] = useState<String>(code);
const cleanupPtyTerm = useStore((store: AtuinState) => store.cleanupPtyTerm);
@@ -68,7 +87,9 @@ const RunBlock = ({
}
if (!isRunning) {
- let pty = await invoke<string>("pty_open");
+ const cwd = findFirstParentOfType(editor, id, "directory");
+ console.log(cwd.props.path);
+ let pty = await invoke<string>("pty_open", { cwd: cwd.props.path });
if (onRun) onRun(pty);
if (currentRunbook) incRunbookPty(currentRunbook);
@@ -150,6 +171,7 @@ export default createReactBlockSpec(
},
code: { default: "" },
pty: { default: "" },
+ global: { default: false },
},
content: "none",
},
@@ -186,6 +208,7 @@ export default createReactBlockSpec(
isEditable={editor.isEditable}
onRun={onRun}
onStop={onStop}
+ editor={editor}
/>
);
},
diff --git a/ui/src/components/runbooks/editor/blocks/RunBlock/terminal.tsx b/ui/src/components/runbooks/editor/blocks/Run/terminal.tsx
index a6dc589f..a6dc589f 100644
--- a/ui/src/components/runbooks/editor/blocks/RunBlock/terminal.tsx
+++ b/ui/src/components/runbooks/editor/blocks/Run/terminal.tsx
diff --git a/ui/src/pages/History.tsx b/ui/src/pages/History.tsx
index 64c2fca6..7002f3c4 100644
--- a/ui/src/pages/History.tsx
+++ b/ui/src/pages/History.tsx
@@ -6,7 +6,7 @@ import HistorySearch from "@/components/HistorySearch.tsx";
import Stats from "@/components/history/Stats.tsx";
import Drawer from "@/components/Drawer.tsx";
-import { useStore } from "@/state/store";
+import { AtuinState, useStore } from "@/state/store";
function Header() {
return (
@@ -49,9 +49,13 @@ function Header() {
}
export default function Search() {
- const history = useStore((state) => state.shellHistory);
- const refreshHistory = useStore((state) => state.refreshShellHistory);
- const historyNextPage = useStore((state) => state.historyNextPage);
+ const history = useStore((state: AtuinState) => state.shellHistory);
+ const refreshHistory = useStore(
+ (state: AtuinState) => state.refreshShellHistory,
+ );
+ const historyNextPage = useStore(
+ (state: AtuinState) => state.historyNextPage,
+ );
let [query, setQuery] = useState("");
@@ -84,12 +88,7 @@ export default function Search() {
return (
<>
- <div className="w-full flex-1 flex-col p-4">
- <div className="p-10 history-header">
- <Header />
- <p>A history of all the commands you run in your shell.</p>
- </div>
-
+ <div className="w-full flex-1 flex-col">
<div className="flex h-16 shrink-0 items-center gap-x-4 border-b border-t border-gray-200 bg-white px-4 shadow-sm sm:gap-x-6 sm:px-6 lg:px-8 history-search">
<HistorySearch
query={query}
diff --git a/ui/src/pages/Runbooks.tsx b/ui/src/pages/Runbooks.tsx
index 6b517553..d0efbc1c 100644
--- a/ui/src/pages/Runbooks.tsx
+++ b/ui/src/pages/Runbooks.tsx
@@ -1,5 +1,8 @@
import Editor from "@/components/runbooks/editor/Editor";
import List from "@/components/runbooks/List";
+
+import { Checkbox } from "@nextui-org/react";
+
import { useStore } from "@/state/store";
export default function Runbooks() {
@@ -8,7 +11,11 @@ export default function Runbooks() {
return (
<div className="flex w-full !max-w-full flex-row ">
<List />
- {currentRunbook && <Editor />}
+ {currentRunbook && (
+ <div className="flex w-full">
+ <Editor />
+ </div>
+ )}
{!currentRunbook && (
<div className="flex align-middle justify-center flex-col h-screen w-full">