From 42678231a82302ffc287a1d108c58cad60dfd3b3 Mon Sep 17 00:00:00 2001 From: Pive01 Date: Fri, 23 Dec 2022 11:29:52 +0100 Subject: [PATCH 01/21] save & exit without clicking "+" --- ui/src/components/Configs/UpsertConfig.tsx | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/ui/src/components/Configs/UpsertConfig.tsx b/ui/src/components/Configs/UpsertConfig.tsx index 34a711d..0cc9fe5 100644 --- a/ui/src/components/Configs/UpsertConfig.tsx +++ b/ui/src/components/Configs/UpsertConfig.tsx @@ -55,7 +55,10 @@ export const UpsertConfig = ({ config, open, onClose }: Props): ReactElement => }; const handleSaveButtonPress = () => { - updateConfig({ name: configName, id: newConfig.id, vars: newConfig.vars }); + updateConfig({ + name: configName, id: newConfig.id, vars: + newVar && newValue ? [...newConfig.vars, { variable: newVar, value: newValue, id: uuid() }] : newConfig.vars, + }); onClose(); }; @@ -123,6 +126,13 @@ export const UpsertConfig = ({ config, open, onClose }: Props): ReactElement => + From 607ecab61b2d1ed518ef5cf858aae96c4b802109 Mon Sep 17 00:00:00 2001 From: Pive01 Date: Fri, 23 Dec 2022 11:33:46 +0100 Subject: [PATCH 03/21] Auto refresh on instance running check --- ui/src/services/hooks/api.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ui/src/services/hooks/api.ts b/ui/src/services/hooks/api.ts index d8597eb..195a0a5 100644 --- a/ui/src/services/hooks/api.ts +++ b/ui/src/services/hooks/api.ts @@ -62,7 +62,7 @@ export const useLocalStack = (): useLocalStackReturn => { .find(container => container.Image === 'localstack/localstack' && container.Command !== 'bin/localstack update docker-images', - ), + ), { refreshInterval: 2000 }, ); return { From 1b2b5d5a962e3803517d521ad4b08a2fde29d213 Mon Sep 17 00:00:00 2001 From: Pive01 Date: Fri, 23 Dec 2022 12:34:10 +0100 Subject: [PATCH 04/21] confirmable update images and listing images --- .../components/Configs/ConfirmableButton.tsx | 7 +++- ui/src/components/Header/Menu.tsx | 38 ++++++++++++++----- 2 files changed, 35 insertions(+), 10 deletions(-) diff --git a/ui/src/components/Configs/ConfirmableButton.tsx b/ui/src/components/Configs/ConfirmableButton.tsx index 2279590..5d16658 100644 --- a/ui/src/components/Configs/ConfirmableButton.tsx +++ b/ui/src/components/Configs/ConfirmableButton.tsx @@ -23,6 +23,8 @@ export type BaseProps = { title: string; text?: string | JSX.Element; okText?: string; + okColor?: ButtonProps['color']; + cancelColor?: ButtonProps['color']; cancelText?: string; children?: ReactNode; } @@ -39,6 +41,8 @@ export const ConfirmableButton = ({ text, component = 'Button', okText, + okColor, + cancelColor, cancelText, children, ...rest @@ -66,6 +70,7 @@ export const ConfirmableButton = ({ )} + } + + ); +}; diff --git a/ui/src/components/Configs/StartConfigs.tsx b/ui/src/MainView/components/Configs/StartConfigs.tsx similarity index 94% rename from ui/src/components/Configs/StartConfigs.tsx rename to ui/src/MainView/components/Configs/StartConfigs.tsx index 6e37d06..2562301 100644 --- a/ui/src/components/Configs/StartConfigs.tsx +++ b/ui/src/MainView/components/Configs/StartConfigs.tsx @@ -4,10 +4,10 @@ import React, { ReactElement, useState } from 'react'; import { createStyles, makeStyles } from '@mui/styles'; import { DataGrid, GridColDef, GridRenderCellParams } from '@mui/x-data-grid'; import { v4 as uuid } from 'uuid'; -import { useRunConfig } from '../../services/hooks'; +import { useRunConfig } from '../../../services/hooks'; import { UpsertConfig } from './UpsertConfig'; -import { Optional, RunConfig } from '../../types'; -import { DEFAULT_CONFIGURATION_ID } from '../../constants'; +import { Optional, RunConfig } from '../../../types'; +import { DEFAULT_CONFIGURATION_ID } from '../../../constants'; import { ConfirmableButton } from './ConfirmableButton'; const useStyles = makeStyles((theme: Theme) => createStyles({ diff --git a/ui/src/components/Configs/UpsertConfig.tsx b/ui/src/MainView/components/Configs/UpsertConfig.tsx similarity index 97% rename from ui/src/components/Configs/UpsertConfig.tsx rename to ui/src/MainView/components/Configs/UpsertConfig.tsx index 0cc9fe5..3d8c5bf 100644 --- a/ui/src/components/Configs/UpsertConfig.tsx +++ b/ui/src/MainView/components/Configs/UpsertConfig.tsx @@ -15,8 +15,8 @@ import { Add, Remove, Settings } from '@mui/icons-material'; import React, { ReactElement, useState } from 'react'; import { v4 as uuid } from 'uuid'; import { createStyles, makeStyles } from '@mui/styles'; -import { useRunConfig } from '../../services/hooks'; -import { RunConfig } from '../../types'; +import { useRunConfig } from '../../../services/hooks'; +import { RunConfig } from '../../../types'; const DEFAULT_COLUMN_WIDTH = 2000; diff --git a/ui/src/components/Configs/index.tsx b/ui/src/MainView/components/Configs/index.tsx similarity index 100% rename from ui/src/components/Configs/index.tsx rename to ui/src/MainView/components/Configs/index.tsx diff --git a/ui/src/components/UpdateDialog.tsx b/ui/src/MainView/components/Dialog/UpdateDialog.tsx similarity index 94% rename from ui/src/components/UpdateDialog.tsx rename to ui/src/MainView/components/Dialog/UpdateDialog.tsx index 5292779..42d7a85 100644 --- a/ui/src/components/UpdateDialog.tsx +++ b/ui/src/MainView/components/Dialog/UpdateDialog.tsx @@ -6,8 +6,8 @@ import { Typography, } from '@mui/material'; import React, { ReactElement, useEffect, useState } from 'react'; -import { UPDATE_ARGS } from '../constants'; -import { useDDClient } from '../services/hooks'; +import { UPDATE_ARGS } from '../../../constants'; +import { useDDClient } from '../../../services/hooks'; type Props = { open: boolean, diff --git a/ui/src/components/Header/Controller.tsx b/ui/src/MainView/components/Header/Controller.tsx similarity index 76% rename from ui/src/components/Header/Controller.tsx rename to ui/src/MainView/components/Header/Controller.tsx index ce93a87..3ed885e 100644 --- a/ui/src/components/Header/Controller.tsx +++ b/ui/src/MainView/components/Header/Controller.tsx @@ -2,9 +2,9 @@ import React, { ReactElement, useEffect, useState } from 'react'; import { Chip, Button, ButtonGroup, Select, MenuItem, FormControl, Box } from '@mui/material'; import { PlayArrow, Stop } from '@mui/icons-material'; import { createStyles, makeStyles } from '@mui/styles'; -import { DEFAULT_CONFIGURATION_ID, START_ARGS, STOP_ARGS } from '../../constants'; -import { DockerImage } from '../../types'; -import { useDDClient, useRunConfig, useLocalStack } from '../../services/hooks'; +import { DEFAULT_CONFIGURATION_ID, START_ARGS, STOP_ARGS } from '../../../constants'; +import { DockerImage } from '../../../types'; +import { useDDClient, useRunConfig, useLocalStack, useMountPoint } from '../../../services/hooks'; import { LongMenu } from './Menu'; const useStyles = makeStyles(() => createStyles({ @@ -19,6 +19,7 @@ export const Controller = (): ReactElement => { const { data, mutate } = useLocalStack(); const [runningConfig, setRunningConfig] = useState('Default'); const isRunning = data && data.State === 'running'; + const { data: mountPoint } = useMountPoint(); const classes = useStyles(); @@ -38,21 +39,33 @@ export const Controller = (): ReactElement => { } else { ddClient.desktopUI.toast.success('Starting LocalStack'); } + const corsArg = '-e EXTRA_CORS_ALLOWED_ORIGINS=http://localhost:3000'; const addedArgs = runConfig.find(config => config.name === runningConfig) .vars.map(item => { if (item.variable === 'EXTRA_CORS_ALLOWED_ORIGINS') { + corsArg.slice(0, 0); return ['-e', `${item.variable}=${item.value},http://localhost:3000`]; } return ['-e', `${item.variable}=${item.value}`]; }).flat(); - const mountArg = `LOCALSTACK_VOLUME_DIR=${ddClient.host.platform === 'darwin' ? '/Volume' : '/home'}`; - ddClient.docker.cli.exec('run', ['-e', mountArg, ...START_ARGS, ...addedArgs]).then(() => mutate()); + const mountArg = + `-e LOCALSTACK_VOLUME_DIR=/${ddClient.host.platform === 'darwin' ? 'Users' : 'home'}/${mountPoint}`; + console.log(`docker run ${[mountArg, corsArg, ...addedArgs, ...START_ARGS].join(' ')}`); + ddClient.docker.cli.exec('run', [mountArg, corsArg, ...addedArgs, ...START_ARGS]).then(() => mutate()); }; const stop = async () => { ddClient.docker.cli.exec('run', STOP_ARGS).then(() => mutate()); }; + const checkHomeDir = async () => { + const res = await ddClient.docker.cli.exec('run', + ['--entrypoint=', '-v', '/home:/users', 'localstack/localstack', 'ls', '/users']); + + const users = res.stdout.split('\n'); + users.pop(); // remove last '' element + }; + return ( @@ -85,10 +98,12 @@ export const Controller = (): ReactElement => { startIcon={}> Start + } + { diff --git a/ui/src/components/Header/Menu.tsx b/ui/src/MainView/components/Header/Menu.tsx similarity index 93% rename from ui/src/components/Header/Menu.tsx rename to ui/src/MainView/components/Header/Menu.tsx index ce9b7c5..9f46c73 100644 --- a/ui/src/components/Header/Menu.tsx +++ b/ui/src/MainView/components/Header/Menu.tsx @@ -1,10 +1,10 @@ import { MoreVert } from '@mui/icons-material'; import { IconButton, Menu } from '@mui/material'; import React, { useEffect, useState } from 'react'; -import { useDDClient } from '../../services/hooks'; -import { DockerImage } from '../../types'; +import { useDDClient } from '../../../services/hooks'; +import { DockerImage } from '../../../types'; import { ConfirmableButton } from '../Configs/ConfirmableButton'; -import { UpdateDialog } from '../UpdateDialog'; +import { UpdateDialog } from '../Dialog/UpdateDialog'; const ITEM_HEIGHT = 80; diff --git a/ui/src/components/Header/index.tsx b/ui/src/MainView/components/Header/index.tsx similarity index 100% rename from ui/src/components/Header/index.tsx rename to ui/src/MainView/components/Header/index.tsx diff --git a/ui/src/components/Logs/Logs.tsx b/ui/src/MainView/components/Logs/Logs.tsx similarity index 88% rename from ui/src/components/Logs/Logs.tsx rename to ui/src/MainView/components/Logs/Logs.tsx index 4238eb4..922ae60 100644 --- a/ui/src/components/Logs/Logs.tsx +++ b/ui/src/MainView/components/Logs/Logs.tsx @@ -1,6 +1,6 @@ import { Box, Typography } from '@mui/material'; import React, { ReactElement, useEffect, useState } from 'react'; -import { useDDClient, useLocalStack } from '../../services/hooks'; +import { useDDClient, useLocalStack } from '../../../services/hooks'; export const Logs = (): ReactElement => { const [logs, setLogs] = useState([]); @@ -32,12 +32,14 @@ export const Logs = (): ReactElement => { } }, [data]); + console.log(data); + return ( <> {!data && - No instance is running - Start LocalStack to see it's logs + No instance is running - Start LocalStack to see its logs } diff --git a/ui/src/components/SystemStatus/Status.tsx b/ui/src/MainView/components/SystemStatus/Status.tsx similarity index 96% rename from ui/src/components/SystemStatus/Status.tsx rename to ui/src/MainView/components/SystemStatus/Status.tsx index 8a5a15a..e36174c 100644 --- a/ui/src/components/SystemStatus/Status.tsx +++ b/ui/src/MainView/components/SystemStatus/Status.tsx @@ -2,7 +2,7 @@ import { Theme } from '@mui/material'; import { createStyles, makeStyles } from '@mui/styles'; import classnames from 'classnames'; import React, { ReactElement } from 'react'; -import { HealthState } from '../../types'; +import { HealthState } from '../../../types'; const useStyles = makeStyles((theme: Theme) => createStyles({ dot: { diff --git a/ui/src/components/SystemStatus/SystemStatus.tsx b/ui/src/MainView/components/SystemStatus/SystemStatus.tsx similarity index 91% rename from ui/src/components/SystemStatus/SystemStatus.tsx rename to ui/src/MainView/components/SystemStatus/SystemStatus.tsx index 3c63711..f6df4e8 100644 --- a/ui/src/components/SystemStatus/SystemStatus.tsx +++ b/ui/src/MainView/components/SystemStatus/SystemStatus.tsx @@ -6,11 +6,11 @@ import { } from '@mui/material'; import { createStyles, makeStyles } from '@mui/styles'; import { Refresh } from '@mui/icons-material'; -import { useLocalStackHealth } from '../../services/hooks/health'; -import { HealthState } from '../../types'; -import { Capitalize } from '../../services/generic/utils'; +import { useLocalStackHealth } from '../../../services/hooks/health'; +import { HealthState } from '../../../types'; +import { Capitalize } from '../../../services/generic/utils'; import { Status as SystemStatusIcon } from './Status'; -import { useLocalStack } from '../../services/hooks'; +import { useLocalStack } from '../../../services/hooks'; const ORDER = [ HealthState.RUNNING, diff --git a/ui/src/components/SystemStatus/index.tsx b/ui/src/MainView/components/SystemStatus/index.tsx similarity index 100% rename from ui/src/components/SystemStatus/index.tsx rename to ui/src/MainView/components/SystemStatus/index.tsx diff --git a/ui/src/components/ControlledTabPanel.tsx b/ui/src/MainView/components/TabPanel/ControlledTabPanel.tsx similarity index 100% rename from ui/src/components/ControlledTabPanel.tsx rename to ui/src/MainView/components/TabPanel/ControlledTabPanel.tsx diff --git a/ui/src/components/index.ts b/ui/src/MainView/components/index.ts similarity index 57% rename from ui/src/components/index.ts rename to ui/src/MainView/components/index.ts index ea28756..f944154 100644 --- a/ui/src/components/index.ts +++ b/ui/src/MainView/components/index.ts @@ -1,6 +1,6 @@ export * from './Configs'; -export * from './ControlledTabPanel'; +export * from './TabPanel/ControlledTabPanel'; export * from './Header'; export * from './Logs/Logs'; export * from './SystemStatus'; -export * from './UpdateDialog'; +export * from './Dialog/UpdateDialog'; diff --git a/ui/src/constants/docker.ts b/ui/src/constants/docker.ts index 01bb360..abf6fa8 100644 --- a/ui/src/constants/docker.ts +++ b/ui/src/constants/docker.ts @@ -9,8 +9,6 @@ const COMMON_ARGS = [ ]; export const START_ARGS = [ - '-e', - 'EXTRA_CORS_ALLOWED_ORIGINS=http://localhost:3000', ...COMMON_ARGS, 'start', '-d', diff --git a/ui/src/constants/keys.ts b/ui/src/constants/keys.ts index 9c6a046..4818c57 100644 --- a/ui/src/constants/keys.ts +++ b/ui/src/constants/keys.ts @@ -4,3 +4,4 @@ export enum SwrCacheKey { export const STORAGE_KEY_ENVVARS = 'envVars'; export const STORAGE_KEY_LOCALSTACK = 'localstack'; +export const STORAGE_KEY_MOUNT = 'mountPoint'; diff --git a/ui/src/index.tsx b/ui/src/index.tsx index 5b62a47..03156db 100644 --- a/ui/src/index.tsx +++ b/ui/src/index.tsx @@ -4,7 +4,7 @@ import CssBaseline from '@mui/material/CssBaseline'; import { DockerMuiThemeProvider } from '@docker/docker-mui-theme'; import { App } from './App'; -import { GlobalDDProvider } from './components/provider'; +import { GlobalDDProvider } from './services/context/provider'; ReactDOM.render( diff --git a/ui/src/components/provider.tsx b/ui/src/services/context/provider.tsx similarity index 88% rename from ui/src/components/provider.tsx rename to ui/src/services/context/provider.tsx index a6815c9..8b4cbba 100644 --- a/ui/src/components/provider.tsx +++ b/ui/src/services/context/provider.tsx @@ -1,7 +1,7 @@ // eslint-disable-next-line import/no-unresolved import { createDockerDesktopClient } from '@docker/extension-api-client'; import React, { ReactNode, useMemo } from 'react'; -import { GlobalDDContext } from '../services/context/GlobalDDContext'; +import { GlobalDDContext } from './GlobalDDContext'; interface Props { children: ReactNode; diff --git a/ui/src/services/hooks/api.ts b/ui/src/services/hooks/api.ts index efe6188..ee3f0f4 100644 --- a/ui/src/services/hooks/api.ts +++ b/ui/src/services/hooks/api.ts @@ -1,5 +1,5 @@ import useSWR from 'swr'; -import { STORAGE_KEY_ENVVARS, STORAGE_KEY_LOCALSTACK } from '../../constants'; +import { STORAGE_KEY_ENVVARS, STORAGE_KEY_LOCALSTACK, STORAGE_KEY_MOUNT } from '../../constants'; import { DockerContainer, RunConfig } from '../../types'; import { useDDClient } from './utils'; @@ -47,6 +47,33 @@ export const useRunConfig = (): useRunConfigReturn => { }; }; +interface useMountPointReturn { + data: string | null, + isLoading: boolean, + setMountPointUser: (data: string) => unknown; +} + +export const useMountPoint = (): useMountPointReturn => { + const ddClient = useDDClient(); + const cacheKey = STORAGE_KEY_MOUNT; + + const { data, mutate, isValidating, error } = useSWR( + cacheKey, + async () => (ddClient.extension.vm.service.get('/mount') as Promise), + ); + + const setMountPointUser = async (user: string) => { + await ddClient.extension.vm.service.post('/mount',{ Data: user }); + mutate(); + }; + + return { + data: (!error && data ) ? data.Message : null, + isLoading: isValidating || (!error && !data), + setMountPointUser, + }; +}; + interface useLocalStackReturn { data: DockerContainer | null, mutate: () => void; diff --git a/vm/main.go b/vm/main.go index 387320d..e21a470 100644 --- a/vm/main.go +++ b/vm/main.go @@ -16,7 +16,8 @@ import ( var ERRORS = [...]string{"Bad format", "Errors while saving data", "Failed retrieving data", "Configuration already present"} -const FILE_NAME = "data.json" +const CONFIG_FILE = "data.json" +const MOUNT_POINT_FILE = "mountPoint.txt" func main() { var socketPath string @@ -41,6 +42,8 @@ func main() { router.POST("/configs", createSetting) router.PUT("/configs", updateSetting) router.DELETE("/configs/:id", deleteSetting) + router.GET("/mount", getMount) + router.POST("/mount", setMount) log.Fatal(router.Start(startURL)) } @@ -67,8 +70,27 @@ type Payload struct { Data string `json:"data"` } +func getMount(ctx echo.Context) error { + content, err := readData(MOUNT_POINT_FILE) + if err != nil { + return ctx.JSON(http.StatusConflict, HTTPMessageBody{Message: ERRORS[2]}) + } + return ctx.JSON(http.StatusOK, HTTPMessageBody{Message: string(content[:])}) +} + +func setMount(ctx echo.Context) error { + var payload Payload + + ctx.Bind(&payload) + err := os.WriteFile(MOUNT_POINT_FILE, []byte(payload.Data), 0644) + if err != nil { + return ctx.JSON(http.StatusConflict, HTTPMessageBody{Message: ERRORS[2]}) + } + return ctx.NoContent(http.StatusOK) +} + func getSettings(ctx echo.Context) error { - content, err := readData() + content, err := readData(CONFIG_FILE) if err != nil { return ctx.JSON(http.StatusConflict, HTTPMessageBody{Message: ERRORS[2]}) } @@ -175,29 +197,29 @@ func createSetting(ctx echo.Context) error { } -func readData() ([]byte, error) { - _, err := os.Stat(FILE_NAME) +func readData(fileName string) ([]byte, error) { + _, err := os.Stat(fileName) var content []byte if errors.Is(err, os.ErrNotExist) { - content, file, err := createFile() + content, file, err := createFile(CONFIG_FILE) file.Close() return content, err } - content, err = os.ReadFile(FILE_NAME) + content, err = os.ReadFile(fileName) return content, err } func readDataKeepOpen() ([]byte, *os.File, error) { - _, err := os.Stat(FILE_NAME) + _, err := os.Stat(CONFIG_FILE) var content []byte if errors.Is(err, os.ErrNotExist) { - return createFile() + return createFile(CONFIG_FILE) } - file, err := os.OpenFile(FILE_NAME, os.O_RDWR, 0755) + file, err := os.OpenFile(CONFIG_FILE, os.O_RDWR, 0755) var buff = make([]byte, 1024) if err == nil { for { @@ -220,10 +242,10 @@ func writeData(data []Configuration, file *os.File) error { return err } -func createFile() ([]byte, *os.File, error) { +func createFile(filename string) ([]byte, *os.File, error) { logrus.New().Infof("File not exists, creating") - file, err := os.OpenFile(FILE_NAME, os.O_CREATE|os.O_RDWR, 0755) + file, err := os.OpenFile(filename, os.O_CREATE|os.O_RDWR, 0755) if err != nil { logrus.New().Infof("Errors while creating file") From 972ed652901545d40648e29591f6d717a9fe04e5 Mon Sep 17 00:00:00 2001 From: Pive01 Date: Wed, 28 Dec 2022 21:07:35 +0100 Subject: [PATCH 11/21] Removed logs and unused code --- ui/src/MainView/components/Header/Controller.tsx | 10 ---------- ui/src/MainView/components/Logs/Logs.tsx | 2 -- 2 files changed, 12 deletions(-) diff --git a/ui/src/MainView/components/Header/Controller.tsx b/ui/src/MainView/components/Header/Controller.tsx index 3ed885e..8d46c38 100644 --- a/ui/src/MainView/components/Header/Controller.tsx +++ b/ui/src/MainView/components/Header/Controller.tsx @@ -50,7 +50,6 @@ export const Controller = (): ReactElement => { }).flat(); const mountArg = `-e LOCALSTACK_VOLUME_DIR=/${ddClient.host.platform === 'darwin' ? 'Users' : 'home'}/${mountPoint}`; - console.log(`docker run ${[mountArg, corsArg, ...addedArgs, ...START_ARGS].join(' ')}`); ddClient.docker.cli.exec('run', [mountArg, corsArg, ...addedArgs, ...START_ARGS]).then(() => mutate()); }; @@ -58,14 +57,6 @@ export const Controller = (): ReactElement => { ddClient.docker.cli.exec('run', STOP_ARGS).then(() => mutate()); }; - const checkHomeDir = async () => { - const res = await ddClient.docker.cli.exec('run', - ['--entrypoint=', '-v', '/home:/users', 'localstack/localstack', 'ls', '/users']); - - const users = res.stdout.split('\n'); - users.pop(); // remove last '' element - }; - return ( @@ -103,7 +94,6 @@ export const Controller = (): ReactElement => { } - { } }, [data]); - console.log(data); - return ( <> {!data && From 8493647b5ac9ed541eea467a35f4a0f2ca40342a Mon Sep 17 00:00:00 2001 From: Pive01 Date: Wed, 28 Dec 2022 21:31:31 +0100 Subject: [PATCH 12/21] added /.localstack-volume to mount point --- ui/src/MainView/components/Header/Controller.tsx | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/ui/src/MainView/components/Header/Controller.tsx b/ui/src/MainView/components/Header/Controller.tsx index 8d46c38..f8bce51 100644 --- a/ui/src/MainView/components/Header/Controller.tsx +++ b/ui/src/MainView/components/Header/Controller.tsx @@ -49,7 +49,8 @@ export const Controller = (): ReactElement => { return ['-e', `${item.variable}=${item.value}`]; }).flat(); const mountArg = - `-e LOCALSTACK_VOLUME_DIR=/${ddClient.host.platform === 'darwin' ? 'Users' : 'home'}/${mountPoint}`; + '-e LOCALSTACK_VOLUME_DIR=/' + + `${ddClient.host.platform === 'darwin' ? 'Users' : 'home'}/${mountPoint}/.localstack-volume`; ddClient.docker.cli.exec('run', [mountArg, corsArg, ...addedArgs, ...START_ARGS]).then(() => mutate()); }; @@ -87,7 +88,7 @@ export const Controller = (): ReactElement => { variant="contained" onClick={start} startIcon={}> - Start + Startasd From eb4e2af84f9c88117279637429e76887b023695a Mon Sep 17 00:00:00 2001 From: Pive01 Date: Thu, 29 Dec 2022 11:02:16 +0100 Subject: [PATCH 13/21] Rearranged components and move to dialog --- ui/src/App.tsx | 67 ++++++++++++------- ui/src/MainView/MainView.tsx | 42 ------------ .../components/Configs/OnBoarding.tsx | 41 ------------ .../components/Configs/ConfirmableButton.tsx | 0 ui/src/components/Configs/OnBoarding.tsx | 60 +++++++++++++++++ .../components/Configs/StartConfigs.tsx | 13 ++-- .../components/Configs/UpsertConfig.tsx | 4 +- .../components/Configs/index.tsx | 1 + .../components/Dialog/UpdateDialog.tsx | 4 +- .../components/Header/Controller.tsx | 6 +- .../components/Header/Header.tsx | 2 +- .../{MainView => }/components/Header/Menu.tsx | 4 +- .../components/Header/index.tsx | 0 .../{MainView => }/components/Logs/Logs.tsx | 2 +- .../components/SystemStatus/Status.tsx | 2 +- .../components/SystemStatus/SystemStatus.tsx | 8 +-- .../components/SystemStatus/index.tsx | 0 .../TabPanel/ControlledTabPanel.tsx | 0 ui/src/{MainView => }/components/index.ts | 0 19 files changed, 126 insertions(+), 130 deletions(-) delete mode 100644 ui/src/MainView/MainView.tsx delete mode 100644 ui/src/MainView/components/Configs/OnBoarding.tsx rename ui/src/{MainView => }/components/Configs/ConfirmableButton.tsx (100%) create mode 100644 ui/src/components/Configs/OnBoarding.tsx rename ui/src/{MainView => }/components/Configs/StartConfigs.tsx (88%) rename ui/src/{MainView => }/components/Configs/UpsertConfig.tsx (97%) rename ui/src/{MainView => }/components/Configs/index.tsx (68%) rename ui/src/{MainView => }/components/Dialog/UpdateDialog.tsx (94%) rename ui/src/{MainView => }/components/Header/Controller.tsx (97%) rename ui/src/{MainView => }/components/Header/Header.tsx (94%) rename ui/src/{MainView => }/components/Header/Menu.tsx (95%) rename ui/src/{MainView => }/components/Header/index.tsx (100%) rename ui/src/{MainView => }/components/Logs/Logs.tsx (95%) rename ui/src/{MainView => }/components/SystemStatus/Status.tsx (96%) rename ui/src/{MainView => }/components/SystemStatus/SystemStatus.tsx (91%) rename ui/src/{MainView => }/components/SystemStatus/index.tsx (100%) rename ui/src/{MainView => }/components/TabPanel/ControlledTabPanel.tsx (100%) rename ui/src/{MainView => }/components/index.ts (100%) diff --git a/ui/src/App.tsx b/ui/src/App.tsx index 9f16040..d90bedf 100644 --- a/ui/src/App.tsx +++ b/ui/src/App.tsx @@ -1,31 +1,46 @@ -import React, { useEffect, useState } from 'react'; -import { useDDClient, useMountPoint } from './services/hooks'; -import { OnBoarding } from './MainView/components/Configs/OnBoarding'; -import { MainView } from './MainView/MainView'; +import React, { ReactElement, useState } from 'react'; +import { createStyles, makeStyles } from '@mui/styles'; +import { ControlledTabPanels, Header, Logs, OnBoarding, StartConfigs, SystemStatus } from './components'; +import { useMountPoint } from './services/hooks'; +const useStyles = makeStyles(() => createStyles({ + sticky: { + position: 'sticky', + top: 0, + zIndex: 2, + }, +})); -export function App() { - const ddClient = useDDClient(); - const { data, isLoading } = useMountPoint(); - const [users, setUsers] = useState([]); - - useEffect(() => { - const checkHomeDir = async () => { - const path = ddClient.host.platform === 'darwin' ? 'Users' : 'home'; - const res = await ddClient.docker.cli.exec('run', - ['--entrypoint=', '-v', `/${path}:/users`, 'localstack/localstack', 'ls', '/users']); - - const foundUsers = res.stdout.split('\n'); - foundUsers.pop(); // remove last '' element - if (foundUsers.join(',') !== users.join(',')) { - setUsers(foundUsers); - } - }; - - checkHomeDir(); - }, [users]); +export const App = (): ReactElement => { + const [selected, setSelected] = useState(0); + const { data: mountPoint } = useMountPoint(); + const classes = useStyles(); + const shouldDialogOpen = !mountPoint || mountPoint === ''; return ( - (data && data !== '') ? : + <> + { shouldDialogOpen && } +
+
+
+ setSelected(to)} + selected={selected} + options={[ + { + label: 'System Status', + panel: , + }, + { + label: 'Configurations', + panel: , + }, + { + label: 'Logs', + panel: , + }, + ]} + /> + ); -} +}; diff --git a/ui/src/MainView/MainView.tsx b/ui/src/MainView/MainView.tsx deleted file mode 100644 index 813158b..0000000 --- a/ui/src/MainView/MainView.tsx +++ /dev/null @@ -1,42 +0,0 @@ -import React, { ReactElement, useState } from 'react'; -import { createStyles, makeStyles } from '@mui/styles'; -import { ControlledTabPanels, Header, Logs, StartConfigs, SystemStatus } from './components'; - -const useStyles = makeStyles(() => createStyles({ - sticky: { - position: 'sticky', - top: 0, - zIndex: 2, - }, -})); - -export const MainView = (): ReactElement => { - const [selected, setSelected] = useState(0); - const classes = useStyles(); - - return ( - <> -
-
-
- setSelected(to)} - selected={selected} - options={[ - { - label: 'System Status', - panel: , - }, - { - label: 'Configurations', - panel: , - }, - { - label: 'Logs', - panel: , - }, - ]} - /> - - ); -}; diff --git a/ui/src/MainView/components/Configs/OnBoarding.tsx b/ui/src/MainView/components/Configs/OnBoarding.tsx deleted file mode 100644 index b51cdad..0000000 --- a/ui/src/MainView/components/Configs/OnBoarding.tsx +++ /dev/null @@ -1,41 +0,0 @@ - -import { Box, Button, FormControl, MenuItem, Select, Typography } from '@mui/material'; -import React, { ReactElement, useEffect, useState } from 'react'; -import { useMountPoint } from '../../../services/hooks'; - -type OnBoardingProps = { - users: string[], - loading: boolean, -}; - -export const OnBoarding = ({ users, loading }: OnBoardingProps): ReactElement => { - const { setMountPointUser } = useMountPoint(); - const [selectedUser, setSelectedUser] = useState(); - - useEffect(() => { - setSelectedUser(users[0]); - }, [users]); - - return ( - - { - loading ? - Loading : - <> - - In order to work LocalStack needs a mount point. Select user: - - - - - } - - ); -}; diff --git a/ui/src/MainView/components/Configs/ConfirmableButton.tsx b/ui/src/components/Configs/ConfirmableButton.tsx similarity index 100% rename from ui/src/MainView/components/Configs/ConfirmableButton.tsx rename to ui/src/components/Configs/ConfirmableButton.tsx diff --git a/ui/src/components/Configs/OnBoarding.tsx b/ui/src/components/Configs/OnBoarding.tsx new file mode 100644 index 0000000..6e791c1 --- /dev/null +++ b/ui/src/components/Configs/OnBoarding.tsx @@ -0,0 +1,60 @@ + +import { + Box, + Button, + CircularProgress, + Dialog, + DialogActions, + DialogContent, + FormControl, + MenuItem, + Select, +} from '@mui/material'; +import React, { ReactElement, useEffect, useState } from 'react'; +import { useDDClient, useMountPoint } from '../../services/hooks'; + + +export const OnBoarding = (): ReactElement => { + const { setMountPointUser } = useMountPoint(); + const ddClient = useDDClient(); + const [state, setState] = useState({ loading: true, selectedUser: '', users: [] }); + + + useEffect(() => { + const checkHomeDir = async () => { + const path = ddClient.host.platform === 'darwin' ? 'Users' : 'home'; + const res = await ddClient.docker.cli.exec('run', + ['--entrypoint=', '-v', `/${path}:/users`, 'localstack/localstack', 'ls', '/users']); + + const foundUsers = res.stdout.split('\n'); + foundUsers.pop(); // remove last '' element + setState({ loading: false, selectedUser: foundUsers[0], users: foundUsers }); + }; + + checkHomeDir(); + }, [state.users]); + + return ( + + + + {state.loading ? : + + + } + + + + + + + ); +}; diff --git a/ui/src/MainView/components/Configs/StartConfigs.tsx b/ui/src/components/Configs/StartConfigs.tsx similarity index 88% rename from ui/src/MainView/components/Configs/StartConfigs.tsx rename to ui/src/components/Configs/StartConfigs.tsx index 2562301..0c5eb88 100644 --- a/ui/src/MainView/components/Configs/StartConfigs.tsx +++ b/ui/src/components/Configs/StartConfigs.tsx @@ -4,10 +4,10 @@ import React, { ReactElement, useState } from 'react'; import { createStyles, makeStyles } from '@mui/styles'; import { DataGrid, GridColDef, GridRenderCellParams } from '@mui/x-data-grid'; import { v4 as uuid } from 'uuid'; -import { useRunConfig } from '../../../services/hooks'; +import { useMountPoint, useRunConfig } from '../../services/hooks'; import { UpsertConfig } from './UpsertConfig'; -import { Optional, RunConfig } from '../../../types'; -import { DEFAULT_CONFIGURATION_ID } from '../../../constants'; +import { Optional, RunConfig } from '../../types'; +import { DEFAULT_CONFIGURATION_ID } from '../../constants'; import { ConfirmableButton } from './ConfirmableButton'; const useStyles = makeStyles((theme: Theme) => createStyles({ @@ -18,8 +18,8 @@ const useStyles = makeStyles((theme: Theme) => createStyles({ export const StartConfigs = (): ReactElement => { - const { deleteConfig } = useRunConfig(); - const { runConfig } = useRunConfig(); + const { runConfig, deleteConfig } = useRunConfig(); + const { setMountPointUser } = useMountPoint(); const [openModal, setOpenModal] = useState(false); const [targetConfig, setTargetConfig] = useState(null); @@ -83,6 +83,9 @@ export const StartConfigs = (): ReactElement => { > New + createStyles({ diff --git a/ui/src/MainView/components/Header/Header.tsx b/ui/src/components/Header/Header.tsx similarity index 94% rename from ui/src/MainView/components/Header/Header.tsx rename to ui/src/components/Header/Header.tsx index 6633b08..f5435bb 100644 --- a/ui/src/MainView/components/Header/Header.tsx +++ b/ui/src/components/Header/Header.tsx @@ -1,7 +1,7 @@ import { OpenInNew } from '@mui/icons-material'; import { Box, Typography, Button, AppBar, Toolbar } from '@mui/material'; import React, { ReactElement } from 'react'; -import { useDDClient } from '../../../services/hooks'; +import { useDDClient } from '../../services/hooks'; import { Controller } from './Controller'; export const Header = (): ReactElement => { diff --git a/ui/src/MainView/components/Header/Menu.tsx b/ui/src/components/Header/Menu.tsx similarity index 95% rename from ui/src/MainView/components/Header/Menu.tsx rename to ui/src/components/Header/Menu.tsx index 9f46c73..c475a56 100644 --- a/ui/src/MainView/components/Header/Menu.tsx +++ b/ui/src/components/Header/Menu.tsx @@ -1,8 +1,8 @@ import { MoreVert } from '@mui/icons-material'; import { IconButton, Menu } from '@mui/material'; import React, { useEffect, useState } from 'react'; -import { useDDClient } from '../../../services/hooks'; -import { DockerImage } from '../../../types'; +import { useDDClient } from '../../services/hooks'; +import { DockerImage } from '../../types'; import { ConfirmableButton } from '../Configs/ConfirmableButton'; import { UpdateDialog } from '../Dialog/UpdateDialog'; diff --git a/ui/src/MainView/components/Header/index.tsx b/ui/src/components/Header/index.tsx similarity index 100% rename from ui/src/MainView/components/Header/index.tsx rename to ui/src/components/Header/index.tsx diff --git a/ui/src/MainView/components/Logs/Logs.tsx b/ui/src/components/Logs/Logs.tsx similarity index 95% rename from ui/src/MainView/components/Logs/Logs.tsx rename to ui/src/components/Logs/Logs.tsx index 246ec6e..cb86b08 100644 --- a/ui/src/MainView/components/Logs/Logs.tsx +++ b/ui/src/components/Logs/Logs.tsx @@ -1,6 +1,6 @@ import { Box, Typography } from '@mui/material'; import React, { ReactElement, useEffect, useState } from 'react'; -import { useDDClient, useLocalStack } from '../../../services/hooks'; +import { useDDClient, useLocalStack } from '../../services/hooks'; export const Logs = (): ReactElement => { const [logs, setLogs] = useState([]); diff --git a/ui/src/MainView/components/SystemStatus/Status.tsx b/ui/src/components/SystemStatus/Status.tsx similarity index 96% rename from ui/src/MainView/components/SystemStatus/Status.tsx rename to ui/src/components/SystemStatus/Status.tsx index e36174c..8a5a15a 100644 --- a/ui/src/MainView/components/SystemStatus/Status.tsx +++ b/ui/src/components/SystemStatus/Status.tsx @@ -2,7 +2,7 @@ import { Theme } from '@mui/material'; import { createStyles, makeStyles } from '@mui/styles'; import classnames from 'classnames'; import React, { ReactElement } from 'react'; -import { HealthState } from '../../../types'; +import { HealthState } from '../../types'; const useStyles = makeStyles((theme: Theme) => createStyles({ dot: { diff --git a/ui/src/MainView/components/SystemStatus/SystemStatus.tsx b/ui/src/components/SystemStatus/SystemStatus.tsx similarity index 91% rename from ui/src/MainView/components/SystemStatus/SystemStatus.tsx rename to ui/src/components/SystemStatus/SystemStatus.tsx index f6df4e8..3c63711 100644 --- a/ui/src/MainView/components/SystemStatus/SystemStatus.tsx +++ b/ui/src/components/SystemStatus/SystemStatus.tsx @@ -6,11 +6,11 @@ import { } from '@mui/material'; import { createStyles, makeStyles } from '@mui/styles'; import { Refresh } from '@mui/icons-material'; -import { useLocalStackHealth } from '../../../services/hooks/health'; -import { HealthState } from '../../../types'; -import { Capitalize } from '../../../services/generic/utils'; +import { useLocalStackHealth } from '../../services/hooks/health'; +import { HealthState } from '../../types'; +import { Capitalize } from '../../services/generic/utils'; import { Status as SystemStatusIcon } from './Status'; -import { useLocalStack } from '../../../services/hooks'; +import { useLocalStack } from '../../services/hooks'; const ORDER = [ HealthState.RUNNING, diff --git a/ui/src/MainView/components/SystemStatus/index.tsx b/ui/src/components/SystemStatus/index.tsx similarity index 100% rename from ui/src/MainView/components/SystemStatus/index.tsx rename to ui/src/components/SystemStatus/index.tsx diff --git a/ui/src/MainView/components/TabPanel/ControlledTabPanel.tsx b/ui/src/components/TabPanel/ControlledTabPanel.tsx similarity index 100% rename from ui/src/MainView/components/TabPanel/ControlledTabPanel.tsx rename to ui/src/components/TabPanel/ControlledTabPanel.tsx diff --git a/ui/src/MainView/components/index.ts b/ui/src/components/index.ts similarity index 100% rename from ui/src/MainView/components/index.ts rename to ui/src/components/index.ts From 1686969d474f2da88d59f4b75fdbe42d96177db5 Mon Sep 17 00:00:00 2001 From: Pive01 Date: Thu, 29 Dec 2022 14:55:24 +0100 Subject: [PATCH 14/21] Changed OnBoarding dialog and logs style --- ui/src/components/Configs/OnBoarding.tsx | 125 ++++++++++++++++----- ui/src/components/Configs/StartConfigs.tsx | 25 +++-- ui/src/components/Header/Controller.tsx | 4 +- ui/src/components/Logs/Logs.tsx | 6 +- ui/src/constants/common.ts | 6 + 5 files changed, 124 insertions(+), 42 deletions(-) diff --git a/ui/src/components/Configs/OnBoarding.tsx b/ui/src/components/Configs/OnBoarding.tsx index 6e791c1..67fa11f 100644 --- a/ui/src/components/Configs/OnBoarding.tsx +++ b/ui/src/components/Configs/OnBoarding.tsx @@ -2,58 +2,131 @@ import { Box, Button, - CircularProgress, Dialog, DialogActions, DialogContent, FormControl, MenuItem, Select, + Skeleton, + Typography, } from '@mui/material'; import React, { ReactElement, useEffect, useState } from 'react'; +import { LOCALSTACK_IMAGES } from '../../constants'; import { useDDClient, useMountPoint } from '../../services/hooks'; +import { DockerImage } from '../../types'; export const OnBoarding = (): ReactElement => { const { setMountPointUser } = useMountPoint(); const ddClient = useDDClient(); - const [state, setState] = useState({ loading: true, selectedUser: '', users: [] }); + const [userState, setUserState] = useState({ loading: false, selectedUser: '', users: [] }); + const [hasLocalImage, setHasLocalImage] = useState({ checking: true, isPresent: false }); + const [isPullingImage, setIsPullingImage] = useState(false); + const [triggerUseEffect, setTriggerUseEffect] = useState(false); + const checkHomeDir = async () => { + setUserState({ loading: true, selectedUser: userState.selectedUser, users: userState.users }); + const path = ddClient.host.platform === 'darwin' ? 'Users' : 'home'; + const res = await ddClient.docker.cli.exec('run', + ['--entrypoint=', '-v', `/${path}:/users`, 'localstack/localstack', 'ls', '/users']); + + const foundUsers = res.stdout.split('\n'); + foundUsers.pop(); // remove last '' element + setUserState({ loading: false, selectedUser: foundUsers[0], users: foundUsers }); + }; + + const checkLocalImage = async () => { + setHasLocalImage({ checking: true, isPresent: hasLocalImage.isPresent }); + const images = await ddClient.docker.listImages() as [DockerImage]; + const isPresent = images.filter(image => LOCALSTACK_IMAGES.includes(image.RepoTags?.at(0).split(':').at(0))); + setHasLocalImage({ checking: false, isPresent: isPresent.length > 0 }); + return isPresent; + }; useEffect(() => { - const checkHomeDir = async () => { - const path = ddClient.host.platform === 'darwin' ? 'Users' : 'home'; - const res = await ddClient.docker.cli.exec('run', - ['--entrypoint=', '-v', `/${path}:/users`, 'localstack/localstack', 'ls', '/users']); - - const foundUsers = res.stdout.split('\n'); - foundUsers.pop(); // remove last '' element - setState({ loading: false, selectedUser: foundUsers[0], users: foundUsers }); + const execChecks = async () => { + if (userState.users.length === 0) { + const isImagePresent = await checkLocalImage(); + if (isImagePresent) { + checkHomeDir(); + } else { + setIsPullingImage(true); + ddClient.docker.cli.exec('pull', ['localstack/localstack'], { + stream: { + onOutput(data): void { + console.log(data.stderr ? data.stderr : data.stdout); + }, + onClose() { + setIsPullingImage(false); + setTriggerUseEffect(!triggerUseEffect); + }, + splitOutputLines: true, + }, + }); + } + + } }; - checkHomeDir(); - }, [state.users]); + execChecks(); + }, [userState.users, triggerUseEffect]); return ( - - {state.loading ? : - - - } + + + Select where LocalStack will be mounted + + + {'For MacOS users it will be under /Users//.localstack-volume'} + + + {'For Linux/Windows users it will be under /home//.localstack-volume'} + + + {hasLocalImage.checking && + + Checking for local LocalStack image + + } + {userState.loading && + + Checking for users + + } + {isPullingImage && + + Pulling localstack/localstack:latest... Please do not exit this view + + } + {(hasLocalImage.checking || userState.loading || isPullingImage) && + } + { + userState.users.length > 0 && + + + + } + - + ); diff --git a/ui/src/components/Configs/StartConfigs.tsx b/ui/src/components/Configs/StartConfigs.tsx index 0c5eb88..bec15c6 100644 --- a/ui/src/components/Configs/StartConfigs.tsx +++ b/ui/src/components/Configs/StartConfigs.tsx @@ -1,5 +1,5 @@ import { Add as AddIcon, Delete, Edit } from '@mui/icons-material'; -import { Box, Button, IconButton, Theme } from '@mui/material'; +import { Box, Button, ButtonGroup, IconButton, Theme } from '@mui/material'; import React, { ReactElement, useState } from 'react'; import { createStyles, makeStyles } from '@mui/styles'; import { DataGrid, GridColDef, GridRenderCellParams } from '@mui/x-data-grid'; @@ -75,17 +75,18 @@ export const StartConfigs = (): ReactElement => { ]; return ( - - + + + + { } return ['-e', `${item.variable}=${item.value}`]; }).flat(); + const mountArg = '-e LOCALSTACK_VOLUME_DIR=/' + `${ddClient.host.platform === 'darwin' ? 'Users' : 'home'}/${mountPoint}/.localstack-volume`; + ddClient.docker.cli.exec('run', [mountArg, corsArg, ...addedArgs, ...START_ARGS]).then(() => mutate()); }; @@ -88,7 +90,7 @@ export const Controller = (): ReactElement => { variant="contained" onClick={start} startIcon={}> - Startasd + Start diff --git a/ui/src/components/Logs/Logs.tsx b/ui/src/components/Logs/Logs.tsx index cb86b08..d260182 100644 --- a/ui/src/components/Logs/Logs.tsx +++ b/ui/src/components/Logs/Logs.tsx @@ -1,4 +1,4 @@ -import { Box, Typography } from '@mui/material'; +import { Box, Card, Typography } from '@mui/material'; import React, { ReactElement, useEffect, useState } from 'react'; import { useDDClient, useLocalStack } from '../../services/hooks'; @@ -41,7 +41,7 @@ export const Logs = (): ReactElement => { } - + {logs.map(log => ( <> @@ -50,7 +50,7 @@ export const Logs = (): ReactElement => {
))} -
+ ); }; diff --git a/ui/src/constants/common.ts b/ui/src/constants/common.ts index d268ae3..bbcecd4 100644 --- a/ui/src/constants/common.ts +++ b/ui/src/constants/common.ts @@ -1 +1,7 @@ export const DEFAULT_CONFIGURATION_ID='00000000-0000-0000-0000-000000000000'; +export const LOCALSTACK_IMAGES = [ + 'localstack/localstack-light', + 'localstack/localstack', + 'localstack/localstack-pro', + 'localstack/localstack-full', +]; From 710bc400e4da0b7dff41856b69ded805a0a5cbb4 Mon Sep 17 00:00:00 2001 From: Pive01 Date: Fri, 30 Dec 2022 12:06:47 +0100 Subject: [PATCH 15/21] Adjusted /tmp mount option --- ui/src/components/Configs/OnBoarding.tsx | 19 ++++++++++++++----- ui/src/components/Header/Controller.tsx | 6 +++--- ui/src/components/Logs/Logs.tsx | 20 ++++++++++---------- 3 files changed, 27 insertions(+), 18 deletions(-) diff --git a/ui/src/components/Configs/OnBoarding.tsx b/ui/src/components/Configs/OnBoarding.tsx index 67fa11f..60ff626 100644 --- a/ui/src/components/Configs/OnBoarding.tsx +++ b/ui/src/components/Configs/OnBoarding.tsx @@ -29,8 +29,13 @@ export const OnBoarding = (): ReactElement => { setUserState({ loading: true, selectedUser: userState.selectedUser, users: userState.users }); const path = ddClient.host.platform === 'darwin' ? 'Users' : 'home'; const res = await ddClient.docker.cli.exec('run', - ['--entrypoint=', '-v', `/${path}:/users`, 'localstack/localstack', 'ls', '/users']); + ['--entrypoint=', '-v', `/${path}:/users`, 'localstack/localstack', 'ls','/users']); + if(res.stderr !== '' || res.stdout === ''){ + ddClient.desktopUI.toast.error(`Error while locating users: ${ res.stderr}\n using /tmp`); + setUserState({ loading: false, selectedUser: 'tmp', users: ['tmp'] }); + setMountPointUser('tmp'); + } const foundUsers = res.stdout.split('\n'); foundUsers.pop(); // remove last '' element setUserState({ loading: false, selectedUser: foundUsers[0], users: foundUsers }); @@ -70,10 +75,14 @@ export const OnBoarding = (): ReactElement => { }; execChecks(); - }, [userState.users, triggerUseEffect]); + }, [triggerUseEffect]); + + const onClose = () => { + setMountPointUser(userState.selectedUser); + }; return ( - + @@ -104,7 +113,7 @@ export const OnBoarding = (): ReactElement => { {(hasLocalImage.checking || userState.loading || isPullingImage) && } { - userState.users.length > 0 && + userState.users.length > 0 &&