feat: add hidden event toggle support for managed events#29752
feat: add hidden event toggle support for managed events#29752Sayan8945 wants to merge 1 commit into
Conversation
Adds the 'Hide from profile' (hidden) toggle to managed event types and propagates it to assigned child event types, with lock/unlock semantics via managedEventConfig.unlockedFields. - Implement handleChildrenEventTypes engine (previously a no-op stub) that creates/updates/deletes child event types for assigned users and propagates the parent's locked managed props, including hidden. - Lock semantics: when hidden is locked (default), children inherit the parent's value; when unlocked, each child keeps its own. - Handle the listing quick-toggle path (payload without children) by syncing hidden to existing children. - Show the hidden toggle for managed parents in the event type listing and disable it for locked children. - Add unit tests covering create/update/delete, lock/unlock, quick-toggle and slug-collision cases.
|
Welcome to Cal.diy, @Sayan8945! Thanks for opening this pull request. A few things to keep in mind:
A maintainer will review your PR soon. Thanks for contributing! |
📝 WalkthroughWalkthroughManaged event-type updates now use a dedicated child synchronizer that propagates locked fields, preserves unlocked hidden values, creates and removes children as assignments change, and avoids slug conflicts. The update handler delegates child processing to this synchronizer. The event-type listing disables or hides hidden controls when managed settings lock the field, with distinct desktop tooltip messages. Vitest coverage validates the synchronization scenarios. 🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✨ Finishing Touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Actionable comments posted: 5
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@apps/web/modules/event-types/views/event-types-listing-view.tsx`:
- Around line 604-614: Add a tooltip branch for lockedByOrg in the tooltip
content surrounding the Hidden Switch, ensuring it takes precedence alongside
isChildHiddenLocked and displays an explanatory locked message whenever either
condition disables the switch. Preserve the existing show/hide messages for
enabled states.
In
`@packages/trpc/server/routers/viewer/eventTypes/heavy/handleChildrenEventTypes.test.ts`:
- Around line 90-107: Add a test alongside the existing locked case that mocks
the parent as hidden false, invokes handleChildrenEventTypes with an existing
child, and asserts updateMany is called with the expected parent/user filter
while updateArg.data does not contain hidden, verifying the child’s existing
hidden value is preserved when unlocked.
In
`@packages/trpc/server/routers/viewer/eventTypes/heavy/handleChildrenEventTypes.ts`:
- Around line 172-188: The existing-child update path in
handleChildrenEventTypes currently overwrites child-specific hidden values with
false when hidden is unlocked. Build the update data once, add hidden only when
isHiddenLocked is true, and replace the per-user Promise.all/updateMany loop
with a single updateMany targeting parentId and oldUserIds via an appropriate
userId filter.
- Around line 139-141: Update the child event synchronization logic to propagate
parent metadata changes to existing children, not only during creation. Locate
the update path in the child event handling logic alongside the childMetadata
initialization, include the parent’s current metadata when building child
updates, and ensure managedEventConfig.unlockedFields is refreshed on every
affected child.
In `@packages/trpc/server/routers/viewer/eventTypes/heavy/update.handler.ts`:
- Around line 725-734: Wrap the parent update and handleChildrenEventTypes call
in a single Prisma transaction so failures roll back both parent and child
changes. Pass the transaction client instead of ctx.prisma to
handleChildrenEventTypes, updating its signature and all required callers to
accept the transaction-scoped client.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro
Run ID: cf7a9fd4-ebbf-4658-aa3c-aedfdb90ce08
📒 Files selected for processing (4)
apps/web/modules/event-types/views/event-types-listing-view.tsxpackages/trpc/server/routers/viewer/eventTypes/heavy/handleChildrenEventTypes.test.tspackages/trpc/server/routers/viewer/eventTypes/heavy/handleChildrenEventTypes.tspackages/trpc/server/routers/viewer/eventTypes/heavy/update.handler.ts
| content={ | ||
| isChildHiddenLocked | ||
| ? t("locked_by_team_admin") | ||
| : type.hidden | ||
| ? t("show_eventtype_on_profile") | ||
| : t("hide_from_profile") | ||
| }> | ||
| <div className="self-center rounded-md p-2"> | ||
| <Switch | ||
| name="Hidden" | ||
| disabled={lockedByOrg || isChildHiddenLocked} |
There was a problem hiding this comment.
🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win
Tooltip doesn't cover the lockedByOrg case.
The tooltip content only special-cases isChildHiddenLocked, but the switch is disabled when lockedByOrg || isChildHiddenLocked (line 614). When lockedByOrg is true but isChildHiddenLocked is false, the tooltip shows a normal "show/hide from profile" message while the switch is disabled — misleading the user. The change details indicate the old tooltip logic considered lockedByOrg; that case appears to have been dropped.
Consider adding a lockedByOrg branch to the tooltip content so all disabled states have an explanatory message.
💡 Suggested tooltip fix
content={
+ lockedByOrg
+ ? t("locked_by_organization")
+ : isChildHiddenLocked
+ ? t("locked_by_team_admin")
+ : type.hidden
+ ? t("show_eventtype_on_profile")
+ : t("hide_from_profile")
- isChildHiddenLocked
- ? t("locked_by_team_admin")
- : type.hidden
- ? t("show_eventtype_on_profile")
- : t("hide_from_profile")
}📝 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.
| content={ | |
| isChildHiddenLocked | |
| ? t("locked_by_team_admin") | |
| : type.hidden | |
| ? t("show_eventtype_on_profile") | |
| : t("hide_from_profile") | |
| }> | |
| <div className="self-center rounded-md p-2"> | |
| <Switch | |
| name="Hidden" | |
| disabled={lockedByOrg || isChildHiddenLocked} | |
| content={ | |
| lockedByOrg | |
| ? t("locked_by_organization") | |
| : isChildHiddenLocked | |
| ? t("locked_by_team_admin") | |
| : type.hidden | |
| ? t("show_eventtype_on_profile") | |
| : t("hide_from_profile") | |
| }> | |
| <div className="self-center rounded-md p-2"> | |
| <Switch | |
| name="Hidden" | |
| disabled={lockedByOrg || isChildHiddenLocked} |
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@apps/web/modules/event-types/views/event-types-listing-view.tsx` around lines
604 - 614, Add a tooltip branch for lockedByOrg in the tooltip content
surrounding the Hidden Switch, ensuring it takes precedence alongside
isChildHiddenLocked and displays an explanatory locked message whenever either
condition disables the switch. Preserve the existing show/hide messages for
enabled states.
| it("updates existing children with the parent's hidden value when locked", async () => { | ||
| prismaMock.eventType.findUniqueOrThrow.mockResolvedValue(buildParent({ hidden: true }) as never); | ||
|
|
||
| const res = await handleChildrenEventTypes({ | ||
| eventTypeId: PARENT_ID, | ||
| updatedEventType: { slug: "managed", schedulingType: SchedulingType.MANAGED }, | ||
| oldEventType: { children: [{ userId: 2 }] }, | ||
| children: [buildChildInput(2, false)], | ||
| prisma: prismaMock, | ||
| }); | ||
|
|
||
| expect(res).toMatchObject({ newUserIds: [], oldUserIds: [2], deletedUserIds: [] }); | ||
| expect(prismaMock.eventType.create).not.toHaveBeenCalled(); | ||
| expect(prismaMock.eventType.updateMany).toHaveBeenCalledTimes(1); | ||
| const updateArg = prismaMock.eventType.updateMany.mock.calls[0][0]; | ||
| expect(updateArg.where).toEqual({ parentId: PARENT_ID, userId: 2 }); | ||
| expect(updateArg.data.hidden).toBe(true); | ||
| }); |
There was a problem hiding this comment.
📐 Maintainability & Code Quality | 🟠 Major | ⚡ Quick win
Add a test for updating existing children when hidden is unlocked.
The suite covers "update existing children when locked" (this test) but misses the unlocked case. This is the exact scenario where the bug at line 178 of handleChildrenEventTypes.ts manifests: when unlocked, the child's existing hidden should be preserved, not overwritten with false. A test asserting that updateMany data omits hidden when unlocked would catch the regression.
✅ Suggested test: unlocked update preserves child's hidden
+ it("preserves the child's own hidden value when updating and the field is unlocked", async () => {
+ prismaMock.eventType.findUniqueOrThrow.mockResolvedValue(
+ buildParent({
+ hidden: false,
+ metadata: { managedEventConfig: { unlockedFields: { hidden: true } } },
+ }) as never
+ );
+
+ await handleChildrenEventTypes({
+ eventTypeId: PARENT_ID,
+ updatedEventType: { slug: "managed", schedulingType: SchedulingType.MANAGED },
+ oldEventType: { children: [{ userId: 2 }] },
+ children: [buildChildInput(2, true)],
+ prisma: prismaMock,
+ });
+
+ expect(prismaMock.eventType.updateMany).toHaveBeenCalledTimes(1);
+ const updateArg = prismaMock.eventType.updateMany.mock.calls[0][0];
+ // Unlocked → hidden should be omitted from the update data to preserve the child's existing value.
+ expect(updateArg.data).not.toHaveProperty("hidden");
+ });📝 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.
| it("updates existing children with the parent's hidden value when locked", async () => { | |
| prismaMock.eventType.findUniqueOrThrow.mockResolvedValue(buildParent({ hidden: true }) as never); | |
| const res = await handleChildrenEventTypes({ | |
| eventTypeId: PARENT_ID, | |
| updatedEventType: { slug: "managed", schedulingType: SchedulingType.MANAGED }, | |
| oldEventType: { children: [{ userId: 2 }] }, | |
| children: [buildChildInput(2, false)], | |
| prisma: prismaMock, | |
| }); | |
| expect(res).toMatchObject({ newUserIds: [], oldUserIds: [2], deletedUserIds: [] }); | |
| expect(prismaMock.eventType.create).not.toHaveBeenCalled(); | |
| expect(prismaMock.eventType.updateMany).toHaveBeenCalledTimes(1); | |
| const updateArg = prismaMock.eventType.updateMany.mock.calls[0][0]; | |
| expect(updateArg.where).toEqual({ parentId: PARENT_ID, userId: 2 }); | |
| expect(updateArg.data.hidden).toBe(true); | |
| }); | |
| it("updates existing children with the parent's hidden value when locked", async () => { | |
| prismaMock.eventType.findUniqueOrThrow.mockResolvedValue(buildParent({ hidden: true }) as never); | |
| const res = await handleChildrenEventTypes({ | |
| eventTypeId: PARENT_ID, | |
| updatedEventType: { slug: "managed", schedulingType: SchedulingType.MANAGED }, | |
| oldEventType: { children: [{ userId: 2 }] }, | |
| children: [buildChildInput(2, false)], | |
| prisma: prismaMock, | |
| }); | |
| expect(res).toMatchObject({ newUserIds: [], oldUserIds: [2], deletedUserIds: [] }); | |
| expect(prismaMock.eventType.create).not.toHaveBeenCalled(); | |
| expect(prismaMock.eventType.updateMany).toHaveBeenCalledTimes(1); | |
| const updateArg = prismaMock.eventType.updateMany.mock.calls[0][0]; | |
| expect(updateArg.where).toEqual({ parentId: PARENT_ID, userId: 2 }); | |
| expect(updateArg.data.hidden).toBe(true); | |
| }); | |
| it("preserves the child's own hidden value when updating and the field is unlocked", async () => { | |
| prismaMock.eventType.findUniqueOrThrow.mockResolvedValue( | |
| buildParent({ | |
| hidden: false, | |
| metadata: { managedEventConfig: { unlockedFields: { hidden: true } } }, | |
| }) as never | |
| ); | |
| await handleChildrenEventTypes({ | |
| eventTypeId: PARENT_ID, | |
| updatedEventType: { slug: "managed", schedulingType: SchedulingType.MANAGED }, | |
| oldEventType: { children: [{ userId: 2 }] }, | |
| children: [buildChildInput(2, true)], | |
| prisma: prismaMock, | |
| }); | |
| expect(prismaMock.eventType.updateMany).toHaveBeenCalledTimes(1); | |
| const updateArg = prismaMock.eventType.updateMany.mock.calls[0][0]; | |
| // Unlocked → hidden should be omitted from the update data to preserve the child's existing value. | |
| expect(updateArg.data).not.toHaveProperty("hidden"); | |
| }); |
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In
`@packages/trpc/server/routers/viewer/eventTypes/heavy/handleChildrenEventTypes.test.ts`
around lines 90 - 107, Add a test alongside the existing locked case that mocks
the parent as hidden false, invokes handleChildrenEventTypes with an existing
child, and asserts updateMany is called with the expected parent/user filter
while updateArg.data does not contain hidden, verifying the child’s existing
hidden value is preserved when unlocked.
| // Children carry the parent's metadata (including managedEventConfig.unlockedFields) | ||
| // so the child editor knows which fields are locked. Copied verbatim on creation. | ||
| const childMetadata = coerceValue("metadata", parent.metadata); |
There was a problem hiding this comment.
🗄️ Data Integrity & Integration | 🟠 Major | 🏗️ Heavy lift
🧩 Analysis chain
🏁 Script executed:
#!/bin/bash
# Description: Search for where the child event type editor reads unlockedFields to determine lock state.
# Look for managedEventConfig.unlockedFields usage in the eventtype editor components.
rg -n -C5 'unlockedFields' --type=ts --type=tsx -g '!**/node_modules/**' -g '!**/*.test.*' packages/ apps/ | head -100Repository: calcom/cal.diy
Length of output: 180
🏁 Script executed:
#!/bin/bash
set -euo pipefail
echo '--- handleChildrenEventTypes.ts outline ---'
ast-grep outline packages/trpc/server/routers/viewer/eventTypes/heavy/handleChildrenEventTypes.ts --view expanded || true
echo
echo '--- find unlockedFields usages ---'
rg -n -C 4 'unlockedFields' packages apps \
-g '*.ts' -g '*.tsx' \
-g '!**/node_modules/**' -g '!**/*.test.*' \
| head -200
echo
echo '--- inspect relevant slice of handleChildrenEventTypes.ts ---'
nl -ba packages/trpc/server/routers/viewer/eventTypes/heavy/handleChildrenEventTypes.ts | sed -n '120,210p'Repository: calcom/cal.diy
Length of output: 15775
🏁 Script executed:
#!/bin/bash
set -euo pipefail
echo '--- handleChildrenEventTypes.ts top section ---'
nl -ba packages/trpc/server/routers/viewer/eventTypes/heavy/handleChildrenEventTypes.ts | sed -n '1,120p'
echo
echo '--- all metadata.unlockedFields reads ---'
rg -n -C 3 'metadata\?.*managedEventConfig\?.unlockedFields|managedEventConfig\?.unlockedFields|unlockedFields' packages apps \
-g '*.ts' -g '*.tsx' \
-g '!**/node_modules/**' -g '!**/*.test.*' \
| sed -n '1,240p'
echo
echo '--- event type editor related files ---'
fd -a 'event-type' packages apps | sed -n '1,120p'Repository: calcom/cal.diy
Length of output: 240
🏁 Script executed:
#!/bin/bash
set -euo pipefail
echo '--- constants and update logic ---'
sed -n '1,220p' packages/trpc/server/routers/viewer/eventTypes/heavy/handleChildrenEventTypes.ts
echo
echo '--- child metadata / unlockedFields consumers ---'
rg -n -C 5 'managedEventConfig\.unlockedFields|unlockedFields' packages apps \
-g '*.ts' -g '*.tsx' \
-g '!**/node_modules/**' -g '!**/*.test.*' \
| sed -n '1,260p'Repository: calcom/cal.diy
Length of output: 25681
Propagate metadata updates to existing children
metadata is copied only on creation and excluded from the update path, so existing children keep stale managedEventConfig.unlockedFields. The child UI reads lock state from each child’s own metadata, so unlocking a field on the parent can leave existing children shown as still locked.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In
`@packages/trpc/server/routers/viewer/eventTypes/heavy/handleChildrenEventTypes.ts`
around lines 139 - 141, Update the child event synchronization logic to
propagate parent metadata changes to existing children, not only during
creation. Locate the update path in the child event handling logic alongside the
childMetadata initialization, include the parent’s current metadata when
building child updates, and ensure managedEventConfig.unlockedFields is
refreshed on every affected child.
| // 2) Update existing children with the parent's locked managed props. | ||
| if (oldUserIds.length) { | ||
| const updateData = buildPropagatedData(parent, UPDATE_EXCLUDED_PROPS, unlockedFields); | ||
| await Promise.all( | ||
| oldUserIds.map((userId) => { | ||
| const childInput = children.find((child) => child.owner.id === userId); | ||
| const hidden = isHiddenLocked ? parent.hidden : childInput?.hidden ?? false; | ||
| return prisma.eventType.updateMany({ | ||
| where: { parentId: eventTypeId, userId }, | ||
| data: { | ||
| ...(updateData as Prisma.EventTypeUpdateManyMutationInput), | ||
| hidden, | ||
| }, | ||
| }); | ||
| }) | ||
| ); | ||
| } |
There was a problem hiding this comment.
🗄️ Data Integrity & Integration | 🟠 Major | ⚡ Quick win
Update path overwrites child hidden with false when unlocked — inconsistent with quick-toggle path.
Line 178 sets hidden = isHiddenLocked ? parent.hidden : childInput?.hidden ?? false. When hidden is unlocked, childInput?.hidden ?? false defaults to false if the payload omits it, overwriting the child's existing hidden value. This directly contradicts the PR objective of preserving child-specific hidden settings when unlocked.
The quick-toggle path (line 127) correctly omits hidden from the update data when unlocked: ...(isHiddenLocked ? { hidden: parent.hidden } : {}). The full update path should follow the same pattern. Additionally, since all old users receive identical update data after this fix, the per-user Promise.all + updateMany loop can be consolidated into a single updateMany — matching the quick-toggle pattern and reducing N concurrent DB calls to 1.
🐛 Proposed fix: omit `hidden` when unlocked and consolidate to single `updateMany`
// 2) Update existing children with the parent's locked managed props.
if (oldUserIds.length) {
const updateData = buildPropagatedData(parent, UPDATE_EXCLUDED_PROPS, unlockedFields);
- await Promise.all(
- oldUserIds.map((userId) => {
- const childInput = children.find((child) => child.owner.id === userId);
- const hidden = isHiddenLocked ? parent.hidden : childInput?.hidden ?? false;
- return prisma.eventType.updateMany({
- where: { parentId: eventTypeId, userId },
- data: {
- ...(updateData as Prisma.EventTypeUpdateManyMutationInput),
- hidden,
- },
- });
- })
- );
+ await prisma.eventType.updateMany({
+ where: { parentId: eventTypeId, userId: { in: oldUserIds } },
+ data: {
+ ...(updateData as Prisma.EventTypeUpdateManyMutationInput),
+ // Only propagate hidden when locked; when unlocked, children own their value.
+ ...(isHiddenLocked ? { hidden: parent.hidden } : {}),
+ },
+ });
}📝 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.
| // 2) Update existing children with the parent's locked managed props. | |
| if (oldUserIds.length) { | |
| const updateData = buildPropagatedData(parent, UPDATE_EXCLUDED_PROPS, unlockedFields); | |
| await Promise.all( | |
| oldUserIds.map((userId) => { | |
| const childInput = children.find((child) => child.owner.id === userId); | |
| const hidden = isHiddenLocked ? parent.hidden : childInput?.hidden ?? false; | |
| return prisma.eventType.updateMany({ | |
| where: { parentId: eventTypeId, userId }, | |
| data: { | |
| ...(updateData as Prisma.EventTypeUpdateManyMutationInput), | |
| hidden, | |
| }, | |
| }); | |
| }) | |
| ); | |
| } | |
| // 2) Update existing children with the parent's locked managed props. | |
| if (oldUserIds.length) { | |
| const updateData = buildPropagatedData(parent, UPDATE_EXCLUDED_PROPS, unlockedFields); | |
| await prisma.eventType.updateMany({ | |
| where: { parentId: eventTypeId, userId: { in: oldUserIds } }, | |
| data: { | |
| ...(updateData as Prisma.EventTypeUpdateManyMutationInput), | |
| // Only propagate hidden when locked; when unlocked, children own their value. | |
| ...(isHiddenLocked ? { hidden: parent.hidden } : {}), | |
| }, | |
| }); | |
| } |
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In
`@packages/trpc/server/routers/viewer/eventTypes/heavy/handleChildrenEventTypes.ts`
around lines 172 - 188, The existing-child update path in
handleChildrenEventTypes currently overwrites child-specific hidden values with
false when hidden is unlocked. Build the update data once, add hidden only when
isHiddenLocked is true, and replace the per-user Promise.all/updateMany loop
with a single updateMany targeting parentId and oldUserIds via an appropriate
userId filter.
| // Handling updates to children event types (managed events types). | ||
| // Propagates the parent's locked managed props (including the `hidden` / | ||
| // "Hide from profile" toggle) to the assigned child event types. | ||
| await handleChildrenEventTypes({ | ||
| eventTypeId: id, | ||
| currentUserId: ctx.user.id, | ||
| oldEventType: eventType, | ||
| updatedEventType, | ||
| oldEventType: eventType, | ||
| children, | ||
| profileId: ctx.user.profile.id, | ||
| prisma: ctx.prisma, | ||
| updatedValues, | ||
| calVideoSettings: calVideoSettingsForChildren, | ||
| }); |
There was a problem hiding this comment.
🗄️ Data Integrity & Integration | 🟠 Major | 🏗️ Heavy lift
🧩 Analysis chain
🏁 Script executed:
#!/bin/bash
# Description: Check if other callers of handleChildrenEventTypes exist and whether they use transactions.
rg -n 'handleChildrenEventTypes' --type=ts -g '!**/*.test.*' packages/ apps/ | head -20
# Check the PrismaClient vs TransactionClient type compatibility
rg -n 'Prisma.TransactionClient' --type=ts packages/trpc/server/routers/viewer/eventTypes/ | head -20Repository: calcom/cal.diy
Length of output: 702
Wrap the parent update and child sync in one transaction
The parent is saved first, then handleChildrenEventTypes runs separate child writes afterward, so a failure there can leave the parent and children out of sync. Passing a transaction client into handleChildrenEventTypes would let this update stay atomic.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@packages/trpc/server/routers/viewer/eventTypes/heavy/update.handler.ts`
around lines 725 - 734, Wrap the parent update and handleChildrenEventTypes call
in a single Prisma transaction so failures roll back both parent and child
changes. Pass the transaction client instead of ctx.prisma to
handleChildrenEventTypes, updating its signature and all required callers to
accept the transaction-scoped client.
What does this PR do?
Adds support for the "Hide from profile" toggle for managed event types and propagates the value to assigned child event types, matching the behavior of standard event types.
When configured on a managed parent event, the
hiddenvalue is synced to child events and respects the existing lock/unlock mechanism viamanagedEventConfig.unlockedFields.Fixes #25903
Motivation
The "Hide from profile" setting was available for standard event types but missing for managed events, preventing team admins from hiding managed event bookings from assignees' public profiles.
This PR brings managed events to feature parity with standard event types.
Changes
handleChildrenEventTypes.tshiddenthrough the listing quick-toggle flow.Hidden field behavior
hiddenvalue.hiddenvalue.update.handler.tsevent-types-listing-view.tsxNotes
updateNewTeamMemberEventTypes(member joins after event creation) is still a stub in this implementation. Newly added members receive the updated child event on the next managed event save or via Assign All.Support for that flow can be added in a follow-up PR if required.