feat(hosts): add delete confirmation modal on hosts list page
Replace the direct dispatch on the Delete button with a pending_delete signal (id + name). A DeleteHostModal identical to the one in host detail opens for confirmation before the action is dispatched. The modal closes automatically after a successful deletion. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -27,6 +27,47 @@ const PER_PAGE_OPTIONS: &[(i64, &str)] = &[
|
||||
(0, "All"),
|
||||
];
|
||||
|
||||
// ─── Delete host modal ────────────────────────────────────────────────────────
|
||||
|
||||
#[component]
|
||||
fn DeleteHostModal(
|
||||
host_name: String,
|
||||
host_id: i64,
|
||||
delete_action: ServerAction<DeleteHost>,
|
||||
pending_delete: RwSignal<Option<(i64, String)>>,
|
||||
) -> impl IntoView {
|
||||
view! {
|
||||
<div class="modal-backdrop" on:click=move |_| pending_delete.set(None)>
|
||||
<div class="modal" on:click=move |e| e.stop_propagation()>
|
||||
<div class="modal__header">
|
||||
<h2>"Delete host"</h2>
|
||||
<button class="modal__close" type="button" aria-label="Close"
|
||||
on:click=move |_| pending_delete.set(None)>
|
||||
"×"
|
||||
</button>
|
||||
</div>
|
||||
<div class="modal__body">
|
||||
<p class="warning">
|
||||
"Are you sure you want to delete "
|
||||
<strong>{host_name}</strong>
|
||||
"? All port associations will also be removed."
|
||||
</p>
|
||||
</div>
|
||||
<div class="modal__actions">
|
||||
<button class="btn-secondary" type="button"
|
||||
on:click=move |_| pending_delete.set(None)>
|
||||
"Cancel"
|
||||
</button>
|
||||
<button class="btn-danger" type="button"
|
||||
on:click=move |_| { delete_action.dispatch(DeleteHost { id: host_id }); }>
|
||||
"Delete"
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
}.into_any()
|
||||
}
|
||||
|
||||
// ─── Add host modal ───────────────────────────────────────────────────────────
|
||||
|
||||
#[component]
|
||||
@@ -247,7 +288,7 @@ fn PaginationBar(
|
||||
#[component]
|
||||
fn HostTable(
|
||||
hosts: Resource<Result<HostsPageData, ServerFnError>>,
|
||||
delete_action: ServerAction<DeleteHost>,
|
||||
pending_delete: RwSignal<Option<(i64, String)>>,
|
||||
) -> impl IntoView {
|
||||
view! {
|
||||
<Suspense fallback=|| view! { <p class="empty">"Loading hosts…"</p> }>
|
||||
@@ -276,6 +317,7 @@ fn HostTable(
|
||||
<tbody>
|
||||
{rows.into_iter().map(|host| {
|
||||
let id = host.id;
|
||||
let delete_name = host.name.clone();
|
||||
view! {
|
||||
<tr>
|
||||
<td>
|
||||
@@ -293,7 +335,7 @@ fn HostTable(
|
||||
<td class="col-count">{host.application_count}</td>
|
||||
<td class="col-actions">
|
||||
<button on:click=move |_| {
|
||||
delete_action.dispatch(DeleteHost { id });
|
||||
pending_delete.set(Some((id, delete_name.clone())));
|
||||
}>
|
||||
"Delete"
|
||||
</button>
|
||||
@@ -319,6 +361,16 @@ pub fn HostsPage() -> impl IntoView {
|
||||
|
||||
let show_modal = RwSignal::new(false);
|
||||
|
||||
// None = no modal, Some((id, name)) = delete confirmation open.
|
||||
let pending_delete: RwSignal<Option<(i64, String)>> = RwSignal::new(None);
|
||||
|
||||
// Close the delete modal automatically after a successful deletion.
|
||||
Effect::new(move |_| {
|
||||
if let Some(Ok(_)) = delete_action.value().get() {
|
||||
pending_delete.set(None);
|
||||
}
|
||||
});
|
||||
|
||||
// Filter signals ("" / 0 = no filter)
|
||||
let name_filter = RwSignal::new(String::new());
|
||||
let network_id_filter = RwSignal::new(0i64);
|
||||
@@ -369,6 +421,15 @@ pub fn HostsPage() -> impl IntoView {
|
||||
/>
|
||||
})}
|
||||
|
||||
{move || pending_delete.get().map(|(host_id, host_name)| view! {
|
||||
<DeleteHostModal
|
||||
host_name=host_name
|
||||
host_id=host_id
|
||||
delete_action=delete_action
|
||||
pending_delete=pending_delete
|
||||
/>
|
||||
})}
|
||||
|
||||
<FilterBar
|
||||
networks_res=networks_res
|
||||
applications_res=applications_res
|
||||
@@ -387,7 +448,7 @@ pub fn HostsPage() -> impl IntoView {
|
||||
|
||||
<PaginationBar total=total page=page per_page=per_page total_pages=total_pages/>
|
||||
|
||||
<HostTable hosts=hosts delete_action=delete_action/>
|
||||
<HostTable hosts=hosts pending_delete=pending_delete/>
|
||||
</section>
|
||||
</div>
|
||||
}.into_any()
|
||||
|
||||
Reference in New Issue
Block a user