Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions .eslintrc.json
Original file line number Diff line number Diff line change
Expand Up @@ -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": [
Expand Down
53 changes: 53 additions & 0 deletions src/app/(main)/query-runner/_components/cql-editor-history.tsx
Original file line number Diff line number Diff line change
@@ -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 (
<Sheet>
<SheetTrigger asChild>
<Button
variant="outline"
className="flex items-center justify-center gap-2"
>
<History size={16} />
History
</Button>
</SheetTrigger>
<SheetContent className="overflow-auto">
<SheetTitle>History</SheetTitle>
<div className="flex flex-col gap-2 pt-2">
{history.map((item) => {
const date = formatDate(item.date);
return (
<Card key={item.date.toString()} className="dark:bg-slate-900">
<CardContent className="pt-4">
<p className=" text-black dark:text-white"> {item.query}</p>
</CardContent>
<CardFooter>
<p className=" text-sm text-slate-400">Executed at {date}</p>
</CardFooter>
</Card>
);
})}
</div>
</SheetContent>
</Sheet>
);
};
89 changes: 58 additions & 31 deletions src/app/(main)/query-runner/_components/cql-editor.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand All @@ -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";
Expand All @@ -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 {
Expand Down Expand Up @@ -74,6 +78,8 @@ export function CqlEditor() {
const decorationsReference =
useRef<editor.IEditorDecorationsCollection | null>(null);

const { history, addQueryToHistory } = useCqlQueryHistory();

const queryExecutor = useAction(executeQueryAction, {
onSuccess: ({ data }) => {
setQueryResult(data?.result ?? []);
Expand Down Expand Up @@ -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
Expand All @@ -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(""));
}
});
};

Expand All @@ -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;
}
}
Expand Down Expand Up @@ -323,33 +340,43 @@ export function CqlEditor() {
>
<div className="flex justify-between px-4 sm:px-8 border-t bg-background/60 py-1">
<ResultFilters />
<DropdownMenu>
<DropdownMenuTrigger className="bg-green-600 rounded p-1">
<Play size={16} />
</DropdownMenuTrigger>
<DropdownMenuContent>
<DropdownMenuItem
className="flex justify-between"
onClick={() => handleExecute(ExecuteType.CURRENT)}
>
<span>Run current query</span>
<kbd className="ml-2 pointer-events-none inline-flex h-5 select-none items-center gap-1 rounded border bg-muted px-1.5 font-mono text-[10px] font-medium text-muted-foreground opacity-100">
<span className="text-xs">
{isMacEnviroment ? "⌘" : "Ctrl"} + Enter
</span>
</kbd>
</DropdownMenuItem>
<DropdownMenuItem
className="flex justify-between"
onClick={() => handleExecute(ExecuteType.ALL)}
>
<span>Run all</span>
<kbd className="ml-2 pointer-events-none inline-flex h-5 select-none items-center gap-1 rounded border bg-muted px-1.5 font-mono text-[10px] font-medium text-muted-foreground opacity-100">
<span className="text-xs">Shift + Enter</span>
</kbd>
</DropdownMenuItem>
</DropdownMenuContent>
</DropdownMenu>
<div className="flex gap-2">
<DropdownMenu>
<DropdownMenuTrigger asChild>
<Button
size="icon"
variant="outline"
className="bg-green-600 text-white"
>
<Play size={16} />
</Button>
</DropdownMenuTrigger>
<DropdownMenuContent>
<DropdownMenuItem
className="flex justify-between"
onClick={() => handleExecute(ExecuteType.CURRENT)}
>
<span>Run current query</span>
<kbd className="ml-2 pointer-events-none inline-flex h-5 select-none items-center gap-1 rounded border bg-muted px-1.5 font-mono text-[10px] font-medium text-muted-foreground opacity-100">
<span className="text-xs">
{isMacEnviroment ? "⌘" : "Ctrl"} + Enter
</span>
</kbd>
</DropdownMenuItem>
<DropdownMenuItem
className="flex justify-between"
onClick={() => handleExecute(ExecuteType.ALL)}
>
<span>Run all</span>
<kbd className="ml-2 pointer-events-none inline-flex h-5 select-none items-center gap-1 rounded border bg-muted px-1.5 font-mono text-[10px] font-medium text-muted-foreground opacity-100">
<span className="text-xs">Shift + Enter</span>
</kbd>
</DropdownMenuItem>
</DropdownMenuContent>
</DropdownMenu>

<CqlEditorHistory history={history} />
</div>
</div>
{currentConnection && isFetchedKeys && (
<Editor
Expand Down
27 changes: 27 additions & 0 deletions src/hooks/use-cql-query-history.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
import { useState } from "react";

export interface HistoryItem {
query: string;
date: Date;
}

export const useCqlQueryHistory = () => {
const [history, setHistory] = useState<HistoryItem[]>([]);

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 };
};
15 changes: 15 additions & 0 deletions src/utils/index.tsx
Original file line number Diff line number Diff line change
@@ -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);
};