Skip to content

Show and edit logic rules where they act - #274

Closed
PhilReinking wants to merge 14 commits into
feat/bits-282c-keyboard-movefrom
feat/bits-284-logic-in-place
Closed

PhilReinking wants to merge 14 commits into
feat/bits-282c-keyboard-movefrom
feat/bits-284-logic-in-place

Conversation

@PhilReinking

@PhilReinking PhilReinking commented Oct 13, 2026 •

Copy link
Copy Markdown
Contributor

Each rule now reads as a sentence under its question ("If “No”, go to 31 · Thank you! See you there."). Edit turns it into pickers in place. The open question gets a line and a blue number on where it jumps. The old logic panel is gone.

Fixes BITS-284

  • Answers come from the source question: choices, rating range, date, number; text gets a case hint.
  • Operators by type, as in the ticket; stored keys don't change.
  • A rule using a deleted question shows red and can't be saved until fixed.
  • Remove rule asks first, like the deletes from Ask before deleting a question, naming its answers and the rules that use it #269.
  • Every rule control is 44 px below 1024 px.
  • logic.showLogicEditor is gone: use addRule(block) from Document/Rules/ruleEditing.ts.

Heads-up: the card's "Rules (2)" is now "Add rule". A closed question's meta drops its rule count and says "Always hidden".

Tested: new Vitest tests, lint, vue-tsc, build. By hand at 1440, 768 and 390: edit, save, leave and return, add, remove, move; the public form follows an edited jump.

Not tested: a screen reader. Stacked PR, so no CI.

Known gap: removing a question's only rule leaves the cursor on the page.

Screenshots (1440, 390) are on BITS-284.

🤖 Generated with Claude Code

PhilReinking and others added 5 commits October 13, 2026 02:25
Each rule reads as a sentence: the question by number, the operator in
words, the answer in quotes, the target as a chip. Edit turns it into
pickers: answers come from the source question, operators fit its type,
and a rule whose question was deleted shows in red and can't be saved.
A thin gutter line runs from the open question to where it jumps.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Rules sit under their question, a group's rules under its header, and
Add rule starts one in place instead of opening the logic panel.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- An update answers only true: keep the saved copy, so the sentence
  doesn't turn into "…" until reload.
- Escape in an open list closes the list, not the rule editor.
- A condition fits one row at desktop width; phones get 44 px buttons
  and no lone "If" row; long question texts are cut at 80 characters
  in the pickers.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Rules are edited in place now. The panel, its rule form and the store
parts only they used (editor state, backup, save-all, the old operator
list and condition transform) go.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

@PhilReinking PhilReinking left a comment

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

OK at 8bef14d. No CI (stacked), local runs: Vitest 323, lint, vue-tsc, build. No PHP change.

One should inline. Held: the new tests fail on the base, rules go out with the same fields as before (value always text, hide and show without a target), operators match the ticket, an old target on a hide rule draws no line, nothing else used the removed store parts, and answer labels show as text, never HTML.

Comment on lines +24 to +42
import { computed, nextTick } from "vue";
import RuleEditor from "./RuleEditor.vue";
import RuleLine from "./RuleLine.vue";
import { editing, editRule, returnFocus } from "./ruleEditing";

const props = defineProps<{
block: FormBlockModel;
numbers: Record<string, number>;
}>();

const id = computed(() => `rules-${props.block.uuid}`);
const owner = computed(() =>
props.block.type === "group"
? `group ${props.block.title || "Group"}`
: `question ${props.numbers[props.block.uuid]}`,
);

const isEditing = (index: number) =>
editing.value?.block === props.block.uuid && editing.value.index === index;

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The rule being edited is kept outside the page, so it stays open after you leave the editor. Back in the editor, that rule shows its pickers again and the cursor jumps into them. Ending the edit when its block's rules unmount fixes it, and a new rule that was never saved goes too:

Suggested change
import { computed, nextTick } from "vue";
import RuleEditor from "./RuleEditor.vue";
import RuleLine from "./RuleLine.vue";
import { editing, editRule, returnFocus } from "./ruleEditing";
const props = defineProps<{
block: FormBlockModel;
numbers: Record<string, number>;
}>();
const id = computed(() => `rules-${props.block.uuid}`);
const owner = computed(() =>
props.block.type === "group"
? `group ${props.block.title || "Group"}`
: `question ${props.numbers[props.block.uuid]}`,
);
const isEditing = (index: number) =>
editing.value?.block === props.block.uuid && editing.value.index === index;
import { computed, nextTick, onBeforeUnmount } from "vue";
import RuleEditor from "./RuleEditor.vue";
import RuleLine from "./RuleLine.vue";
import { editing, editRule, returnFocus, stopEditing } from "./ruleEditing";
const props = defineProps<{
block: FormBlockModel;
numbers: Record<string, number>;
}>();
const id = computed(() => `rules-${props.block.uuid}`);
const owner = computed(() =>
props.block.type === "group"
? `group ${props.block.title || "Group"}`
: `question ${props.numbers[props.block.uuid]}`,
);
const isEditing = (index: number) =>
editing.value?.block === props.block.uuid && editing.value.index === index;
// leaving the page ends editing: coming back shows the sentence again
onBeforeUnmount(() => {
if (editing.value?.block === props.block.uuid) stopEditing();
});

PhilReinking and others added 9 commits October 13, 2026 02:55
…nto feat/bits-284-logic-in-place

# Conflicts:
#	CHANGELOG.md
#	resources/js/components/Factory/Sidebar/BlockLogicRule.vue
Part a now asks before every delete; the old panel's test moves here.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Coming back showed the pickers again and moved the cursor into them.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…ogether

Pickers, text fields, Cancel and Save rule grow on phones; Edit, Add
condition, Remove rule and remove condition stay 44 px on tablets.
Cancel and Save rule wrap as one pair.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
"Hidden" read against "Hidden if …" right under it, and the rules
show as sentences, so the count said nothing new.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The faint elbow at a grey number looked like every other row.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…to feat/bits-284-logic-in-place

# Conflicts:
#	resources/js/components/Factory/Document/DocumentGroup.vue
#	resources/js/components/Factory/Document/DocumentQuestion.vue
#	resources/js/components/Factory/Document/FormDocument.vue
#	resources/js/components/Factory/Document/QuestionCard.vue
Part b's number column is 32 px below sm; the rules kept the 48 px indent.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@PhilReinking
PhilReinking changed the base branch from feat/bits-282-document-editor to feat/bits-282c-keyboard-move October 13, 2026 01:15

@PhilReinking PhilReinking left a comment

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

OK at 5a39ee9 (re-check of 8bef14d..5a39ee9, now on part c). No CI (stacked), local runs: Vitest 387, lint, vue-tsc, build.

The should is fixed: leaving the editor ends the edit and drops an unsaved rule. Held: both merges keep parts a, b and c (only this PR's own lines change in the shared files), Remove rule asks first, Escape closes only that dialog, a failed remove keeps the rule, and the pill and the line mark the same jumps.

@PhilReinking

Copy link
Copy Markdown
Contributor Author

Landed in main with #282 (the editor rebuild as one PR); this PR's commits are part of it.

ferbinu pushed a commit to ferbinu/input that referenced this pull request Oct 15, 2026
deck9#273

deck9#274 saves each rule with saveSingleRule; saveBlockLogic is gone.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant