Confirm potentially destructive actions
All checks were successful
continuous-integration/drone/push Build is passing

This commit is contained in:
Pierre HUBERT 2024-05-07 20:01:31 +02:00
parent 4c5e1080ca
commit 5dc3f49d73
3 changed files with 19 additions and 3 deletions

View File

@ -7,9 +7,9 @@ use std::io::ErrorKind;
pub mod auth_controller; pub mod auth_controller;
pub mod server_controller; pub mod server_controller;
pub mod static_controller;
pub mod sys_info_controller; pub mod sys_info_controller;
pub mod vm_controller; pub mod vm_controller;
pub mod static_controller;
/// Custom error to ease controller writing /// Custom error to ease controller writing
#[derive(Debug)] #[derive(Debug)]

View File

@ -11,7 +11,9 @@ use actix_web::{web, App, HttpServer};
use light_openid::basic_state_manager::BasicStateManager; use light_openid::basic_state_manager::BasicStateManager;
use remote_backend::app_config::AppConfig; use remote_backend::app_config::AppConfig;
use remote_backend::constants; use remote_backend::constants;
use remote_backend::controllers::{auth_controller, server_controller, static_controller, sys_info_controller, vm_controller}; use remote_backend::controllers::{
auth_controller, server_controller, static_controller, sys_info_controller, vm_controller,
};
use remote_backend::middlewares::auth_middleware::AuthChecker; use remote_backend::middlewares::auth_middleware::AuthChecker;
use std::time::Duration; use std::time::Duration;
@ -108,7 +110,7 @@ async fn main() -> std::io::Result<()> {
"/api/sysinfo/status", "/api/sysinfo/status",
web::get().to(sys_info_controller::status), web::get().to(sys_info_controller::status),
) )
// Static assets // Static assets
.route("/", web::get().to(static_controller::root_index)) .route("/", web::get().to(static_controller::root_index))
.route( .route(
"/{tail:.*}", "/{tail:.*}",

View File

@ -25,6 +25,7 @@ import { useToast } from "../hooks/providers/ToastProvider";
import { AsyncWidget } from "./AsyncWidget"; import { AsyncWidget } from "./AsyncWidget";
import { SectionContainer } from "./SectionContainer"; import { SectionContainer } from "./SectionContainer";
import { VMLiveScreenshot } from "./VMLiveScreenshot"; import { VMLiveScreenshot } from "./VMLiveScreenshot";
import { useConfirm } from "../hooks/providers/ConfirmDialogProvider";
const useStyles = makeStyles({ const useStyles = makeStyles({
body1Stronger: typographyStyles.body1Stronger, body1Stronger: typographyStyles.body1Stronger,
@ -151,6 +152,7 @@ function VMWidget(p: { vm: VMInfo }): React.ReactElement {
onClick={VMApi.SuspendVM} onClick={VMApi.SuspendVM}
/> />
<VMAction <VMAction
confirmAction
{...p} {...p}
label="Shutdown" label="Shutdown"
icon={<PowerRegular />} icon={<PowerRegular />}
@ -160,6 +162,7 @@ function VMWidget(p: { vm: VMInfo }): React.ReactElement {
onClick={VMApi.ShutdownVM} onClick={VMApi.ShutdownVM}
/> />
<VMAction <VMAction
confirmAction
{...p} {...p}
label="Kill" label="Kill"
icon={<StopRegular />} icon={<StopRegular />}
@ -174,6 +177,7 @@ function VMWidget(p: { vm: VMInfo }): React.ReactElement {
onClick={VMApi.KillVM} onClick={VMApi.KillVM}
/> />
<VMAction <VMAction
confirmAction
{...p} {...p}
label="Reset" label="Reset"
icon={<ArrowResetRegular />} icon={<ArrowResetRegular />}
@ -213,6 +217,7 @@ function VMPreview(p: { vm: VMInfo; state?: VMState }): React.ReactElement {
} }
function VMAction(p: { function VMAction(p: {
confirmAction?: boolean;
vm: VMInfo; vm: VMInfo;
label: string; label: string;
primary?: boolean; primary?: boolean;
@ -223,11 +228,20 @@ function VMAction(p: {
onClick: (vm: VMInfo) => Promise<void>; onClick: (vm: VMInfo) => Promise<void>;
}): React.ReactElement { }): React.ReactElement {
const toast = useToast(); const toast = useToast();
const confirm = useConfirm();
const [loading, setLoading] = React.useState(false); const [loading, setLoading] = React.useState(false);
const onClick = async () => { const onClick = async () => {
try { try {
if (
p.confirmAction &&
!(await confirm(
`Do you really want to ${p.label} the VM '${p.vm.name}'?`
))
)
return;
setLoading(true); setLoading(true);
await p.onClick(p.vm); await p.onClick(p.vm);