diff --git a/src/renderer/App.tsx b/src/renderer/App.tsx index 932a6fb2d..44269447d 100644 --- a/src/renderer/App.tsx +++ b/src/renderer/App.tsx @@ -10,7 +10,6 @@ import { initialize as initializeIpcListeners } from './ipc'; import NodeScreen from './NodeScreen'; import DataRefresher from './DataRefresher'; import electron from './electronGlobal'; -import Sidebar from './Presentational/Sidebar/Sidebar'; import { SidebarWrapper } from './Presentational/SidebarWrapper/SidebarWrapper'; import NNSplash from './Presentational/NNSplashScreen/NNSplashScreen'; import { dragWindowContainer } from './app.css'; @@ -81,15 +80,7 @@ const MainScreen = () => { flex: 1, }} > - - {(sUserNodes) => ( - - )} - + diff --git a/src/renderer/Generics/redesign/Banner/Banner.tsx b/src/renderer/Generics/redesign/Banner/Banner.tsx index 67f6512b2..a117313e6 100644 --- a/src/renderer/Generics/redesign/Banner/Banner.tsx +++ b/src/renderer/Generics/redesign/Banner/Banner.tsx @@ -12,21 +12,31 @@ export interface BannerProps { /** * Is it offline? */ - offline: boolean; + offline?: boolean; /** * Is update available? */ - updateAvailable: boolean; + updateAvailable?: boolean; + /** + * Is docker not running? + */ + dockerStopped?: boolean; + onClick?: () => void; } /** * Primary UI component for user interaction */ -export const Banner = ({ offline, updateAvailable }: BannerProps) => { +export const Banner = ({ + offline, + updateAvailable, + dockerStopped, + onClick, +}: BannerProps) => { let iconId: IconId = 'blank'; let title = ''; let description = ''; - let onClick = () => {}; + let internalOnClick = () => {}; if (offline) { iconId = 'boltstrike'; title = 'Currently offline'; @@ -35,16 +45,30 @@ export const Banner = ({ offline, updateAvailable }: BannerProps) => { iconId = 'download1'; title = 'Update available'; description = 'New version ready to install'; - onClick = () => { + internalOnClick = () => { console.log('update nice node!'); }; + } else if (dockerStopped) { + iconId = 'play'; + title = 'Docker is not running'; + description = 'Click to start Docker'; + internalOnClick = () => { + console.log('Start Docker!'); + }; } + const onClickBanner = () => { + internalOnClick(); + if (onClick) { + onClick(); + } + }; + return (
diff --git a/src/renderer/Presentational/DockerInstallation/StartDockerBanner.tsx b/src/renderer/Presentational/DockerInstallation/StartDockerBanner.tsx new file mode 100644 index 000000000..5de3b1173 --- /dev/null +++ b/src/renderer/Presentational/DockerInstallation/StartDockerBanner.tsx @@ -0,0 +1,36 @@ +import electron from '../../electronGlobal'; +import { Banner } from '../../Generics/redesign/Banner/Banner'; +import { useGetIsDockerRunningQuery } from '../../state/settingsService'; + +export const DockerStoppedBanner = () => { + const qIsDockerRunning = useGetIsDockerRunningQuery(null, { + pollingInterval: 15000, + }); + + const onClickStartDocker = async () => { + await electron.startDocker(); + // todo: verify it is started and changed banner for 5 secs? + qIsDockerRunning.refetch(); + // console.log('installDocker finished. Install result: ', installResult); + }; + + return ( + + //
+ //
+ // + //
+ //
{title}
+ //
{description}
+ //
+ //
+ //
+ ); +}; diff --git a/src/renderer/Presentational/Sidebar/Sidebar.tsx b/src/renderer/Presentational/Sidebar/Sidebar.tsx index 073056e17..8af0e5e7b 100644 --- a/src/renderer/Presentational/Sidebar/Sidebar.tsx +++ b/src/renderer/Presentational/Sidebar/Sidebar.tsx @@ -15,6 +15,7 @@ import { IconId } from '../../assets/images/icons'; import { Modal } from '../../Generics/redesign/Modal/Modal'; import AddNodeStepper from '../AddNodeStepper/AddNodeStepper'; import PreferencesWrapper from '../PreferencesModal/PreferencesWrapper'; +import { DockerStoppedBanner } from '../DockerInstallation/StartDockerBanner'; export interface SidebarProps { /** @@ -25,7 +26,11 @@ export interface SidebarProps { * Nice Node update available? */ updateAvailable: boolean; - sUserNodes: UserNodes; + /** + * Is docker not running? + */ + dockerStopped: boolean; + sUserNodes?: UserNodes; } const itemListData: { iconId: IconId; label: string; count?: number }[] = [ @@ -62,7 +67,12 @@ const NODE_SIDEBAR_STATUS_MAP: Record = { unknown: 'error', }; -const Sidebar = ({ sUserNodes, updateAvailable, offline }: SidebarProps) => { +const Sidebar = ({ + sUserNodes, + updateAvailable, + offline, + dockerStopped, +}: SidebarProps) => { const dispatch = useAppDispatch(); const [sIsModalOpenAddNode, setIsModalOpenAddNode] = useState(); const [sIsModalOpenSettings, setIsModalOpenSettings] = @@ -115,6 +125,7 @@ const Sidebar = ({ sUserNodes, updateAvailable, offline }: SidebarProps) => { return (
+ {dockerStopped && } {renderBanners()}
diff --git a/src/renderer/Presentational/SidebarWrapper/SidebarWrapper.tsx b/src/renderer/Presentational/SidebarWrapper/SidebarWrapper.tsx index 0266d021a..5f73654af 100644 --- a/src/renderer/Presentational/SidebarWrapper/SidebarWrapper.tsx +++ b/src/renderer/Presentational/SidebarWrapper/SidebarWrapper.tsx @@ -1,23 +1,31 @@ -import React, { ReactElement, useEffect } from 'react'; +import { ReactElement, useEffect } from 'react'; import { useAppDispatch, useAppSelector } from '../../state/hooks'; import { selectSelectedNodeId, selectUserNodes, updateSelectedNodeId, } from '../../state/node'; +import { useGetIsDockerRunningQuery } from '../../state/settingsService'; +import Sidebar from '../Sidebar/Sidebar'; export interface SidebarWrapperProps { children: ReactElement; } -export const SidebarWrapper = ({ - children, -}: { - children: (sUserNodes: any) => React.ReactNode; -}) => { +export const SidebarWrapper = () => { const sSelectedNodeId = useAppSelector(selectSelectedNodeId); const sUserNodes = useAppSelector(selectUserNodes); const dispatch = useAppDispatch(); + // todo: implement a back-off polling strategy which can be "reset" + const qIsDockerRunning = useGetIsDockerRunningQuery(null, { + pollingInterval: 15000, + }); + // default to docker is running while data is being fetched, so + // the user isn't falsely warned + let isDockerRunning = true; + if (qIsDockerRunning && !qIsDockerRunning.fetching) { + isDockerRunning = qIsDockerRunning.data; + } // Default selected node to be the first node useEffect(() => { @@ -31,5 +39,12 @@ export const SidebarWrapper = ({ } }, [sSelectedNodeId, sUserNodes, dispatch]); - return <>{children(sUserNodes)}; + return ( + + ); };