diff --git a/remote_backend/src/controllers/mod.rs b/remote_backend/src/controllers/mod.rs index 1bf9cbd..c0d541f 100644 --- a/remote_backend/src/controllers/mod.rs +++ b/remote_backend/src/controllers/mod.rs @@ -7,9 +7,9 @@ use std::io::ErrorKind; pub mod auth_controller; pub mod server_controller; +pub mod static_controller; pub mod sys_info_controller; pub mod vm_controller; -pub mod static_controller; /// Custom error to ease controller writing #[derive(Debug)] diff --git a/remote_backend/src/main.rs b/remote_backend/src/main.rs index 3e3e84e..f6fc36e 100644 --- a/remote_backend/src/main.rs +++ b/remote_backend/src/main.rs @@ -11,7 +11,9 @@ use actix_web::{web, App, HttpServer}; use light_openid::basic_state_manager::BasicStateManager; use remote_backend::app_config::AppConfig; 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 std::time::Duration; @@ -108,7 +110,7 @@ async fn main() -> std::io::Result<()> { "/api/sysinfo/status", web::get().to(sys_info_controller::status), ) - // Static assets + // Static assets .route("/", web::get().to(static_controller::root_index)) .route( "/{tail:.*}", diff --git a/remote_frontend/src/widgets/VirtualMachinesWidget.tsx b/remote_frontend/src/widgets/VirtualMachinesWidget.tsx index 6f01f6c..982d1f9 100644 --- a/remote_frontend/src/widgets/VirtualMachinesWidget.tsx +++ b/remote_frontend/src/widgets/VirtualMachinesWidget.tsx @@ -25,6 +25,7 @@ import { useToast } from "../hooks/providers/ToastProvider"; import { AsyncWidget } from "./AsyncWidget"; import { SectionContainer } from "./SectionContainer"; import { VMLiveScreenshot } from "./VMLiveScreenshot"; +import { useConfirm } from "../hooks/providers/ConfirmDialogProvider"; const useStyles = makeStyles({ body1Stronger: typographyStyles.body1Stronger, @@ -151,6 +152,7 @@ function VMWidget(p: { vm: VMInfo }): React.ReactElement { onClick={VMApi.SuspendVM} /> } @@ -160,6 +162,7 @@ function VMWidget(p: { vm: VMInfo }): React.ReactElement { onClick={VMApi.ShutdownVM} /> } @@ -174,6 +177,7 @@ function VMWidget(p: { vm: VMInfo }): React.ReactElement { onClick={VMApi.KillVM} /> } @@ -213,6 +217,7 @@ function VMPreview(p: { vm: VMInfo; state?: VMState }): React.ReactElement { } function VMAction(p: { + confirmAction?: boolean; vm: VMInfo; label: string; primary?: boolean; @@ -223,11 +228,20 @@ function VMAction(p: { onClick: (vm: VMInfo) => Promise; }): React.ReactElement { const toast = useToast(); + const confirm = useConfirm(); const [loading, setLoading] = React.useState(false); const onClick = async () => { try { + if ( + p.confirmAction && + !(await confirm( + `Do you really want to ${p.label} the VM '${p.vm.name}'?` + )) + ) + return; + setLoading(true); await p.onClick(p.vm);