diff --git a/crates/engine/src/cmd/keywords.rs b/crates/engine/src/cmd/keywords.rs index 00f6d24d2..1e9dacbae 100644 --- a/crates/engine/src/cmd/keywords.rs +++ b/crates/engine/src/cmd/keywords.rs @@ -301,15 +301,16 @@ pub fn specs() -> Vec { Some(Value::Null) => None, _ => return Err(bad("keyword.move", "`parent` is a keyword, or null for the top level")), }; + // where it lands, as the catalog spells it: a parent that doesn't exist yet is made + let leaf = from.rsplit('|').next().unwrap_or(&from).to_string(); + let to = match parent.as_deref().map(|k| s.catalog.keyword_path(k).unwrap_or_else(|| clean(k))).filter(|k| !k.is_empty()) { + Some(parent) => format!("{parent}|{leaf}"), + None => leaf, + }; let op = s .catalog .move_keyword_ops(&from, parent.as_deref(), bool_or(p, "merge", false)) .map_err(|e| refused("keyword.move", e, ": moving would merge the two (merge: true)"))?; - let leaf = from.rsplit('|').next().unwrap_or(&from).to_string(); - let to = match parent.as_deref().and_then(|k| s.catalog.keyword_path(k)) { - Some(parent) => format!("{parent}|{leaf}"), - None => leaf, - }; commit_keywords(s, "Move Keyword", op, |k| Some(if is_under(k, &from) { reparent(k, &from, &to) } else { k.to_string() })) } ), diff --git a/crates/engine/src/tests_keyword_list.rs b/crates/engine/src/tests_keyword_list.rs index 18932dd3d..eba8e34b0 100644 --- a/crates/engine/src/tests_keyword_list.rs +++ b/crates/engine/src/tests_keyword_list.rs @@ -129,3 +129,16 @@ fn purging_unused_keywords() { s.execute("edit.undo", &json!({})).unwrap(); assert!(s.execute("keyword.info", &json!({"keyword": "Weddings"})).is_ok()); } + +/// Moving a keyword into a parent that doesn't exist yet makes that parent, and the keyword filter +/// follows the keyword there (the grid kept filtering by the old path, and showed nothing). +#[test] +fn the_filter_follows_a_keyword_moved_into_a_new_parent() { + let mut s = Session::with_demo(); + let id = s.visible_cloned()[0].0; + s.execute("photo.setMeta", &json!({"ids": [id], "keywords": ["Rome"]})).unwrap(); + s.execute("library.filter", &json!({"keyword": "Rome"})).unwrap(); + s.execute("keyword.move", &json!({"keyword": "rome", "parent": "Italy"})).unwrap(); + assert_eq!(keywords_of(&s, id), ["Italy|Rome"]); + assert_eq!(s.filter.keyword.as_deref(), Some("Italy|Rome")); +}