Conditional formatting - #2538
Draft
AndyScherzinger wants to merge 27 commits into
Draft
Conversation
AndyScherzinger
force-pushed
the
feat/360/conditional-formatting
branch
3 times, most recently
from
May 3, 2026 14:52
b43b008 to
0d4a078
Compare
AndyScherzinger
force-pushed
the
feat/360/conditional-formatting
branch
from
September 7, 2026 12:47
0d4a078 to
cc24f5c
Compare
AndyScherzinger
force-pushed
the
feat/360/conditional-formatting
branch
23 times, most recently
from
September 8, 2026 19:52
839c3da to
76f37dd
Compare
AndyScherzinger
force-pushed
the
feat/360/conditional-formatting
branch
2 times, most recently
from
September 9, 2026 18:11
cd7e6c0 to
123cec1
Compare
… table Assisted-by: ClaudeCode:claude-sonnet-4-6 Signed-off-by: Andy Scherzinger <info@andy-scherzinger.de>
Assisted-by: ClaudeCode:claude-sonnet-4-6 Signed-off-by: Andy Scherzinger <info@andy-scherzinger.de>
…etion hooks Assisted-by: ClaudeCode:claude-sonnet-4-6 Signed-off-by: Andy Scherzinger <info@andy-scherzinger.de>
…onse types Assisted-by: ClaudeCode:claude-sonnet-4-6 Signed-off-by: Andy Scherzinger <info@andy-scherzinger.de>
… hooks Assisted-by: ClaudeCode:claude-sonnet-4-6 Signed-off-by: Andy Scherzinger <info@andy-scherzinger.de>
…ion option ID remapping Assisted-by: ClaudeCode:claude-sonnet-4-6 Signed-off-by: Andy Scherzinger <info@andy-scherzinger.de>
…mutation routes for formatting API Assisted-by: ClaudeCode:claude-sonnet-4-6 Signed-off-by: Andy Scherzinger <info@andy-scherzinger.de>
Assisted-by: ClaudeCode:claude-sonnet-4-6 Signed-off-by: Andy Scherzinger <info@andy-scherzinger.de>
Assisted-by: ClaudeCode:claude-sonnet-4-6 Signed-off-by: Andy Scherzinger <info@andy-scherzinger.de>
…onents Assisted-by: ClaudeCode:claude-sonnet-4-6 Assisted-by: ClaudeCode:claude-fable-5-1 Claude-Session: https://claude.ai/code/session_01XfLgKWUTg2M1jPdqgQz3FD Signed-off-by: Andy Scherzinger <info@andy-scherzinger.de>
…ponents Assisted-by: ClaudeCode:claude-sonnet-4-6 Assisted-by: ClaudeCode:claude-fable-5-1 Claude-Session: https://claude.ai/code/session_01XfLgKWUTg2M1jPdqgQz3FD Signed-off-by: Andy Scherzinger <info@andy-scherzinger.de>
…cement Assisted-by: ClaudeCode:claude-sonnet-4-6 Signed-off-by: Andy Scherzinger <info@andy-scherzinger.de>
Assisted-by: ClaudeCode:claude-sonnet-4-6 Signed-off-by: Andy Scherzinger <info@andy-scherzinger.de>
Assisted-by: ClaudeCode:claude-sonnet-4-6 Signed-off-by: Andy Scherzinger <info@andy-scherzinger.de>
Adds Format rules button to table toolbar, connects FormattingManager modal, propagates viewId through CustomTable/TableHeader for column popovers, and evaluates formatting rules on row load and changes. Assisted-by: ClaudeCode:claude-sonnet-4-6 Signed-off-by: Andy Scherzinger <info@andy-scherzinger.de>
…tingRuleColMapper Covers column deletion marking rules broken, column type change, selection option deletion, saveForView junction rebuild, and mapper sync/find/delete operations. Assisted-by: ClaudeCode:claude-sonnet-4-6 Assisted-by: ClaudeCode:claude-fable-5-1 Claude-Session: https://claude.ai/code/session_01XfLgKWUTg2M1jPdqgQz3FD Signed-off-by: Andy Scherzinger <info@andy-scherzinger.de>
…atting UI Assisted-by: ClaudeCode:claude-sonnet-4-6 Signed-off-by: Andy Scherzinger <info@andy-scherzinger.de>
Use OCP\DB\IResult instead of Doctrine\DBAL\Result for executeQuery mock (IQueryBuilder declares that return type). Set newTable->setId(1) in TablesMigratorTest formatting tests so tableIdMap entry is non-null and the importView callback fires. Assisted-by: ClaudeCode:claude-sonnet-4-6 Signed-off-by: Andy Scherzinger <info@andy-scherzinger.de>
- Remove unused loadTable import in e2e spec - Remove unused showError import in formatting store - Fix v-if/v-for on same element in ConditionGroupBuilder (use wrapper template) - Replace self-closing <input/> with <input> on void elements (FormatStylePicker, RuleEditor, RuleSetEditor) - Remove alignment spaces before return in switch statements (no-multi-spaces) - Replace boolean ternary with plain expression (no-unneeded-ternary) - Fix multiline-ternary in toCSS textDecoration - Add parentheses around mixed && / || in hasRulesForColumn (no-mixed-operators) - Move props above setup in TableRow and Options (vue/order-in-components) Assisted-by: ClaudeCode:claude-sonnet-4-6 Signed-off-by: Andy Scherzinger <info@andy-scherzinger.de>
…faults Move TablesFormatting* psalm-types before TablesView in ResponseDefinitions so the forward reference to TablesFormattingRuleSet is resolved in order. Use ['groups' => []] as default for \$condition params to match declared array shape. Widen FormattingConditionGroupInput constructor docblock to include optional value/values fields. Assisted-by: ClaudeCode:claude-sonnet-4-6 Signed-off-by: Andy Scherzinger <info@andy-scherzinger.de>
…Request::getFormat() conflict 'format' is a reserved request parameter consumed by Nextcloud's AppFramework to determine response content type. Sending an array as the top-level 'format' POST parameter in createRule/updateRule caused Request::getFormat() to return array instead of ?string, producing an HTTP 500. Renamed controller params $format → $style (mapping back to the internal 'format' key for FormattingRuleInput). Store actions destructure 'format' from caller data and re-key it as 'style' before POST/PUT so all callers remain unchanged. Assisted-by: ClaudeCode:claude-sonnet-4-6 Signed-off-by: Andy Scherzinger <info@andy-scherzinger.de>
Placeholder conditions created by ConditionGroupBuilder have null columnId and operator until the user fills them in. These caused a HTTP 400 because PHP's isset() returns false for null, triggering the 'Condition requires columnId, columnType and operator' validation. Filter out any condition missing columnId, operator, or columnType before posting, and drop groups that become empty after filtering. Assisted-by: ClaudeCode:claude-sonnet-4-6 Signed-off-by: Andy Scherzinger <info@andy-scherzinger.de>
…rect mutations FilterEntry mutates its filterEntry prop in-place rather than emitting update:filter-entry events, so onConditionUpdate was never called and localCondition in RuleEditor always held the initial empty state. Add a deep watcher on mutableGroups with a syncingFromProp guard so any in-place mutation made by FilterEntry is still emitted upward, while re-assignment from the conditionSet prop watcher does not trigger a redundant re-emit loop. Assisted-by: ClaudeCode:claude-sonnet-4-6 Assisted-by: ClaudeCode:claude-fable-5-1 Claude-Session: https://claude.ai/code/session_01XfLgKWUTg2M1jPdqgQz3FD Signed-off-by: Andy Scherzinger <info@andy-scherzinger.de>
The rename of the rule request parameter from 'format' to 'style' and the ['groups' => []] default for the condition parameter changed the API contract, but the generated openapi.json and openapi.ts were not regenerated. Regenerate both so the openapi CI check matches the code. Assisted-by: ClaudeCode:claude-fable-5-1 Claude-Session: https://claude.ai/code/session_01XfLgKWUTg2M1jPdqgQz3FD Signed-off-by: Andy Scherzinger <info@andy-scherzinger.de>
… CRUD paths and API controller Cover the parts of the formatting backend that had no tests: - FormattingInputTest: every whitelisted operator, style validation, condition/group/rule/rule-set limits and required fields. - FormattingServiceCrudTest: create/update/delete/reorder of rule sets and rules, permission and not-found errors, column ownership checks, the 50 rule-set and 20 rule limits, junction index sync, and re-validation of broken rules after a rule update. - FormattingApiControllerTest: 400 mapping for invalid input, 403/404/500 mapping for service errors, and the 'style' request parameter being mapped to the internal 'format' key. Assisted-by: ClaudeCode:claude-fable-5-1 Claude-Session: https://claude.ai/code/session_01XfLgKWUTg2M1jPdqgQz3FD Signed-off-by: Andy Scherzinger <info@andy-scherzinger.de>
…ne and style picker formattingStore.cy.js exercises the client-side evaluation through the Pinia store: every operator of the current vocabulary including selection option ids and date helpers, AND within a group and OR across groups, row versus column targets, first-match versus all-matches, disabled and broken rule sets and rules, hasRulesForColumn, re-evaluation, and the toCSS mapping. FormatStylePicker.cy.js covers the toggle buttons, the automatic black or white text color derived from the background luminance, the WCAG contrast warning once the user overrides the text color, invalid hex input and the clear buttons. Assisted-by: ClaudeCode:claude-fable-5-1 Claude-Session: https://claude.ai/code/session_01XfLgKWUTg2M1jPdqgQz3FD Signed-off-by: Andy Scherzinger <info@andy-scherzinger.de>
…erage The previous spec only opened the dialog; three of its five tests had no assertions. The table, columns, view and rows are now created through the REST API in beforeAll so the tests do not depend on the column creation UI. API tests cover rule set creation for row and column targets, the 400 for a missing target column, rule creation exposed through the view payload, 400s for unknown operators and style keys, reorder persistence, rule set and rule updates keeping their ids, 404 for unknown rules, rejection of a user without manage rights, and rules being marked broken and disabled when a referenced column is deleted. UI tests create a rule set and a 'contains' rule through the dialog and assert the row background, toggle the rule set from the column header popover, and check the broken indicator after the column is deleted. Assisted-by: ClaudeCode:claude-fable-5-1 Claude-Session: https://claude.ai/code/session_01XfLgKWUTg2M1jPdqgQz3FD Signed-off-by: Andy Scherzinger <info@andy-scherzinger.de>
AndyScherzinger
force-pushed
the
feat/360/conditional-formatting
branch
from
September 10, 2026 05:28
123cec1 to
27c5a4b
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
WIP