Skip to content

Commit

Permalink
feat: Add ability to configure manual VRM portals
Browse files Browse the repository at this point in the history
  • Loading branch information
mman committed Oct 17, 2024
1 parent 5d8ee03 commit be391d8
Showing 1 changed file with 138 additions and 31 deletions.
169 changes: 138 additions & 31 deletions src/client/views/settings/VRM.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -17,16 +17,19 @@ import {
CNavLink,
CTabPane,
CTabContent,
CCol,
CRow,
} from "@coreui/react"

import { useGetConfig, usePutConfig, useVRMLogin, useVRMLogout, useVRMRefresh } from "../../hooks/useAdminApi"
import { useFormValidation, extractParameterNameAndValue } from "../../hooks/useFormValidation"
import { DeviceList } from "./DeviceList"
import { AppConfig, AppVRMConfig, AppVRMConfigKey } from "../../../shared/types"
import { AppState } from "../../store"
import { VRMLoginMethod, VRMLoginRequest } from "../../../shared/api"
import { VRMDeviceType, VRMLoginMethod, VRMLoginRequest } from "../../../shared/api"
import { VRMStatus } from "../../../shared/state"
import { WebSocketStatus } from "./WebsocketStatus"
import { EditableHostList } from "./EditableDeviceList"

function VRM() {
const [{ data: config, loading: _isLoading, error: _loadError }, loadConfig, _cancelLoadConfig] = useGetConfig()
Expand Down Expand Up @@ -55,7 +58,9 @@ function VRM() {
] = useVRMRefresh()

const isSaveEnabled = useFormValidation(() => {
return temporaryConfig !== undefined
return (
temporaryConfig !== undefined && temporaryConfig.vrm.manualPortalIds.filter((x) => x.portalId === "").length === 0
)
})

function handleEnableChange(event: React.ChangeEvent<HTMLInputElement>) {
Expand Down Expand Up @@ -136,7 +141,43 @@ function VRM() {
})
}

function handleAddPortal(_event: React.MouseEvent<HTMLButtonElement | HTMLAnchorElement, MouseEvent>) {
const clone = { ...temporaryConfig!! }
clone.vrm.manualPortalIds.push({ portalId: "", enabled: true })
setTemporaryConfig(clone)
}

function handleDeletePortal(
_event: React.MouseEvent<HTMLButtonElement | HTMLAnchorElement, MouseEvent>,
index: number,
) {
const clone = { ...temporaryConfig!! }
clone.vrm.manualPortalIds.splice(index, 1)
setTemporaryConfig(clone)
}

function handlePortalIdChange(event: React.ChangeEvent<HTMLInputElement>, index: number) {
const clone = { ...temporaryConfig!! }
clone.vrm.manualPortalIds[index].portalId = event.target.value
setTemporaryConfig(clone)
}

function handleEnableHostChange(event: React.ChangeEvent<HTMLInputElement>, index: number) {
const clone = { ...temporaryConfig!! }
clone.vrm.manualPortalIds[index].enabled = event.target.checked
setTemporaryConfig(clone)
}

function handleEnableAllHostsChange(event: React.ChangeEvent<HTMLInputElement>) {
const clone = { ...temporaryConfig!! }
clone.vrm.manualPortalIds = clone.vrm.manualPortalIds.map((element) => {
return { portalId: element.portalId, enabled: event.target.checked }
})
setTemporaryConfig(clone)
}

const [loginMethod, setLoginMethod] = useState<VRMLoginMethod>("credentials")
const [displayedDevices, setDisplayedDevices] = useState<VRMDeviceType>("discovered")
const [showStatusPane, setShowStatusPane] = useState(false)

const websocketStatus = useSelector((state: AppState) => state.websocketStatus)
Expand Down Expand Up @@ -199,37 +240,88 @@ function VRM() {
vrmStatus={vrmStatus}
loginMethod={loginMethod}
/>
<CButton
color="primary"
onClick={() => handleVRMRefresh()}
hidden={!temporaryConfig.vrm.hasToken}
disabled={isVRMRefreshInProgress}
>
{isVRMRefreshInProgress ? "Working..." : "Refresh"}
</CButton>{" "}
<CButton
color="primary"
onClick={() => handleVRMLogout()}
hidden={!temporaryConfig.vrm.hasToken}
disabled={!temporaryConfig.vrm.hasToken}
>
{isVRMLogoutInProgress ? "Working..." : "Logout"}
</CButton>
<VRMStatusPane hidden={!showStatusPane} status={vrmStatus} />
<CForm>
<DeviceList
hidden={!temporaryConfig.vrm.hasToken}
settings={temporaryConfig.vrm}
availablePortalIds={vrmDiscovered}
onEnablePortalChange={handleEnablePortalChange}
onEnableAllPortalsChange={handleEnableAllPortalsChange}
/>
</CForm>
<CNav variant="underline">
<CNavItem>
<CNavLink
href="#!"
active={displayedDevices == "discovered"}
onClick={(e) => {
e.preventDefault()
setDisplayedDevices("discovered")
}}
>
Discovered ({vrmDiscovered.length})
</CNavLink>
</CNavItem>
<CNavItem>
<CNavLink
href="#!"
active={displayedDevices == "configured"}
onClick={(e) => {
e.preventDefault()
setDisplayedDevices("configured")
}}
>
Configured ({temporaryConfig.vrm.manualPortalIds.length})
</CNavLink>
</CNavItem>
</CNav>
<CTabContent>
<CTabPane role="tabpanel" visible={displayedDevices === "discovered"}>
<VRMStatusPane hidden={!showStatusPane} status={vrmStatus} />
<CForm>
<DeviceList
hidden={!temporaryConfig.vrm.hasToken}
settings={temporaryConfig.vrm}
availablePortalIds={vrmDiscovered}
onEnablePortalChange={handleEnablePortalChange}
onEnableAllPortalsChange={handleEnableAllPortalsChange}
/>
</CForm>
<CButton
color="primary"
onClick={() => handleVRMRefresh()}
hidden={!temporaryConfig.vrm.hasToken}
disabled={isVRMRefreshInProgress}
>
{isVRMRefreshInProgress ? "Working..." : "Refresh"}
</CButton>{" "}
</CTabPane>
<CTabPane role="tabpanel" visible={displayedDevices === "configured"}>
<VRMInfoPane hidden={!showStatusPane} text="Add Installations by specifying their Portal ID" />
<CForm>
<EditableHostList
entries={temporaryConfig.vrm.manualPortalIds}
onEntryValueChange={handlePortalIdChange}
onEnableEntryChange={handleEnableHostChange}
onEnableAllEntriesChange={handleEnableAllHostsChange}
onAddEntry={handleAddPortal}
onDeleteEntry={handleDeletePortal}
entryTitleText="Portal ID"
addEntryButtonText="Add Installation"
/>
</CForm>
</CTabPane>
</CTabContent>
</CCardBody>
<CCardFooter>
<CButton color="primary" onClick={() => save({ data: temporaryConfig })} disabled={!isSaveEnabled}>
{isSaving ? "Saving..." : "Save"}
</CButton>
<CRow>
<CCol>
<CButton color="primary" onClick={() => save({ data: temporaryConfig })} disabled={!isSaveEnabled}>
{isSaving ? "Saving..." : "Save"}
</CButton>
</CCol>
<CCol xs="auto">
<CButton
color="primary"
onClick={() => handleVRMLogout()}
hidden={!temporaryConfig.vrm.hasToken}
disabled={!temporaryConfig.vrm.hasToken}
>
{isVRMLogoutInProgress ? "Working..." : "Logout"}
</CButton>
</CCol>
</CRow>
</CCardFooter>
</CCard>
)
Expand Down Expand Up @@ -383,4 +475,19 @@ function VRMStatusPane(props: VRMStatusPaneProps) {
)
}

interface VRMInfoPaneProps {
hidden: boolean
text: string
}

function VRMInfoPane(props: VRMInfoPaneProps) {
return (
<div className="pt-3">
<CAlert hidden={props.hidden} color="secondary">
<small>{props.text}</small>
</CAlert>
</div>
)
}

export default VRM

0 comments on commit be391d8

Please sign in to comment.