diff --git a/.eslintrc.json b/.eslintrc.json index 02a9f43..38cc499 100644 --- a/.eslintrc.json +++ b/.eslintrc.json @@ -17,7 +17,9 @@ "unicorn/no-array-reduce": 0, "unicorn/prevent-abbreviations": 0, "unicorn/prefer-global-this": 0, + "unicorn/no-array-callback-reference": 0, "unicorn/prefer-logical-operator-over-ternary": 0, + "unicorn/no-object-as-default-parameter": 0, // TODO: Check these rules later "@typescript-eslint/no-explicit-any": 0, "@typescript-eslint/no-unused-vars": [ diff --git a/src/app/(main)/query-runner/_components/cql-editor-history.tsx b/src/app/(main)/query-runner/_components/cql-editor-history.tsx new file mode 100644 index 0000000..eb90765 --- /dev/null +++ b/src/app/(main)/query-runner/_components/cql-editor-history.tsx @@ -0,0 +1,53 @@ +import { Button } from "@scylla-studio/components/ui/button"; +import { + Card, + CardContent, + CardFooter, +} from "@scylla-studio/components/ui/card"; +import { + Sheet, + SheetContent, + SheetTitle, + SheetTrigger, +} from "@scylla-studio/components/ui/sheet"; +import { HistoryItem } from "@scylla-studio/hooks/use-cql-query-history"; +import { formatDate } from "@scylla-studio/utils"; +import { History } from "lucide-react"; + +interface CqlEditorHistoryProps { + history: HistoryItem[]; +} + +export const CqlEditorHistory = ({ history }: CqlEditorHistoryProps) => { + return ( + + + + + + History +
+ {history.map((item) => { + const date = formatDate(item.date); + return ( + + +

{item.query}

+
+ +

Executed at {date}

+
+
+ ); + })} +
+
+
+ ); +}; diff --git a/src/app/(main)/query-runner/_components/cql-editor.tsx b/src/app/(main)/query-runner/_components/cql-editor.tsx index 52d90ef..bce9a72 100644 --- a/src/app/(main)/query-runner/_components/cql-editor.tsx +++ b/src/app/(main)/query-runner/_components/cql-editor.tsx @@ -6,6 +6,8 @@ import { executeQueryAction } from "@scylla-studio/actions/execute-query"; import { queryKeyspaceAction } from "@scylla-studio/actions/query-keyspaces"; import { cqlCompletionItemProvider } from "@scylla-studio/app/(main)/query-runner/_components/cql-autocompleter"; import { cql_language } from "@scylla-studio/app/(main)/query-runner/_components/cql-language"; +import { Button } from "@scylla-studio/components/ui/button"; + import { DropdownMenu, DropdownMenuContent, @@ -17,8 +19,9 @@ import { ResizablePanel, ResizablePanelGroup, } from "@scylla-studio/components/ui/resizable"; -import { Skeleton } from "@scylla-studio/components/ui/skeleton"; + import { useCqlFilters } from "@scylla-studio/hooks/use-cql-filters"; +import { useCqlQueryHistory } from "@scylla-studio/hooks/use-cql-query-history"; import type { AvailableConnections } from "@scylla-studio/lib/connections"; import type { TracingResult } from "@scylla-studio/lib/execute-query"; import { getIsMacEnviroment } from "@scylla-studio/utils"; @@ -33,6 +36,7 @@ import type { import { useAction } from "next-safe-action/hooks"; import { useCallback, useEffect, useRef, useState } from "react"; import { toast } from "sonner"; +import { CqlEditorHistory } from "./cql-editor-history"; import { CqlResultPanel } from "./cql-resultpanel"; import { ResultFilters } from "./result-filters"; import { @@ -74,6 +78,8 @@ export function CqlEditor() { const decorationsReference = useRef(null); + const { history, addQueryToHistory } = useCqlQueryHistory(); + const queryExecutor = useAction(executeQueryAction, { onSuccess: ({ data }) => { setQueryResult(data?.result ?? []); @@ -241,7 +247,10 @@ export function CqlEditor() { editor.addCommand(monaco.KeyMod.CtrlCmd | monaco.KeyCode.Enter, () => { const fullQuery = getFullQueryAtCursor(editor, monaco); - if (fullQuery?.query) executeQuery(fullQuery.query); + if (fullQuery?.query) { + addQueryToHistory(fullQuery.query); + executeQuery(fullQuery.query); + } }); // Shift+Enter to execute all queries @@ -251,7 +260,11 @@ export function CqlEditor() { ?.getValue() .split(";") .filter((stmt) => stmt.trim() !== ""); - statements?.forEach(executeQuery); + if (statements) { + statements.forEach(executeQuery); + console.log(statements.join("")); + addQueryToHistory(statements.join("")); + } }); }; @@ -261,12 +274,16 @@ export function CqlEditor() { switch (executeType) { case ExecuteType.CURRENT: { const fullQuery = getFullQueryAtCursor(editorReference.current, monaco); - if (fullQuery?.query) executeQuery(fullQuery.query); + if (fullQuery?.query) { + addQueryToHistory(fullQuery.query); + executeQuery(fullQuery.query); + } break; } case ExecuteType.ALL: { const statements = code.split(";").filter((stmt) => stmt.trim() !== ""); statements.forEach((stmt) => executeQuery(stmt)); + addQueryToHistory(statements.join("")); break; } } @@ -323,33 +340,43 @@ export function CqlEditor() { >
- - - - - - handleExecute(ExecuteType.CURRENT)} - > - Run current query - - - {isMacEnviroment ? "⌘" : "Ctrl"} + Enter - - - - handleExecute(ExecuteType.ALL)} - > - Run all - - Shift + Enter - - - - +
+ + + + + + handleExecute(ExecuteType.CURRENT)} + > + Run current query + + + {isMacEnviroment ? "⌘" : "Ctrl"} + Enter + + + + handleExecute(ExecuteType.ALL)} + > + Run all + + Shift + Enter + + + + + + +
{currentConnection && isFetchedKeys && ( { + const [history, setHistory] = useState([]); + + const addQueryToHistory = (query: string) => { + const newHistoryItem = { + query, + date: new Date(), + }; + + setHistory((prevState) => { + return [...prevState, newHistoryItem].sort((history1, history2) => { + return ( + new Date(history2.date).getTime() - new Date(history1.date).getTime() + ); + }); + }); + }; + + return { history, addQueryToHistory }; +}; diff --git a/src/utils/index.tsx b/src/utils/index.tsx index 2a92035..f5ec5a5 100644 --- a/src/utils/index.tsx +++ b/src/utils/index.tsx @@ -1,3 +1,18 @@ export const getIsMacEnviroment = (OS: string) => { return OS.includes("MAC") ? true : false; }; + +export const formatDate = ( + date: Date, + options: Intl.DateTimeFormatOptions = { + year: "numeric", + month: "numeric", + day: "numeric", + hour: "numeric", + minute: "numeric", + second: "numeric", + hour12: false, + }, +) => { + return new Intl.DateTimeFormat("en-US", options).format(date); +};