Skip to content

Commit

Permalink
Add confirmation dialog for shutdown and reboot operation
Browse files Browse the repository at this point in the history
  • Loading branch information
skobyda committed May 11, 2023
1 parent b34ff55 commit 3cb456b
Show file tree
Hide file tree
Showing 3 changed files with 144 additions and 7 deletions.
2 changes: 1 addition & 1 deletion node_modules
Submodule node_modules updated 243 files
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,7 @@
"react-dom": "18.2.0",
"redux": "4.1.2",
"redux-thunk": "2.4.2",
"remarkable": "^2.0.1",
"throttle-debounce": "3.0.1",
"xterm": "5.1.0",
"xterm-addon-canvas": "0.3.0"
Expand Down
148 changes: 142 additions & 6 deletions src/components/vm/vmActions.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -20,9 +20,13 @@ import cockpit from 'cockpit';
import React, { useEffect, useState } from 'react';
import PropTypes from 'prop-types';
import { Button } from "@patternfly/react-core/dist/esm/components/Button";
import { DescriptionList, DescriptionListDescription, DescriptionListGroup, DescriptionListTerm } from "@patternfly/react-core/dist/esm/components/DescriptionList";
import { Dropdown, DropdownItem, DropdownSeparator, KebabToggle } from "@patternfly/react-core/dist/esm/deprecated/components/Dropdown";
import { Modal } from "@patternfly/react-core/dist/esm/components/Modal";
import { Tooltip } from "@patternfly/react-core/dist/esm/components/Tooltip";
import { PowerOffIcon, RedoIcon } from '@patternfly/react-icons';
import { useDialogs } from 'dialogs.jsx';
import { Remarkable } from "remarkable";

import { updateVm } from '../../actions/store-actions.js';
import {
Expand Down Expand Up @@ -53,6 +57,7 @@ import {
domainStart,
} from '../../libvirtApi/domain.js';
import store from "../../store.js";
import { distanceToNow } from 'timeformat.js';

const _ = cockpit.gettext;

Expand Down Expand Up @@ -166,6 +171,45 @@ const onSendNMI = (vm) => domainSendNMI({ name: vm.name, id: vm.id, connectionNa
);
});

export const ConfirmModal = ({ idPrefix, actionsList, startTime, title, titleIcon }) => {
const Dialogs = useDialogs();

const actions = actionsList.map(action =>
<Button variant={action.variant}
key={action.id}
id={`${idPrefix}-${action.id}`}
onClick={() => {
action.handler();
Dialogs.close();
}}>
{action.name}
</Button>
);
actions.push(
<Button variant="link" key="cancel" onClick={Dialogs.close}>
{_("Cancel")}
</Button>
);

return (
<Modal id={`${idPrefix}-confirm-action-modal`}
position="top"
variant="small"
onClose={Dialogs.close}
title={title}
titleIconVariant={titleIcon}
isOpen
footer={actions}>
<DescriptionList isHorizontal>
<DescriptionListGroup id="uptim">
<DescriptionListTerm>{_("Uptime")}</DescriptionListTerm>
<DescriptionListDescription>{distanceToNow(new Date(startTime))}</DescriptionListDescription>
</DescriptionListGroup>
</DescriptionList>
</Modal>
);
};

const VmActions = ({ vm, onAddErrorNotification, isDetailsPage }) => {
const Dialogs = useDialogs();
const [isActionOpen, setIsActionOpen] = useState(false);
Expand All @@ -183,6 +227,8 @@ const VmActions = ({ vm, onAddErrorNotification, isDetailsPage }) => {
setOperationInProgress(false);
}

const remarkable = new Remarkable();

const id = `${vmId(vm.name)}-${vm.connectionName}`;
const state = vm.state;
const hasInstallPhase = vm.metadata && vm.metadata.hasInstallPhase;
Expand Down Expand Up @@ -219,29 +265,93 @@ const VmActions = ({ vm, onAddErrorNotification, isDetailsPage }) => {
variant={isDetailsPage ? 'primary' : 'secondary'}
isLoading={operationInProgress}
isDisabled={operationInProgress}
onClick={() => { setOperationInProgress(true); onShutdown(vm, setOperationInProgress) }} id={`${id}-shutdown-button`}>
id={`${id}-shutdown-button`}
onClick={() => Dialogs.show(
<ConfirmModal idPrefix={id}
title={<span dangerouslySetInnerHTML={{ __html: remarkable.render(cockpit.format(_("Shut down **$0**"), vm.name)) }} />}
titleIcon={PowerOffIcon}
startTime={vm.startTime}
actionsList={[
{
variant: "primary",
handler: () => {
setOperationInProgress(true);
onShutdown(vm, setOperationInProgress);
},
name: _("Shut down"),
id: "shutdown",
},
{
variant: "secondary",
handler: () => {
setOperationInProgress(true);
onReboot(vm);
},
name: _("Reboot"),
id: "reboot",
},
]} />
)}>
{_("Shut down")}
</Button>
);
dropdownItems.push(
<DropdownItem key={`${id}-off`}
id={`${id}-off`}
onClick={() => onShutdown(vm)}>
onClick={() => Dialogs.show(
<ConfirmModal idPrefix={id}
title={<span dangerouslySetInnerHTML={{ __html: remarkable.render(cockpit.format(_("Shut down **$0**"), vm.name)) }} />}
titleIcon={PowerOffIcon}
startTime={vm.startTime}
actionsList={[
{
variant: "primary",
handler: () => onShutdown(vm),
name: _("Shut down"),
id: "shutdown",
},
]} />
)}>
{_("Shut down")}
</DropdownItem>
);
dropdownItems.push(
<DropdownItem key={`${id}-forceOff`}
id={`${id}-forceOff`}
onClick={() => onForceoff(vm)}>
onClick={() => Dialogs.show(
<ConfirmModal idPrefix={id}
title={<span dangerouslySetInnerHTML={{ __html: remarkable.render(cockpit.format(_("Force shut down **$0**"), vm.name)) }} />}
titleIcon={PowerOffIcon}
startTime={vm.startTime}
actionsList={[
{
variant: "primary",
handler: () => onForceoff(vm),
name: _("Force shut down"),
id: "forceoff",
},
]} />
)}>
{_("Force shut down")}
</DropdownItem>
);
dropdownItems.push(<DropdownSeparator key="separator-shutdown" />);
dropdownItems.push(
<DropdownItem key={`${id}-sendNMI`}
id={`${id}-sendNMI`}
onClick={() => onSendNMI(vm)}>
onClick={() => Dialogs.show(
<ConfirmModal idPrefix={id}
title={<span dangerouslySetInnerHTML={{ __html: remarkable.render(cockpit.format(_("Send non-maskable interrupt to **$0**"), vm.name)) }} />}
startTime={vm.startTime}
actionsList={[
{
variant: "primary",
handler: () => onSendNMI(vm),
name: _("Send non-maskable interrupt"),
id: "forceoff",
},
]} />
)}>
{_("Send non-maskable interrupt")}
</DropdownItem>
);
Expand All @@ -252,14 +362,40 @@ const VmActions = ({ vm, onAddErrorNotification, isDetailsPage }) => {
dropdownItems.push(
<DropdownItem key={`${id}-reboot`}
id={`${id}-reboot`}
onClick={() => onReboot(vm)}>
onClick={() => Dialogs.show(
<ConfirmModal idPrefix={id}
title={<span dangerouslySetInnerHTML={{ __html: remarkable.render(cockpit.format(_("Reboot **$0**"), vm.name)) }} />}
titleIcon={RedoIcon}
startTime={vm.startTime}
actionsList={[
{
variant: "primary",
handler: onReboot(vm),
name: _("Reboot"),
id: "reboot",
},
]} />
)}>
{_("Reboot")}
</DropdownItem>
);
dropdownItems.push(
<DropdownItem key={`${id}-forceReboot`}
id={`${id}-forceReboot`}
onClick={() => onForceReboot(vm)}>
onClick={() => Dialogs.show(
<ConfirmModal idPrefix={id}
title={<span dangerouslySetInnerHTML={{ __html: remarkable.render(cockpit.format(_("Force reboot **$0**"), vm.name)) }} />}
startTime={vm.startTime}
titleIcon={RedoIcon}
actionsList={[
{
variant: "primary",
handler: onForceReboot(vm),
name: _("Force reboot"),
id: "reboot",
},
]} />
)}>
{_("Force reboot")}
</DropdownItem>
);
Expand Down

0 comments on commit 3cb456b

Please sign in to comment.