Skip to content

fix: adjusting validations and payload on sponsor forms template #823

Open
tomrndom wants to merge 4 commits intomasterfrom
fix/sponsor-forms-template-validations
Open

fix: adjusting validations and payload on sponsor forms template #823
tomrndom wants to merge 4 commits intomasterfrom
fix/sponsor-forms-template-validations

Conversation

@tomrndom
Copy link

@tomrndom tomrndom commented Mar 11, 2026

ref:
https://app.clickup.com/t/86b8u5uqb
https://app.clickup.com/t/86b8u65jm

Signed-off-by: Tomás Castillo tcastilloboireau@gmail.com

Summary by CodeRabbit

  • Bug Fixes

    • Global template popup now resets selected items and navigation state when closed, improving reopen behavior.
  • Improvements

    • Apply button in sponsorship selection dialog remains enabled so users can proceed regardless of selection state.
    • Removed add-on validation when configuring sponsor form templates.
  • New Features

    • Form handling now correctly supports and normalizes "Select All" choices for sponsors and add-ons.

…oints

Signed-off-by: Tomás Castillo <tcastilloboireau@gmail.com>
@coderabbitai
Copy link

coderabbitai bot commented Mar 11, 2026

📝 Walkthrough

Walkthrough

Adds a new utility normalizeSelectAllField and applies it to sponsor form actions to centralize "select all" handling; resets local state on global-template dialog close; keeps Apply button enabled in sponsorships dialog; removes Formik/Yup validation for add-on requirement.

Changes

Cohort / File(s) Summary
Utilities
src/utils/methods.js, src/utils/__tests__/methods.test.js
Add exported normalizeSelectAllField(items, flagName, listName, allSelected) and tests covering empty, "all", allSelected flag, object ids, and primitive values.
Sponsor Forms Actions
src/actions/sponsor-forms-actions.js
Replace inline "select all" logic with spreads of normalizeSelectAllField(...) in cloneGlobalTemplate, saveSponsorManagedForm, and normalizeSponsorManagedForm; removed former conditional branches that cleared lists when "all" was selected.
Global Template Dialog
src/pages/sponsors/sponsor-forms-list-page/components/global-template/global-template-popup.js
Change Dialog wrapper onClose to use internal handleClose that resets stage and selectedTemplates before calling external onClose.
Select Sponsorships Dialog
src/pages/sponsors/sponsor-forms-list-page/components/global-template/select-sponsorships-dialog.js
Remove disabled prop from the Apply button so it remains enabled regardless of selection state.
Add Sponsor Form Template Popup
src/pages/sponsors/sponsor-forms-tab/components/add-sponsor-form-template-popup/index.js
Remove Yup import and Formik validationSchema that enforced at-least-one add_ons constraint.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Possibly related PRs

Suggested reviewers

  • smarcet
  • gcutrini

Poem

🐰 I hopped through arrays and flags today,
I wrapped "all" in tidy boolean play,
Dialogs reset, selections cleared,
Apply waits ready, unchecked or shared,
Add-ons lined up, neat as hay.

🚥 Pre-merge checks | ✅ 3
✅ Passed checks (3 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title 'fix: adjusting validations and payload on sponsor forms template' directly aligns with the changeset, which refactors validation logic and payload handling across multiple sponsor form components.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
  • 📝 Generate docstrings (stacked PR)
  • 📝 Generate docstrings (commit on current branch)
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch fix/sponsor-forms-template-validations
📝 Coding Plan
  • Generate coding plan for human review comments

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

🧹 Nitpick comments (1)
src/actions/sponsor-forms-actions.js (1)

568-575: Consider restructuring to avoid intermediate undefined mapping.

When add_ons contains the string "all", line 569 maps it to undefined (since "all".id is undefined) before lines 572-573 overwrite the array. The code works correctly, but could be clearer:

♻️ Suggested refactor for clarity
   if (entity.add_ons?.length > 0) {
-    normalizedEntity.allowed_add_ons = entity.add_ons.map((a) => a.id);
-    normalizedEntity.apply_to_all_add_ons = false;
     if (entity.add_ons.includes("all")) {
       normalizedEntity.apply_to_all_add_ons = true;
       normalizedEntity.allowed_add_ons = [];
+    } else {
+      normalizedEntity.allowed_add_ons = entity.add_ons.map((a) => a.id);
+      normalizedEntity.apply_to_all_add_ons = false;
     }
   }
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/actions/sponsor-forms-actions.js` around lines 568 - 575, The current
block maps entity.add_ons to normalizedEntity.allowed_add_ons before checking
for the special "all" token, which yields an undefined entry for the string
"all"; update the logic in the sponsor-forms normalization so you first detect
if entity.add_ons includes the string "all" and set
normalizedEntity.apply_to_all_add_ons = true and
normalizedEntity.allowed_add_ons = [] in that case, otherwise set
apply_to_all_add_ons = false and populate normalizedEntity.allowed_add_ons by
mapping only addon objects (e.g., filter out non-objects or use a guard when
mapping) to avoid producing undefined values from ("all").
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Nitpick comments:
In `@src/actions/sponsor-forms-actions.js`:
- Around line 568-575: The current block maps entity.add_ons to
normalizedEntity.allowed_add_ons before checking for the special "all" token,
which yields an undefined entry for the string "all"; update the logic in the
sponsor-forms normalization so you first detect if entity.add_ons includes the
string "all" and set normalizedEntity.apply_to_all_add_ons = true and
normalizedEntity.allowed_add_ons = [] in that case, otherwise set
apply_to_all_add_ons = false and populate normalizedEntity.allowed_add_ons by
mapping only addon objects (e.g., filter out non-objects or use a guard when
mapping) to avoid producing undefined values from ("all").

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: d2d8dc02-cd64-496a-85d9-d8132f348799

📥 Commits

Reviewing files that changed from the base of the PR and between b29d23f and 5aab6e1.

📒 Files selected for processing (4)
  • src/actions/sponsor-forms-actions.js
  • src/pages/sponsors/sponsor-forms-list-page/components/global-template/global-template-popup.js
  • src/pages/sponsors/sponsor-forms-list-page/components/global-template/select-sponsorships-dialog.js
  • src/pages/sponsors/sponsor-forms-tab/components/add-sponsor-form-template-popup/index.js
💤 Files with no reviewable changes (1)
  • src/pages/sponsors/sponsor-forms-tab/components/add-sponsor-form-template-popup/index.js

Signed-off-by: Tomás Castillo <tcastilloboireau@gmail.com>
@tomrndom tomrndom requested a review from smarcet March 11, 2026 20:49
Signed-off-by: Tomás Castillo <tcastilloboireau@gmail.com>
// eslint-disable-next-line no-magic-numbers
export const bytesToMb = (bytes) => (bytes / BYTES_IN_MEGABYTE).toFixed(2);

export const normalizeSelectAllField = (
Copy link

Choose a reason for hiding this comment

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

@tomrndom
returns {} when items is empty or null:

if (!items?.length) return {};

The old code in normalizeSponsorManagedForm always sent both fields:
allowed_add_ons: entity.add_ons.map((a) => a.id), // [] when empty
apply_to_all_add_ons: false

After this change, an empty add_ons array produces no allowed_add_ons or apply_to_all_add_ons in the payload at all. Same issue applies to cloneGlobalTemplate — empty sponsorIds now omits both sponsorship_types and
apply_to_all_types. If the API requires or expects these fields, this is a breaking change.

Suggestion: Return both fields with defaults instead of {}:
if (!items?.length) return { [flagName]: false, [listName]: [] };
create a unit test for this

Copy link

@smarcet smarcet left a comment

Choose a reason for hiding this comment

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

@tomrndom please review comments

Signed-off-by: Tomás Castillo <tcastilloboireau@gmail.com>
Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🧹 Nitpick comments (1)
src/utils/__tests__/methods.test.js (1)

59-104: Add one regression case for allSelected = false with "all" present.

Nice coverage overall; one extra case would protect the precedence edge case in normalizeSelectAllField.

Suggested test addition
   describe("normalizeSelectAllField", () => {
@@
     it("should return all selected when allSelected flag is true", () => {
       expect(
         normalizeSelectAllField([{ id: 1 }], "apply_to_all", "items", true)
       ).toEqual({
         apply_to_all: true,
         items: []
       });
     });
+
+    it("should still return all selected when items contains 'all' and allSelected is false", () => {
+      expect(
+        normalizeSelectAllField(["all", { id: 1 }], "apply_to_all", "items", false)
+      ).toEqual({
+        apply_to_all: true,
+        items: []
+      });
+    });
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/utils/__tests__/methods.test.js` around lines 59 - 104, Add a regression
test for normalizeSelectAllField to ensure an explicit allSelected = false
overrides a literal "all" in the items array: call
normalizeSelectAllField(["all", { id: 1 }], "apply_to_all", "items", false) and
assert the result is { apply_to_all: false, items: [1] } so the function ignores
the "all" marker when the allSelected flag is explicitly false.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@src/utils/methods.js`:
- Around line 571-580: The current isAllSelected calculation (isAllSelected =
allSelected ?? items.includes("all")) lets an explicit false with items
containing "all" leak into the payload; change the logic so
items.includes("all") takes precedence (e.g. compute isAllSelected =
items.includes("all") || Boolean(allSelected)) and also ensure when building the
fallback list you filter out the literal "all" before mapping (use
items.filter(a => a !== "all") before .map) so flagName/listName behavior is
consistent.

---

Nitpick comments:
In `@src/utils/__tests__/methods.test.js`:
- Around line 59-104: Add a regression test for normalizeSelectAllField to
ensure an explicit allSelected = false overrides a literal "all" in the items
array: call normalizeSelectAllField(["all", { id: 1 }], "apply_to_all", "items",
false) and assert the result is { apply_to_all: false, items: [1] } so the
function ignores the "all" marker when the allSelected flag is explicitly false.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 0733dd8b-6b5d-4a47-ab6d-475d50d37cba

📥 Commits

Reviewing files that changed from the base of the PR and between b7e33a2 and 310e79d.

📒 Files selected for processing (2)
  • src/utils/__tests__/methods.test.js
  • src/utils/methods.js

Comment on lines +571 to +580
const isAllSelected = allSelected ?? items.includes("all");
if (isAllSelected) {
return {
[flagName]: true,
[listName]: []
};
}
return {
[flagName]: false,
[listName]: items.map((a) => a.id ?? a)
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

allSelected precedence can leak "all" into payload.

On Line 571, allSelected ?? items.includes("all") treats explicit false as final. If items still contains "all", the function can return listName: ["all", ...] instead of toggling flagName: true, which can break payload expectations.

Suggested fix
-  const isAllSelected = allSelected ?? items.includes("all");
+  const isAllSelected = allSelected === true || items.includes("all");
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
const isAllSelected = allSelected ?? items.includes("all");
if (isAllSelected) {
return {
[flagName]: true,
[listName]: []
};
}
return {
[flagName]: false,
[listName]: items.map((a) => a.id ?? a)
const isAllSelected = allSelected === true || items.includes("all");
if (isAllSelected) {
return {
[flagName]: true,
[listName]: []
};
}
return {
[flagName]: false,
[listName]: items.map((a) => a.id ?? a)
};
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/utils/methods.js` around lines 571 - 580, The current isAllSelected
calculation (isAllSelected = allSelected ?? items.includes("all")) lets an
explicit false with items containing "all" leak into the payload; change the
logic so items.includes("all") takes precedence (e.g. compute isAllSelected =
items.includes("all") || Boolean(allSelected)) and also ensure when building the
fallback list you filter out the literal "all" before mapping (use
items.filter(a => a !== "all") before .map) so flagName/listName behavior is
consistent.

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.

2 participants