diff --git a/web/src/analytics.ts b/web/src/analytics.ts index 376ef90..bd14c93 100644 --- a/web/src/analytics.ts +++ b/web/src/analytics.ts @@ -7,7 +7,7 @@ import { useConnectionState } from "@/view/hooks/hooks"; export function trackAnalyticsEvent( event: string, - params?: Record + params?: Record ) { if (window.analytics) { window.analytics.track(`rtdm-${event}`, params); diff --git a/web/src/components/EnableSimulatorButton.tsx b/web/src/components/EnableSimulatorButton.tsx index b0c624a..712bb1d 100644 --- a/web/src/components/EnableSimulatorButton.tsx +++ b/web/src/components/EnableSimulatorButton.tsx @@ -1,69 +1,136 @@ +import { Icon, InfoIcon } from "@chakra-ui/icons"; import { Alert, + AlertDescription, AlertIcon, AlertTitle, + Box, Button, - useBoolean, + FormControl, + FormControlProps, + FormLabel, + Switch, + SwitchProps, + Text, + Tooltip, useColorModeValue, } from "@chakra-ui/react"; import * as React from "react"; -import { useRecoilValue, useSetRecoilState } from "recoil"; +import { useRecoilState, useRecoilValue } from "recoil"; import { trackAnalyticsEvent } from "@/analytics"; import { setSessionController } from "@/data/queries"; import { connectionConfig, simulatorEnabled } from "@/data/recoil"; -import { useConnectionState, useMountedCallback } from "@/view/hooks/hooks"; +import { useConnectionState } from "@/view/hooks/hooks"; import { useSession } from "@/view/hooks/useSession"; -export const EnableSimulatorButton = () => { - const setEnabled = useSetRecoilState(simulatorEnabled); +export const EnableSimulatorWarning = () => { + return ( + + + + The simulator is disabled + + This application uses a simulator to generate new data like live + notifications and subscribers. To experience the full power of + real-time digital marketing, please enable the simulator in the nav + bar. + + + + ); +}; + +export const SimulatorToggler = ({ + switchProps, + containerProps, +}: { + switchProps?: SwitchProps; + containerProps?: FormControlProps; +}) => { + const [enabled, setEnabled] = useRecoilState(simulatorEnabled); const { session, refresh: refreshSession } = useSession(); const config = useRecoilValue(connectionConfig); const { connected, initialized } = useConnectionState(); + const [toggling, setToggling] = React.useState(false); - const [enabling, enablingCtrl] = useBoolean(false); - const stopSpinner = useMountedCallback( - () => enablingCtrl.off, - [enablingCtrl] - ); - const onEnableSimulator = React.useCallback(async () => { - enablingCtrl.on(); - trackAnalyticsEvent("enable-simulator"); - + const onToggleSimulator = React.useCallback(async () => { + setToggling(true); + const newState = !enabled; + trackAnalyticsEvent("change-simulator-state", { + enabled: newState, + }); if (connected && initialized) { - await setSessionController(config, session.sessionID, true); + await setSessionController(config, session.sessionID, newState); } - setEnabled(true); - + setEnabled(newState); refreshSession(); - stopSpinner(); + setToggling(false); }, [ config, connected, - enablingCtrl, initialized, - refreshSession, session.sessionID, + enabled, + refreshSession, setEnabled, - stopSpinner, ]); return ( - - - The simulator is disabled + + + + Simulator + + + + + + ); +}; + +export const SimulatorButton = () => { + return ( + + The simulator generates live notifications and subscribers even if the + application browser window is closed. Toggle off to stop new data + generation or suspend cluster in SingleStoreDB portal. + + } + hasArrow + textAlign="center" + > - + ); }; diff --git a/web/src/components/navBar/Nav.tsx b/web/src/components/navBar/Nav.tsx index 797e146..11623db 100644 --- a/web/src/components/navBar/Nav.tsx +++ b/web/src/components/navBar/Nav.tsx @@ -40,6 +40,8 @@ import SinglestoreLogo from "@/assets/singlestore-logo-filled-sm.svg"; import { GithubStargazer } from "@/components/GithubButtons"; import { LinkedinIconButton, TwitterIconButton } from "@/components/IconLinks"; +import { SimulatorButton } from "../EnableSimulatorButton"; + export const SinglestoreBrandLogo = () => { const [isSmallScreen] = useMediaQuery("(max-width: 640px)"); @@ -104,6 +106,7 @@ export const NavTools = () => { {themeModeIcon} + ({ a: { - color: colorMode === "light" ? "#553ACF" : "#CCC3F9", + color: colorMode === "light" ? "indigo.600" : "indigo.300", }, }), }, components: { Link: { baseStyle: ({ colorMode }: { colorMode: ColorMode }) => ({ - color: colorMode === "light" ? "#553ACF" : "#CCC3F9", + color: colorMode === "light" ? "indigo.600" : "indigo.300", }), }, Button: { @@ -52,11 +66,32 @@ export const chakraTheme = extendTheme({ } return { container: { - bg: colorMode === "light" ? "#553ACF" : "#CCC3F9", + bg: colorMode === "light" ? "indigo.600" : "indigo.300", }, }; }, }, }, + Switch: { + variants: { + simulator: ({ colorMode }: { colorMode: ColorMode }) => ({ + track: { + _checked: { + bg: colorMode === "light" ? "black" : "white", + }, + }, + thumb: { + bg: colorMode === "light" ? "white" : "black", + }, + }), + }, + }, + Tooltip: { + variants: { + simulator: ({ colorMode }: { colorMode: ColorMode }) => ({ + bg: colorMode === "light" ? "#171923" : "#F3F3F5", + }), + }, + }, }, }); diff --git a/web/src/data/client.ts b/web/src/data/client.ts index 9d0bca3..c66f69f 100644 --- a/web/src/data/client.ts +++ b/web/src/data/client.ts @@ -1,7 +1,7 @@ const rectifyHostAddress = (hostAddress: string) => { if ( hostAddress.toLowerCase().startsWith("http://") || - hostAddress.toLocaleLowerCase().startsWith("https://") || + hostAddress.toLowerCase().startsWith("https://") || hostAddress === "" ) { return hostAddress; diff --git a/web/src/pages/Analytics.tsx b/web/src/pages/Analytics.tsx index 8a44c1f..b35b6cc 100644 --- a/web/src/pages/Analytics.tsx +++ b/web/src/pages/Analytics.tsx @@ -35,7 +35,7 @@ import { useRecoilValue } from "recoil"; import useSWR from "swr"; import { Loader } from "@/components/customcomponents/loader/Loader"; -import { EnableSimulatorButton } from "@/components/EnableSimulatorButton"; +import { EnableSimulatorWarning } from "@/components/EnableSimulatorButton"; import { Heatmap } from "@/components/HeatMap"; import { SetupDatabaseButton } from "@/components/SetupDatabaseButton"; import { @@ -127,7 +127,7 @@ const DashboardContainerChild = () => { if (!initialized) { return ; } else if (!enabled) { - return ; + return ; } return ( diff --git a/web/src/pages/Dashboard.tsx b/web/src/pages/Dashboard.tsx index 750ae92..2e65a40 100644 --- a/web/src/pages/Dashboard.tsx +++ b/web/src/pages/Dashboard.tsx @@ -16,7 +16,7 @@ import * as React from "react"; import { BsEye, BsInfoCircleFill } from "react-icons/bs"; import { useRecoilState, useRecoilValue } from "recoil"; -import { EnableSimulatorButton } from "@/components/EnableSimulatorButton"; +import { EnableSimulatorWarning } from "@/components/EnableSimulatorButton"; import { IngestChart, useIngestChartData } from "@/components/IngestChart"; import { PixiMap } from "@/components/PixiMap"; import { SetupDatabaseButton } from "@/components/SetupDatabaseButton"; @@ -235,7 +235,7 @@ export const NotificationsMap = () => { if (!initialized) { mapStatisticsContainer = ; } else if (!enabled) { - mapStatisticsContainer = ; + mapStatisticsContainer = ; } else { mapStatisticsContainer = ; }