From c97225b00a48b4259bec7be7c3d8599c66fa22f8 Mon Sep 17 00:00:00 2001 From: Peli de Halleux Date: Fri, 10 Feb 2023 05:44:15 +0000 Subject: [PATCH] removed brains, better dark mode --- jacdac-ts | 2 +- pxt-jacdac | 2 +- .../brains/BrainConnectedButton.tsx | 19 - src/components/brains/BrainDeviceCard.tsx | 179 ------ .../brains/BrainDeviceGridItems.tsx | 87 --- src/components/brains/BrainHome.tsx | 24 - .../brains/BrainLiveConnectionButton.tsx | 38 -- src/components/brains/BrainManagerContext.tsx | 197 ------- src/components/brains/BrainManagerToolbar.tsx | 69 --- .../brains/BrainManagerTreeViewItem.tsx | 229 -------- src/components/brains/BrainScriptCard.tsx | 184 ------ .../brains/BrainScriptGridItems.tsx | 52 -- .../brains/CreateBrainScriptDialog.tsx | 65 --- .../brains/RegisterBrainDeviceDialog.tsx | 104 ---- src/components/brains/WebSocketBridge.ts | 62 --- src/components/brains/braindom.ts | 522 ------------------ src/components/brains/useBrainDevice.ts | 14 - src/components/brains/useBrainScript.ts | 9 - .../dashboard/DashboardCloudConfiguration.tsx | 76 +-- .../devicescript/DeviceScriptDevTools.tsx | 11 - .../devicescript/DeviceScriptManagerChip.tsx | 11 +- .../devicescript/DeviceScriptTextEditor.tsx | 10 - .../devicescript/DeviceScriptTextField.tsx | 27 +- .../devicescript/JacscriptEditorToolbar.tsx_ | 29 - src/components/layout.tsx | 8 +- src/components/shell/AppDrawer.tsx | 4 +- src/components/shell/DrawerToolsButton.tsx | 24 +- src/components/shell/MainAppBar.tsx | 43 +- src/components/tools/JDomTreeView.tsx | 17 - src/components/ui/ThemedLayout.tsx | 11 +- src/pages/brains.tsx | 14 - src/pages/brains/manager.tsx | 39 -- yarn.lock | 506 ++++++++--------- 33 files changed, 297 insertions(+), 2391 deletions(-) delete mode 100644 src/components/brains/BrainConnectedButton.tsx delete mode 100644 src/components/brains/BrainDeviceCard.tsx delete mode 100644 src/components/brains/BrainDeviceGridItems.tsx delete mode 100644 src/components/brains/BrainHome.tsx delete mode 100644 src/components/brains/BrainLiveConnectionButton.tsx delete mode 100644 src/components/brains/BrainManagerContext.tsx delete mode 100644 src/components/brains/BrainManagerToolbar.tsx delete mode 100644 src/components/brains/BrainManagerTreeViewItem.tsx delete mode 100644 src/components/brains/BrainScriptCard.tsx delete mode 100644 src/components/brains/BrainScriptGridItems.tsx delete mode 100644 src/components/brains/CreateBrainScriptDialog.tsx delete mode 100644 src/components/brains/RegisterBrainDeviceDialog.tsx delete mode 100644 src/components/brains/WebSocketBridge.ts delete mode 100644 src/components/brains/braindom.ts delete mode 100644 src/components/brains/useBrainDevice.ts delete mode 100644 src/components/brains/useBrainScript.ts delete mode 100644 src/pages/brains.tsx delete mode 100644 src/pages/brains/manager.tsx diff --git a/jacdac-ts b/jacdac-ts index cefb2a9332f4..931b0131f27f 160000 --- a/jacdac-ts +++ b/jacdac-ts @@ -1 +1 @@ -Subproject commit cefb2a9332f4f5dd908dd112afee99f05b810041 +Subproject commit 931b0131f27fb20e066addf05d65112e5bec9345 diff --git a/pxt-jacdac b/pxt-jacdac index a30a0016b781..63d0dc59248e 160000 --- a/pxt-jacdac +++ b/pxt-jacdac @@ -1 +1 @@ -Subproject commit a30a0016b78134a137d259e385ccccc77e849ead +Subproject commit 63d0dc59248e3e567d0d6698c9ffb65c79cd0dcc diff --git a/src/components/brains/BrainConnectedButton.tsx b/src/components/brains/BrainConnectedButton.tsx deleted file mode 100644 index 39bf82c064e7..000000000000 --- a/src/components/brains/BrainConnectedButton.tsx +++ /dev/null @@ -1,19 +0,0 @@ -import React from "react" -import useChange from "../../jacdac/useChange" -import ServiceConnectedIconButton from "../buttons/ServiceConnectedIconButton" -import { BrainDevice } from "./braindom" - -export default function BrainConnectedButton(props: { brain: BrainDevice }) { - const { brain } = props - const connected = useChange(brain, _ => _.connected) - const handleConnectionClick = ev => { - ev.stopPropagation() - ev.preventDefault() - } - return ( - - ) -} diff --git a/src/components/brains/BrainDeviceCard.tsx b/src/components/brains/BrainDeviceCard.tsx deleted file mode 100644 index 54477f013ed9..000000000000 --- a/src/components/brains/BrainDeviceCard.tsx +++ /dev/null @@ -1,179 +0,0 @@ -import { - Card, - CardActions, - CardContent, - CardHeader, - Grid, - MenuItem, - SelectChangeEvent, - Typography, -} from "@mui/material" -import React, { lazy, useContext, useState, useEffect } from "react" -import DeviceIconFromProductIdentifier from "../devices/DeviceIconFromProductIdentifier" -import { BrainDevice } from "./braindom" -import useChange from "../../jacdac/useChange" -import BrainConnectedButton from "./BrainConnectedButton" -import BrainManagerContext from "./BrainManagerContext" -import BrainLiveConnectionButton from "./BrainLiveConnectionButton" -import { shortDeviceId } from "../../../jacdac-ts/src/jacdac" -import CmdButton from "../CmdButton" -import Suspense from "../ui/Suspense" -import IconButtonWithTooltip from "../ui/IconButtonWithTooltip" -import DeleteIcon from "@mui/icons-material/Delete" -import SelectWithLabel from "../ui/SelectWithLabel" -import useEffectAsync from "../useEffectAsync" -import UploadIcon from "@mui/icons-material/Upload" - -const ConfirmDialog = lazy(() => import("../shell/ConfirmDialog")) - -function BrainDeviceScriptSelect(props: { brain: BrainDevice }) { - const { brain } = props - const { brainManager } = useContext(BrainManagerContext) - const scriptId = useChange(brain, _ => _?.scriptId) || "" - const scriptVersion = useChange(brain, _ => _?.scriptVersion) || undefined - const scripts = useChange(brainManager, _ => _?.scripts()) - - const [currentScriptId, setCurrentScriptId] = useState(scriptId) - const [currentVersion, setCurrentVersion] = useState(undefined) - const currentScript = useChange( - brainManager, - _ => _.script(currentScriptId), - [currentScriptId] - ) - const currentVersions = useChange(currentScript, _ => _?.versions()) - - const handleScriptChange = (ev: SelectChangeEvent) => { - const newId = ev.target.value - setCurrentScriptId(newId) - const newVersion = !newId - ? undefined - : newId === scriptId - ? scriptVersion - : brainManager.script(newId)?.version - setCurrentVersion(newVersion) - } - const handleVersionChange = (ev: SelectChangeEvent) => { - const newVersion = ev.target.value - setCurrentVersion(parseInt(newVersion) || undefined) - } - const handleDeploy = async () => { - await brain.updateScript(currentScriptId, currentVersion) - } - - // refresh from cloud - useEffect(() => { - setCurrentScriptId(scriptId) - setCurrentVersion(scriptVersion) - }, [scriptId, scriptVersion]) - - // refresh from cloud - useEffectAsync(() => currentScript?.refreshVersions(), [currentScript]) - - const scriptChanged = currentScriptId !== scriptId - const versionChanged = currentVersion !== scriptVersion - - return ( - - - - None - {scripts.map(script => ( - - {script.name} - - ))} - - - - - None - {currentVersions?.map(v => ( - - v{v.version} - - ))} - - - - } - /> - - - ) -} - -export default function BrainDeviceCard(props: { brain: BrainDevice }) { - const { brain } = props - const { productId } = useChange(brain, _ => _.meta) - const { deviceId } = brain - const name = useChange(brain, _ => _.name) - const [confirmDeleteOpen, setConfirmDeleteOpen] = useState(false) - - const handleOpenDelete = () => setConfirmDeleteOpen(true) - const handleDelete = async () => { - await brain.delete() - } - - return ( - - - - - {productId && ( - - )} - - } - action={ - - - - } - /> - - {name} - {deviceId} - - - - - - - - - ) -} diff --git a/src/components/brains/BrainDeviceGridItems.tsx b/src/components/brains/BrainDeviceGridItems.tsx deleted file mode 100644 index 6bf5519fed06..000000000000 --- a/src/components/brains/BrainDeviceGridItems.tsx +++ /dev/null @@ -1,87 +0,0 @@ -import { - Grid, - TextField, -} from "@mui/material" -import React, { - useContext, - useState, - useId, -} from "react" -import SearchIcon from "@mui/icons-material/Search" -import useChange from "../../jacdac/useChange" -import BrainManagerContext from "./BrainManagerContext" -import GridHeader from "../ui/GridHeader" -import CmdButton from "../CmdButton" -import RefreshIcon from "@mui/icons-material/Refresh" -import IconButtonWithTooltip from "../ui/IconButtonWithTooltip" -import { useDebounce } from "use-debounce" -import BrainDeviceCard from "./BrainDeviceCard" - -export default function BrainDeviceGridItems() { - const { brainManager } = useContext(BrainManagerContext) - const id = useId() - const searchId = id + "-search" - const [search, setSearch] = useState(false) - const [query, setQuery] = useState("") - const [debouncedFilter] = useDebounce(query, 200) - const handleQueryChange = (event: React.ChangeEvent) => - setQuery(event.target.value || "") - - const brains = useChange( - brainManager, - _ => - _?.devices()?.filter( - d => - !search || - d.name.indexOf(debouncedFilter) > -1 || - d.deviceId.indexOf(debouncedFilter) > -1 - ), - [debouncedFilter] - ) - - const handleRefresh = () => brainManager?.refreshDevices() - const handleSearchClick = () => setSearch(!search) - return ( - <> - - } - disabled={!brainManager} - /> - - - - - } - /> - {search && ( - - - - )} - {brains?.map(brain => ( - - - - ))} - - ) -} \ No newline at end of file diff --git a/src/components/brains/BrainHome.tsx b/src/components/brains/BrainHome.tsx deleted file mode 100644 index 3d9b88a9fc1d..000000000000 --- a/src/components/brains/BrainHome.tsx +++ /dev/null @@ -1,24 +0,0 @@ -import { Grid, Typography } from "@mui/material" -import React, { useContext } from "react" -import BrainManagerContext from "./BrainManagerContext" -import BrainScriptGridItems from "./BrainScriptGridItems" -import BrainDeviceGridItems from "./BrainDeviceGridItems" - -export default function BrainHome() { - const { brainManager } = useContext(BrainManagerContext) - if (!brainManager) return null - return ( - - - - connected to{" "} - - {brainManager.apiRoot} - - - - - - - ) -} diff --git a/src/components/brains/BrainLiveConnectionButton.tsx b/src/components/brains/BrainLiveConnectionButton.tsx deleted file mode 100644 index f722e19ae710..000000000000 --- a/src/components/brains/BrainLiveConnectionButton.tsx +++ /dev/null @@ -1,38 +0,0 @@ -import React, { useContext } from "react" -import { BrainDevice } from "./braindom" -import BrainManagerContext from "./BrainManagerContext" -import ScreenShareIcon from "@mui/icons-material/ScreenShare" -import StopScreenShareIcon from "@mui/icons-material/StopScreenShare" -import CmdButton from "../CmdButton" -import useChange from "../../jacdac/useChange" -import useBus from "../../jacdac/useBus" - -export default function BrainLiveConnectionButton(props: { - brain: BrainDevice -}) { - const { brain } = props - const { liveDeviceId, connectLiveDevice } = useContext(BrainManagerContext) - const { deviceId } = brain - const bus = useBus() - const device = useChange(bus, _ => _?.device(deviceId, true), [deviceId]) - const connected = useChange(brain, _ => _.connected) - const selected = liveDeviceId === deviceId - const disabled = (!connected || !!device) && !selected - - const handleClick = () => connectLiveDevice(selected ? "" : deviceId) - - return ( - - ) : ( - - ) - } - /> - ) -} diff --git a/src/components/brains/BrainManagerContext.tsx b/src/components/brains/BrainManagerContext.tsx deleted file mode 100644 index c6e64d5f9528..000000000000 --- a/src/components/brains/BrainManagerContext.tsx +++ /dev/null @@ -1,197 +0,0 @@ -import { navigate } from "gatsby" -import React, { - createContext, - useEffect, - useMemo, - useState, - useRef, - lazy, -} from "react" -import { CLOSE } from "../../../jacdac-ts/src/jdom/constants" -import useBus from "../../jacdac/useBus" -import useChange from "../../jacdac/useChange" -import useLocalStorage, { getLocalStorageItem } from "../hooks/useLocalStorage" -import Suspense from "../ui/Suspense" -import useEffectAsync from "../useEffectAsync" -import { BrainManager, BrainScript } from "./braindom" -import WebSocketBridge from "./WebSocketBridge" -const CreateBrainScriptDialog = lazy(() => import("./CreateBrainScriptDialog")) - -export interface BrainManagerProps { - domain?: string - setDomain: (domain: string) => void - token?: string - setToken: (token: string) => void - brainManager: BrainManager - scriptId?: string - setScriptId: (id: string) => void - createScript: ( - name: string, - editor?: "js" | "blocks" - ) => Promise - openScript: (id: string) => Promise - showNewScriptDialog: () => void - deviceId?: string - setDeviceId: (id: string) => void - liveDeviceId?: string - connectLiveDevice: (id: string) => Promise -} - -const defaultContextProps: BrainManagerProps = Object.freeze({ - setDomain: () => {}, - setToken: () => {}, - setScriptId: () => {}, - setDeviceId: () => {}, - connectLiveDevice: async () => {}, - createScript: async () => undefined, - showNewScriptDialog: () => {}, - openScript: async () => {}, - brainManager: undefined, -}) -const BrainManagerContext = - createContext(defaultContextProps) -BrainManagerContext.displayName = "brains" - -export default BrainManagerContext - -const DOMAIN_KEY = "brain-manager-domain" -const TOKEN_KEY = "brain-manager-token" - -export function isBrainManagerEnabled() { - return !!getLocalStorageItem(TOKEN_KEY) -} - -// eslint-disable-next-line react/prop-types -export const BrainManagerProvider = ({ children }) => { - const bus = useBus() - const [createScriptOpen, setCreateScriptOpen] = useState(false) - const [domain, _setDomain] = useLocalStorage( - DOMAIN_KEY, - "https://jacdac-portal2.azurewebsites.net" - ) - const [token, setToken] = useLocalStorage(TOKEN_KEY) - const brainManager = useMemo( - () => - token && domain ? new BrainManager(bus, domain, token) : undefined, - [domain, token] - ) - const [scriptId, setScriptId] = useState("") - const [deviceId, setDeviceId] = useState("") - const [liveDeviceId, setLiveDeviceId] = useState("") - const bridgeRef = useRef<{ - deviceId: string - bridge: WebSocketBridge - }>() - - const handleCloseCreateScriptDialog = () => setCreateScriptOpen(false) - const showNewScriptDialog = () => setCreateScriptOpen(true) - - const setDomain = (domain: string) => { - _setDomain(domain?.replace(/\/$/, "")) - setToken("") - } - - const openScript = async (sid: string) => { - const script = brainManager?.script(sid) - if (!script) return - const body = await script.refreshBody() - if (!body) return - - // commit script and open - setScriptId(script.scriptId) - navigate("/editors/devicescript/") - } - - const createScript = async (name: string, editor?: "js" | "blocks") => { - const script = await brainManager?.createScript( - name || `my device.${editor || "js"}`, - editor - ) - return script - } - - // refresh selected device, scripts - useChange( - brainManager, - (_: BrainManager) => { - if (scriptId && !_?.script(scriptId)) setScriptId("") - if (deviceId && !_?.device(deviceId)) setDeviceId("") - if (liveDeviceId) { - const ld = _?.device(liveDeviceId) - if (!ld?.connected) setLiveDeviceId("") - } - }, - [scriptId, deviceId, liveDeviceId] - ) - - // first reload - useEffectAsync(() => brainManager?.refresh(), []) - - const cleanupBridge = () => { - const { bridge } = bridgeRef.current || {} - if (bridge) { - console.debug(`cleanup transport`) - bridge.bus = undefined - bridgeRef.current = undefined - } - } - - const connectLiveDevice = async (did: string) => { - const dev = brainManager?.device(did) - if (dev && did === liveDeviceId) return // already opened - - cleanupBridge() - - const { url, protocol } = (await dev?.createConnection()) || {} - if (!url) { - setLiveDeviceId("") - return - } - - console.debug(`connect websocket ${url}`) - const bridge = new WebSocketBridge(url, protocol) - bridge.on(CLOSE, () => brainManager.refreshDevices()) - bridge.bus = bus - bridgeRef.current = { - deviceId: liveDeviceId, - bridge, - } - bridge.connect() - setLiveDeviceId(did) - } - - useEffect(() => { - if (!liveDeviceId) cleanupBridge() - }, [liveDeviceId]) - useEffect(() => cleanupBridge, []) - - return ( - - {children} - {createScriptOpen && ( - - - - )} - - ) -} diff --git a/src/components/brains/BrainManagerToolbar.tsx b/src/components/brains/BrainManagerToolbar.tsx deleted file mode 100644 index d9ff44375bcc..000000000000 --- a/src/components/brains/BrainManagerToolbar.tsx +++ /dev/null @@ -1,69 +0,0 @@ -import { Grid, TextField } from "@mui/material" -import React, { useContext, useState } from "react" -import CloudUploadIcon from "@mui/icons-material/CloudUpload" -import BlockContext from "../blockly/BlockContext" -import useChange from "../../jacdac/useChange" -import { BrainScript } from "./braindom" -import CmdButton from "../CmdButton" -import useDeviceScript from "../devicescript/DeviceScriptContext" -import { toHex } from "../../../jacdac-ts/src/jdom/utils" - -function SaveScriptButton(props: { script: BrainScript; name: string }) { - const { script, name } = props - const { workspaceSaved } = useContext(BlockContext) - const { source, bytecode } = useDeviceScript() - - const sourceBlocks = useChange(script, _ => _.sourceBlocks) - const ws = JSON.stringify(workspaceSaved) - const changed = name !== script.name || sourceBlocks !== ws - - const handleUpload = async () => { - if (name && name !== script.name) await script.updateName(name) - await script.uploadBody({ - blocks: workspaceSaved ? JSON.stringify(workspaceSaved) : undefined, - text: source, - compiled: bytecode ? toHex(bytecode) : undefined, - }) - } - return ( - } - onClick={handleUpload} - color={changed ? "warning" : "primary"} - variant={changed ? "contained" : "outlined"} - > - Save - - ) -} - -export default function BrainManagerToolbar(props: { script: BrainScript }) { - const { script } = props - const { name } = script - const [_name, _setName] = useState(name) - const nameChanged = name !== _name - - const handleChange = (ev: React.ChangeEvent) => { - _setName(ev.target.value) - } - - return ( - - - - - - - - - ) -} diff --git a/src/components/brains/BrainManagerTreeViewItem.tsx b/src/components/brains/BrainManagerTreeViewItem.tsx deleted file mode 100644 index 6af3ed9883e2..000000000000 --- a/src/components/brains/BrainManagerTreeViewItem.tsx +++ /dev/null @@ -1,229 +0,0 @@ -import React, { useContext, useState, MouseEvent } from "react" -import { JDomTreeViewProps } from "../tools/JDomTreeViewItems" -import StyledTreeItem, { StyledTreeViewItemProps } from "../ui/StyledTreeItem" -import CloudQueueIcon from "@mui/icons-material/CloudQueue" -import { DEVICE_NODE_NAME } from "../../../jacdac-ts/src/jdom/constants" -import BrainManagerContext from "./BrainManagerContext" -import RefreshIcon from "@mui/icons-material/Refresh" -import CmdButton from "../CmdButton" -import useChange from "../../jacdac/useChange" -import EditIcon from "@mui/icons-material/Edit" -import { BrainDevice, BrainScript } from "./braindom" -import AddIcon from "@mui/icons-material/Add" -import IconButtonWithTooltip from "../ui/IconButtonWithTooltip" -import RegisterBrainDeviceDialog from "./RegisterBrainDeviceDialog" -import { navigate } from "gatsby" -import useEffectAsync from "../useEffectAsync" -import DeviceIconFromProductIdentifier from "../devices/DeviceIconFromProductIdentifier" -import SourceIcon from "@mui/icons-material/Source" -import ArticleIcon from "@mui/icons-material/Article" -import BrainConnectedButton from "./BrainConnectedButton" -import { shortDeviceId } from "../../../jacdac-ts/src/jdom/pretty" -import FolderOpenIcon from "@mui/icons-material/FolderOpen" -import BrainLiveConnectionButton from "./BrainLiveConnectionButton" -import useBrainScript from "./useBrainScript" -import { Button } from "gatsby-theme-material-ui" -export default function BrainManagerTreeItem( - props: StyledTreeViewItemProps & JDomTreeViewProps -) { - const nodeId = "brain-manager" - const name = "brains" - const { brainManager } = useContext(BrainManagerContext) - - const handleRefresh = async () => { - await brainManager?.refresh() - } - const handleOpenBrains = ev => { - ev.stopPropagation() - ev.preventDefault() - navigate("/brains") - } - useEffectAsync(handleRefresh, [brainManager]) - - return ( - } - actions={ - <> - - - - } - onClick={handleRefresh} - /> - - } - > - - - - ) -} - -function BrainScriptsTreeItem( - props: StyledTreeViewItemProps & JDomTreeViewProps -) { - const { brainManager, showNewScriptDialog } = - useContext(BrainManagerContext) - const scripts = useChange(brainManager, _ => _?.scripts()) - const nodeId = "brain-manager-programs" - const name = "programs" - - const handleNewScript = (ev: MouseEvent) => { - ev.stopPropagation() - ev.preventDefault() - showNewScriptDialog() - } - - return ( - } - actions={ - - - - } - > - {scripts?.map(script => ( - - ))} - - ) -} - -function BrainScriptTreeItem( - props: { script: BrainScript } & StyledTreeViewItemProps & JDomTreeViewProps -) { - const { script } = props - const { scriptId, openScript } = useContext(BrainManagerContext) - const { id } = script - const name = useChange(script, _ => _.name) - const version = useChange(script, _ => _.version) - const nodeId = `brain-manager-programs-${id}` - const current = id === scriptId - const caption = `v${version || ""}` - const info = useChange(script, _ => _.creationTime?.toLocaleString()) - - const handleOpen = async () => await openScript(script.scriptId) - - return ( - } - onClick={handleOpen} - /> - } - icon={} - > - ) -} - -function BrainDevicesTreeItem( - props: StyledTreeViewItemProps & JDomTreeViewProps -) { - const { brainManager } = useContext(BrainManagerContext) - const [open, setOpen] = useState(false) - const devices = useChange(brainManager, _ => _?.devices()) - const nodeId = "brain-manager-devices" - const name = "devices" - - const handleDialogOpenToggle = ev => { - ev.stopPropagation() - ev.preventDefault() - setOpen(v => !v) - } - - return ( - - - - } - > - {devices?.map(device => ( - - ))} - - - ) -} - -function BrainDeviceTreeItem( - props: { brain: BrainDevice } & StyledTreeViewItemProps & JDomTreeViewProps -) { - const { brain } = props - const { id } = brain - const { deviceId, setDeviceId } = useContext(BrainManagerContext) - const nodeId = `brain-manager-devices-${id}` - const devId = brain.deviceId - - const connected = useChange(brain, _ => _.connected) - const data = useChange(brain, _ => _.data) - - const { name, scriptId, meta = {} } = data - const { productId } = meta - const script = useBrainScript(scriptId) - const current = devId === deviceId - const caption = script?.toString() || scriptId || `no script` - - const handleClick = () => { - setDeviceId(id) - } - - return ( - - } - actions={ - <> - {connected && } - - - } - /> - ) -} diff --git a/src/components/brains/BrainScriptCard.tsx b/src/components/brains/BrainScriptCard.tsx deleted file mode 100644 index 79d2a3feb006..000000000000 --- a/src/components/brains/BrainScriptCard.tsx +++ /dev/null @@ -1,184 +0,0 @@ -import { - Card, - CardActions, - CardContent, - CardHeader, - Grid, - MenuItem, - SelectChangeEvent, - Typography, -} from "@mui/material" -import React, { lazy, useContext, useState, MouseEvent, useEffect } from "react" -import { BrainDevice, BrainScript } from "./braindom" -import useChange from "../../jacdac/useChange" -import BrainManagerContext from "./BrainManagerContext" -import CmdButton from "../CmdButton" -import ArticleIcon from "@mui/icons-material/Article" -import Suspense from "../ui/Suspense" -import IconButtonWithTooltip from "../ui/IconButtonWithTooltip" -import DeleteIcon from "@mui/icons-material/Delete" -import SelectWithLabel from "../ui/SelectWithLabel" -import { Button } from "gatsby-theme-material-ui" -import useEffectAsync from "../useEffectAsync" -import UploadIcon from "@mui/icons-material/Upload" - -const ConfirmDialog = lazy(() => import("../shell/ConfirmDialog")) - -export default function BrainScriptCard(props: { script: BrainScript }) { - const { script } = props - const { scriptId } = script - const { openScript } = useContext(BrainManagerContext) - const name = useChange(script, _ => _.name) - const version = useChange(script, _ => _.version) - const creationTime = useChange( - script, - _ => _.creationTime, - [], - (a, b) => a?.toLocaleString() === b?.toLocaleString() - ) - const [confirmDeleteOpen, setConfirmDeleteOpen] = useState(false) - const handleDelete = async () => await script.delete() - const handleOpenDelete = (ev: MouseEvent) => { - ev.stopPropagation() - ev.preventDefault() - setConfirmDeleteOpen(true) - } - const handleOpen = () => openScript(scriptId) - return ( - - } - action={ - - - - } - /> - - - {name}{" "} - - v{version} - - - {creationTime && ( - - {creationTime.toLocaleString()} - - )} - - - - - - - - - ) -} - -function BrainDeviceScriptSelect(props: { brain: BrainDevice }) { - const { brain } = props - const { brainManager } = useContext(BrainManagerContext) - const scriptId = useChange(brain, _ => _?.scriptId) || "" - const scriptVersion = useChange(brain, _ => _?.scriptVersion) || undefined - const scripts = useChange(brainManager, _ => _?.scripts()) - - const [currentScriptId, setCurrentScriptId] = useState(scriptId) - const [currentVersion, setCurrentVersion] = useState(undefined) - const currentScript = useChange( - brainManager, - _ => _.script(currentScriptId), - [currentScriptId] - ) - const currentVersions = useChange(currentScript, _ => _?.versions()) - - const handleScriptChange = (ev: SelectChangeEvent) => { - const newId = ev.target.value - setCurrentScriptId(newId) - const newVersion = !newId - ? undefined - : newId === scriptId - ? scriptVersion - : brainManager.script(newId)?.version - setCurrentVersion(newVersion) - } - const handleVersionChange = (ev: SelectChangeEvent) => { - const newVersion = ev.target.value - setCurrentVersion(parseInt(newVersion) || undefined) - } - const handleDeploy = async () => { - await brain.updateScript(currentScriptId, currentVersion) - } - - // refresh from cloud - useEffect(() => { - setCurrentScriptId(scriptId) - setCurrentVersion(scriptVersion) - }, [scriptId, scriptVersion]) - - // refresh from cloud - useEffectAsync(() => currentScript?.refreshVersions(), [currentScript]) - - const scriptChanged = currentScriptId !== scriptId - const versionChanged = currentVersion !== scriptVersion - - return ( - - - - None - {scripts.map(script => ( - - {script.name} - - ))} - - - - - None - {currentVersions?.map(v => ( - - v{v.version} - - ))} - - - - } - /> - - - ) -} diff --git a/src/components/brains/BrainScriptGridItems.tsx b/src/components/brains/BrainScriptGridItems.tsx deleted file mode 100644 index a3a6cc2d6343..000000000000 --- a/src/components/brains/BrainScriptGridItems.tsx +++ /dev/null @@ -1,52 +0,0 @@ -import { Grid } from "@mui/material" -import React, { useContext, MouseEvent } from "react" -import useChange from "../../jacdac/useChange" -import BrainManagerContext from "./BrainManagerContext" -import GridHeader from "../ui/GridHeader" -import CmdButton from "../CmdButton" -import RefreshIcon from "@mui/icons-material/Refresh" -import { Button } from "gatsby-theme-material-ui" -import AddIcon from "@mui/icons-material/Add" -import BrainScriptCard from "./BrainScriptCard" - -export default function BrainScriptGridItems() { - const { brainManager, showNewScriptDialog } = - useContext(BrainManagerContext) - const scripts = useChange(brainManager, _ => _?.scripts()) - - const handleRefresh = () => brainManager?.refreshScripts() - const handleNewScript = (ev: MouseEvent) => { - ev.stopPropagation() - ev.preventDefault() - showNewScriptDialog() - } - - return ( - <> - -