feat(invitations): CSV header validation and ext ID conflict resolution#8427
Draft
LWS49 wants to merge 1 commit into
Draft
feat(invitations): CSV header validation and ext ID conflict resolution#8427LWS49 wants to merge 1 commit into
LWS49 wants to merge 1 commit into
Conversation
37a5204 to
211f960
Compare
… resolution - validate CSV column headers explicitly instead of checking column count - detect external ID changes on existing users/invitations before applying; surface a confirmation prompt (Keep Existing / Replace) with a side-by-side Current / New External ID table capped at 320px for large uploads - conflict resolution wired into both file upload and individual invite form; file ref preserved on Go Back so admin need not re-select - add ExternalIdResolution and PendingExternalIdConflict types; update invite API and operations layer to detect and return conflict payload - controller rescues PendingExternalIdUpdates, renders jbuilder partial; concern branches on @resolution to populate pending vs updated arrays - i18n: add EN/KO/ZH translations for conflict prompt and new table columns
211f960 to
67de552
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
This PR adds two features to the CSV invitation flow. First, it introduces an external ID conflict resolution prompt: when an uploaded CSV would change existing external IDs on pending invitations or enrolled members, the upload is held and the admin is shown a non-dismissible dialog listing affected records, with options to Keep Existing IDs, Replace All, or Cancel. The hold-and-retry is handled client-side via a
useRefholding the originalFileobject, keeping temporary upload state out of Redux. Second, it replaces the column-count heuristic (timeline_template_mismatch) with strict header name validation - the CSV header row must now exactly match the template file's column names (case-insensitive), so column name mismatches liketimeline_algorithmvsTimelineproduce an actionable error message instead of a numeric column count complaint.Design decisions
PendingExternalIdUpdatesis aStandardError(notActiveRecord::Rollback), so it propagates out of the transaction naturally and guarantees a rollback without a manual guard.useRef, not Redux - the retry after conflict resolution reuses the originalFileobject from the first submit, keeping transient upload state out of the store.Regression prevention
Tests cover: header row acceptance (exact match, case-insensitive), header rejection (wrong column names for both timeline and no-timeline modes), headerless CSV passthrough, conflict detection (non-destructive first-pass rollback), Keep Existing and Replace All resolution flows,
ExternalIdConflictTablecolumn rendering and null external ID display,ExternalIdConflictPromptconditional section rendering and callback firing.Manual testing confirmed all 8 scenarios: valid template upload, invalid-header rejection, headerless CSV, timeline-template-to-no-timeline-course rejection, conflict prompt appearance, Keep Existing, Replace All, and Cancel.
Backward compat: admins uploading CSVs without external ID changes are unaffected. CSVs without a header row continue to parse as before. Admins using old-format column names (e.g.,
timeline_algorithm,external_id) will now see an actionable error directing them to the template file rather than a column-count message.