Skip to content

Commit

Permalink
feat: Annotate redux store with TS types
Browse files Browse the repository at this point in the history
  • Loading branch information
mman committed Oct 15, 2024
1 parent 5c1b2f0 commit f1bc4fd
Show file tree
Hide file tree
Showing 2 changed files with 250 additions and 0 deletions.
39 changes: 39 additions & 0 deletions src/client/actions.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
import { Dispatch } from "redux"
import { AppStateAction } from "../shared/state"

// NOTE: defined as global via webpack.DefinePlugin
declare const VENUS_INFLUX_LOADER_ADMIN_API_PORT: number | undefined

export function openServerEventsConnection(dispatch: Dispatch<AppStateAction>) {
console.log(`VENUS_INFLUX_LOADER_ADMIN_API_PORT: ${VENUS_INFLUX_LOADER_ADMIN_API_PORT}`)
const host = `${window.location.hostname}:${(VENUS_INFLUX_LOADER_ADMIN_API_PORT || window.location.port)}`

console.log("openServerEventsConnection: host: " + host)
const proto = window.location.protocol === "https:" ? "wss" : "ws"
const ws = new WebSocket(new URL("/stream", `${proto}://${host}`))
ws.onmessage = function (event) {
const serverEvent = JSON.parse(event.data)
if (serverEvent.type) {
dispatch(serverEvent)
}
}
ws.onclose = () => {
console.log("closed")
dispatch({
type: "WEBSOCKET_CLOSE",
})
}
ws.onerror = (error) => {
console.log(`error: ${JSON.stringify(error)}`)
dispatch({
type: "WEBSOCKET_ERROR",
})
}
ws.onopen = () => {
console.log("connected")
dispatch({
type: "WEBSOCKET_OPEN",
data: ws,
})
}
}
211 changes: 211 additions & 0 deletions src/client/store.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,211 @@
import { createStore } from "redux"
import { openServerEventsConnection } from "./actions"
import { AppConfig, LogEntry } from "../shared/types"
import { AppStateAction, LoaderStatistics, VRMStatus } from "../shared/state"

// TODO: migrate store.js to redux toolkit
// TODO: specify slices with concrete state + actions
// TODO: figure out where to handle live server connection
// TODO: initial connect and reconnect

export interface AppState {
websocketStatus: "initial" | "open" | "connected" | "error" | "closed"
webSocket?: WebSocket
webSocketTimer?: any // TODO: what is the proper type in browser context
restarting: boolean

settings?: AppConfig
loaderStatistics: LoaderStatistics

vrmStatus: VRMStatus
vrmDiscovered: { portalId: string, name: string }[]

upnpDiscovered: string[]

debug: boolean
log: {
entries: LogEntry[]
}

sidebarShow: boolean
editSettings: {
showEditDiscoverySettings: boolean
showEditVRMSettings: boolean
showEditManualSettings: boolean
showEditSecuritySettings: boolean
showEditInfluxDBSettings: boolean
},
}

const initialState: AppState = {
websocketStatus: "initial",
webSocket: undefined,
restarting: false,

loaderStatistics: { measurementCount: 0, measurementRate: 0, deviceStatistics: {} },

vrmStatus: { status: "success", message: "" },

vrmDiscovered: [],
upnpDiscovered: [],

debug: false,
log: {
entries: [] as LogEntry[],
},
sidebarShow: true,

editSettings: {
showEditDiscoverySettings: true,
showEditVRMSettings: true,
showEditManualSettings: true,
showEditSecuritySettings: true,
showEditInfluxDBSettings: true,
},
}


const changeState = (state = initialState, action: AppStateAction): AppState => {
if (action.type === "set") {
return {
...state,
...action,
}
}
if (action.type === "LOADERSTATISTICS") {
return {
...state,
loaderStatistics: action.data,
}
}
if (action.type === "UPNPDISCOVERY") {
return {
...state,
upnpDiscovered: action.data,
}
}
if (action.type === "VRMDISCOVERY") {
return {
...state,
vrmDiscovered: action.data,
}
}
if (action.type === "VRMSTATUS") {
return {
...state,
vrmStatus: action.data,
}
}
if (action.type === "SETTINGSCHANGED") {
return {
...state,
settings: action.data,
}
}
if (action.type === "DEBUG") {
return {
...state,
debug: action.data,
}
}
if (action.type === "EDIT_SECURITY_SETTINGS_ENABLED") {
return {
...state,
editSettings: {
...state.editSettings,
showEditSecuritySettings: action.data,
},
}
}
if (action.type === "EDIT_INFLUXDB_SETTINGS_ENABLED") {
return {
...state,
editSettings: {
...state.editSettings,
showEditInfluxDBSettings: action.data,
},
}
}
if (action.type === "EDIT_DISCOVERY_SETTINGS_ENABLED") {
return {
...state,
editSettings: {
...state.editSettings,
showEditDiscoverySettings: action.data,
},
}
}
if (action.type === "EDIT_MANUAL_SETTINGS_ENABLED") {
return {
...state,
editSettings: {
...state.editSettings,
showEditManualSettings: action.data,
},
}
}
if (action.type === "EDIT_VRM_SETTINGS_ENABLED") {
return {
...state,
editSettings: {
...state.editSettings,
showEditVRMSettings: action.data,
},
}
}
if (action.type === "LOG") {
state.log.entries.push(action.data)
if (state.log.entries.length > 100) {
state.log.entries.splice(0, state.log.entries.length - 100)
}
return {
...state,
log: {
entries: state.log.entries,
},
}
}
if (action.type === "WEBSOCKET_CONNECTED") {
return {
...state,
websocketStatus: "connected",
}
}
if (action.type === "WEBSOCKET_OPEN") {
if (state.webSocketTimer) {
clearInterval(state.webSocketTimer)
delete state.webSocketTimer
}
if (state.restarting) {
state.restarting = false
}
return {
...state,
websocketStatus: "open",
webSocket: action.data,
}
}
if (action.type === "WEBSOCKET_ERROR") {
return {
...state,
websocketStatus: "error",
}
}
if (action.type === "WEBSOCKET_CLOSE") {
if (!state.webSocketTimer) {
state.webSocketTimer = setInterval(() => {
console.log("retry...")
openServerEventsConnection(store.dispatch)
}, 5 * 1000)
}
return {
...state,
websocketStatus: "closed",
webSocket: undefined,
}
}
return state
}

const store = createStore(changeState)
export default store

0 comments on commit f1bc4fd

Please sign in to comment.