mirror of
https://github.com/bherbruck/solidcraft.git
synced 2026-11-08 13:01:52 +00:00
Configuration rules: Then says it lists only the table's columns, and how to add one (#10532) (#10544)
* Configuration rules: Then says it lists only the table's columns, and how to add one (#10532) A rule drives or restricts a column of the table only, so Then leaves out a feature without a Suppress column or a parameter without a column, where When lists them all. A note under the list now says so and points at Add Column. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * Configuration rules: the two notes in the complete catalogs (Arabic, Hebrew, Japanese, Vietnamese, Chinese) Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,30 @@
|
||||
{
|
||||
"en": {
|
||||
"config.rule_parameter_columns": "Only parameters with a column in the table are listed. Add one with Add Column (+) to use it here.",
|
||||
"config.rule_suppression_columns": "Only features with a Suppress column in the table are listed. Add one with Add Column (+) to drive it here."
|
||||
},
|
||||
"ar": {
|
||||
"config.rule_parameter_columns": "لا تظهر هنا إلا المعاملات التي لها عمود في الجدول. أضف عمودًا عبر «إضافة عمود» (+) لاستخدام المعامل هنا.",
|
||||
"config.rule_suppression_columns": "لا تظهر هنا إلا الميزات التي لها عمود «تعطيل» في الجدول. أضف عمودًا عبر «إضافة عمود» (+) للتحكم بالميزة هنا."
|
||||
},
|
||||
"de": {
|
||||
"config.rule_parameter_columns": "Hier stehen nur Parameter mit einer Spalte in der Tabelle. Fügen Sie eine mit „Spalte hinzufügen“ (+) hinzu, um den Parameter hier zu verwenden.",
|
||||
"config.rule_suppression_columns": "Hier stehen nur Funktionen mit einer Spalte „Unterdrücken“ in der Tabelle. Fügen Sie eine mit „Spalte hinzufügen“ (+) hinzu, um die Funktion hier zu steuern."
|
||||
},
|
||||
"he": {
|
||||
"config.rule_parameter_columns": "מוצגים כאן רק פרמטרים שיש להם עמודה בטבלה. הוסיפו עמודה דרך \"הוספת עמודה\" (+) כדי להשתמש בפרמטר כאן.",
|
||||
"config.rule_suppression_columns": "מוצגים כאן רק פיצ'רים שיש להם עמודת \"השבתה\" בטבלה. הוסיפו עמודה דרך \"הוספת עמודה\" (+) כדי לשלוט בפיצ'ר כאן."
|
||||
},
|
||||
"ja": {
|
||||
"config.rule_parameter_columns": "表に列があるパラメータのみが表示されます。ここで使うには「列を追加」(+) で列を追加してください。",
|
||||
"config.rule_suppression_columns": "表に「抑制」列があるフィーチャーのみが表示されます。ここで制御するには「列を追加」(+) で列を追加してください。"
|
||||
},
|
||||
"vi": {
|
||||
"config.rule_parameter_columns": "Chỉ những tham số có cột trong bảng mới được liệt kê. Thêm cột bằng “Thêm cột” (+) để dùng tham số đó ở đây.",
|
||||
"config.rule_suppression_columns": "Chỉ những tính năng có cột “Bỏ kích hoạt (Suppress)” trong bảng mới được liệt kê. Thêm cột bằng “Thêm cột” (+) để điều khiển tính năng đó ở đây."
|
||||
},
|
||||
"zh": {
|
||||
"config.rule_parameter_columns": "此处仅列出在表中有列的参数。使用“添加列”(+) 添加一列,即可在此使用该参数。",
|
||||
"config.rule_suppression_columns": "此处仅列出在表中有“抑制”列的特征。使用“添加列”(+) 添加一列,即可在此控制该特征。"
|
||||
}
|
||||
}
|
||||
@@ -86,6 +86,10 @@ pub(super) fn show(ui: &mut Ui, app: &mut SolveApp, error: &mut Option<String>,
|
||||
let features: Vec<(u64, String)> = app.session.doc.features.iter().map(|f| (f.id, f.name.clone())).collect();
|
||||
let suppression_features: Vec<(u64, String)> =
|
||||
features.iter().filter(|(id, _)| app.session.doc.configs.columns.contains(&Column::Suppress(*id))).cloned().collect();
|
||||
// A rule's target must be a column of the table (the engine refuses any other), so the Then
|
||||
// lists leave out what has none; a note then says so, where When lists everything (#10532).
|
||||
let unlisted_features = suppression_features.len() < features.len();
|
||||
let unlisted_parameters = all_parameters.iter().any(|p| !parameters.contains(p));
|
||||
ui_kit::divider(ui, "configuration_rules");
|
||||
ui_kit::text(ui, crate::i18n::tr_label("Configuration rules"), ui_kit::Text::Heading("rules_heading"));
|
||||
ui_kit::text(
|
||||
@@ -179,17 +183,20 @@ pub(super) fn show(ui: &mut Ui, app: &mut SolveApp, error: &mut Option<String>,
|
||||
RuleEffect::DriveParameter { parameter, expression: value } => {
|
||||
ui.vertical(|ui| {
|
||||
choose(ui, "effect_parameter", parameter, ¶meters);
|
||||
columns_note(ui, unlisted_parameters, "config.rule_parameter_columns");
|
||||
expression(ui, "Value", value);
|
||||
});
|
||||
}
|
||||
RuleEffect::DriveSuppression { feature, value } => {
|
||||
ui.vertical(|ui| {
|
||||
feature_choice(ui, "effect_feature", feature, &suppression_features);
|
||||
columns_note(ui, unlisted_features, "config.rule_suppression_columns");
|
||||
ui_kit::checkbox(ui, crate::i18n::tr_label("Suppressed"), value);
|
||||
});
|
||||
}
|
||||
RuleEffect::ParameterRange { parameter, minimum, maximum } => {
|
||||
choose(ui, "range_parameter", parameter, ¶meters);
|
||||
columns_note(ui, unlisted_parameters, "config.rule_parameter_columns");
|
||||
ui.vertical(|ui| {
|
||||
expression(ui, "Minimum", minimum);
|
||||
});
|
||||
@@ -199,6 +206,7 @@ pub(super) fn show(ui: &mut Ui, app: &mut SolveApp, error: &mut Option<String>,
|
||||
}
|
||||
RuleEffect::AllowParameterValues { parameter, expressions } => {
|
||||
choose(ui, "allowed_parameter", parameter, ¶meters);
|
||||
columns_note(ui, unlisted_parameters, "config.rule_parameter_columns");
|
||||
let mut text = expressions.join("; ");
|
||||
if ui_kit::row(ui, "Allowed expressions, separated by semicolons", |ui| ui_kit::text_field(ui, &mut text, "").1) {
|
||||
*expressions = text.split(';').map(|s| s.trim().to_string()).collect();
|
||||
@@ -313,6 +321,13 @@ pub(super) fn show(ui: &mut Ui, app: &mut SolveApp, error: &mut Option<String>,
|
||||
}
|
||||
});
|
||||
}
|
||||
/// Under a Then list that leaves some out (`unlisted`): only the table's columns are listed, and
|
||||
/// how to add one.
|
||||
fn columns_note(ui: &mut Ui, unlisted: bool, message: &'static str) {
|
||||
if unlisted {
|
||||
ui_kit::text(ui, crate::i18n::tr(message), ui_kit::Text::Note(message));
|
||||
}
|
||||
}
|
||||
fn report(ui: &mut Ui, text: impl AsRef<str>) {
|
||||
ui_kit::text(ui, crate::i18n::tr_label(text.as_ref()), ui_kit::Text::Report("rule_report", false));
|
||||
}
|
||||
|
||||
@@ -895,11 +895,19 @@ mod tests {
|
||||
|
||||
// Kit rows publish identities independently of translated text. Long forms scroll through
|
||||
// the same wheel events as a person; assertions still verify the saved rules and geometry.
|
||||
// A table row scrolled out of view is not built, so its handle is missing until the form
|
||||
// scrolls back up to the table above the rules.
|
||||
fn reveal_config_handle(h: &mut crate::scenario::Harness, handle: &str) {
|
||||
for _ in 0..24 {
|
||||
let at = crate::scenario::handle_at(handle).unwrap_or_else(|| panic!("missing {handle}: {:?}", h.app.dialog));
|
||||
let header = crate::scenario::rect_of("dialog:header").unwrap();
|
||||
let footer = crate::scenario::rect_of("dialog:footer").unwrap();
|
||||
let at = crate::scenario::handle_at(handle);
|
||||
if handle.starts_with("config:activate:") && at.is_none() {
|
||||
h.call("ui.scroll", json!({"x":header.left()+Tokens::get().space_6,"y":(header.bottom()+footer.top())*0.5,"delta":160.0}));
|
||||
h.frames(6);
|
||||
continue;
|
||||
}
|
||||
let at = at.unwrap_or_else(|| panic!("missing {handle}: {:?}", h.app.dialog));
|
||||
if at.y > header.bottom() + 8.0 && at.y < footer.top() - 8.0 {
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -542,6 +542,32 @@ fn configuration_add_column_menu_filters_as_typed_and_resets_on_close() {
|
||||
assert!(h.app.dialog.is_some(), "menu Escape leaves the card open");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn a_rule_says_why_then_lists_only_the_tables_columns() {
|
||||
// A rule drives or restricts a column of the table only, so Then leaves out a parameter or a
|
||||
// feature without one, where When lists them all: a note says so and how to add one (#10532).
|
||||
let parameters = "Only parameters with a column in the table are listed. Add one with Add Column (+) to use it here.";
|
||||
let features = "Only features with a Suppress column in the table are listed. Add one with Add Column (+) to drive it here.";
|
||||
let mut h = fixture();
|
||||
h.app.run("parameters.add", json!({"name":"depth","expression":"5 mm"})).unwrap();
|
||||
h.app.run("config.configure", json!({"params":["width"]})).unwrap();
|
||||
h.app.start("config.table");
|
||||
h.frames(4);
|
||||
h.step(&json!({"click":{"handle":"dialog:section:Add or edit rule"}})).unwrap();
|
||||
h.frames(3);
|
||||
assert!(h.widget(parameters).is_some(), "depth has no column, so Drive parameter says why it is not listed");
|
||||
h.step(&json!({"click":{"handle":"dialog:Then"}})).unwrap();
|
||||
h.step(&json!({"click":{"handle":"dialog:Then:Drive suppression"}})).unwrap();
|
||||
h.frames(3);
|
||||
assert!(h.widget(features).is_some(), "no feature has a Suppress column, so the empty list says why");
|
||||
assert!(h.widget(parameters).is_none(), "the parameter note belongs to the parameter effects");
|
||||
for feature in h.app.session.doc.features.iter().map(|f| f.name.clone()).collect::<Vec<_>>() {
|
||||
h.app.run("config.column", json!({"feature": feature})).unwrap();
|
||||
}
|
||||
h.frames(3);
|
||||
assert!(h.widget(features).is_none(), "with a column for every feature, all are listed and the note goes");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn draft_bins_do_not_delete_saved_rows_named_new() {
|
||||
for command in ["parameters.change", "config.table"] {
|
||||
|
||||
Reference in New Issue
Block a user