Skip to content

Commit

Permalink
Broken deep validations in nested repeating groups (#2867)
Browse files Browse the repository at this point in the history
Co-authored-by: Ole Martin Handeland <git@olemartin.org>
  • Loading branch information
olemartinorg and Ole Martin Handeland authored Jan 6, 2025
1 parent f9e61eb commit cb3c328
Show file tree
Hide file tree
Showing 5 changed files with 219 additions and 129 deletions.
36 changes: 21 additions & 15 deletions src/features/validation/ValidationStorePlugin.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ export interface ValidationStorePluginConfig {
useVisibleValidationsDeep: (
node: LayoutNode | undefined,
mask: NodeVisibility,
stopAtDepth?: number,
includeSelf: boolean,
restriction?: TraversalRestriction,
severity?: ValidationSeverity,
) => NodeRefValidation[];
Expand Down Expand Up @@ -136,12 +136,12 @@ export class ValidationStorePlugin extends NodeDataPlugin<ValidationStorePluginC
}
return getValidations({ state, node, mask: showAll ? 'showAll' : 'visible' });
}),
useVisibleValidationsDeep: (node, mask, stopAtDepth, restriction, severity) =>
useVisibleValidationsDeep: (node, mask, includeSelf, restriction, severity) =>
store.useMemoSelector((state) => {
if (!node) {
return emptyArray;
}
return getRecursiveValidations({ state, node, mask, severity, stopAtDepth, restriction });
return getRecursiveValidations({ state, node, mask, severity, includeSelf, restriction });
}),
useValidationsSelector: () =>
store.useDelayedSelector({
Expand Down Expand Up @@ -252,28 +252,34 @@ function getValidations({ state, node, mask, severity, includeHidden = false }:
}

interface GetDeepValidationsProps extends GetValidationsProps {
depth?: number;
stopAtDepth?: number;
includeSelf: boolean;
restriction?: TraversalRestriction;
}

function getRecursiveValidations(props: GetDeepValidationsProps): NodeRefValidation[] {
const out: NodeRefValidation[] = [];
const depth = props.depth ?? 0;

const nodeValidations = getValidations(props);
for (const validation of nodeValidations) {
out.push({ ...validation, nodeId: props.node.id });
}

if (props.stopAtDepth !== undefined && depth >= props.stopAtDepth) {
return out;
if (props.includeSelf) {
const nodeValidations = getValidations(props);
for (const validation of nodeValidations) {
out.push({ ...validation, nodeId: props.node.id });
}
}

const nodes = props.node.page.layoutSet;
if (nodes) {
for (const child of props.node.children(new TraversalTask(props.state, nodes, undefined, props.restriction))) {
out.push(...getRecursiveValidations({ ...props, node: child, depth: depth + 1 }));
const children = props.node.children(new TraversalTask(props.state, nodes, undefined, props.restriction));
for (const child of children) {
out.push(
...getRecursiveValidations({
...props,
node: child,

// Restriction and includeSelf should only be applied to the first level (not recursively)
restriction: undefined,
includeSelf: true,
}),
);
}
}

Expand Down
4 changes: 2 additions & 2 deletions src/features/validation/selectors/deepValidationsForNode.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,10 +9,10 @@ import type { TraversalRestriction } from 'src/utils/layout/useNodeTraversal';
*/
export function useDeepValidationsForNode(
node: LayoutNode | undefined,
onlyChildren: boolean = false,
includeSelf = true,
restriction?: TraversalRestriction,
): NodeRefValidation[] {
const showAll = Validation.useShowAllBackendErrors();
const mask = showAll ? 'showAll' : 'visible';
return NodesInternal.useVisibleValidationsDeep(node, mask, onlyChildren ? 1 : undefined, restriction);
return NodesInternal.useVisibleValidationsDeep(node, mask, includeSelf, restriction);
}
2 changes: 1 addition & 1 deletion src/layout/RepeatingGroup/Table/RepeatingGroupTableRow.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -123,7 +123,7 @@ export const RepeatingGroupTableRow = React.memo(function RepeatingGroupTableRow
const tableEditingNodeIds = tableNodes
.filter((n) => shouldEditInTable(editForGroup, n, columnSettings))
.map((n) => n.id);
const rowValidations = useDeepValidationsForNode(node, true, index);
const rowValidations = useDeepValidationsForNode(node, false, index);
const rowHasErrors = rowValidations.some(
(validation) => validation.severity === 'error' && !tableEditingNodeIds.includes(validation.nodeId),
);
Expand Down
Loading

0 comments on commit cb3c328

Please sign in to comment.