diff --git a/src/api/index.js b/src/api/index.js new file mode 100644 index 0000000..3ee57a3 --- /dev/null +++ b/src/api/index.js @@ -0,0 +1,3 @@ +import useApi from "./useApi"; + +export default useApi; diff --git a/src/api/useApi.js b/src/api/useApi.js new file mode 100644 index 0000000..bd25d57 --- /dev/null +++ b/src/api/useApi.js @@ -0,0 +1,65 @@ +import { useToast } from "../hooks"; +import { get, post } from "../utils/axios"; + +const networkRoute = `${process.env.REACT_APP_NETWORK_RESURRECTOR_API_URL}/network`; +const powerActionsRoute = `${process.env.REACT_APP_NETWORK_RESURRECTOR_API_URL}/resurrector`; + +const useApi = () => { + const { error } = useToast(); + + const handleError = err => { + let message; + switch (err.response.status) { + case 500: + message = err.response.statusText; + break; + + default: + message = err.message; + } + + error(message); + }; + + const defaultOptions = { onCompleted: () => {}, onError: handleError }; + + const call = async (request, options) => { + const internalOptions = { ...defaultOptions, ...options }; + const { onCompleted, onError } = internalOptions; + + try { + const result = await request(); + onCompleted(result); + } catch (error) { + onError(error); + } + }; + + const readMachines = (options = defaultOptions) => { + const machinesPromise = call( + () => get(`${networkRoute}/machines`), + options + ); + return machinesPromise; + }; + + const wakeMachine = (machineId, options = defaultOptions) => { + const promise = call( + () => post(`${powerActionsRoute}/wake`, { machineId }), + options + ); + return promise; + }; + + const pingMachine = (machineId, options = defaultOptions) => { + const promise = call( + () => post(`${powerActionsRoute}/ping`, { machineId }), + options + ); + return promise; + }; + + return { readMachines, wakeMachine, pingMachine }; +}; + +export default useApi; diff --git a/src/features/machines/api.js b/src/features/machines/api.js deleted file mode 100644 index 99ebd12..0000000 --- a/src/features/machines/api.js +++ /dev/null @@ -1,26 +0,0 @@ -import { get, post } from "../../utils/axios"; - -const networkRoute = `${process.env.REACT_APP_NETWORK_RESURRECTOR_API_URL}/network`; -const powerActionsRoute = `${process.env.REACT_APP_NETWORK_RESURRECTOR_API_URL}/resurrector`; - -const readMachines = () => { - const machinesPromise = get(`${networkRoute}/machines`); - return machinesPromise; -}; - -const wakeMachine = async machineId => { - try { - const promise = await post(`${powerActionsRoute}/wake`, { machineId }); - return promise; - } catch (ex) { - debugger; - console.log(ex); - } -}; - -const pingMachine = machineId => { - const promise = post(`${powerActionsRoute}/ping`, { machineId }); - return promise; -}; - -export { readMachines, wakeMachine, pingMachine }; diff --git a/src/features/machines/components/MachineContainer.js b/src/features/machines/components/MachineContainer.js index 6f76692..c9c0cce 100644 --- a/src/features/machines/components/MachineContainer.js +++ b/src/features/machines/components/MachineContainer.js @@ -1,16 +1,18 @@ import React, { useState, useCallback } from "react"; import PropTypes from "prop-types"; import Machine from "./Machine"; -import * as api from "../api"; import { useToast } from "../../../hooks"; import { LastPage } from "@material-ui/icons"; import { useTranslation } from "react-i18next"; +import useApi from "../../../api"; const MachineContainer = ({ machine }) => { const [logs, setLogs] = useState([]); const { success, error } = useToast(); const { t } = useTranslation(); + const api = useApi(); + const addLog = useCallback( text => { setLogs(prev => [...prev, text]); @@ -20,15 +22,18 @@ const MachineContainer = ({ machine }) => { const pingMachine = useCallback( machine => async () => { - const result = await api.pingMachine(machine.machineId); - addLog(`Success: ${result.success}. Status: ${result.status}`); - if (result.success) { - success(result.status); - } else { - error(result.status); - } + await api.pingMachine(machine.machineId, { + onCompleted: result => { + addLog(`Success: ${result.success}. Status: ${result.status}`); + if (result.success) { + success(result.status); + } else { + error(result.status); + } + } + }); }, - [error, success, addLog] + [error, success, addLog, api] ); const actions = [ diff --git a/src/features/machines/components/MachinesContainer.js b/src/features/machines/components/MachinesContainer.js index 368b8de..7c59cbf 100644 --- a/src/features/machines/components/MachinesContainer.js +++ b/src/features/machines/components/MachinesContainer.js @@ -3,18 +3,23 @@ import { ApplicationStateContext, ApplicationDispatchContext } from "../../../state/ApplicationContexts"; -import * as api from "../api"; +import useApi from "../../../api"; import MachinesList from "./MachinesList"; const MachinesContainer = () => { const state = useContext(ApplicationStateContext); const dispatchActions = useContext(ApplicationDispatchContext); + const api = useApi(); + const handleReadMachines = useCallback(async () => { - const machines = await api.readMachines(); - const data = Object.assign(machines, { loaded: true }); - dispatchActions.onNetworkChange("machines", data); - }, [dispatchActions]); + await api.readMachines({ + onCompleted: machines => { + const data = Object.assign(machines, { loaded: true }); + dispatchActions.onNetworkChange("machines", data); + } + }); + }, [dispatchActions, api]); useEffect(() => { if (!state.network.machines.loaded) { diff --git a/src/features/machines/components/WakeComponent.js b/src/features/machines/components/WakeComponent.js index b3832d0..6fb923d 100644 --- a/src/features/machines/components/WakeComponent.js +++ b/src/features/machines/components/WakeComponent.js @@ -4,8 +4,8 @@ import { IconButton, Tooltip } from "@material-ui/core"; import { PowerSettingsNew } from "@material-ui/icons"; import { useTranslation } from "react-i18next"; import { useToast } from "../../../hooks"; -import * as api from "../api"; import { msToMinAndSec } from "../../../utils/time"; +import useApi from "../../../api"; const initialState = { on: false }; const defaultPingInterval = 1200000; //20 minutes @@ -17,6 +17,7 @@ const WakeComponent = ({ machine, addLog }) => { const { t } = useTranslation(); const { success, error } = useToast(); + const api = useApi(); const pingInterval = process.env.REACT_APP_MACHINE_PING_INTERVAL || defaultPingInterval; @@ -37,38 +38,47 @@ const WakeComponent = ({ machine, addLog }) => { ); const wakeMachine = useCallback(async () => { - const result = await api.wakeMachine(machine.machineId); - setState(prev => ({ ...prev, on: result.success })); - log(`[Wake]: Success: ${result.success}. Status: ${result.status}`); - if (result.success) { - success(result.status); + await api.wakeMachine(machine.machineId, { + onCompleted: result => { + setState(prev => ({ ...prev, on: result.success })); + log(`[Wake]: Success: ${result.success}. Status: ${result.status}`); + if (result.success) { + success(result.status); - //retrigger - log( - `Periodic ping will be re-triggered in ${startingTime} ms [${msToMinAndSec( - startingTime - )}]` - ); - setTimeout(() => { - setTrigger(prev => !prev); - }, startingTime); - } else { - error(result.status); - } - }, [log, success, error, startingTime, machine.machineId]); - - useEffect(() => { - api.pingMachine(machine.machineId).then(result => { - setState(prev => ({ ...prev, on: result.success })); - log(`[Ping]: Success: ${result.success}. Status: ${result.status}`); - - if (result.success) { - setTimeout(() => { - setTrigger(prev => !prev); - }, pingInterval); + //retrigger + log( + `Periodic ping will be re-triggered in ${startingTime} ms [${msToMinAndSec( + startingTime + )}]` + ); + setTimeout(() => { + setTrigger(prev => !prev); + }, startingTime); + } else { + error(result.status); + } } }); - }, [machine, log, pingInterval, trigger]); + }, [log, success, error, startingTime, machine.machineId, api]); + + const pingInLoop = useCallback(async () => { + await api.pingMachine(machine.machineId, { + onCompleted: result => { + setState(prev => ({ ...prev, on: result.success })); + log(`[Ping]: Success: ${result.success}. Status: ${result.status}`); + + if (result.success) { + setTimeout(() => { + setTrigger(prev => !prev); + }, pingInterval); + } + }, + onError: () => {} + }); + }, [machine, log, pingInterval]); // eslint-disable-line react-hooks/exhaustive-deps + // if "api" is added in pingInLoop dependencies, the useEffect is triggered in loop + + useEffect(pingInLoop, [trigger, pingInLoop]); return (