Explain captured removal impact and exercise rendered confirmation buttons

This commit is contained in:
2026-09-12 05:18:07 -07:00
parent 49a4cb17b1
commit 12b2237ee9
3 changed files with 51 additions and 5 deletions
@@ -47,6 +47,27 @@ fn placement(app: &App) -> Option<Id> {
/// The derived canvases remove semantic occurrences, not reusable definitions.
/// Kept beside target capture so confirmation rendering uses the same meaning.
pub(crate) fn explanation(app: &App, object: Id) -> &'static str {
if app
.project()
.diagrams
.values()
.any(|diagram| diagram.nodes.contains_key(&object))
{
return "Remove only this diagram placement. The model element and its placements in other diagrams remain. Undo restores this placement.";
}
if app
.project()
.relations
.get(&object)
.is_some_and(|relation| {
matches!(
relation.kind(),
RelationKind::StateAction | RelationKind::StateTransition
)
})
{
return "Remove this state relation. Its states and referenced activities or functions remain. Undo restores the relation.";
}
if app
.project()
.relations
@@ -331,8 +331,8 @@ async fn mounted_shift_delete_captures_target_cancel_escape_and_confirmation_rep
let target = f.app.delete_target.as_ref().unwrap();
assert_eq!(target.snapshot.request.object, f.object);
let stale_token = target.snapshot.token;
let task = f.app.update(Message::CancelDelete);
mounted.perform(&mut f.app, task).await;
let cancel = mounted.geometry(&f.app).bounds("delete-cancel").center();
mounted.click(&mut f.app, cancel).await;
let task = f.app.update(Message::ConfirmDelete(stale_token));
mounted.perform(&mut f.app, task).await;
assert_eq!(f.app.document.bundle(), &before.bundle);
@@ -345,8 +345,9 @@ async fn mounted_shift_delete_captures_target_cancel_escape_and_confirmation_rep
f.app.delete_pending,
"old dialog must not accept a new confirmation"
);
let task = f.app.update(Message::ConfirmDelete(token));
mounted.perform(&mut f.app, task).await;
assert_eq!(f.app.delete_target.as_ref().unwrap().snapshot.token, token);
let confirm = mounted.geometry(&f.app).bounds("delete-confirm").center();
mounted.click(&mut f.app, confirm).await;
assert!(!f.app.project().contains(f.object));
assert!(f.app.project().contains(f.other));
consistent(&f.app);
+25 -1
View File
@@ -344,7 +344,31 @@ pub fn view(app: &App) -> View<'_, Message> {
);
}
if let Some(target) = app.delete_target.as_ref().filter(|_| app.delete_pending) {
return modal(root,column![text("Delete from model?").size(21),text(format!("{} and its owned elements will be removed. Incident relationships, occurrences and view placements are updated together. Counterparts in the other layer remain.",p.named(target.snapshot.request.object))).size(13),label("Undo restores the complete change. Use Hide for diagram-only removal."),row![action("Cancel",Message::CancelDelete),button("Delete from model").style(button::danger).padding(10).on_press(Message::ConfirmDelete(target.snapshot.token))].spacing(10)].spacing(16).into());
return modal(
root,
column![
text("Delete from model?").size(21),
text(p.named(target.snapshot.request.object)).size(16),
text(crate::app::diagram_removal::explanation(
app,
target.snapshot.request.object
))
.size(13),
row![
widget::container(action("Cancel", Message::CancelDelete)).id("delete-cancel"),
widget::container(
button("Delete from model")
.style(button::danger)
.padding(10)
.on_press(Message::ConfirmDelete(target.snapshot.token))
)
.id("delete-confirm")
]
.spacing(10)
]
.spacing(16)
.into(),
);
}
if app.pending.is_some() {
return modal(root,column![text("Keep your changes?").size(21),text("Save the model and pending edits before continuing. Invalid drafts stay available for correction.").size(13),row![action("Cancel",Message::Cancel),action("Discard changes",Message::Discard),button("Save & continue").padding(10).on_press(Message::SaveAndContinue)].spacing(8)].spacing(16).into());