From ce577c107dfb7989d5be9238eea4c7fc91054de0 Mon Sep 17 00:00:00 2001 From: Van Buren Date: Mon, 1 Dec 2025 10:13:05 -0500 Subject: [PATCH 01/12] feat: toast --- client/package.json | 2 + client/pnpm-lock.yaml | 28 +++++ client/src/App.tsx | 4 + .../src/components/base/MessageSnackbar.tsx | 101 ------------------ client/src/components/base/index.ts | 1 - client/src/components/ui/sonner.tsx | 28 +++++ client/src/contexts/AppContext.tsx | 40 ++----- .../src/pages/layouts/InitializedLayout.tsx | 7 +- 8 files changed, 70 insertions(+), 141 deletions(-) delete mode 100644 client/src/components/base/MessageSnackbar.tsx create mode 100644 client/src/components/ui/sonner.tsx diff --git a/client/package.json b/client/package.json index 1fdc78f..49de548 100644 --- a/client/package.json +++ b/client/package.json @@ -38,10 +38,12 @@ "class-variance-authority": "^0.7.1", "clsx": "^2.1.1", "lucide-react": "^0.553.0", + "next-themes": "^0.4.6", "postcss": "^8.5.6", "react": "^18.3.1", "react-dom": "^18.3.1", "react-router-dom": "^7.9.6", + "sonner": "^2.0.7", "tailwind-merge": "^3.4.0", "tailwindcss": "^4.1.17", "tw-animate-css": "^1.4.0" diff --git a/client/pnpm-lock.yaml b/client/pnpm-lock.yaml index 1d4505c..a64b800 100644 --- a/client/pnpm-lock.yaml +++ b/client/pnpm-lock.yaml @@ -104,6 +104,9 @@ importers: lucide-react: specifier: ^0.553.0 version: 0.553.0(react@18.3.1) + next-themes: + specifier: ^0.4.6 + version: 0.4.6(react-dom@18.3.1(react@18.3.1))(react@18.3.1) postcss: specifier: ^8.5.6 version: 8.5.6 @@ -116,6 +119,9 @@ importers: react-router-dom: specifier: ^7.9.6 version: 7.9.6(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + sonner: + specifier: ^2.0.7 + version: 2.0.7(react-dom@18.3.1(react@18.3.1))(react@18.3.1) tailwind-merge: specifier: ^3.4.0 version: 3.4.0 @@ -1532,6 +1538,12 @@ packages: engines: {node: ^10 || ^12 || ^13.7 || ^14 || >=15.0.1} hasBin: true + next-themes@0.4.6: + resolution: {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-releases@2.0.27: resolution: {integrity: sha512-nmh3lCkYZ3grZvqcCH+fjmQ7X+H0OeZgP40OierEaAptX4XofMh5kwNbWh7lBduUzCcV/8kZ+NDLCwm2iorIlA==} @@ -1628,6 +1640,12 @@ packages: set-cookie-parser@2.7.2: resolution: {integrity: sha512-oeM1lpU/UvhTxw+g3cIfxXHyJRc/uidd3yK1P242gzHds0udQBYzs3y8j4gCCW+ZJ7ad0yctld8RYO+bdurlvw==} + sonner@2.0.7: + resolution: {integrity: sha512-W6ZN4p58k8aDKA4XPcx2hpIQXBRAgyiWVkYhT7CvK6D3iAu7xjvVyhQHg2/iaKJZ1XVJ4r7XuwGL+WGEK37i9w==} + peerDependencies: + react: ^18.0.0 || ^19.0.0 || ^19.0.0-rc + react-dom: ^18.0.0 || ^19.0.0 || ^19.0.0-rc + source-map-js@1.2.1: resolution: {integrity: sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==} engines: {node: '>=0.10.0'} @@ -3033,6 +3051,11 @@ snapshots: nanoid@3.3.11: {} + next-themes@0.4.6(react-dom@18.3.1(react@18.3.1))(react@18.3.1): + dependencies: + react: 18.3.1 + react-dom: 18.3.1(react@18.3.1) + node-releases@2.0.27: {} normalize-range@0.1.2: {} @@ -3138,6 +3161,11 @@ snapshots: set-cookie-parser@2.7.2: {} + sonner@2.0.7(react-dom@18.3.1(react@18.3.1))(react@18.3.1): + dependencies: + react: 18.3.1 + react-dom: 18.3.1(react@18.3.1) + source-map-js@1.2.1: {} source-map-support@0.5.21: diff --git a/client/src/App.tsx b/client/src/App.tsx index 8809b9f..b730c71 100644 --- a/client/src/App.tsx +++ b/client/src/App.tsx @@ -1,5 +1,6 @@ import { Env } from "@semoss/sdk"; import { InsightProvider } from "@semoss/sdk/react"; +import { Toaster } from "sonner"; import { AppContextProvider } from "./contexts"; import { Router } from "./pages"; @@ -26,6 +27,9 @@ export const App = () => { This component is custom to this project, and can be edited in Router.tsx */} + + {/* Toaster for displaying toast notifications */} + ); }; diff --git a/client/src/components/base/MessageSnackbar.tsx b/client/src/components/base/MessageSnackbar.tsx deleted file mode 100644 index afffd87..0000000 --- a/client/src/components/base/MessageSnackbar.tsx +++ /dev/null @@ -1,101 +0,0 @@ -import { AlertCircle, AlertTriangle, CheckCircle, Info, X } from "lucide-react"; -import { useEffect } from "react"; -import { Alert } from "@/components/ui/alert"; -import { Button } from "@/components/ui/button"; -import { useAppContext } from "@/contexts"; - -export interface MessageSnackbarProps { - message: string; - severity: "success" | "error" | "info" | "warning"; - open: boolean; -} - -/** - * Renders a snackbar for displaying messages, typically used for error or success notifications - * - * @component - */ -export const MessageSnackbar = ({ - open, - severity, - message, -}: MessageSnackbarProps) => { - const { setMessageSnackbarProps } = useAppContext(); - - /** - * Functions - */ - const handleClose = () => { - setMessageSnackbarProps((prev) => ({ - ...prev, - open: false, - })); - }; - - // Auto close after 5 seconds - useEffect(() => { - if (open) { - const timer = setTimeout(() => { - setMessageSnackbarProps((prev) => ({ - ...prev, - open: false, - })); - }, 5000); - return () => clearTimeout(timer); - } - }, [open, setMessageSnackbarProps]); - - const getIcon = () => { - switch (severity) { - case "success": - return ; - case "error": - return ; - case "warning": - return ; - default: - return ; - } - }; - - const getVariant = () => { - switch (severity) { - case "error": - return "destructive" as const; - default: - return "default" as const; - } - }; - - const getColors = () => { - switch (severity) { - case "success": - return "border-green-500/50 text-green-600 bg-green-50 dark:border-green-500 [&>svg]:text-green-600"; - case "warning": - return "border-yellow-500/50 text-yellow-600 bg-yellow-50 dark:border-yellow-500 [&>svg]:text-yellow-600"; - case "info": - return "border-blue-500/50 text-blue-600 bg-blue-50 dark:border-blue-500 [&>svg]:text-blue-600"; - default: - return ""; - } - }; - - if (!open) return null; - - return ( -
- - {getIcon()} -
{message}
- -
-
- ); -}; diff --git a/client/src/components/base/index.ts b/client/src/components/base/index.ts index 75b5cfc..65eb876 100644 --- a/client/src/components/base/index.ts +++ b/client/src/components/base/index.ts @@ -1,3 +1,2 @@ export * from "./LoadingScreen"; export * from "./MainNavigation"; -export * from "./MessageSnackbar"; diff --git a/client/src/components/ui/sonner.tsx b/client/src/components/ui/sonner.tsx new file mode 100644 index 0000000..1e5bfde --- /dev/null +++ b/client/src/components/ui/sonner.tsx @@ -0,0 +1,28 @@ +import { useTheme } from "next-themes"; +import { Toaster as Sonner } from "sonner"; + +type ToasterProps = React.ComponentProps; + +const Toaster = ({ ...props }: ToasterProps) => { + const { theme = "system" } = useTheme(); + + return ( + + ); +}; + +export { Toaster }; diff --git a/client/src/contexts/AppContext.tsx b/client/src/contexts/AppContext.tsx index 89e598b..453a78a 100644 --- a/client/src/contexts/AppContext.tsx +++ b/client/src/contexts/AppContext.tsx @@ -6,15 +6,13 @@ import { import { useInsight } from "@semoss/sdk/react"; import { createContext, - type Dispatch, type PropsWithChildren, - type SetStateAction, useCallback, useContext, useEffect, useState, } from "react"; -import type { MessageSnackbarProps } from "@/components"; +import { toast } from "sonner"; import { useLoadingState } from "@/hooks"; import type { MCPToolRequest } from "@/types"; @@ -33,8 +31,6 @@ export interface AppContextType { userLoginName: string; isAppDataLoading: boolean; exampleStateData?: number; - messageSnackbarProps: MessageSnackbarProps; - setMessageSnackbarProps: Dispatch>; tool: MCPToolRequest; } @@ -72,12 +68,6 @@ export const AppContextProvider = ({ children }: PropsWithChildren) => { const [isAppDataLoading, setIsAppDataLoading] = useLoadingState(true); const [userLoginName, setUserLoginName] = useState(null); const [tool, setTool] = useState(null); - const [messageSnackbarProps, setMessageSnackbarProps] = - useState({ - open: false, - message: "", - severity: "info", - }); // Example state variable to store the result of a pixel operation const [exampleStateData, setExampleStateData] = useState(); @@ -117,19 +107,11 @@ export const AppContextProvider = ({ children }: PropsWithChildren) => { .join(", "), ); if (successMessage) { - setMessageSnackbarProps({ - open: true, - message: successMessage, - severity: "success", - }); + toast.success(successMessage); } return response.pixelReturn[0].output; } catch (error) { - setMessageSnackbarProps({ - open: true, - message: `${error.message ?? "Error during operation"}`, - severity: "error", - }); + toast.error(`${error.message ?? "Error during operation"}`); throw error; } }, @@ -149,11 +131,7 @@ export const AppContextProvider = ({ children }: PropsWithChildren) => { throw new Error("No output from MCP tool"); return response.output; } catch (error) { - setMessageSnackbarProps({ - open: true, - message: `${error.message ?? "Error during operation"}`, - severity: "error", - }); + toast.error(`${error.message ?? "Error during operation"}`); throw error; } }, @@ -244,11 +222,9 @@ export const AppContextProvider = ({ children }: PropsWithChildren) => { ); } catch (e) { // If any loader fails, display an error message - setMessageSnackbarProps({ - open: true, - message: `Error initializing app data${e.message ? `: ${e.message}` : ""}`, - severity: "error", - }); + toast.error( + `Error initializing app data${e.message ? `: ${e.message}` : ""}`, + ); } }; @@ -273,8 +249,6 @@ export const AppContextProvider = ({ children }: PropsWithChildren) => { runMCPTool, exampleStateData, isAppDataLoading, - messageSnackbarProps, - setMessageSnackbarProps, login, logout, userLoginName, diff --git a/client/src/pages/layouts/InitializedLayout.tsx b/client/src/pages/layouts/InitializedLayout.tsx index 2e42542..c00485a 100644 --- a/client/src/pages/layouts/InitializedLayout.tsx +++ b/client/src/pages/layouts/InitializedLayout.tsx @@ -1,7 +1,6 @@ import { useInsight } from "@semoss/sdk/react"; import { Outlet } from "react-router-dom"; -import { LoadingScreen, MainNavigation, MessageSnackbar } from "@/components"; -import { useAppContext } from "@/contexts"; +import { LoadingScreen, MainNavigation } from "@/components"; /** * Renders a loading wheel if SEMOSS is not initialized. @@ -13,16 +12,12 @@ export const InitializedLayout = () => { * Library hooks */ const { isInitialized } = useInsight(); - const { messageSnackbarProps } = useAppContext(); return (
{/* Allow users to navigate around the app */} - {/* Show message snackbar with notifications */} - - {isInitialized ? ( // If initialized, set up padding and scroll
From cdf96139bce5718a4730425a3f8fedadce0744a1 Mon Sep 17 00:00:00 2001 From: Van Buren Date: Mon, 1 Dec 2025 10:27:12 -0500 Subject: [PATCH 02/12] feat: up --- biome.json | 2 +- client/package.json | 4 +- client/pnpm-lock.yaml | 64 +++++++------- .../components/examples/ExampleComponent.tsx | 12 +++ client/src/contexts/AppContext.tsx | 15 +--- client/src/types.d.ts | 17 ---- package.json | 2 +- pnpm-lock.yaml | 84 +++++++++---------- 8 files changed, 91 insertions(+), 109 deletions(-) diff --git a/biome.json b/biome.json index c96170e..56f12d2 100644 --- a/biome.json +++ b/biome.json @@ -1,5 +1,5 @@ { - "$schema": "https://biomejs.dev/schemas/2.3.7/schema.json", + "$schema": "https://biomejs.dev/schemas/2.3.8/schema.json", "vcs": { "enabled": true, "clientKind": "git", diff --git a/client/package.json b/client/package.json index 49de548..66d8826 100644 --- a/client/package.json +++ b/client/package.json @@ -32,7 +32,7 @@ "@radix-ui/react-toggle": "^1.1.10", "@radix-ui/react-toggle-group": "^1.1.11", "@radix-ui/react-tooltip": "^1.2.8", - "@semoss/sdk": "1.0.0-beta.31", + "@semoss/sdk": "1.0.0-beta.32", "@tailwindcss/postcss": "^4.1.17", "autoprefixer": "^10.4.22", "class-variance-authority": "^0.7.1", @@ -54,6 +54,6 @@ "@types/react-dom": "^18.3.7", "@vitejs/plugin-react": "^5.1.1", "typescript": "^5.9.3", - "vite": "^7.2.4" + "vite": "^7.2.6" } } diff --git a/client/pnpm-lock.yaml b/client/pnpm-lock.yaml index a64b800..a2fc5d8 100644 --- a/client/pnpm-lock.yaml +++ b/client/pnpm-lock.yaml @@ -87,8 +87,8 @@ importers: specifier: ^1.2.8 version: 1.2.8(@types/react-dom@18.3.7(@types/react@18.3.27))(@types/react@18.3.27)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) '@semoss/sdk': - specifier: 1.0.0-beta.31 - version: 1.0.0-beta.31(react@18.3.1) + specifier: 1.0.0-beta.32 + version: 1.0.0-beta.32(react@18.3.1) '@tailwindcss/postcss': specifier: ^4.1.17 version: 4.1.17 @@ -143,13 +143,13 @@ importers: version: 18.3.7(@types/react@18.3.27) '@vitejs/plugin-react': specifier: ^5.1.1 - version: 5.1.1(vite@7.2.4(@types/node@24.10.1)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.0)) + version: 5.1.1(vite@7.2.6(@types/node@24.10.1)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.0)) typescript: specifier: ^5.9.3 version: 5.9.3 vite: - specifier: ^7.2.4 - version: 7.2.4(@types/node@24.10.1)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.0) + specifier: ^7.2.6 + version: 7.2.6(@types/node@24.10.1)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.0) packages: @@ -1186,8 +1186,8 @@ packages: cpu: [x64] os: [win32] - '@semoss/sdk@1.0.0-beta.31': - resolution: {integrity: sha512-JIo4TvJvYhkw1aa3DsQ1rEC4zJXF9Qp7ImcdyrRTZpTXC1mxzFB0tqUC4hCGSwrbXN79q20Qr+nxo2fyO7H2Rg==} + '@semoss/sdk@1.0.0-beta.32': + resolution: {integrity: sha512-645fPMDQZxwbmzwXHlJi/JhxHT/upMRQHpHd9wrm3cfgdfjvG5MDDdPGGUlhk5xFPKANUsjnTx8WNQv9QzqvVQ==} peerDependencies: react: 18.3.1 peerDependenciesMeta: @@ -1333,8 +1333,8 @@ packages: peerDependencies: postcss: ^8.1.0 - baseline-browser-mapping@2.8.31: - resolution: {integrity: sha512-a28v2eWrrRWPpJSzxc+mKwm0ZtVx/G8SepdQZDArnXYU/XS+IF6mp8aB/4E+hH1tyGCoDo3KlUCdlSxGDsRkAw==} + baseline-browser-mapping@2.8.32: + resolution: {integrity: sha512-OPz5aBThlyLFgxyhdwf/s2+8ab3OvT7AdTNvKHBwpXomIYeXqpUUuT8LrdtxZSsWJ4R4CU1un4XGh5Ez3nlTpw==} hasBin: true browserslist@4.28.0: @@ -1361,8 +1361,8 @@ packages: convert-source-map@2.0.0: resolution: {integrity: sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==} - cookie@1.0.2: - resolution: {integrity: sha512-9Kr/j4O16ISv8zBBhJoi4bXOYNTkFLOqSL3UDB0njXxCXNezjeyVrJyGOWtgfs/q2km1gwBcfH8q1yEGoMYunA==} + cookie@1.1.1: + resolution: {integrity: sha512-ei8Aos7ja0weRpFzJnEA9UHJ/7XQmqglbRwnf2ATjcB9Wq874VKH9kfjjirM6UhU2/E5fFYadylyhFldcqSidQ==} engines: {node: '>=18'} csstype@3.2.3: @@ -1384,8 +1384,8 @@ packages: detect-node-es@1.1.0: resolution: {integrity: sha512-ypdmJU/TbBby2Dxibuv7ZLW3Bs1QEmM7nHjEANfohJLvE0XVujisn1qPJcZxg+qDucsr+bP6fLD1rPS3AhJ7EQ==} - electron-to-chromium@1.5.260: - resolution: {integrity: sha512-ov8rBoOBhVawpzdre+Cmz4FB+y66Eqrk6Gwqd8NGxuhv99GQ8XqMAr351KEkOt7gukXWDg6gJWEMKgL2RLMPtA==} + electron-to-chromium@1.5.262: + resolution: {integrity: sha512-NlAsMteRHek05jRUxUR0a5jpjYq9ykk6+kO0yRaMi5moe7u0fVIOeQ3Y30A8dIiWFBNUoQGi1ljb1i5VtS9WQQ==} enhanced-resolve@5.18.3: resolution: {integrity: sha512-d4lC8xfavMeBjzGr2vECC3fsGXziXZQyJxD868h2M/mBI3PwAuODxAkLkq5HYuvrPYcUtiLzsTo8U3PgX3Ocww==} @@ -1584,8 +1584,8 @@ packages: '@types/react': optional: true - react-remove-scroll@2.7.1: - resolution: {integrity: sha512-HpMh8+oahmIdOuS5aFKKY6Pyog+FNaZV/XyJOq7b4YFwsFHe5yYfdbIalI4k3vU2nSDql7YskmUseHsRrJqIPA==} + react-remove-scroll@2.7.2: + resolution: {integrity: sha512-Iqb9NjCCTt6Hf+vOdNIZGdTiH1QSqr27H/Ek9sv/a97gfueI/5h1s3yRi1nngzMUaOOToin5dI1dXKdXiF+u0Q==} engines: {node: '>=10'} peerDependencies: '@types/react': '*' @@ -1721,8 +1721,8 @@ packages: peerDependencies: react: ^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 - vite@7.2.4: - resolution: {integrity: sha512-NL8jTlbo0Tn4dUEXEsUg8KeyG/Lkmc4Fnzb8JXN/Ykm9G4HNImjtABMJgkQoVjOBN/j2WAwDTRytdqJbZsah7w==} + vite@7.2.6: + resolution: {integrity: sha512-tI2l/nFHC5rLh7+5+o7QjKjSR04ivXDF4jcgV0f/bTQ+OJiITy5S6gaynVsEM+7RqzufMnVbIon6Sr5x1SDYaQ==} engines: {node: ^20.19.0 || >=22.12.0} hasBin: true peerDependencies: @@ -2159,7 +2159,7 @@ snapshots: aria-hidden: 1.2.6 react: 18.3.1 react-dom: 18.3.1(react@18.3.1) - react-remove-scroll: 2.7.1(@types/react@18.3.27)(react@18.3.1) + react-remove-scroll: 2.7.2(@types/react@18.3.27)(react@18.3.1) optionalDependencies: '@types/react': 18.3.27 '@types/react-dom': 18.3.7(@types/react@18.3.27) @@ -2269,7 +2269,7 @@ snapshots: aria-hidden: 1.2.6 react: 18.3.1 react-dom: 18.3.1(react@18.3.1) - react-remove-scroll: 2.7.1(@types/react@18.3.27)(react@18.3.1) + react-remove-scroll: 2.7.2(@types/react@18.3.27)(react@18.3.1) optionalDependencies: '@types/react': 18.3.27 '@types/react-dom': 18.3.7(@types/react@18.3.27) @@ -2332,7 +2332,7 @@ snapshots: aria-hidden: 1.2.6 react: 18.3.1 react-dom: 18.3.1(react@18.3.1) - react-remove-scroll: 2.7.1(@types/react@18.3.27)(react@18.3.1) + react-remove-scroll: 2.7.2(@types/react@18.3.27)(react@18.3.1) optionalDependencies: '@types/react': 18.3.27 '@types/react-dom': 18.3.7(@types/react@18.3.27) @@ -2479,7 +2479,7 @@ snapshots: aria-hidden: 1.2.6 react: 18.3.1 react-dom: 18.3.1(react@18.3.1) - react-remove-scroll: 2.7.1(@types/react@18.3.27)(react@18.3.1) + react-remove-scroll: 2.7.2(@types/react@18.3.27)(react@18.3.1) optionalDependencies: '@types/react': 18.3.27 '@types/react-dom': 18.3.7(@types/react@18.3.27) @@ -2743,7 +2743,7 @@ snapshots: '@rollup/rollup-win32-x64-msvc@4.53.3': optional: true - '@semoss/sdk@1.0.0-beta.31(react@18.3.1)': + '@semoss/sdk@1.0.0-beta.32(react@18.3.1)': optionalDependencies: react: 18.3.1 @@ -2854,7 +2854,7 @@ snapshots: '@types/prop-types': 15.7.15 csstype: 3.2.3 - '@vitejs/plugin-react@5.1.1(vite@7.2.4(@types/node@24.10.1)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.0))': + '@vitejs/plugin-react@5.1.1(vite@7.2.6(@types/node@24.10.1)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.0))': dependencies: '@babel/core': 7.28.5 '@babel/plugin-transform-react-jsx-self': 7.27.1(@babel/core@7.28.5) @@ -2862,7 +2862,7 @@ snapshots: '@rolldown/pluginutils': 1.0.0-beta.47 '@types/babel__core': 7.20.5 react-refresh: 0.18.0 - vite: 7.2.4(@types/node@24.10.1)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.0) + vite: 7.2.6(@types/node@24.10.1)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.0) transitivePeerDependencies: - supports-color @@ -2883,13 +2883,13 @@ snapshots: postcss: 8.5.6 postcss-value-parser: 4.2.0 - baseline-browser-mapping@2.8.31: {} + baseline-browser-mapping@2.8.32: {} browserslist@4.28.0: dependencies: - baseline-browser-mapping: 2.8.31 + baseline-browser-mapping: 2.8.32 caniuse-lite: 1.0.30001757 - electron-to-chromium: 1.5.260 + electron-to-chromium: 1.5.262 node-releases: 2.0.27 update-browserslist-db: 1.1.4(browserslist@4.28.0) @@ -2909,7 +2909,7 @@ snapshots: convert-source-map@2.0.0: {} - cookie@1.0.2: {} + cookie@1.1.1: {} csstype@3.2.3: {} @@ -2921,7 +2921,7 @@ snapshots: detect-node-es@1.1.0: {} - electron-to-chromium@1.5.260: {} + electron-to-chromium@1.5.262: {} enhanced-resolve@5.18.3: dependencies: @@ -3088,7 +3088,7 @@ snapshots: optionalDependencies: '@types/react': 18.3.27 - react-remove-scroll@2.7.1(@types/react@18.3.27)(react@18.3.1): + react-remove-scroll@2.7.2(@types/react@18.3.27)(react@18.3.1): dependencies: react: 18.3.1 react-remove-scroll-bar: 2.3.8(@types/react@18.3.27)(react@18.3.1) @@ -3107,7 +3107,7 @@ snapshots: react-router@7.9.6(react-dom@18.3.1(react@18.3.1))(react@18.3.1): dependencies: - cookie: 1.0.2 + cookie: 1.1.1 react: 18.3.1 set-cookie-parser: 2.7.2 optionalDependencies: @@ -3229,7 +3229,7 @@ snapshots: dependencies: react: 18.3.1 - vite@7.2.4(@types/node@24.10.1)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.0): + vite@7.2.6(@types/node@24.10.1)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.0): dependencies: esbuild: 0.25.12 fdir: 6.5.0(picomatch@4.0.3) diff --git a/client/src/components/examples/ExampleComponent.tsx b/client/src/components/examples/ExampleComponent.tsx index 224e57a..c3cb71e 100644 --- a/client/src/components/examples/ExampleComponent.tsx +++ b/client/src/components/examples/ExampleComponent.tsx @@ -1,3 +1,4 @@ +import { useInsight } from "@semoss/sdk/react"; import { useState } from "react"; import { Input } from "@/components/ui/input"; import { useLoadingPixel } from "@/hooks"; @@ -16,6 +17,7 @@ export const ExampleComponent = () => { /** * Library hooks */ + const { tool } = useInsight(); const [helloUserResponse, isLoadingHelloUser] = useLoadingPixel("HelloUser()"); const [callPythonResponse, isLoadingCallPython] = useLoadingPixel( @@ -68,6 +70,16 @@ export const ExampleComponent = () => { +

+ Tool call sent from Playground: +

+
    +
  • +

    + {tool ? JSON.stringify(tool) : "No tool call sent"} +

    +
  • +
); }; diff --git a/client/src/contexts/AppContext.tsx b/client/src/contexts/AppContext.tsx index 453a78a..70c5d2c 100644 --- a/client/src/contexts/AppContext.tsx +++ b/client/src/contexts/AppContext.tsx @@ -1,8 +1,4 @@ -import { - getSystemConfig, - Insight, - runPixel as runPixelSemossSdk, -} from "@semoss/sdk"; +import { getSystemConfig, runPixel as runPixelSemossSdk } from "@semoss/sdk"; import { useInsight } from "@semoss/sdk/react"; import { createContext, @@ -14,7 +10,6 @@ import { } from "react"; import { toast } from "sonner"; import { useLoadingState } from "@/hooks"; -import type { MCPToolRequest } from "@/types"; export interface AppContextType { runPixel: ( @@ -31,7 +26,6 @@ export interface AppContextType { userLoginName: string; isAppDataLoading: boolean; exampleStateData?: number; - tool: MCPToolRequest; } const AppContext = createContext(undefined); @@ -67,7 +61,6 @@ export const AppContextProvider = ({ children }: PropsWithChildren) => { */ const [isAppDataLoading, setIsAppDataLoading] = useLoadingState(true); const [userLoginName, setUserLoginName] = useState(null); - const [tool, setTool] = useState(null); // Example state variable to store the result of a pixel operation const [exampleStateData, setExampleStateData] = useState(); @@ -198,11 +191,6 @@ export const AppContextProvider = ({ children }: PropsWithChildren) => { }, setter: (response) => setExampleStateData(response), } satisfies LoadSetPair, - { - loader: async () => await new Insight().initialize(), - // Optionally handle the result or remove the setter if not needed - setter: (initConfig) => setTool(initConfig.tool), - } satisfies LoadSetPair<{ tool: MCPToolRequest }>, ]; // Execute all loaders in parallel and wait for them all to complete @@ -252,7 +240,6 @@ export const AppContextProvider = ({ children }: PropsWithChildren) => { login, logout, userLoginName, - tool, }} > {children} diff --git a/client/src/types.d.ts b/client/src/types.d.ts index 3216278..e69de29 100644 --- a/client/src/types.d.ts +++ b/client/src/types.d.ts @@ -1,17 +0,0 @@ -export interface MCPToolRequest { - type: "MCP"; - message: string; - id: string; - name: string; - parameters: Record; - roomId: string; -} - -export interface MCPToolResponse { - type: "MCP"; - message: string; - id: string; - name: string; - response: string; - roomId: string; -} diff --git a/package.json b/package.json index 9dd6b70..5efc243 100644 --- a/package.json +++ b/package.json @@ -6,7 +6,7 @@ "javadoc": "mvn clean javadoc:javadoc && mvn site && pnpm exec http-server target/site/apidocs -p 1227 -a localhost -o" }, "devDependencies": { - "@biomejs/biome": "2.3.7", + "@biomejs/biome": "2.3.8", "http-server": "^14.1.1", "husky": "^9.1.7", "lint-staged": "^16.2.7" diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 8a95e27..e32c807 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -9,8 +9,8 @@ importers: .: devDependencies: '@biomejs/biome': - specifier: 2.3.7 - version: 2.3.7 + specifier: 2.3.8 + version: 2.3.8 http-server: specifier: ^14.1.1 version: 14.1.1 @@ -23,55 +23,55 @@ importers: packages: - '@biomejs/biome@2.3.7': - resolution: {integrity: sha512-CTbAS/jNAiUc6rcq94BrTB8z83O9+BsgWj2sBCQg9rD6Wkh2gjfR87usjx0Ncx0zGXP1NKgT7JNglay5Zfs9jw==} + '@biomejs/biome@2.3.8': + resolution: {integrity: sha512-Qjsgoe6FEBxWAUzwFGFrB+1+M8y/y5kwmg5CHac+GSVOdmOIqsAiXM5QMVGZJ1eCUCLlPZtq4aFAQ0eawEUuUA==} engines: {node: '>=14.21.3'} hasBin: true - '@biomejs/cli-darwin-arm64@2.3.7': - resolution: {integrity: sha512-LirkamEwzIUULhXcf2D5b+NatXKeqhOwilM+5eRkbrnr6daKz9rsBL0kNZ16Hcy4b8RFq22SG4tcLwM+yx/wFA==} + '@biomejs/cli-darwin-arm64@2.3.8': + resolution: {integrity: sha512-HM4Zg9CGQ3txTPflxD19n8MFPrmUAjaC7PQdLkugeeC0cQ+PiVrd7i09gaBS/11QKsTDBJhVg85CEIK9f50Qww==} engines: {node: '>=14.21.3'} cpu: [arm64] os: [darwin] - '@biomejs/cli-darwin-x64@2.3.7': - resolution: {integrity: sha512-Q4TO633kvrMQkKIV7wmf8HXwF0dhdTD9S458LGE24TYgBjSRbuhvio4D5eOQzirEYg6eqxfs53ga/rbdd8nBKg==} + '@biomejs/cli-darwin-x64@2.3.8': + resolution: {integrity: sha512-lUDQ03D7y/qEao7RgdjWVGCu+BLYadhKTm40HkpJIi6kn8LSv5PAwRlew/DmwP4YZ9ke9XXoTIQDO1vAnbRZlA==} engines: {node: '>=14.21.3'} cpu: [x64] os: [darwin] - '@biomejs/cli-linux-arm64-musl@2.3.7': - resolution: {integrity: sha512-/afy8lto4CB8scWfMdt+NoCZtatBUF62Tk3ilWH2w8ENd5spLhM77zKlFZEvsKJv9AFNHknMl03zO67CiklL2Q==} + '@biomejs/cli-linux-arm64-musl@2.3.8': + resolution: {integrity: sha512-PShR4mM0sjksUMyxbyPNMxoKFPVF48fU8Qe8Sfx6w6F42verbwRLbz+QiKNiDPRJwUoMG1nPM50OBL3aOnTevA==} engines: {node: '>=14.21.3'} cpu: [arm64] os: [linux] - '@biomejs/cli-linux-arm64@2.3.7': - resolution: {integrity: sha512-inHOTdlstUBzgjDcx0ge71U4SVTbwAljmkfi3MC5WzsYCRhancqfeL+sa4Ke6v2ND53WIwCFD5hGsYExoI3EZQ==} + '@biomejs/cli-linux-arm64@2.3.8': + resolution: {integrity: sha512-Uo1OJnIkJgSgF+USx970fsM/drtPcQ39I+JO+Fjsaa9ZdCN1oysQmy6oAGbyESlouz+rzEckLTF6DS7cWse95g==} engines: {node: '>=14.21.3'} cpu: [arm64] os: [linux] - '@biomejs/cli-linux-x64-musl@2.3.7': - resolution: {integrity: sha512-CQUtgH1tIN6e5wiYSJqzSwJumHYolNtaj1dwZGCnZXm2PZU1jOJof9TsyiP3bXNDb+VOR7oo7ZvY01If0W3iFQ==} + '@biomejs/cli-linux-x64-musl@2.3.8': + resolution: {integrity: sha512-YGLkqU91r1276uwSjiUD/xaVikdxgV1QpsicT0bIA1TaieM6E5ibMZeSyjQ/izBn4tKQthUSsVZacmoJfa3pDA==} engines: {node: '>=14.21.3'} cpu: [x64] os: [linux] - '@biomejs/cli-linux-x64@2.3.7': - resolution: {integrity: sha512-fJMc3ZEuo/NaMYo5rvoWjdSS5/uVSW+HPRQujucpZqm2ZCq71b8MKJ9U4th9yrv2L5+5NjPF0nqqILCl8HY/fg==} + '@biomejs/cli-linux-x64@2.3.8': + resolution: {integrity: sha512-QDPMD5bQz6qOVb3kiBui0zKZXASLo0NIQ9JVJio5RveBEFgDgsvJFUvZIbMbUZT3T00M/1wdzwWXk4GIh0KaAw==} engines: {node: '>=14.21.3'} cpu: [x64] os: [linux] - '@biomejs/cli-win32-arm64@2.3.7': - resolution: {integrity: sha512-aJAE8eCNyRpcfx2JJAtsPtISnELJ0H4xVVSwnxm13bzI8RwbXMyVtxy2r5DV1xT3WiSP+7LxORcApWw0LM8HiA==} + '@biomejs/cli-win32-arm64@2.3.8': + resolution: {integrity: sha512-H4IoCHvL1fXKDrTALeTKMiE7GGWFAraDwBYFquE/L/5r1927Te0mYIGseXi4F+lrrwhSWbSGt5qPFswNoBaCxg==} engines: {node: '>=14.21.3'} cpu: [arm64] os: [win32] - '@biomejs/cli-win32-x64@2.3.7': - resolution: {integrity: sha512-pulzUshqv9Ed//MiE8MOUeeEkbkSHVDVY5Cz5wVAnH1DUqliCQG3j6s1POaITTFqFfo7AVIx2sWdKpx/GS+Nqw==} + '@biomejs/cli-win32-x64@2.3.8': + resolution: {integrity: sha512-RguzimPoZWtBapfKhKjcWXBVI91tiSprqdBYu7tWhgN8pKRZhw24rFeNZTNf6UiBfjCYCi9eFQs/JzJZIhuK4w==} engines: {node: '>=14.21.3'} cpu: [x64] os: [win32] @@ -408,46 +408,46 @@ packages: resolution: {integrity: sha512-42AtmgqjV+X1VpdOfyTGOYRi0/zsoLqtXQckTmqTeybT+BDIbM/Guxo7x3pE2vtpr1ok6xRqM9OpBe+Jyoqyww==} engines: {node: '>=18'} - yaml@2.8.1: - resolution: {integrity: sha512-lcYcMxX2PO9XMGvAJkJ3OsNMw+/7FKes7/hgerGUYWIoWu5j/+YQqcZr5JnPZWzOsEBgMbSbiSTn/dv/69Mkpw==} + yaml@2.8.2: + resolution: {integrity: sha512-mplynKqc1C2hTVYxd0PU2xQAc22TI1vShAYGksCCfxbn/dFwnHTNi1bvYsBTkhdUNtGIf5xNOg938rrSSYvS9A==} engines: {node: '>= 14.6'} hasBin: true snapshots: - '@biomejs/biome@2.3.7': + '@biomejs/biome@2.3.8': optionalDependencies: - '@biomejs/cli-darwin-arm64': 2.3.7 - '@biomejs/cli-darwin-x64': 2.3.7 - '@biomejs/cli-linux-arm64': 2.3.7 - '@biomejs/cli-linux-arm64-musl': 2.3.7 - '@biomejs/cli-linux-x64': 2.3.7 - '@biomejs/cli-linux-x64-musl': 2.3.7 - '@biomejs/cli-win32-arm64': 2.3.7 - '@biomejs/cli-win32-x64': 2.3.7 - - '@biomejs/cli-darwin-arm64@2.3.7': + '@biomejs/cli-darwin-arm64': 2.3.8 + '@biomejs/cli-darwin-x64': 2.3.8 + '@biomejs/cli-linux-arm64': 2.3.8 + '@biomejs/cli-linux-arm64-musl': 2.3.8 + '@biomejs/cli-linux-x64': 2.3.8 + '@biomejs/cli-linux-x64-musl': 2.3.8 + '@biomejs/cli-win32-arm64': 2.3.8 + '@biomejs/cli-win32-x64': 2.3.8 + + '@biomejs/cli-darwin-arm64@2.3.8': optional: true - '@biomejs/cli-darwin-x64@2.3.7': + '@biomejs/cli-darwin-x64@2.3.8': optional: true - '@biomejs/cli-linux-arm64-musl@2.3.7': + '@biomejs/cli-linux-arm64-musl@2.3.8': optional: true - '@biomejs/cli-linux-arm64@2.3.7': + '@biomejs/cli-linux-arm64@2.3.8': optional: true - '@biomejs/cli-linux-x64-musl@2.3.7': + '@biomejs/cli-linux-x64-musl@2.3.8': optional: true - '@biomejs/cli-linux-x64@2.3.7': + '@biomejs/cli-linux-x64@2.3.8': optional: true - '@biomejs/cli-win32-arm64@2.3.7': + '@biomejs/cli-win32-arm64@2.3.8': optional: true - '@biomejs/cli-win32-x64@2.3.7': + '@biomejs/cli-win32-x64@2.3.8': optional: true ansi-escapes@7.2.0: @@ -625,7 +625,7 @@ snapshots: nano-spawn: 2.0.0 pidtree: 0.6.0 string-argv: 0.3.2 - yaml: 2.8.1 + yaml: 2.8.2 listr2@9.0.5: dependencies: @@ -775,4 +775,4 @@ snapshots: string-width: 7.2.0 strip-ansi: 7.1.2 - yaml@2.8.1: {} + yaml@2.8.2: {} From d6cd1d3f47c8b95d0283f0d14ea06c2b5017fcd7 Mon Sep 17 00:00:00 2001 From: Van Buren Date: Mon, 1 Dec 2025 12:08:10 -0500 Subject: [PATCH 03/12] fix: state --- client/src/components/base/MainNavigation.tsx | 13 +- .../src/components/base/UserProfileMenu.tsx | 12 +- client/src/components/ui/dropdown-menu.tsx | 402 ++++++++---------- 3 files changed, 174 insertions(+), 253 deletions(-) diff --git a/client/src/components/base/MainNavigation.tsx b/client/src/components/base/MainNavigation.tsx index 6cacc8a..aa0e44d 100644 --- a/client/src/components/base/MainNavigation.tsx +++ b/client/src/components/base/MainNavigation.tsx @@ -1,5 +1,4 @@ import { useInsight } from "@semoss/sdk/react"; -import { useState } from "react"; import { useNavigate } from "react-router-dom"; import { SemossBlueLogo } from "@/assets"; import { Button } from "@/components/ui/button"; @@ -25,11 +24,6 @@ export const MainNavigation = () => { const { isAuthorized } = useInsight(); // Read whether the user is authorized, so that buttons only work if they are const navigate = useNavigate(); - /** - * State - */ - const [userMenuOpen, setUserMenuOpen] = useState(false); - return (
@@ -77,12 +71,7 @@ export const MainNavigation = () => {
{/* If the user is logged in, allow them to see their info */} - {isAuthorized && ( - - )} + {isAuthorized && }
); diff --git a/client/src/components/base/UserProfileMenu.tsx b/client/src/components/base/UserProfileMenu.tsx index c21c5eb..c9feb0f 100644 --- a/client/src/components/base/UserProfileMenu.tsx +++ b/client/src/components/base/UserProfileMenu.tsx @@ -11,20 +11,12 @@ import { import { useAppContext } from "@/contexts"; import { useLoadingState } from "@/hooks"; -export interface UserProfileMenuProps { - open: boolean; - onOpenChange?: (open: boolean) => void; -} - /** * Renders a menu showing users their name and allowing them to log out * * @component */ -export const UserProfileMenu = ({ - open, - onOpenChange, -}: UserProfileMenuProps) => { +export const UserProfileMenu = () => { const { logout, userLoginName } = useAppContext(); /** @@ -44,7 +36,7 @@ export const UserProfileMenu = ({ }; return ( - +