Skip to content

feat(data-forwarding): migrate project override form to useScrapsForm#108807

Merged
JonasBa merged 6 commits intojb/settings/data-forwarding-edit-formfrom
jb/settings/data-forwarding-form
Feb 26, 2026
Merged

feat(data-forwarding): migrate project override form to useScrapsForm#108807
JonasBa merged 6 commits intojb/settings/data-forwarding-edit-formfrom
jb/settings/data-forwarding-form

Conversation

@JonasBa
Copy link
Member

@JonasBa JonasBa commented Feb 21, 2026

Migrates the per-project override form from the legacy JsonForm/FormModel system to useScrapsForm (TanStack-based), completing the data forwarding form migration.

The old implementation rendered each project override as a flat Panel/PanelHeader with a JsonForm inside. The new implementation uses Disclosure from @sentry/scraps/disclosure, giving a cleaner collapsed/expanded UX with status tags (Forwarding, Forwarding with Overrides, Disabled) visible in the title row without expanding.

Also adds dataForwarderOverrideSchema to util/forms.tsx and removes all remaining legacy helpers (getProjectOverrideForm, getProviderForm, the provider form constants, and CalmTag), leaving util/forms.tsx with only getCreateTooltip and the two Zod schemas.

Stacked on: #108806

Fix DE-945

@github-actions github-actions bot added the Scope: Frontend Automatically applied to PRs that change frontend components label Feb 21, 2026
JonasBa and others added 3 commits February 24, 2026 13:48
…rwarding-edit-form

Merge forms.tsx conflict by combining both branches: keep
dataForwarderOverrideSchema (used by ProjectOverrideForm) and adopt
buildDataForwardingProviderSchema and buildDataForwardingProviderConfig
from the incoming branch (used by the edit form). Drop the legacy
JsonFormObject-based getProjectOverrideForm and related constants that
were superseded by the new useScrapsForm-based component.

Co-Authored-By: Claude <noreply@anthropic.com>
@JonasBa JonasBa force-pushed the jb/settings/data-forwarding-form branch from 1c1b6c9 to 467ae8c Compare February 24, 2026 21:52
@JonasBa JonasBa marked this pull request as ready for review February 24, 2026 21:54
@JonasBa JonasBa requested a review from a team as a code owner February 24, 2026 21:54
@JonasBa JonasBa requested review from a team and leeandher February 24, 2026 21:56
@linear
Copy link

linear bot commented Feb 24, 2026

Comment on lines 64 to 74
write_key: z.string(),
// Splunk
instance_url: z.string(),
token: z.string(),
index: z.string(),
source: z.string(),
});

/**
* Builds a provider-specific validation schema by extending the base form schema
* with required-field checks for the given provider.
Copy link
Contributor

Choose a reason for hiding this comment

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

Bug: Submitting the project override form sends empty strings for unmodified fields, which incorrectly overwrites the global data forwarding configuration on the backend.
Severity: HIGH

Suggested Fix

Before submitting the form, filter the overrides object to remove key-value pairs where the value is an empty string. This will prevent unmodified fields from being sent to the backend and incorrectly overwriting the base configuration.

Prompt for AI Agent
Review the code at the location below. A potential bug has been identified by an AI
agent.
Verify if this is a real issue. If it is, propose a fix; if not, explain why it's not
valid.

Location: static/app/views/settings/organizationDataForwarding/util/forms.tsx#L47-L74

Potential issue: The new project override form initializes all provider-specific fields
with empty strings. When a user saves the form, these empty strings are sent in the
`overrides` payload, even for fields the user did not modify. The backend uses
`dict.update()` to apply these overrides, which causes the empty strings to overwrite
valid global configuration values. This can corrupt the project's data forwarding
settings, causing forwarding to fail or behave incorrectly as essential fields like
`queue_url` become empty.

Comment on lines +299 to +308
<form.AppField name="source">
{field => (
<field.Layout.Row
padding="md"
label={t('Source')}
hintText={t('The source to use for the events.')}
>
<field.Input
value={field.state.value ?? ''}
onChange={field.handleChange}
Copy link
Contributor

Choose a reason for hiding this comment

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

Bug: The project override form does not update with new data after a successful save, continuing to show stale, pre-save values to the user.
Severity: MEDIUM

Suggested Fix

Add a useEffect hook that monitors changes to the projectConfig data. When projectConfig changes (e.g., after a successful save and data refetch), call form.setValues() or a similar method to explicitly update the form's state with the new data, ensuring the UI reflects the latest configuration.

Prompt for AI Agent
Review the code at the location below. A potential bug has been identified by an AI
agent.
Verify if this is a real issue. If it is, propose a fix; if not, explain why it's not
valid.

Location:
static/app/views/settings/organizationDataForwarding/components/projectOverrideForm.tsx#L299-L308

Potential issue: The form's state is not updated after a successful save. The
`useScrapsForm` hook is initialized with `defaultValues` only once. After a user saves
changes, the underlying data is refetched, but the form does not reset to reflect these
new values because `defaultValues` is not reactive. As a result, the form continues to
display the stale, pre-save data, which can confuse the user into thinking their changes
were not saved.

Copy link
Contributor

@cursor cursor bot left a comment

Choose a reason for hiding this comment

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

Cursor Bugbot has reviewed your changes and found 2 potential issues.

Bugbot Autofix is OFF. To automatically fix reported issues with Cloud Agents, enable Autofix in the Cursor dashboard.

project_id: `${project.id}`,
overrides,
is_enabled,
});
Copy link
Contributor

Choose a reason for hiding this comment

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

Override form submits all provider fields, not just relevant ones

High Severity

The onSubmit handler sends all form fields as overrides, including empty-string values for fields that belong to other providers. For example, saving a Segment override also sends queue_url: '', region: '', access_key: '', etc. The edit form correctly uses buildDataForwardingProviderConfig to filter fields by provider before submission, but the override form skips this filtering entirely. The old implementation only included provider-specific fields in the form model, so this is a regression.

Additional Locations (1)

Fix in Cursor Fix in Web

is_enabled,
});
},
});
Copy link
Contributor

Choose a reason for hiding this comment

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

Form state not reset after "Clear Override" mutation

Medium Severity

The old code had a useEffect that called formModel.setInitialData whenever projectConfig changed, keeping the form in sync after mutations. The new code only passes defaultValues to useScrapsForm, which is read once on mount. After clicking "Clear Override" (which bypasses the form and directly calls the mutation), the query is invalidated and fresh data arrives, but the form fields retain stale override values. The user sees old data in the inputs even though the server-side overrides were cleared.

Additional Locations (1)

Fix in Cursor Fix in Web

This PR splits the data forwarded forms into separate schemas, using
useFieldGroup to manage form configuration between the otherwise
duplicate fields
@JonasBa JonasBa merged commit 99b75af into jb/settings/data-forwarding-edit-form Feb 26, 2026
51 of 52 checks passed
@JonasBa JonasBa deleted the jb/settings/data-forwarding-form branch February 26, 2026 12:50
Comment on lines +318 to +328
<Flex justify="end" gap="md" padding="lg 0">
<Button
size="sm"
disabled={disabled}
onClick={() => {
updateDataForwarder({
project_id: `${project.id}`,
overrides: {},
is_enabled: projectConfig?.isEnabled ?? false,
});
}}
Copy link
Contributor

Choose a reason for hiding this comment

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

Bug: The ProjectOverrideForm does not update its state after the "Clear Override" action, causing the UI to display stale data until the component is remounted.
Severity: MEDIUM

Suggested Fix

Implement a useEffect hook that observes the projectConfig prop for changes. When projectConfig is updated, call form.setValues() to synchronize the form's state with the new data, ensuring the UI accurately reflects the current configuration.

Prompt for AI Agent
Review the code at the location below. A potential bug has been identified by an AI
agent.
Verify if this is a real issue. If it is, propose a fix; if not, explain why it's not
valid.

Location:
static/app/views/settings/organizationDataForwarding/components/projectOverrideForm.tsx#L318-L328

Potential issue: When a user clicks "Clear Override" in the `ProjectOverrideForm`, a
mutation successfully clears the data on the backend and refetches the updated
configuration. However, the form's state is not synchronized with this new data. The
form is initialized once with `defaultValues` from `projectConfig.overrides` but lacks a
mechanism, like a `useEffect` hook, to update the form state when the `projectConfig`
prop changes. As a result, the UI continues to display the old, stale override values,
confusing the user into thinking the operation failed, until the form is closed and
reopened.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Scope: Frontend Automatically applied to PRs that change frontend components

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants