Skip to content

Commit

Permalink
feature(front): queries history in playground (#55)
Browse files Browse the repository at this point in the history
  • Loading branch information
daavidrgz authored Nov 4, 2024
1 parent 2bbdf30 commit 3425b87
Show file tree
Hide file tree
Showing 64 changed files with 1,477 additions and 849 deletions.
7 changes: 7 additions & 0 deletions crates/web/frontend/package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions crates/web/frontend/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@
"copy-webpack-plugin": "^12.0.2",
"framer-motion": "^11.9.0",
"gq-web": "file:pkg",
"idb": "^8.0.0",
"lucide-react": "^0.447.0",
"next": "14.2.14",
"next-themes": "^0.3.0",
Expand Down
24 changes: 12 additions & 12 deletions crates/web/frontend/src/app/global-error.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import { cn } from "@/lib/utils";
import { Fira_Mono, Montserrat } from "next/font/google";
import { useEffect } from "react";
import "./globals.css";
import { deleteDatabase } from "@/services/queries/query-service";

const montserrat = Montserrat({ subsets: ["latin"], variable: "--font-sans" });
const firaCode = Fira_Mono({
Expand All @@ -21,6 +22,12 @@ export default function GlobalError({
}) {
useEffect(() => console.error(error), [error]);

const handleTryAgain = async () => {
localStorage.clear();
await deleteDatabase();
window.location.reload();
};

return (
<html lang="en" className="dark">
<body
Expand All @@ -32,21 +39,14 @@ export default function GlobalError({
>
<div
style={{ boxShadow: "0 60px 60px -90px var(--shadow-accent)" }}
className="flex flex-col items-center px-48 py-24 border border-accent-background rounded-lg bg-background"
className="w-[50rem] flex flex-col items-center px-12 py-12 border bg-background"
>
<h2 className="text-4xl font-bold">Something went wrong!</h2>
<p className="text-sm font-light mt-4">
Click the button below to refresh the playground state
<p className="text-sm font-light mt-4 text-center">
Click the button below to refresh the playground state. This will delete all your saved
queries and your settings aiming to solve the issue.
</p>
<Button
className="mt-8"
variant="outline"
type="button"
onClick={() => {
localStorage.clear();
window.location.reload();
}}
>
<Button className="mt-8" variant="outline" type="button" onClick={handleTryAgain}>
Try again
</Button>
</div>
Expand Down
12 changes: 12 additions & 0 deletions crates/web/frontend/src/app/globals.css
Original file line number Diff line number Diff line change
Expand Up @@ -94,3 +94,15 @@ code {
li[aria-selected="true"] {
@apply !bg-accent-background !text-[var(--code-secondary)];
}

h3 {
@apply text-lg font-semibold leading-none tracking-tight;
}

h4 {
@apply text-base font-semibold leading-none tracking-tight;
}

p {
@apply text-xs;
}
5 changes: 2 additions & 3 deletions crates/web/frontend/src/app/layout.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,6 @@ export default function RootLayout({
<html lang="en">
<body className={cn("min-h-screen antialiased", montserrat.variable, firaCode.variable)}>
<Toaster
offset="32px"
duration={2000}
visibleToasts={4}
expand={false}
Expand All @@ -38,10 +37,10 @@ export default function RootLayout({
unstyled: true,
classNames: {
toast:
"w-full flex gap-4 bg-background items-center border border-accent-background p-4 rounded-md shadow-md",
"w-full flex gap-4 bg-background items-center border border-accent-background p-4 shadow-md",
title: "text-foreground text-sm",
actionButton:
"min-w-max bg-foreground text-background text-xs px-2 py-1 rounded-md justify-self-end",
"min-w-max bg-foreground text-background text-xs px-2 py-1 justify-self-end",
closeButton:
"text-foreground hover:text-accent bg-background transition-colors h-4 w-4",
icon: "",
Expand Down
185 changes: 94 additions & 91 deletions crates/web/frontend/src/app/page.tsx
Original file line number Diff line number Diff line change
@@ -1,26 +1,21 @@
"use client";

import ActionButton from "@/components/action-button/action-button";
import ApplyButton from "@/components/apply-button/apply-button";
import Editor from "@/components/editor/editor";
import Footer from "@/components/footer/footer";
import Header from "@/components/header/header";
import useDebounce from "@/hooks/useDebounce";
import { LeftSidebar } from "@/components/left-sidebar/left-sidebar";
import useDebounce from "@/hooks/use-debounce";
import { notify } from "@/lib/notify";
import { cn, i } from "@/lib/utils";
import { i } from "@/lib/utils";
import { Data } from "@/model/data";
import FileType from "@/model/file-type";
import { type LoadingState, loading, notLoading } from "@/model/loading-state";
import { setLinkEditors } from "@/model/settings";
import { useSettings } from "@/providers/settings-provider";
import { useWorker } from "@/providers/worker-provider";
import type { CompletionSource } from "@codemirror/autocomplete";
import { Link2, Link2Off } from "lucide-react";
import { useSearchParams } from "next/navigation";
import { type MutableRefObject, Suspense, useCallback, useEffect, useRef, useState } from "react";
import type PromiseWorker from "webworker-promise";
import { applyGq, getQueryCompletionSource, importShare } from "./page-utils";
import styles from "./page.module.css";

const ShareLoader = ({
updateInputEditorCallback,
Expand Down Expand Up @@ -80,6 +75,8 @@ const Home = () => {
const [queryCompletionSource, setQueryCompletionSource] = useState<CompletionSource>();
const [isApplying, setIsApplying] = useState(false);
const [shareLink, setShareLink] = useState<string>();
const [sidebarOpen, setSidebarOpen] = useState(false);
const addNewQueryCallback = useRef<(queryContent: string) => void>(i);
const {
settings: {
autoApplySettings: { autoApply, debounceTime },
Expand All @@ -88,7 +85,7 @@ const Home = () => {
},
setSettings,
} = useSettings();
const debounce = useDebounce(debounceTime);
const debounce = useDebounce();
const { gqWorker, lspWorker } = useWorker();

const updateOutputData = useCallback(
Expand All @@ -114,6 +111,7 @@ const Home = () => {
gqWorker,
silent,
);
addNewQueryCallback.current(queryContent);
setErrorMessage(undefined);
updateOutputEditorCallback.current(result);
} catch (err) {
Expand All @@ -137,6 +135,10 @@ const Home = () => {
[updateOutputData],
);

const handleClickQuery = useCallback((queryContent: string) => {
updateQueryEditorCallback.current(new Data(queryContent, FileType.GQ));
}, []);

const handleChangeInputDataFileType = useCallback(
(fileType: FileType) => {
setShareLink(undefined);
Expand All @@ -153,9 +155,9 @@ const Home = () => {
[linkEditors],
);

const handleChangeLinked = useCallback(() => {
const handleToggleLinked = useCallback(() => {
setSettings((prev) => setLinkEditors(prev, !linkEditors));
notify.info(`${linkEditors ? "Unlinked" : "Linked"} editors!`);
notify.info(`Editors ${linkEditors ? "unlinked" : "linked"}!`);
if (!linkEditors) convertOutputEditorCallback.current(inputType.current);
}, [linkEditors, setSettings]);

Expand All @@ -166,7 +168,7 @@ const Home = () => {
getQueryCompletionSource(lspWorker, new Data(content, inputType.current)),
);
autoApply &&
debounce(() =>
debounce(debounceTime, () =>
updateOutputData(content, inputType.current, queryContent.current, debounceTime < 500),
);
},
Expand All @@ -177,101 +179,102 @@ const Home = () => {
(content: string) => {
setShareLink(undefined);
autoApply &&
debounce(() =>
debounce(debounceTime, () =>
updateOutputData(inputContent.current, inputType.current, content, debounceTime < 500),
);
},
[autoApply, debounce, updateOutputData, debounceTime],
);

return (
<main className="flex flex-col items-center pt-4 px-12 h-screen">
<Header
className="w-full mb-8"
<div className="flex h-screen w-screen overflow-hidden">
<LeftSidebar
open={sidebarOpen}
setOpen={setSidebarOpen}
onClickExample={handleClickExample}
onClickQuery={handleClickQuery}
addNewQueryCallback={addNewQueryCallback}
inputContent={inputContent}
inputType={inputType}
queryContent={queryContent}
outputType={outputType}
shareLink={shareLink}
setShareLink={setShareLink}
/>
<section className="flex items-center justify-center w-full">
<aside className="flex flex-col gap-8">
<Editor
className="w-[44vw] h-[40vh]"
onChangeFileType={handleChangeInputDataFileType}
onChangeContent={handleChangeInputContent}
title="Input"
defaultFileName="input"
fileTypes={[FileType.JSON, FileType.YAML]}
convertCodeCallback={convertInputEditorCallback}
updateCallback={updateInputEditorCallback}
contentRef={inputContent}
typeRef={inputType}
/>
<Editor
className="w-[44vw] h-[40vh]"
onChangeContent={handleChangeQueryContent}
title="Input"
defaultFileName="query"
fileTypes={[FileType.GQ]}
completionSource={queryCompletionSource}
updateCallback={updateQueryEditorCallback}
contentRef={queryContent}
/>
</aside>
<div className="h-full flex justify-center items-center px-8 relative">
<div className="absolute top-40 flex w-full items-center">
<div className={styles.linkLeftBorder} data-linked={linkEditors} />
<ActionButton
className={cn(
"p-2 min-w-max border-2",
linkEditors ? "border-accent" : "border-accent-background",
)}
description={`${linkEditors ? "Link" : "Unlink"} input and output editor file types`}
onClick={handleChangeLinked}
>
{linkEditors ? <Link2 className="w-3 h-3" /> : <Link2Off className="w-3 h-3" />}
</ActionButton>
<div className={styles.linkRightBorder} data-linked={linkEditors} />
</div>
<ApplyButton
autoApply={autoApply}
onClick={() =>
updateOutputData(inputContent.current, inputType.current, queryContent.current, false)
}
/>
</div>
<aside className="flex flex-col">
<Editor
className="w-[44vw] h-[83vh]"
onChangeFileType={handleChangeOutputDataFileType}
title="Output"
editable={false}
defaultFileName="output"
fileTypes={[FileType.JSON, FileType.YAML]}
errorMessage={errorMessage}
onDismissError={() => setErrorMessage(undefined)}
warningMessages={warningMessages}
convertCodeCallback={convertOutputEditorCallback}
loadingCallback={outputEditorLoadingCallback}
updateCallback={updateOutputEditorCallback}
typeRef={outputType}
/>
</aside>
</section>
<Footer className="my-auto" />
<Suspense>
<ShareLoader
updateInputEditorCallback={updateInputEditorCallback}
updateQueryEditorCallback={updateQueryEditorCallback}
updateOutputData={updateOutputData}
gqWorker={gqWorker}
setLinkEditors={(value) => setSettings((prev) => setLinkEditors(prev, value))}
<main className="flex flex-col items-center">
<section className="flex items-center justify-between w-full h-full relative">
<aside className="flex flex-col">
<Editor
width={`calc(50vw - 32px ${sidebarOpen ? "- 192px" : ""})`}
height="calc(50vh - 20px)"
className="border-b transition-all"
onChangeFileType={handleChangeInputDataFileType}
onChangeContent={handleChangeInputContent}
title="Input"
defaultFileName="input"
fileTypes={[FileType.JSON, FileType.YAML]}
convertCodeCallback={convertInputEditorCallback}
updateCallback={updateInputEditorCallback}
contentRef={inputContent}
typeRef={inputType}
/>
<Editor
width={`calc(50vw - 32px ${sidebarOpen ? "- 192px" : ""})`}
height="calc(50vh - 20px)"
className="transition-all"
onChangeContent={handleChangeQueryContent}
onApply={() =>
updateOutputData(
inputContent.current,
inputType.current,
queryContent.current,
false,
)
}
title="Input"
defaultFileName="query"
fileTypes={[FileType.GQ]}
completionSource={queryCompletionSource}
updateCallback={updateQueryEditorCallback}
contentRef={queryContent}
/>
</aside>
<aside className="flex flex-col">
<Editor
width={`calc(50vw - 32px ${sidebarOpen ? "- 192px" : ""})`}
height="calc(100vh - 40px)"
className="border-l transition-all"
onChangeFileType={handleChangeOutputDataFileType}
title="Output"
editable={false}
defaultFileName="output"
fileTypes={[FileType.JSON, FileType.YAML]}
errorMessage={errorMessage}
onDismissError={() => setErrorMessage(undefined)}
warningMessages={warningMessages}
convertCodeCallback={convertOutputEditorCallback}
loadingCallback={outputEditorLoadingCallback}
updateCallback={updateOutputEditorCallback}
typeRef={outputType}
/>
</aside>
</section>
<Footer
className="h-10"
linkEditors={linkEditors}
handleToggleLinked={handleToggleLinked}
/>
</Suspense>
</main>
<Suspense>
<ShareLoader
updateInputEditorCallback={updateInputEditorCallback}
updateQueryEditorCallback={updateQueryEditorCallback}
updateOutputData={updateOutputData}
gqWorker={gqWorker}
setLinkEditors={(value) => setSettings((prev) => setLinkEditors(prev, value))}
/>
</Suspense>
</main>
</div>
);
};

Expand Down
Loading

0 comments on commit 3425b87

Please sign in to comment.