ENG-3328: Add property picker to integration forms#7909
ENG-3328: Add property picker to integration forms#7909
Conversation
|
The latest updates on your projects. Learn more about Vercel for GitHub.
1 Skipped Deployment
|
There was a problem hiding this comment.
Code Review: Add property picker to integration forms
Good feature overall — the hook abstraction is clean, the diff logic is correct, and the UI integration follows the existing patterns in both forms. A few issues need attention before merge.
Critical (must fix)
1. Duplicate hand-rolled interfaces in dataset-properties.slice.ts
Five interfaces declared locally (DatasetPropertyIdsResponse, BulkPropertyAssignment, BulkPropertyRemoval, DatasetPropertyResponse, BulkDatasetPropertyResponse) already exist as auto-generated types in ~/types/api. These will silently drift if the backend schema changes. Import from ~/types/api instead and delete the local declarations. BulkPropertyRemoval doesn't appear in the generated models at all (the removal endpoint reuses BulkPropertyAssignment) and should be removed entirely. See inline comment.
2. Empty-array guard is wrong — can silently delete all property assignments
if (isEditing && values.property_ids) passes when property_ids is [] (arrays are always truthy in JS). When the user opens the form and saves without touching the picker, savePropertyAssignments([]) fires and computes all existing assignments as toRemove, issuing a bulkRemove that deletes everything silently. Fix: values.property_ids !== undefined && hasDatasets. Affects both ConnectorParametersForm.tsx and ConfigureIntegrationForm.tsx. See inline comments.
3. onSaveClick is not awaited before savePropertyAssignments in ConnectorParametersForm.tsx
The integration patch and property save run in parallel rather than sequentially. If the patch fails, the property save has already committed. ConfigureIntegrationForm.tsx correctly awaits the patch result first. The fix requires either making onSaveClick return a Promise, or moving the property save logic into the parent ConnectorParameters.tsx alongside the existing mutation handler. See inline comment.
Suggestions
-
Duplicated save block in
ConfigureIntegrationForm.tsx: theif (isEditing && values.property_ids)block is copy-pasted verbatim at two save paths (~lines 296 and 354). Extract a sharedhandlePropertySavelocal function so both get the same fix and future changes only need to happen once. -
BulkDatasetPropertyResponse.failedis never checked:unwrap()throws on HTTP errors but not on partial failures. If one dataset config fails while others succeed, the operation silently half-completes. Checkresult.failed?.lengthafter each bulk call and surface it to the user. -
"First dataset config" heuristic: the hook fetches property IDs only for
datasetFidesKeys[0], documented as an assumption that all configs share the same assignments. If they ever diverge (e.g., via API), the picker silently shows incomplete state and overwrites on save. Worth a// TODOat minimum. -
Hardcoded
size: 100: mirrors the same un-paginated pattern already flagged with a// TODOin the dataset fetch. Add a matching TODO here. -
property_idsnot declared inConnectionConfigFormValues: the type has a[key: string]: anyindex signature so TypeScript won't catch a key rename. Addproperty_ids?: string[]explicitly, matching howdatasetis typed. -
useIntegrationPropertySelectnot re-exported fromproperties/index.ts: the hook is imported via its full path, bypassing the feature barrel. Either export from the barrel or document it as intentionally internal.
🔬 Codegraph: unavailable
💡 Write /code-review in a comment to re-run this review.
There was a problem hiding this comment.
Review: ENG-3328 — Property picker for integration forms
Overall this is a clean, well-scoped addition. The hook abstraction is the right call — keeping the fetch/diff/save logic out of both form components avoids duplication nicely. The tag-based cache invalidation in the slice is correct, and the error-toast-without-blocking pattern for property failures is the right UX tradeoff. A few things to address before merge:
Bug (should fix)
"Remove all properties" is silently skipped on the secrets-save path. In ConfigureIntegrationForm, the secrets submit guard is if (isEditing && values.property_ids) — an empty array is falsy, so clearing all properties and saving secrets leaves the old assignments in place. The main submit path uses !== undefined correctly; the secrets path should too. See inline comment.
Design concern (worth discussing)
Only the first dataset's assignments seed the diff. If dataset configs under a connection ever have diverging property assignments (direct API, partial prior failure, etc.), the UI silently treats the first dataset as canonical and overwrites the rest on save. The "bulk-assign keeps them in sync" invariant is reasonable but fragile without a guard. At minimum a code comment explaining the invariant would help future readers; a cheap runtime check (warn if any dataset has different IDs) would make bugs surface faster.
Minor
- Hard-coded
size: 100for the property dropdown — fine for now but worth a follow-up if property counts grow. - Redundant
isEditingConnection ? connectionConfig?.key : undefinedexpression inConnectorParametersForm— can just beconnectionConfig?.key.
🔬 Codegraph: connected (46711 nodes)
💡 Write /code-review in a comment to re-run this review.
gilluminate
left a comment
There was a problem hiding this comment.
Approved with a tiny nit-pick
| await savePropertyAssignments(propertyIds); | ||
| } catch { | ||
| messageApi.error( | ||
| "Integration saved but failed to update properties. Please try again.", |
There was a problem hiding this comment.
nit: this message is repeated below. Can we set it as a constant?
Ticket ENG-3328
Description Of Changes
Adds a "Properties" multi-select field to integration edit forms, allowing users to assign properties to an integration's dataset configs. Properties scope privacy request processing to specific domains/brands.
The picker appears on two surfaces: the integrations modal (
ConfigureIntegrationForm) and the system portal config connector form (ConnectorParametersForm). It is gated behind Plus and only shown when the integration has linked dataset configs.Property assignments are computed as a diff on submit (add new, remove deselected) and applied via bulk-assign/bulk-remove API calls.
Code Changes
dataset-properties.slice.ts— RTK Query endpoints forGET /plus/dataset-properties/{fides_key},POST /plus/dataset-properties/bulk-assign, andDELETE /plus/dataset-properties/bulk-removeuseIntegrationPropertySelect.ts— hook that fetches dataset configs, property options, and current assignments, and exposes asavePropertyAssignmentsdiff-based submit handlerConfigureIntegrationFormandConnectorParametersFormto render theControlledSelectproperty picker when editing a Plus-enabled integration with datasetsSteps to Confirm
Pre-Merge Checklist
CHANGELOG.mdupdated