-
Notifications
You must be signed in to change notification settings - Fork 10.4k
feat: Support an array response for a field when used as Value of Field
#22740
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
feat: Support an array response for a field when used as Value of Field
#22740
Conversation
WalkthroughThis set of changes introduces significant refactoring and new functionality related to the processing of RAQB (Rule-based Attribute Query Builder) queries. The core logic for resolving query values is centralized in a new Estimated code review effort🎯 4 (Complex) | ⏱️ ~45 minutes
Warning Review ran into problems🔥 ProblemsErrors were encountered while retrieving linked issues. Errors (1)
✨ Finishing Touches
🧪 Generate unit tests
🪧 TipsChatThere are 3 ways to chat with CodeRabbit:
SupportNeed help? Create a ticket on our support page for assistance with any issues or questions. Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments. CodeRabbit Commands (Invoked using PR comments)
Other keywords and placeholders
CodeRabbit Configuration File (
|
Hey there and thank you for opening this pull request! 👋🏼 We require pull request titles to follow the Conventional Commits specification and it looks like your proposed title needs to be adjusted. Details:
|
Value of Field
function getFieldResponseValueAsLabel({ | ||
field, | ||
fieldResponseValue, | ||
}: { | ||
fieldResponseValue: dynamicFieldValueOperandsResponse[keyof dynamicFieldValueOperandsResponse]["value"]; | ||
field: { | ||
type: string; | ||
options?: { | ||
id: string | null; | ||
label: string; | ||
}[]; | ||
}; | ||
}) { | ||
if (!field.options) { | ||
return fieldResponseValue; | ||
} | ||
|
||
const valueArray = fieldResponseValue instanceof Array ? fieldResponseValue : [fieldResponseValue]; | ||
|
||
const chosenOptions = valueArray.map((idOrLabel) => { | ||
const foundOptionById = field.options?.find((option) => { | ||
return option.id === idOrLabel; | ||
}); | ||
if (foundOptionById) { | ||
return { | ||
label: foundOptionById.label, | ||
id: foundOptionById.id, | ||
}; | ||
} else { | ||
return { | ||
label: idOrLabel.toString(), | ||
id: null, | ||
}; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This and all other deleted code here is actually moved to resolveQueryValue.ts or utils.ts
…ute-routing-error-with-value-of-field-when-the-field
* Replace attribute option Ids with the attribute option label(compatible to be matched with form field value) | ||
*/ | ||
const replaceAttributeOptionIdsWithOptionLabel = ({ | ||
queryValue, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This fn came from raqbUtils with the difference that it now accepts queryValue and returned updated queryValue instead of accepting queryValueString and returning back updated string. It builds queryValueString itself
This change ensures that we pass a typed queryValue and get typed queryValue in return
const nonNumberFieldResponseValue = | ||
typeof fieldResponseValue === "number" ? fieldResponseValue.toString() : fieldResponseValue; | ||
|
||
if (!field.options) { | ||
return nonNumberFieldResponseValue; | ||
} | ||
|
||
if (nonNumberFieldResponseValue instanceof Array) { | ||
return nonNumberFieldResponseValue.map(transformValue); | ||
} | ||
|
||
return transformValue(nonNumberFieldResponseValue); | ||
|
||
function transformValue(idOrLabel: string) { | ||
const foundOptionById = field.options?.find((option) => { | ||
return option.id === idOrLabel; | ||
}); | ||
if (foundOptionById) { | ||
return foundOptionById.label; | ||
} else { | ||
return idOrLabel.toString(); | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This fn also comes from raqbUtils with the change that it now never returns a number type which was unexpected as label can't be a number.
Also, earlier it was returning an array regardless of whether the fieldResponseValue was an array or string, now it returns array for array and string for string, making the function do its job well.
* // Returns: '{"value": [["delhi", "mumbai"]], "operator": "multiselect_some_in"}' | ||
* ``` | ||
*/ | ||
export const resolveQueryValue = ({ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This fn replaces the earlier replaceFieldTemplateVariableWithOptionLabel which was working on queryValueString and it now works on queryValue as an object(which is the original form).
It was required because string regex replacement can't handle all the scenarios.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Also, this fn itself calls replaceAttributeOptionIdsWithOptionLabel now, instead of letting the caller do it first before calling this fn.
This makes the job of this fn focussed on resolving the query value which involves.
- Repacing optionId with optionLabel
- Replacing {field:FIELD_ID} with the field's response
This fn is now being unit tested well.
value: [[Option1OfAttribute1.id, Option2OfAttribute1.id]], | ||
operator: "multiselect_some_in", | ||
valueType: ["multiselect"], | ||
it("should handle field template mixed with regular values in multiselect array", async () => { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is a new test.
]); | ||
}); | ||
describe("with `Value of field`", () => { | ||
it("when 'Any in'(multiselect_some_in) option is selected and more than one option is used in attribute and more than one option is selected in the field", async () => { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is a new test
describe("with a SINGLE_SELECT attribute", () => { | ||
it("when a static option is selected, troubleshooter should be null by default", async () => { | ||
const Option1OfAttribute1 = { id: "opt1", value: "Option 1", slug: "option-1" }; | ||
const Attribute1 = { | ||
id: "attr1", | ||
name: "Attribute 1", | ||
type: "SINGLE_SELECT" as const, | ||
slug: "attribute-1", | ||
options: [Option1OfAttribute1], | ||
}; | ||
|
||
mockAttributesScenario({ | ||
attributes: [Attribute1], | ||
teamMembersWithAttributeOptionValuePerAttribute: [ | ||
{ userId: 1, attributes: { [Attribute1.id]: Option1OfAttribute1.value } }, | ||
], | ||
}); | ||
mockAttributesScenario({ | ||
attributes: [Attribute1], |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
A lot of restructuring of tests.
The latest updates on your projects. Learn more about Vercel for Git ↗︎ |
Value of Field
Value of Field
Graphite Automations"Add consumer team as reviewer" took an action on this PR • (07/28/25)1 reviewer was added to this PR based on Keith Williams's automation. |
There was a problem hiding this 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 (2)
packages/lib/raqb/resolveQueryValue.ts (1)
156-167
: Consider using a more robust regex pattern for field template validationThe current string manipulation approach for field template detection works but could be more robust.
- const isFieldTemplate = (str: string): boolean => { - const trimmedStr = str.trim(); - return trimmedStr.startsWith("{field:") && trimmedStr.endsWith("}"); - }; - - // Extract field ID from template string - const extractFieldId = (template: string): string | null => { - const trimmedTemplate = template.trim(); - if (!isFieldTemplate(trimmedTemplate)) return null; - // Remove {field: and } to get the ID - return trimmedTemplate.slice(7, -1); - }; + const FIELD_TEMPLATE_REGEX = /^\s*\{field:([^}]+)\}\s*$/; + + const isFieldTemplate = (str: string): boolean => { + return FIELD_TEMPLATE_REGEX.test(str); + }; + + // Extract field ID from template string + const extractFieldId = (template: string): string | null => { + const match = template.match(FIELD_TEMPLATE_REGEX); + return match ? match[1] : null; + };packages/lib/raqb/raqbUtils.test.ts (1)
1703-1719
: Consider adding assertion for error logging in null query testWhile the test handles null input gracefully, it would be valuable to verify that appropriate error logging occurs.
Consider using a spy to verify error logging:
+ const loggerSpy = vi.spyOn(logger, 'error'); const result = resolveQueryValue({ queryValue: invalidQueryValue, // ... rest of params }); expect(result).toBeNull(); + // Optionally verify error was logged + expect(loggerSpy).toHaveBeenCalled();
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (7)
packages/lib/raqb/findTeamMembersMatchingAttributeLogic.test.ts
(3 hunks)packages/lib/raqb/raqbUtils.test.ts
(2 hunks)packages/lib/raqb/raqbUtils.ts
(4 hunks)packages/lib/raqb/resolveQueryValue.test.ts
(1 hunks)packages/lib/raqb/resolveQueryValue.ts
(1 hunks)packages/lib/raqb/utils.ts
(1 hunks)packages/lib/raqb/zod.ts
(1 hunks)
🧰 Additional context used
📓 Path-based instructions (1)
**/*.{js,jsx,ts,tsx}
📄 CodeRabbit Inference Engine (.cursor/rules/review.mdc)
Flag excessive Day.js use in performance-critical code. Functions like .add, .diff, .isBefore, and .isAfter are slow, especially in timezone mode. Prefer .utc() for better performance. Where possible, replace with native Date and direct .valueOf() comparisons for faster execution. Recommend using native methods or Day.js .utc() consistently in hot paths like loops.
Files:
packages/lib/raqb/utils.ts
packages/lib/raqb/zod.ts
packages/lib/raqb/resolveQueryValue.ts
packages/lib/raqb/raqbUtils.ts
packages/lib/raqb/raqbUtils.test.ts
packages/lib/raqb/resolveQueryValue.test.ts
packages/lib/raqb/findTeamMembersMatchingAttributeLogic.test.ts
🧠 Learnings (2)
packages/lib/raqb/raqbUtils.ts (5)
Learnt from: eunjae-lee
PR: #22106
File: packages/lib/server/service/insightsRouting.ts:367-368
Timestamp: 2025-07-15T13:02:17.403Z
Learning: In the InsightsRoutingService (packages/lib/server/service/insightsRouting.ts), multi-select filter data is already validated by zod before reaching the buildFormFieldSqlCondition method, so null/undefined values are not present in filterValue.data arrays and don't need to be filtered out.
Learnt from: CR
PR: calcom/cal.com#0
File: .cursor/rules/review.mdc:0-0
Timestamp: 2025-07-21T13:54:11.770Z
Learning: Applies to backend/**/*.{ts,tsx} : For Prisma queries: Never use Includes - use select.
Learnt from: CR
PR: calcom/cal.com#0
File: .cursor/rules/review.mdc:0-0
Timestamp: 2025-07-21T13:54:11.770Z
Learning: Applies to backend/**/*.{ts,tsx} : For Prisma queries: Only select data you need.
Learnt from: CR
PR: calcom/cal.com#0
File: .cursor/rules/review.mdc:0-0
Timestamp: 2025-07-21T13:54:11.770Z
Learning: Applies to backend/**/*.{ts,tsx} : For Prisma queries: Select selects only the fields you specify explicitly.
Learnt from: eunjae-lee
PR: #22106
File: packages/features/insights/components/FailedBookingsByField.tsx:65-71
Timestamp: 2025-07-15T12:59:34.389Z
Learning: In the FailedBookingsByField component (packages/features/insights/components/FailedBookingsByField.tsx), although routingFormId is typed as optional in useInsightsParameters, the system automatically enforces a routing form filter, so routingFormId is always present in practice. This means the data always contains only one entry, making the single-entry destructuring approach safe.
packages/lib/raqb/raqbUtils.test.ts (1)
Learnt from: eunjae-lee
PR: #22106
File: packages/lib/server/service/insightsRouting.ts:367-368
Timestamp: 2025-07-15T13:02:17.403Z
Learning: In the InsightsRoutingService (packages/lib/server/service/insightsRouting.ts), multi-select filter data is already validated by zod before reaching the buildFormFieldSqlCondition method, so null/undefined values are not present in filterValue.data arrays and don't need to be filtered out.
🧬 Code Graph Analysis (1)
packages/lib/raqb/raqbUtils.ts (1)
packages/lib/raqb/resolveQueryValue.ts (1)
resolveQueryValue
(137-267)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (2)
- GitHub Check: Analyze Build / analyze
- GitHub Check: Codacy Static Code Analysis
🔇 Additional comments (20)
packages/lib/raqb/utils.ts (1)
1-9
: LGTM!The
caseInsensitive
utility function is well-implemented with proper TypeScript conditional return types, maintaining the input structure while converting to lowercase.packages/lib/raqb/zod.ts (1)
87-119
: Helpful documentation addition!The JSON example clearly illustrates the expected structure of
raqbQueryValueSchema
, including nested groups, rules, and field templates. This will aid developers in understanding the complex query value format.packages/lib/raqb/findTeamMembersMatchingAttributeLogic.test.ts (3)
50-50
: Good addition ofattributeId
to options.Adding
attributeId
to the option objects is necessary for the attribute resolution logic to work correctly.
293-795
: Excellent test organization and coverage!The restructured tests with nested
describe
blocks for SINGLE_SELECT and MULTI_SELECT attributes provide clear organization and comprehensive coverage of:
- Static option selection
- Dynamic "Value of field" resolution
- Complex multiselect scenarios with mixed field templates and fixed values
- Edge cases with array handling
The test scenarios effectively validate the new
resolveQueryValue
functionality.
1214-1252
: Good edge case coverage for non-existent option IDs.This test ensures the system gracefully handles invalid option IDs by returning no matches rather than throwing errors.
packages/lib/raqb/resolveQueryValue.test.ts (4)
11-152
: Well-structured test data builders!The helper functions (
createQueryValueRule
,createAttributesQueryValue
, etc.) provide a clean and maintainable way to create test scenarios, reducing boilerplate and improving test readability.
211-581
: Comprehensive coverage of attribute option ID conversion!These tests thoroughly validate the conversion of attribute option IDs to lowercase labels, covering:
- Single and multiple option conversions
- Mixed arrays with field templates
- Special characters preservation
- Edge cases with missing attributes
The tests effectively verify the critical functionality for field matching.
1154-1181
: Good performance consideration with large arrays.Testing with 100-item arrays ensures the implementation handles large datasets efficiently.
1621-1654
: Excellent stack overflow prevention test!Testing with 100 levels of nesting ensures the recursive implementation won't cause stack overflow issues in production.
packages/lib/raqb/raqbUtils.ts (2)
160-166
: Clean refactoring to use centralizedresolveQueryValue
!The simplified implementation delegates the complex logic of attribute option ID resolution and field template processing to the dedicated
resolveQueryValue
function, improving maintainability and separation of concerns.
223-223
: Good addition ofresolveQueryValue
to exports.Exposing
resolveQueryValue
through theacrossQueryValueCompatiblity
object allows external modules to use this functionality when needed.packages/lib/raqb/resolveQueryValue.ts (3)
47-77
: LGTM!The function correctly handles field response value transformation with proper type conversions and array handling.
200-227
: Array flattening implementation correctly supports multiselect fieldsThe flattening behavior for field templates that resolve to arrays (lines 213-217) properly addresses the PR objective of supporting array responses for multiselect fields when used as "Value of Field".
251-267
: Good error handling with comprehensive loggingThe error handling provides detailed context for debugging including field counts and response keys.
packages/lib/raqb/raqbUtils.test.ts (6)
12-18
: Well-structured test setup with appropriate mockingThe mock for
getFieldResponseValueAsLabel
appropriately simplifies testing by returning values as-is, allowing focus on the core logic ofresolveQueryValue
.
20-163
: Excellent test data builders improve test maintainabilityThe test data builders (
createQueryValueRule
,createAttributesQueryValue
, etc.) provide a clean API for creating test scenarios, making tests more readable and maintainable.
281-645
: Comprehensive test coverage for attribute option ID replacementThe test suite thoroughly covers attribute ID replacement scenarios including edge cases like special characters, empty arrays, and complex nested structures.
759-799
: Critical test validates array field template resolutionThis test specifically validates the PR's core objective - when multiple field templates are used in a multiselect context and one resolves to an array while another to a single value, they are properly combined into a flat array.
1286-1313
: Good performance consideration with large array testTesting with a 100-item array ensures the implementation handles large datasets efficiently.
1560-1595
: Excellent edge case coverage for empty responsesThe tests properly verify that field templates remain unchanged when responses are missing, ensuring graceful degradation.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM 🙏
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks good
…value-of-field-when-the-field
E2E results are ready! |
…eld` (#22740) * Passing tests and fixed * self review addressed adn more tests
* fix: resolve username constraint violation in removeMember - Update username to - format when removing users from organizations - Fix unique constraint violation on (username, organizationId) when organizationId is null - Add test case to verify username format change and successful removal - Fix skipped test by adding proper imports and removing describe.skip Co-Authored-By: anik@cal.com <adhabal2002@gmail.com> * test: update removeMember test to verify constraint violation scenario - Create two users with same username (one with null orgId, one with orgId) - Verify removing org user updates username without unique constraint error - Test ensures username gets updated to - format Co-Authored-By: anik@cal.com <adhabal2002@gmail.com> * test: add comprehensive unit tests for handleInstantMeeting - Revert previous removeMember changes - Add full test coverage for instant meeting functionality - Test team validation, booking creation, token generation - Test webhook triggers and browser notifications - Mock external dependencies for isolated unit tests - Translation issue to be addressed in future iteration Co-Authored-By: anik@cal.com <adhabal2002@gmail.com> * update * Update handleInstantMeeting.test.ts * fix: redir parameter for connect atoms (#22815) * encode redirect url to make sure it has all parameters * add changesets * feat: Support an array response for a field when used as `Value of Field` (#22740) * Passing tests and fixed * self review addressed adn more tests * fix: flaky e2e (#22819) * fix: merge working hours when adjacent (#21912) * fix: Adjacency issue when working hours connect over multiple days * Add tests to validate the new merging of day end logic * Update to correct annotation. Co-authored-by: cubic-dev-ai[bot] <191113872+cubic-dev-ai[bot]@users.noreply.github.com> * Implement subsequent date ranges for date overrides also * The map needs to be updated on successful resolve. * test: add failing test for overlapping ranges with same end time Demonstrates bug where overlapping working hour ranges (6:00-10:00 and 8:00-10:00) lose the earlier portion (6:00-8:00), showing only 8:00 and 9:00 slots instead of all 4 slots (6:00, 7:00, 8:00, 9:00). Related to Carina's comment on PR #21912. Co-Authored-By: alex@cal.com <me@alexvanandel.com> * fix: properly merge overlapping ranges with same end time Fixes bug where overlapping working hour ranges with the same end time (e.g., 6:00-10:00 and 8:00-10:00) would lose the earlier portion of the first range. The merging logic now correctly preserves the earliest start time when ranges overlap and share the same end time. This ensures all expected time slots are available (6:00, 7:00, 8:00, 9:00) instead of losing the earlier slots (6:00, 7:00). Resolves the issue identified in Carina's comment on PR #21912. Co-Authored-By: alex@cal.com <me@alexvanandel.com> * perf: optimize overlapping range detection from O(n²) to O(n) Replaces Object.keys().find() with Map-based lookup for ranges with same end time. This optimization handles 2000+ date ranges efficiently, reducing complexity from 4M operations to linear time while maintaining the same merging behavior. Performance improvement for high-volume event types with many availability ranges. Co-Authored-By: alex@cal.com <me@alexvanandel.com> --------- Co-authored-by: cubic-dev-ai[bot] <191113872+cubic-dev-ai[bot]@users.noreply.github.com> Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com> * feat: Improving Booking Visibility at Month-End (#22770) * remove first weeks and add last * fix added last week * prefetch availability of next month * don't switch month * On hover show month * only show new UI in monthly view * show month tooldtip only when needed * show month on first day of month * remove isFirstDayOfNextMonth * fix prefetching next month * fix datePicker tests * preventMonthSwitching in monthly view * add tests * code clean up * code clean up * code clena up for ooo days * push first day of month * remove bg color for the month badge * fix text colour * remove not needed * use object param * revert: use object param * use object param * fix DatePicker tests --------- Co-authored-by: CarinaWolli <wollencarina@gmail.com> Co-authored-by: Sean Brydon <sean@cal.com> Co-authored-by: Eunjae Lee <hey@eunjae.dev> * chore: Refactor logs (#22824) * Refactor logs * Add specific info to log * fix: Errors in org onboarding in some edge cases (#22711) * Automatically enable migration of a team that conflicts with Orgs slug * Allow changing the orgs slug and name if user goes back and changes it * avoid crashing on some scenarios * Revert "Allow changing the orgs slug and name if user goes back and changes it" This reverts commit f8872b0. * fix: handle unpublished teams gracefully in org migration - Change 'No oldSlug for team' from error to warning for unpublished teams - Keep 'No slug for team' as error since org onboarding ensures teams have names - Add test for migrating unpublished teams without oldSlug - Add clarifying comments about when each condition can occur * feat: enable PBAC checking on organization settings page (#22467) * refactor: convert checkBookingLimits to class service with dependency injection (#22768) * refactor: convert checkBookingLimits to class service with dependency injection - Create CheckBookingLimitsService class following AvailableSlotsService pattern - Add countBookingsByEventTypeAndDateRange method to BookingRepository - Move direct prisma calls from service to repository layer - Implement dependency injection with proper DI tokens and modules - Update all usage points to use the new service through DI - Maintain backward compatibility with error-throwing wrapper functions - Update tests to use the new service pattern - Resolve TODO comment in AvailableSlotsService for DI integration Co-Authored-By: morgan@cal.com <morgan@cal.com> * chore: DI CheckBookingLimitsService in v2 slots service * chore: bump libraries * chore: create getCheckBookingLimitsService * refactor: convert checkBookingAndDurationLimits to service class with DI - Create CheckBookingAndDurationLimitsService class following DI pattern - Add DI tokens and module for the new service - Update booking-limits container to provide the new service - Refactor handleNewBooking.ts to use service through DI - Maintain backward compatibility with deprecated function export - Preserve all existing functionality while improving code organization Co-Authored-By: morgan@cal.com <morgan@cal.com> * chore: CheckBookingAndDurationLimitsService * chore: bump platform libs --------- Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com> Co-authored-by: morgan@cal.com <morgan@cal.com> Co-authored-by: Morgan <33722304+ThyMinimalDev@users.noreply.github.com> * fix: Return empty available days if error querying calendar (#22828) * Return a busy block placeholder if calendar throws an error * Refactor `getCalendarsEvents` to return an object with a success prop * Throw error in `getBusyTimes` if failed to fetch calendar availability * Return empty available days if error getting busy times * yeet. * Type fix * Fix type error in getLuckyUsers * Type fixes * Type fix * Type fix * Fix test * Fix test mocks * Refactor calendars.service to use new calendarBusyTimesQuery --------- Co-authored-by: Alex van Andel <me@alexvanandel.com> * chore: release v5.5.9 * include mobile layout (#22836) Co-authored-by: CarinaWolli <wollencarina@gmail.com> * test: fix handleInstantMeeting test with setupAndTeardown and proper mocking - Add setupAndTeardown() for proper test environment setup - Use mockNoTranslations() to fix translation function mocking - Simplify NextApiRequest mock to resolve TypeScript errors - Both test cases now pass successfully Co-Authored-By: anik@cal.com <adhabal2002@gmail.com> * fix typo --------- Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com> Co-authored-by: Rajiv Sahal <sahalrajiv-extc@atharvacoe.ac.in> Co-authored-by: Hariom Balhara <hariombalhara@gmail.com> Co-authored-by: Alex van Andel <me@alexvanandel.com> Co-authored-by: cubic-dev-ai[bot] <191113872+cubic-dev-ai[bot]@users.noreply.github.com> Co-authored-by: Carina Wollendorfer <30310907+CarinaWolli@users.noreply.github.com> Co-authored-by: CarinaWolli <wollencarina@gmail.com> Co-authored-by: Sean Brydon <sean@cal.com> Co-authored-by: Eunjae Lee <hey@eunjae.dev> Co-authored-by: Joe Au-Yeung <65426560+joeauyeung@users.noreply.github.com> Co-authored-by: sean-brydon <55134778+sean-brydon@users.noreply.github.com> Co-authored-by: morgan@cal.com <morgan@cal.com> Co-authored-by: Morgan <33722304+ThyMinimalDev@users.noreply.github.com>
What does this PR do?
Video Demo (if applicable):
After the fix: https://www.loom.com/share/8ab462f3d9c44641996e7d7ec9a3bdc3
Before the fix: https://www.loom.com/share/4b6684ddd75d469c87319e079b076c45
Mandatory Tasks (DO NOT REMOVE)
How should this be tested?
See loom.
Earlier, if a multiselect form field was provided with multiple options and that field is selected as 'Value of Field', there was an intentional error