Skip to content

Commit

Permalink
New Simulator button to toggle simulation status in database (#41)
Browse files Browse the repository at this point in the history
* Give simulator toggle button

* Reset

* Prettier fix

* Introduce indigo color schema

* New simulator button

* Fix toLocalLowerCase usage

* Rename simulator warning component

* Prettier fix

* Prettier fix

* Restructured onToggle function for simulator button

* Use kebab case

---------

Co-authored-by: sbafna1 <sbafna@ip-10-170-33-212>
  • Loading branch information
sandeshvijayraj and sbafna1 authored Mar 30, 2023
1 parent e8db6dd commit 5e33c71
Show file tree
Hide file tree
Showing 7 changed files with 148 additions and 43 deletions.
2 changes: 1 addition & 1 deletion web/src/analytics.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import { useConnectionState } from "@/view/hooks/hooks";

export function trackAnalyticsEvent(
event: string,
params?: Record<string, string | number>
params?: Record<string, string | number | boolean>
) {
if (window.analytics) {
window.analytics.track(`rtdm-${event}`, params);
Expand Down
135 changes: 101 additions & 34 deletions web/src/components/EnableSimulatorButton.tsx
Original file line number Diff line number Diff line change
@@ -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 (
<Alert status="warning" borderRadius="md">
<AlertIcon />
<Box display="flex" flexDirection="column">
<AlertTitle>The simulator is disabled</AlertTitle>
<AlertDescription>
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.
</AlertDescription>
</Box>
</Alert>
);
};

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 (
<Alert status="warning" borderRadius="md">
<AlertIcon />
<AlertTitle>The simulator is disabled</AlertTitle>
<FormControl {...containerProps} gap={3}>
<FormLabel
htmlFor="simulator-switch"
fontSize="xs"
fontWeight="bold"
display="inline"
padding={0}
margin={0}
>
<Box gap={1} display="flex">
<Text>Simulator</Text>
<Icon as={InfoIcon} fontSize="1.1em" />
</Box>
</FormLabel>
<Switch
id="simulator-switch"
disabled={toggling}
isChecked={enabled}
onChange={onToggleSimulator}
{...switchProps}
/>
</FormControl>
);
};

export const SimulatorButton = () => {
return (
<Tooltip
variant="simulator"
label={
<Text padding={2}>
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.
</Text>
}
hasArrow
textAlign="center"
>
<Button
position="absolute"
right={4}
top={3}
size="xs"
background={useColorModeValue("#ECE8FD", "#2F206E")}
color={useColorModeValue("#553ACF", "#ECE8FD")}
disabled={enabling}
onClick={onEnableSimulator}
style={{
color: useColorModeValue("black", "white"),
backgroundColor: useColorModeValue("#DCD5FB", "#3A249E"),
border: "none",
boxShadow: "none",
}}
padding="8px 18px 8px 18px"
size="sm"
>
Enable simulator
<SimulatorToggler
switchProps={{ size: "sm", variant: "simulator" }}
containerProps={{ display: "flex", alignItems: "center" }}
/>
</Button>
</Alert>
</Tooltip>
);
};
3 changes: 3 additions & 0 deletions web/src/components/navBar/Nav.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -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)");

Expand Down Expand Up @@ -104,6 +106,7 @@ export const NavTools = () => {
</MenuList>
</Menu>
{themeModeIcon}
<SimulatorButton />
<GithubStargazer
color="black"
owner="singlestore-labs"
Expand Down
41 changes: 38 additions & 3 deletions web/src/components/theme.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,20 @@ import "@fontsource/inter/variable-full.css";
import "@fontsource/source-code-pro/variable.css";

export const chakraTheme = extendTheme({
colors: {
indigo: {
50: "#F7F6FE",
100: "#ECE8FD",
200: "#DCD5FB",
300: "#CCC3F9",
400: "#B0A0F8",
500: "#7760E1",
600: "#553ACF",
700: "#472EB7",
800: "#3A249E",
900: "#2F206E",
},
},
fonts: {
heading: "InterVariable, sans-serif",
body: "InterVariable, sans-serif",
Expand All @@ -17,14 +31,14 @@ export const chakraTheme = extendTheme({
styles: {
global: ({ colorMode }: { colorMode: ColorMode }) => ({
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: {
Expand Down Expand Up @@ -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",
}),
},
},
},
});
2 changes: 1 addition & 1 deletion web/src/data/client.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
const rectifyHostAddress = (hostAddress: string) => {
if (
hostAddress.toLowerCase().startsWith("http://") ||
hostAddress.toLocaleLowerCase().startsWith("https://") ||
hostAddress.toLowerCase().startsWith("https://") ||
hostAddress === ""
) {
return hostAddress;
Expand Down
4 changes: 2 additions & 2 deletions web/src/pages/Analytics.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down Expand Up @@ -127,7 +127,7 @@ const DashboardContainerChild = () => {
if (!initialized) {
return <SetupDatabaseButton />;
} else if (!enabled) {
return <EnableSimulatorButton />;
return <EnableSimulatorWarning />;
}
return (
<Stack gap={10}>
Expand Down
4 changes: 2 additions & 2 deletions web/src/pages/Dashboard.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -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";
Expand Down Expand Up @@ -235,7 +235,7 @@ export const NotificationsMap = () => {
if (!initialized) {
mapStatisticsContainer = <SetupDatabaseButton />;
} else if (!enabled) {
mapStatisticsContainer = <EnableSimulatorButton />;
mapStatisticsContainer = <EnableSimulatorWarning />;
} else {
mapStatisticsContainer = <StatsWrapper />;
}
Expand Down

0 comments on commit 5e33c71

Please sign in to comment.