From e015e024e06b945f862661d3b308fb0726c4fa97 Mon Sep 17 00:00:00 2001 From: Jonas Date: Sat, 4 Oct 2025 21:08:23 +0200 Subject: [PATCH 01/18] Pre Tailwind --- package-lock.json | 4 +-- public/logo_color.svg | 15 ++++++++++ src/app/page.tsx | 5 ++-- src/app/welcome/page.tsx | 29 +++++++++++++++++++ src/components/ui/button.tsx | 56 ++++++++++++++++++++++++++++++++++++ tailwind.config.ts | 3 ++ 6 files changed, 107 insertions(+), 5 deletions(-) create mode 100644 public/logo_color.svg create mode 100644 src/app/welcome/page.tsx create mode 100644 src/components/ui/button.tsx diff --git a/package-lock.json b/package-lock.json index f7b4eed..7c08da6 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "nuts-client", - "version": "0.2.1", + "version": "0.2.1.1", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "nuts-client", - "version": "0.2.1", + "version": "0.2.1.1", "dependencies": { "@dnd-kit/core": "^6.3.1", "@dnd-kit/sortable": "^10.0.0", diff --git a/public/logo_color.svg b/public/logo_color.svg new file mode 100644 index 0000000..e7ada6f --- /dev/null +++ b/public/logo_color.svg @@ -0,0 +1,15 @@ + + + + + + + + + + + + + + + diff --git a/src/app/page.tsx b/src/app/page.tsx index df782af..a0c0166 100644 --- a/src/app/page.tsx +++ b/src/app/page.tsx @@ -43,9 +43,8 @@ export default function Home() { await window.center(); await setIsLoading(false); - // Redirect to explorer - dispatch(setSelectedTab("explorer")); - redirect("/client/explorer"); + // Redirect to welcome section + redirect("/welcome"); } startClient(); diff --git a/src/app/welcome/page.tsx b/src/app/welcome/page.tsx new file mode 100644 index 0000000..3899bef --- /dev/null +++ b/src/app/welcome/page.tsx @@ -0,0 +1,29 @@ +"use client"; + +import React, { useEffect } from "react"; +import { getCurrentWindow, LogicalSize } from '@tauri-apps/api/window'; +import Image from "next/image"; +import { Button } from "@/components/ui/button"; + + +export default function WelcomePage() { + const window = getCurrentWindow(); + + useEffect(() => { + async function setupWindow() { + await window.setTitle("Welcome to Nuts Client"); + await window.setSize(new LogicalSize(300, 440)); + await window.setResizable(true); + await window.center(); + } + + setupWindow(); + }, []); + + return ( +
+ Nuts Client Logo + +
+ ); +} \ No newline at end of file diff --git a/src/components/ui/button.tsx b/src/components/ui/button.tsx new file mode 100644 index 0000000..36496a2 --- /dev/null +++ b/src/components/ui/button.tsx @@ -0,0 +1,56 @@ +import * as React from "react" +import { Slot } from "@radix-ui/react-slot" +import { cva, type VariantProps } from "class-variance-authority" + +import { cn } from "@/lib/utils" + +const buttonVariants = cva( + "inline-flex items-center justify-center gap-2 whitespace-nowrap rounded-md text-sm font-medium ring-offset-background transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50 [&_svg]:pointer-events-none [&_svg]:size-4 [&_svg]:shrink-0", + { + variants: { + variant: { + default: "bg-primary text-primary-foreground hover:bg-primary/90", + destructive: + "bg-destructive text-destructive-foreground hover:bg-destructive/90", + outline: + "border border-input bg-background hover:bg-accent hover:text-accent-foreground", + secondary: + "bg-secondary text-secondary-foreground hover:bg-secondary/80", + ghost: "hover:bg-accent hover:text-accent-foreground", + link: "text-primary underline-offset-4 hover:underline", + }, + size: { + default: "h-10 px-4 py-2", + sm: "h-9 rounded-md px-3", + lg: "h-11 rounded-md px-8", + icon: "h-10 w-10", + }, + }, + defaultVariants: { + variant: "default", + size: "default", + }, + } +) + +export interface ButtonProps + extends React.ButtonHTMLAttributes, + VariantProps { + asChild?: boolean +} + +const Button = React.forwardRef( + ({ className, variant, size, asChild = false, ...props }, ref) => { + const Comp = asChild ? Slot : "button" + return ( + + ) + } +) +Button.displayName = "Button" + +export { Button, buttonVariants } diff --git a/tailwind.config.ts b/tailwind.config.ts index 00bfe13..eade746 100644 --- a/tailwind.config.ts +++ b/tailwind.config.ts @@ -9,6 +9,9 @@ export default { theme: { extend: { colors: { + orbit: { + background: "#0E0E0F", + }, clientColors: { windowBorder: "#2d2d2e", windowBackground: "#252526", From c34009648ee944170ff538cb58c52a02100a96ff Mon Sep 17 00:00:00 2001 From: Jonas Date: Sat, 4 Oct 2025 22:47:48 +0200 Subject: [PATCH 02/18] Shad --- components.json | 21 -- package-lock.json | 12 +- package.json | 3 +- src/app/globals.css | 96 ++++++--- src/app/layout.tsx | 23 ++- src/app/page.tsx | 4 +- src/app/welcome/page.tsx | 80 +++++++- src/components/sidebar/explorer/explorer.tsx | 48 +---- src/components/theme-provider.tsx | 11 + tailwind.config.ts | 200 ++++++++++++------- 10 files changed, 307 insertions(+), 191 deletions(-) delete mode 100644 components.json create mode 100644 src/components/theme-provider.tsx diff --git a/components.json b/components.json deleted file mode 100644 index d710b49..0000000 --- a/components.json +++ /dev/null @@ -1,21 +0,0 @@ -{ - "$schema": "https://ui.shadcn.com/schema.json", - "style": "default", - "rsc": true, - "tsx": true, - "tailwind": { - "config": "tailwind.config.ts", - "css": "src/app/globals.css", - "baseColor": "neutral", - "cssVariables": true, - "prefix": "" - }, - "aliases": { - "components": "@/components", - "utils": "@/lib/utils", - "ui": "@/components/ui", - "lib": "@/lib", - "hooks": "@/hooks" - }, - "iconLibrary": "lucide" -} \ No newline at end of file diff --git a/package-lock.json b/package-lock.json index 7c08da6..5c89516 100644 --- a/package-lock.json +++ b/package-lock.json @@ -30,9 +30,10 @@ "@vitejs/plugin-react": "^4.3.4", "class-variance-authority": "^0.7.1", "clsx": "^2.1.1", - "lucide-react": "^0.471.0", + "lucide-react": "^0.471.2", "monaco-editor": "^0.52.2", "next": "^15.3.4", + "next-themes": "^0.4.6", "react": "^19.0.0", "react-dom": "^19.0.0", "react-redux": "^9.2.0", @@ -8015,6 +8016,15 @@ } } }, + "node_modules/next-themes": { + "version": "0.4.6", + "resolved": "https://registry.npmjs.org/next-themes/-/next-themes-0.4.6.tgz", + "integrity": "sha512-pZvgD5L0IEvX5/9GWyHMf3m8BKiVQwsCMHfoFosXtXBMnaS0ZnIJ9ST4b4NqLVKDEm8QBxoNNGNaBv2JNF6XNA==", + "peerDependencies": { + "react": "^16.8 || ^17 || ^18 || ^19 || ^19.0.0-rc", + "react-dom": "^16.8 || ^17 || ^18 || ^19 || ^19.0.0-rc" + } + }, "node_modules/next/node_modules/postcss": { "version": "8.4.31", "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.31.tgz", diff --git a/package.json b/package.json index eb045eb..0b1816a 100644 --- a/package.json +++ b/package.json @@ -37,9 +37,10 @@ "@vitejs/plugin-react": "^4.3.4", "class-variance-authority": "^0.7.1", "clsx": "^2.1.1", - "lucide-react": "^0.471.0", + "lucide-react": "^0.471.2", "monaco-editor": "^0.52.2", "next": "^15.3.4", + "next-themes": "^0.4.6", "react": "^19.0.0", "react-dom": "^19.0.0", "react-redux": "^9.2.0", diff --git a/src/app/globals.css b/src/app/globals.css index 1a4ecb3..8974388 100644 --- a/src/app/globals.css +++ b/src/app/globals.css @@ -2,29 +2,6 @@ @tailwind components; @tailwind utilities; -:root { - /* ShadCN UI Colors */ - --background: 224 71% 4%; - --foreground: 213 31% 91%; - --muted: 223 47% 11%; - --muted-foreground: 215.4 16.3% 56.9%; - --accent: 216 34% 17%; - --accent-foreground: 210 40% 98%; - --popover: 224 71% 4%; - --popover-foreground: 215 20.2% 65.1%; - --border: 216 34% 17%; - --input: 216 34% 17%; - --card: 224 71% 4%; - --card-foreground: 213 31% 91%; - --primary: 210 40% 98%; - --primary-foreground: 222.2 47.4% 1.2%; - --secondary: 222.2 47.4% 11.2%; - --secondary-foreground: 210 40% 98%; - --destructive: 0 63% 31%; - --destructive-foreground: 210 40% 98%; - --ring: 216 34% 17%; -} - html, body { margin: 0; padding: 0; @@ -36,12 +13,6 @@ html, body { color: white; } -body { - color: var(--foreground); - background: var(--background); - font-family: Arial, Helvetica, sans-serif; -} - ::-webkit-scrollbar { width: 7px; height: 7px; @@ -64,3 +35,70 @@ body { ::-webkit-scrollbar-track { background: transparent; } + +@layer base { + :root { + --background: 0 0% 3.9%; + --foreground: 0 0% 98%; + --card: 0 0% 3.9%; + --card-foreground: 0 0% 98%; + --popover: 0 0% 3.9%; + --popover-foreground: 0 0% 98%; + --primary: 0 0% 98%; + --primary-foreground: 0 0% 9%; + --secondary: 0 0% 14.9%; + --secondary-foreground: 0 0% 98%; + --muted: 0 0% 14.9%; + --muted-foreground: 0 0% 63.9%; + --accent: 0 0% 14.9%; + --accent-foreground: 0 0% 98%; + --destructive: 0 62.8% 30.6%; + --destructive-foreground: 0 0% 98%; + --border: 0 0% 14.9%; + --input: 0 0% 14.9%; + --ring: 0 0% 83.1%; + --chart-1: 220 70% 50%; + --chart-2: 160 60% 45%; + --chart-3: 30 80% 55%; + --chart-4: 280 65% 60%; + --chart-5: 340 75% 55%; + --radius: 0.5rem; + } + .dark { + --background: 0 0% 3.9%; + --foreground: 0 0% 98%; + --card: 0 0% 3.9%; + --card-foreground: 0 0% 98%; + --popover: 0 0% 3.9%; + --popover-foreground: 0 0% 98%; + --primary: 0 0% 98%; + --primary-foreground: 0 0% 9%; + --secondary: 0 0% 14.9%; + --secondary-foreground: 0 0% 98%; + --muted: 0 0% 14.9%; + --muted-foreground: 0 0% 63.9%; + --accent: 0 0% 14.9%; + --accent-foreground: 0 0% 98%; + --destructive: 0 62.8% 30.6%; + --destructive-foreground: 0 0% 98%; + --border: 0 0% 14.9%; + --input: 0 0% 14.9%; + --ring: 0 0% 83.1%; + --chart-1: 220 70% 50%; + --chart-2: 160 60% 45%; + --chart-3: 30 80% 55%; + --chart-4: 280 65% 60%; + --chart-5: 340 75% 55%; + } +} + + + +@layer base { + * { + @apply border-border; + } + body { + @apply bg-background text-foreground; + } +} diff --git a/src/app/layout.tsx b/src/app/layout.tsx index 733c77c..b0d42a9 100644 --- a/src/app/layout.tsx +++ b/src/app/layout.tsx @@ -5,6 +5,8 @@ import RootWrapper from "@/components/RootWrapper"; import { getCurrentWindow } from "@tauri-apps/api/window"; import { TooltipProvider } from "@/components/ui/tooltip"; +import { ThemeProvider } from "@/components/theme-provider"; + const geistSans = Geist({ variable: "--font-geist-sans", subsets: ["latin"], @@ -26,13 +28,20 @@ export default function RootLayout({ children: React.ReactNode; }>) { return ( - - - - - {children} - - + + + + + {children} + + ); diff --git a/src/app/page.tsx b/src/app/page.tsx index a0c0166..87d7fce 100644 --- a/src/app/page.tsx +++ b/src/app/page.tsx @@ -41,9 +41,9 @@ export default function Home() { await window.setResizable(true); await window.setSize(new LogicalSize(1000, 600)); await window.center(); - await setIsLoading(false); - + // Redirect to welcome section + await setIsLoading(false); redirect("/welcome"); } diff --git a/src/app/welcome/page.tsx b/src/app/welcome/page.tsx index 3899bef..0f21250 100644 --- a/src/app/welcome/page.tsx +++ b/src/app/welcome/page.tsx @@ -4,26 +4,94 @@ import React, { useEffect } from "react"; import { getCurrentWindow, LogicalSize } from '@tauri-apps/api/window'; import Image from "next/image"; import { Button } from "@/components/ui/button"; +import { createProjectFile, openProjectFile } from '@/services/fileManager'; +import { useDispatch } from "react-redux"; +import { redirect } from 'next/navigation' +import { + setFileContent, + setFilePath, + setSelectedRequestIndex, + setUnsavedChanges, +} from '@/redux/slices/projectFile'; export default function WelcomePage() { const window = getCurrentWindow(); + const dispatch = useDispatch(); useEffect(() => { async function setupWindow() { await window.setTitle("Welcome to Nuts Client"); await window.setSize(new LogicalSize(300, 440)); await window.setResizable(true); - await window.center(); + // await window.center(); } setupWindow(); }, []); - return ( -
- Nuts Client Logo - + async function handleNewProject() { + const result = await createProjectFile(); + if (result !== "ERROR" && result !== "CANCELED") { + const [filePath, fileContent] = result; + dispatch(setFileContent(fileContent)); + dispatch(setFilePath(filePath)); + await redirectToExplorer(); + } + } + + async function handleOpenProject() { + const result = await openProjectFile(); + if (result === "ERROR") { + // On Error, stay on welcome page + } else if (result !== "CANCELED") { + // On Success, redirect to explorer with loaded file + const [filePath, fileContent] = result; + dispatch(setFileContent(fileContent)); + dispatch(setFilePath(filePath)); + dispatch(setUnsavedChanges(false)); + await redirectToExplorer(); + } + } + + async function redirectToExplorer() { + await window.setResizable(true); + await window.setSize(new LogicalSize(1000, 600)); + await redirect("/client/explorer"); + } + + return ( +
+ {/* Logo */} +
+ Nuts Client Logo + + {/* Buttons */} +
+ + +
+
- ); + ) } \ No newline at end of file diff --git a/src/components/sidebar/explorer/explorer.tsx b/src/components/sidebar/explorer/explorer.tsx index d828d74..cd49afb 100644 --- a/src/components/sidebar/explorer/explorer.tsx +++ b/src/components/sidebar/explorer/explorer.tsx @@ -4,12 +4,9 @@ import { IcoPlusBorder } from '@/components/Icons'; import { ask } from '@tauri-apps/plugin-dialog'; import { setFileContent, - setFilePath, setSelectedRequestIndex, - setUnsavedChanges, } from '@/redux/slices/projectFile'; import { RootState } from '@/redux/store'; -import { createProjectFile, openProjectFile } from '@/services/fileManager'; import React, { useEffect } from 'react'; import { useDispatch, useSelector } from 'react-redux'; import { @@ -43,7 +40,7 @@ interface SidebarItemProps { name: string; index: number; active?: boolean; - id: string; // sortable id + id: string; } function SidebarItem({ name, index, active, id }: SidebarItemProps) { @@ -63,7 +60,6 @@ function SidebarItem({ name, index, active, id }: SidebarItemProps) { setNodeRef, setActivatorNodeRef, transform, - transition, isDragging, } = useSortable({ id, disabled: isEditing }); @@ -226,28 +222,6 @@ export default function ExplorerSideBar() { } } - async function openFile() { - const result = await openProjectFile(); - if (result === "ERROR") { - dispatch(setFileContent(null)); - dispatch(setFilePath(null)); - } else if (result !== "CANCELED") { - const [filePath, fileContent] = result; - dispatch(setFileContent(fileContent)); - dispatch(setFilePath(filePath)); - dispatch(setUnsavedChanges(false)); - } - } - - async function createNewFile() { - const result = await createProjectFile(); - if (result !== "ERROR" && result !== "CANCELED") { - const [filePath, fileContent] = result; - dispatch(setFileContent(fileContent)); - dispatch(setFilePath(filePath)); - } - } - async function addNewRequest() { if (content.fileContent) { await dispatch(setFileContent({ @@ -269,8 +243,6 @@ export default function ExplorerSideBar() { return (
- {content.filePath ? ( - <>
{isEditingProjectName ? ( - - ) : ( -
-
No file selected
- - -
- )}
); } diff --git a/src/components/theme-provider.tsx b/src/components/theme-provider.tsx new file mode 100644 index 0000000..e018a73 --- /dev/null +++ b/src/components/theme-provider.tsx @@ -0,0 +1,11 @@ +"use client" + +import * as React from "react" +import { ThemeProvider as NextThemesProvider } from "next-themes" + +export function ThemeProvider({ + children, + ...props +}: React.ComponentProps) { + return {children} +} \ No newline at end of file diff --git a/tailwind.config.ts b/tailwind.config.ts index eade746..907eba4 100644 --- a/tailwind.config.ts +++ b/tailwind.config.ts @@ -1,89 +1,135 @@ import type { Config } from "tailwindcss"; export default { - content: [ + content: [ "./src/pages/**/*.{js,ts,jsx,tsx,mdx}", "./src/components/**/*.{js,ts,jsx,tsx,mdx}", "./src/app/**/*.{js,ts,jsx,tsx,mdx}", ], theme: { - extend: { - colors: { - orbit: { - background: "#0E0E0F", - }, - clientColors: { - windowBorder: "#2d2d2e", - windowBackground: "#252526", - card: { - background: "#1e1e1e", - border: "#2d2d2e", - }, - scrollbarThumb: { - base: "#fff", - hover: "#4a4a4a", - active: "#4a4a4a", - }, - button: { - background: "#1e1e1e", - hover: "#4a4a4a", - active: "#4a4a4a", - }, - windowSpecfic: { - titleBarCloseBtn: "#00000000", - titleBarCloseBtnHover: "#e81123", - titleBarCloseBtnActive: "#c42b1c", - titleBarOtherBtn: "#00000000", - titleBarOtherBtnHover: "#64D5EA", - titleBarOtherBtnActive: "#64D5EA", - }, - accentColor: "#64D5EA", - brand: { - red: "#FF7780", - } - }, - cshadcn: { - switchActiveBg: "#f3f3f3", - }, - shadcn: { - border: "#2d2d2e", - input: "#1e1e1e", - ring: "hsl(var(--ring))", - background: "#4a4a4a", - foreground: "hsl(var(--foreground))", - primary: { - DEFAULT: "hsl(var(--primary))", - foreground: "hsl(var(--primary-foreground))", - }, - secondary: { - DEFAULT: "hsl(var(--secondary))", - foreground: "hsl(var(--secondary-foreground))", - }, - destructive: { - DEFAULT: "hsl(var(--destructive))", - foreground: "hsl(var(--destructive-foreground))", - }, - muted: { - DEFAULT: "hsl(var(--muted))", - foreground: "hsl(var(--muted-foreground))", - }, - accent: { - DEFAULT: "#2a2a2a", - foreground: "hsl(var(--accent-foreground))", - }, - popover: { - DEFAULT: "#1e1e1e", - foreground: "hsl(var(--popover-foreground))", - }, - card: { - DEFAULT: "hsl(var(--card))", - foreground: "hsl(var(--card-foreground))", - }, - } - }, - }, + extend: { + colors: { + orbit: { + background: '#0E0E0F' + }, + clientColors: { + windowBorder: '#2d2d2e', + windowBackground: '#252526', + card: { + background: '#1e1e1e', + border: '#2d2d2e' + }, + scrollbarThumb: { + base: '#fff', + hover: '#4a4a4a', + active: '#4a4a4a' + }, + button: { + background: '#1e1e1e', + hover: '#4a4a4a', + active: '#4a4a4a' + }, + windowSpecfic: { + titleBarCloseBtn: '#00000000', + titleBarCloseBtnHover: '#e81123', + titleBarCloseBtnActive: '#c42b1c', + titleBarOtherBtn: '#00000000', + titleBarOtherBtnHover: '#64D5EA', + titleBarOtherBtnActive: '#64D5EA' + }, + accentColor: '#64D5EA', + brand: { + red: '#FF7780' + } + }, + cshadcn: { + switchActiveBg: '#f3f3f3' + }, + shadcn: { + border: '#2d2d2e', + input: '#1e1e1e', + ring: 'hsl(var(--ring))', + background: '#4a4a4a', + foreground: 'hsl(var(--foreground))', + primary: { + DEFAULT: 'hsl(var(--primary))', + foreground: 'hsl(var(--primary-foreground))' + }, + secondary: { + DEFAULT: 'hsl(var(--secondary))', + foreground: 'hsl(var(--secondary-foreground))' + }, + destructive: { + DEFAULT: 'hsl(var(--destructive))', + foreground: 'hsl(var(--destructive-foreground))' + }, + muted: { + DEFAULT: 'hsl(var(--muted))', + foreground: 'hsl(var(--muted-foreground))' + }, + accent: { + DEFAULT: '#2a2a2a', + foreground: 'hsl(var(--accent-foreground))' + }, + popover: { + DEFAULT: '#1e1e1e', + foreground: 'hsl(var(--popover-foreground))' + }, + card: { + DEFAULT: 'hsl(var(--card))', + foreground: 'hsl(var(--card-foreground))' + } + }, + background: 'hsl(var(--background))', + foreground: 'hsl(var(--foreground))', + card: { + DEFAULT: 'hsl(var(--card))', + foreground: 'hsl(var(--card-foreground))' + }, + popover: { + DEFAULT: 'hsl(var(--popover))', + foreground: 'hsl(var(--popover-foreground))' + }, + primary: { + DEFAULT: 'hsl(var(--primary))', + foreground: 'hsl(var(--primary-foreground))' + }, + secondary: { + DEFAULT: 'hsl(var(--secondary))', + foreground: 'hsl(var(--secondary-foreground))' + }, + muted: { + DEFAULT: 'hsl(var(--muted))', + foreground: 'hsl(var(--muted-foreground))' + }, + accent: { + DEFAULT: 'hsl(var(--accent))', + foreground: 'hsl(var(--accent-foreground))' + }, + destructive: { + DEFAULT: 'hsl(var(--destructive))', + foreground: 'hsl(var(--destructive-foreground))' + }, + border: 'hsl(var(--border))', + input: 'hsl(var(--input))', + ring: 'hsl(var(--ring))', + chart: { + '1': 'hsl(var(--chart-1))', + '2': 'hsl(var(--chart-2))', + '3': 'hsl(var(--chart-3))', + '4': 'hsl(var(--chart-4))', + '5': 'hsl(var(--chart-5))' + } + }, + borderRadius: { + lg: 'var(--radius)', + md: 'calc(var(--radius) - 2px)', + sm: 'calc(var(--radius) - 4px)' + } + } }, plugins: [ require('tailwind-scrollbar'), - ], + require("tailwindcss-animate") +], } satisfies Config; From 3e736302cde2eaf59963dcce964cb5d5d0d14d87 Mon Sep 17 00:00:00 2001 From: Jonas Date: Sat, 4 Oct 2025 23:02:39 +0200 Subject: [PATCH 03/18] Shad working --- components.json | 22 ++++++++++++++++++++++ src/app/globals.css | 4 ++-- src/app/welcome/page.tsx | 5 ++--- tailwind.config.ts | 1 + 4 files changed, 27 insertions(+), 5 deletions(-) create mode 100644 components.json diff --git a/components.json b/components.json new file mode 100644 index 0000000..f826c54 --- /dev/null +++ b/components.json @@ -0,0 +1,22 @@ +{ + "$schema": "https://ui.shadcn.com/schema.json", + "style": "new-york", + "rsc": true, + "tsx": true, + "tailwind": { + "config": "tailwind.config.ts", + "css": "src/app/globals.css", + "baseColor": "neutral", + "cssVariables": true, + "prefix": "" + }, + "iconLibrary": "lucide", + "aliases": { + "components": "@/components", + "utils": "@/lib/utils", + "ui": "@/components/ui", + "lib": "@/lib", + "hooks": "@/hooks" + }, + "registries": {} +} diff --git a/src/app/globals.css b/src/app/globals.css index 8974388..4487f9c 100644 --- a/src/app/globals.css +++ b/src/app/globals.css @@ -71,8 +71,8 @@ html, body { --card-foreground: 0 0% 98%; --popover: 0 0% 3.9%; --popover-foreground: 0 0% 98%; - --primary: 0 0% 98%; - --primary-foreground: 0 0% 9%; + --primary: 0, 0%, 9%; + --primary-foreground: 0 0% 100%; --secondary: 0 0% 14.9%; --secondary-foreground: 0 0% 98%; --muted: 0 0% 14.9%; diff --git a/src/app/welcome/page.tsx b/src/app/welcome/page.tsx index 0f21250..4763bfa 100644 --- a/src/app/welcome/page.tsx +++ b/src/app/welcome/page.tsx @@ -78,14 +78,13 @@ export default function WelcomePage() { {/* Buttons */}
- +
{children} diff --git a/src/app/client/explorer/page.tsx b/src/app/client/explorer/page.tsx index 9817214..4b60d6d 100644 --- a/src/app/client/explorer/page.tsx +++ b/src/app/client/explorer/page.tsx @@ -1,10 +1,21 @@ "use client"; -import { ResizableHandle, ResizablePanel, ResizablePanelGroup } from "@/components/ui/resizable"; +import { + ResizableHandle, + ResizablePanel, + ResizablePanelGroup, +} from "@/components/ui/resizable"; import { RootState } from "@/redux/store"; import { useMemo, useCallback, useRef, useEffect, useState } from "react"; import { useDispatch, useSelector } from "react-redux"; -import { setAuthenticationType, setFileContent, setLastResponse, setNatsServerURL, setNATSToken, setUsernamePassword } from "@/redux/slices/projectFile"; +import { + setAuthenticationType, + setFileContent, + setLastResponse, + setNatsServerURL, + setNATSToken, + setUsernamePassword, +} from "@/redux/slices/projectFile"; import { setClientSettings } from "@/redux/slices/windowProperties"; import { NatsAuth, sendNatsMessage } from "@/services/natsWrapper"; import Logger from "@/services/logging"; @@ -12,16 +23,31 @@ import { setTitle } from "@/redux/slices/windowProperties"; import { IcoPlusBorder } from "@/components/Icons"; import AuthDialog from "@/components/AuthDialog"; import * as utils from "@/services/utils"; -import { Badge } from "@/components/ui/badge" +import { Badge } from "@/components/ui/badge"; import { AuthTypes } from "@/types/Auth"; import Editor, { useMonaco } from "@monaco-editor/react"; +import { redirect } from "next/navigation"; +import { Button } from "@/components/ui/button"; +import { + handleNewProject, + handleOpenProject, +} from "@/components/titlebar/utils"; export default function Page() { const content = useSelector((state: RootState) => state.projectFile); - const selectedRequest = useSelector((state: RootState) => state.projectFile.fileContent?.requests[state.projectFile.selectedRequestIndex]); - const settings = useSelector((state: RootState) => state.windowProperties.clientSettings); + const selectedRequest = useSelector( + (state: RootState) => + state.projectFile.fileContent?.requests[ + state.projectFile.selectedRequestIndex + ] + ); + const settings = useSelector( + (state: RootState) => state.windowProperties.clientSettings + ); const dispatch = useDispatch(); - const [natsUrl, setNatsUrl] = useState(content.fileContent?.requests[content.selectedRequestIndex]?.url || ""); + const [natsUrl, setNatsUrl] = useState( + content.fileContent?.requests[content.selectedRequestIndex]?.url || "" + ); const [disableAuthPoupup, setDisableAuthPopup] = useState(false); const textareaRef = useRef(null); const saveId = "explorercontent"; @@ -38,10 +64,9 @@ export default function Page() { ); useEffect(() => { - dispatch(setTitle("NUTS - " + content.fileContent?.name)); + dispatch(setTitle("Orbit - " + content.fileContent?.name)); }, [content.selectedRequestIndex]); - // Function to format JSON const formatJson = (jsonString: string) => { try { @@ -54,28 +79,38 @@ export default function Page() { // Memoized onChange handler const handleChange = useCallback( - (e: React.ChangeEvent, key: string) => { + ( + e: React.ChangeEvent, + key: string + ) => { if (selectedRequest && content.fileContent) { const lastResponse = selectedRequest.lastResponse; dispatch( setFileContent({ ...content.fileContent, - requests: content.fileContent.requests.map((request: any, index: any) => { - if (index === content.selectedRequestIndex) { - return { - ...selectedRequest, - [key]: e.target.value || "", - }; + requests: content.fileContent.requests.map( + (request: any, index: any) => { + if (index === content.selectedRequestIndex) { + return { + ...selectedRequest, + [key]: e.target.value || "", + }; + } + return request; } - return request; - }), + ), }) ); dispatch(setLastResponse(lastResponse || "")); // More of a hack, but it works and i don't care enough to fix it - it's 2:43am } }, - [dispatch, content.fileContent, selectedRequest, content.selectedRequestIndex] + [ + dispatch, + content.fileContent, + selectedRequest, + content.selectedRequestIndex, + ] ); const handleAutoResize = () => { @@ -102,7 +137,7 @@ export default function Page() { const url = utils.parseNatsUrl(natsUrl); const isDisabled = !!(url.token || (url.username && url.password)); - // + // if (isDisabled) { dispatch(setAuthenticationType(AuthTypes.NONE)); } @@ -113,8 +148,29 @@ export default function Page() { // If no file is opened, show the message if (!content.fileContent) { return ( -
-
Please open a file to view its contents
+
+
+

(・_・;)

+

No Project Opened

+
+
+ + +
); } @@ -122,14 +178,14 @@ export default function Page() { // If no request is selected, show the message if (!selectedRequest || !content.fileContent) { return ( -
-
-          Ready to get started? (ง •̀_•́)ง
-        
-
-          Select a request from the sidebar or create a new one by clicking .
-        
- +
+
+

(・_・;)

+

No Request Selected

+

+ Select or create a request from the sidebar +

+
); } @@ -144,23 +200,28 @@ export default function Page() { auth = { authType: AuthTypes.TOKEN, token: selectedRequest.authentication.token || "NO-TOKEN-PROVIDED", - } + }; break; case AuthTypes.USERPASSWORD: auth = { authType: AuthTypes.USERPASSWORD, - username: selectedRequest.authentication.usernamepassword?.username || "NO-USERNAME-PROVIDED", - password: selectedRequest.authentication.usernamepassword?.password || "NO-PASSWORD-PROVIDED", - } + username: + selectedRequest.authentication.usernamepassword?.username || + "NO-USERNAME-PROVIDED", + password: + selectedRequest.authentication.usernamepassword?.password || + "NO-PASSWORD-PROVIDED", + }; break; case AuthTypes.NKEYS: auth = { authType: AuthTypes.NKEYS, jwt: selectedRequest.authentication.nkeys?.jwt || "NO-JWT-PROVIDED", - seed: selectedRequest.authentication.nkeys?.seed || "NO-SEED-PROVIDED", - } + seed: + selectedRequest.authentication.nkeys?.seed || "NO-SEED-PROVIDED", + }; break; case AuthTypes.NONE: default: @@ -183,13 +244,27 @@ export default function Page() { } } + // Render the main content return ( - - + + + {/* NATS URL Input and Auth Button */}

NATS Server

{selectedRequest.authentication?.type !== "NONE" && ( - Auth: {selectedRequest.authentication?.type} + + Auth: {selectedRequest.authentication?.type} + )}
@@ -207,13 +282,28 @@ export default function Page() { selectedRequest={selectedRequest} disabled={disableAuthPoupup} /> -
- - - - + + + {/* Topic, Payload, and Response Sections */} + +

Topic

@@ -225,27 +315,28 @@ export default function Page() { />
-

Payload

+

Payload

{settings.useMonacoEditor ? ( { - const syntheticEvent = { - target: { value: value ?? "" } - } as React.ChangeEvent; - handleChange(syntheticEvent, "data"); - }} - theme="vs-dark" - options={{ - minimap: { enabled: false }, - lineNumbers: "on", - lineNumbersMinChars: 2, - fontSize: 14, - automaticLayout: true, - }}/> + className="p-3" + height="350px" + defaultLanguage={settings.monacoEditorLanguage || "plain"} + value={selectedRequest?.data || ""} + onChange={(value) => { + const syntheticEvent = { + target: { value: value ?? "" }, + } as React.ChangeEvent; + handleChange(syntheticEvent, "data"); + }} + theme="vs-dark" + options={{ + minimap: { enabled: false }, + lineNumbers: "on", + lineNumbersMinChars: 2, + fontSize: 14, + automaticLayout: true, + }} + /> ) : (