Shutdown and restart actions
parent
5536cddf1b
commit
8eb5f0caa0
|
@ -12,4 +12,9 @@ Log-ul va fi popup iar continutul lui poate fi ultima componenta de aici https:/
|
|||
|
||||
https://medium.com/@tacomanator/environments-with-create-react-app-7b645312c09d
|
||||
https://create-react-app.dev/docs/adding-custom-environment-variables/
|
||||
https://stackoverflow.com/questions/55690143/what-is-the-difference-between-env-local-and-env-development-local
|
||||
https://stackoverflow.com/questions/55690143/what-is-the-difference-between-env-local-and-env-development-local
|
||||
|
||||
|
||||
REACT v4:
|
||||
https://v4.mui.com/getting-started/installation/
|
||||
https://v4.mui.com/components/material-icons/
|
|
@ -36,7 +36,11 @@
|
|||
"PoweredOn": "Powered on",
|
||||
"Actions": {
|
||||
"Wake": "Wake",
|
||||
"Ping": "Ping"
|
||||
"Ping": "Ping",
|
||||
"More": "More",
|
||||
"Shutdown": "Shutdown",
|
||||
"Restart": "Restart",
|
||||
"Advanced": "Advanced"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -27,7 +27,11 @@
|
|||
"PoweredOn": "Pornit",
|
||||
"Actions": {
|
||||
"Wake": "Pornește",
|
||||
"Ping": "Ping"
|
||||
"Ping": "Ping",
|
||||
"More": "Mai mult",
|
||||
"Shutdown": "Oprește",
|
||||
"Restart": "Repornește",
|
||||
"Advanced": "Avansat"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -25,7 +25,10 @@ const useApi = () => {
|
|||
error(message);
|
||||
};
|
||||
|
||||
const defaultOptions = { onCompleted: () => {}, onError: handleError };
|
||||
const defaultOptions = {
|
||||
onCompleted: () => {},
|
||||
onError: handleError
|
||||
};
|
||||
|
||||
const call = async (request, options) => {
|
||||
const internalOptions = { ...defaultOptions, ...options };
|
||||
|
@ -63,7 +66,39 @@ const useApi = () => {
|
|||
return promise;
|
||||
};
|
||||
|
||||
return { readMachines, wakeMachine, pingMachine };
|
||||
const shutdownMachine = (
|
||||
machineId,
|
||||
delay,
|
||||
force,
|
||||
options = defaultOptions
|
||||
) => {
|
||||
const promise = call(
|
||||
() => post(`${powerActionsRoute}/shutdown`, { machineId, delay, force }),
|
||||
options
|
||||
);
|
||||
return promise;
|
||||
};
|
||||
|
||||
const restartMachine = (
|
||||
machineId,
|
||||
delay,
|
||||
force,
|
||||
options = defaultOptions
|
||||
) => {
|
||||
const promise = call(
|
||||
() => post(`${powerActionsRoute}/restart`, { machineId, delay, force }),
|
||||
options
|
||||
);
|
||||
return promise;
|
||||
};
|
||||
|
||||
return {
|
||||
readMachines,
|
||||
wakeMachine,
|
||||
pingMachine,
|
||||
shutdownMachine,
|
||||
restartMachine
|
||||
};
|
||||
};
|
||||
|
||||
export default useApi;
|
||||
|
|
|
@ -1,11 +1,12 @@
|
|||
import React from "react";
|
||||
import React, { useMemo } from "react";
|
||||
import PropTypes from "prop-types";
|
||||
import {
|
||||
TableCell,
|
||||
TableRow,
|
||||
IconButton,
|
||||
Collapse,
|
||||
Tooltip
|
||||
Tooltip,
|
||||
Menu
|
||||
} from "@material-ui/core";
|
||||
import { KeyboardArrowDown, KeyboardArrowUp } from "@material-ui/icons";
|
||||
import { makeStyles } from "@material-ui/core/styles";
|
||||
|
@ -20,10 +21,46 @@ const useRowStyles = makeStyles({
|
|||
}
|
||||
});
|
||||
|
||||
const Machine = ({ machine, actions, logs, addLog }) => {
|
||||
const ActionButton = React.forwardRef((props, _ref) => {
|
||||
const { action, machine } = props;
|
||||
return (
|
||||
<Tooltip
|
||||
id={`machine-item-${machine.machineId}-${action.code}-tooltip`}
|
||||
title={action.tooltip}
|
||||
>
|
||||
<span>
|
||||
<IconButton
|
||||
id={`machine-item-${machine.machineId}-${action.code}`}
|
||||
size={"small"}
|
||||
onClick={action.system ? action.effect : action.effect(machine)}
|
||||
>
|
||||
<action.icon />
|
||||
</IconButton>
|
||||
</span>
|
||||
</Tooltip>
|
||||
);
|
||||
});
|
||||
|
||||
const Machine = ({
|
||||
machine,
|
||||
actions,
|
||||
logs,
|
||||
addLog,
|
||||
secondaryActionsMenuProps
|
||||
}) => {
|
||||
const [open, setOpen] = React.useState(false);
|
||||
const classes = useRowStyles();
|
||||
|
||||
const topActions = useMemo(
|
||||
() => actions.filter(a => a.top === true),
|
||||
[actions]
|
||||
);
|
||||
|
||||
const secondaryActions = useMemo(
|
||||
() => actions.filter(a => a.top === false),
|
||||
[actions]
|
||||
);
|
||||
|
||||
return (
|
||||
<React.Fragment>
|
||||
<TableRow className={classes.root}>
|
||||
|
@ -44,22 +81,28 @@ const Machine = ({ machine, actions, logs, addLog }) => {
|
|||
<TableCell>{machine.macAddress}</TableCell>
|
||||
<TableCell align="right">
|
||||
<WakeComponent machine={machine} addLog={addLog} />
|
||||
{actions.map(action => (
|
||||
<Tooltip
|
||||
title={action.tooltip}
|
||||
key={`machine-item-${machine.machineId}-${action.code}-tooltip`}
|
||||
>
|
||||
<span>
|
||||
<IconButton
|
||||
id={`machine-item-${machine.machineId}-${action.code}`}
|
||||
size={"small"}
|
||||
onClick={action.effect(machine)}
|
||||
>
|
||||
<action.icon />
|
||||
</IconButton>
|
||||
</span>
|
||||
</Tooltip>
|
||||
{topActions.map(action => (
|
||||
<ActionButton
|
||||
key={`machine-item-${machine.machineId}-${action.code}`}
|
||||
action={action}
|
||||
machine={machine}
|
||||
/>
|
||||
))}
|
||||
<Menu
|
||||
id="secondary-actions-menu"
|
||||
anchorEl={secondaryActionsMenuProps.anchor}
|
||||
keepMounted
|
||||
open={Boolean(secondaryActionsMenuProps.anchor)}
|
||||
onClose={secondaryActionsMenuProps.onCloseSecondaryActions}
|
||||
>
|
||||
{secondaryActions.map(action => (
|
||||
<ActionButton
|
||||
key={`machine-item-${machine.machineId}-${action.code}`}
|
||||
action={action}
|
||||
machine={machine}
|
||||
/>
|
||||
))}
|
||||
</Menu>
|
||||
</TableCell>
|
||||
</TableRow>
|
||||
<TableRow>
|
||||
|
@ -84,7 +127,8 @@ Machine.propTypes = {
|
|||
}).isRequired,
|
||||
actions: PropTypes.array.isRequired,
|
||||
logs: PropTypes.array.isRequired,
|
||||
addLog: PropTypes.func.isRequired
|
||||
addLog: PropTypes.func.isRequired,
|
||||
secondaryActionsMenuProps: PropTypes.object.isRequired
|
||||
};
|
||||
|
||||
export default Machine;
|
||||
|
|
|
@ -2,12 +2,21 @@ import React, { useState, useCallback } from "react";
|
|||
import PropTypes from "prop-types";
|
||||
import Machine from "./Machine";
|
||||
import { useToast } from "../../../hooks";
|
||||
import { LastPage } from "@material-ui/icons";
|
||||
import {
|
||||
LastPage,
|
||||
MoreHoriz,
|
||||
RotateLeft,
|
||||
Launch,
|
||||
Stop
|
||||
} from "@material-ui/icons";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import useApi from "../../../api";
|
||||
|
||||
const MachineContainer = ({ machine }) => {
|
||||
const [logs, setLogs] = useState([]);
|
||||
const [secondaryActionsAnchor, setSecondaryActionsAnchor] =
|
||||
React.useState(null);
|
||||
|
||||
const { success, error } = useToast();
|
||||
const { t } = useTranslation();
|
||||
|
||||
|
@ -20,20 +29,58 @@ const MachineContainer = ({ machine }) => {
|
|||
[setLogs]
|
||||
);
|
||||
|
||||
const manageActionResponse = useCallback(
|
||||
response => {
|
||||
addLog(`Success: ${response.success}. Status: ${response.status}`);
|
||||
if (response.success) {
|
||||
success(response.status);
|
||||
} else {
|
||||
error(response.status);
|
||||
}
|
||||
},
|
||||
[error, success, addLog]
|
||||
);
|
||||
|
||||
const pingMachine = useCallback(
|
||||
machine => async () => {
|
||||
await api.pingMachine(machine.machineId, {
|
||||
onCompleted: result => {
|
||||
addLog(`Success: ${result.success}. Status: ${result.status}`);
|
||||
if (result.success) {
|
||||
success(result.status);
|
||||
} else {
|
||||
error(result.status);
|
||||
}
|
||||
}
|
||||
onCompleted: manageActionResponse
|
||||
});
|
||||
},
|
||||
[error, success, addLog, api]
|
||||
[manageActionResponse, api]
|
||||
);
|
||||
|
||||
const handleOpenSecondaryActions = event => {
|
||||
setSecondaryActionsAnchor(event.currentTarget);
|
||||
};
|
||||
|
||||
const handleCloseSecondaryActions = () => {
|
||||
setSecondaryActionsAnchor(null);
|
||||
};
|
||||
|
||||
const secondaryActionsMenuProps = {
|
||||
anchor: secondaryActionsAnchor,
|
||||
onCloseSecondaryActions: handleCloseSecondaryActions
|
||||
};
|
||||
|
||||
const shutdownMachine = useCallback(
|
||||
machine => async () => {
|
||||
await api.shutdownMachine(machine.machineId, 0, false, {
|
||||
onCompleted: manageActionResponse
|
||||
});
|
||||
handleCloseSecondaryActions();
|
||||
},
|
||||
[manageActionResponse, api]
|
||||
);
|
||||
|
||||
const restartMachine = useCallback(
|
||||
machine => async () => {
|
||||
await api.restartMachine(machine.machineId, 0, false, {
|
||||
onCompleted: manageActionResponse
|
||||
});
|
||||
handleCloseSecondaryActions();
|
||||
},
|
||||
[manageActionResponse, api]
|
||||
);
|
||||
|
||||
const actions = [
|
||||
|
@ -41,12 +88,48 @@ const MachineContainer = ({ machine }) => {
|
|||
code: "ping",
|
||||
effect: pingMachine,
|
||||
icon: LastPage,
|
||||
tooltip: t("Machine.Actions.Ping")
|
||||
tooltip: t("Machine.Actions.Ping"),
|
||||
top: true
|
||||
},
|
||||
{
|
||||
code: "more",
|
||||
effect: handleOpenSecondaryActions,
|
||||
icon: MoreHoriz,
|
||||
tooltip: t("Machine.Actions.More"),
|
||||
top: true,
|
||||
system: true
|
||||
},
|
||||
{
|
||||
code: "shutdown",
|
||||
effect: shutdownMachine,
|
||||
icon: Stop,
|
||||
tooltip: t("Machine.Actions.Shutdown"),
|
||||
top: false
|
||||
},
|
||||
{
|
||||
code: "restart",
|
||||
effect: restartMachine,
|
||||
icon: RotateLeft,
|
||||
tooltip: t("Machine.Actions.Restart"),
|
||||
top: false
|
||||
},
|
||||
{
|
||||
code: "advanced",
|
||||
effect: () => {},
|
||||
icon: Launch,
|
||||
tooltip: t("Machine.Actions.Advanced"),
|
||||
top: false
|
||||
}
|
||||
];
|
||||
|
||||
return (
|
||||
<Machine machine={machine} actions={actions} logs={logs} addLog={addLog} />
|
||||
<Machine
|
||||
machine={machine}
|
||||
actions={actions}
|
||||
logs={logs}
|
||||
addLog={addLog}
|
||||
secondaryActionsMenuProps={secondaryActionsMenuProps}
|
||||
/>
|
||||
);
|
||||
};
|
||||
|
||||
|
|
Loading…
Reference in New Issue