Skip to content

Allow viewing and uploading access source CSVs#1164

Open
gearnode wants to merge 3 commits into
mainfrom
cursor/access-review-csv-view-and-upload
Open

Allow viewing and uploading access source CSVs#1164
gearnode wants to merge 3 commits into
mainfrom
cursor/access-review-csv-view-and-upload

Conversation

@gearnode

@gearnode gearnode commented May 7, 2026

Copy link
Copy Markdown
Contributor

Summary

Customer feedback (in French) on the Access Review feature was: "Pouvoir voir les CSV uploadés (écrits) serait top; QUID d'upload des CSV directement" — i.e. (1) be able to view CSVs that were submitted, and (2) upload CSV files directly instead of pasting them. This PR addresses both.

  • View CSV — Add a View CSV action on each CSV access source row in AccessReviewSourcesTab. The action opens a read-only dialog that lazy-loads AccessSource.csvData (already exposed by the backend) only when clicked, so the table page payload is unchanged. The CSV is shown in a Textarea with readOnly, font-mono, whitespace-pre. The action is gated on the source not having a connector (i.e. CSV-only).
  • CSV file upload — Replace the paste-into-textarea on CreateCsvAccessSourcePage with a Dropzone (drag-and-drop + click-to-browse), restricted to .csv (text/csv / application/csv) at 10MB max. The picked file is read in the browser via file.text() and submitted through the existing csvData string argument of createAccessSource, so the GraphQL schema, mutation, and worker pipeline are all unchanged.
  • The page also auto-suggests the source Name from the file name (without extension) when the user hasn't typed one, shows a small file summary (KB and parsed row count), and exposes a Remove button to re-pick a file before submitting.

No backend changes — csvData is already a queryable field on AccessSource and the create/update mutations already accept it as a string. The existing e2e/console/access_review_test.go already exercises both paths via the GraphQL contract this PR reuses.

Test plan

  • Console → Access Reviews → Sources: click Add sourceManual CSV, drop a CSV file with the documented header columns, confirm the file name appears with row count, and submit. Source appears in the table with status Connected.
  • Re-pick a file before submitting (Remove + drop a different one): verify the Name field updates only if it was empty.
  • Drop an unsupported file type (e.g. .xlsx): verify the Dropzone shows the not supported error.
  • Drop a file larger than 10MB: verify the too large error.
  • Drop an empty .csv: verify the inline empty file error and that the submit button stays disabled.
  • On a CSV source row, open the action dropdown → click View CSV and confirm the dialog opens, fetches csvData once, and renders it in the read-only textarea. Re-open: verify the cached payload is reused (no extra network call).
  • On a connector-backed source row (e.g. Google Workspace, Linear), confirm the View CSV action is not shown.
  • Permissions: verify a viewer without core:access-source:create cannot reach the create page; a viewer without core:access-source:delete still sees View CSV on CSV sources but no Delete.
  • make relay and npm run check --workspace=@probo/console are clean.

Summary by cubic

Adds CSV upload to the create flow and a read-only View CSV dialog, so users can upload files instead of pasting and inspect stored data. Reuses the existing csvData field and lazy-loads content to keep the table fast.

  • New Features

    • CSV upload on create: replaced textarea with Dropzone from @probo/ui; accepts .csv up to 10MB, reads in-browser, and submits via existing csvData; auto-suggests name from filename; shows size/row count; includes Remove.
    • View CSV in table: new action for CSV-only sources opens a dialog that fetches csvData on open and displays it read-only; hidden for connector-backed sources.
  • Bug Fixes

    • Cleaned up ViewCsvAccessSourceDialog lints (removed unused field, wrapped Suspense fallback).
    • Disabled Remove while a file is being read to avoid repopulating cleared content if the read resolves late.

Written for commit 2a77097. Summary will update on new commits.

The CSV access source flow accepted only pasted text, and once a
source was created its CSV content was not viewable in the console.
Customers asked to upload CSV files directly and to inspect what was
stored.

Replace the textarea on the create page with a Dropzone that reads
the file in the browser and submits its content through the existing
csvData mutation argument, so the GraphQL contract is unchanged.
Add a "View CSV" action on each CSV access source row that opens a
dialog lazy-loading csvData and rendering it in a read-only textarea.

Signed-off-by: Bryan Frimin <bryan@getprobo.com>

@cubic-dev-ai cubic-dev-ai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

1 issue found across 3 files

Prompt for AI agents (unresolved issues)

Check if these issues are valid — if so, understand the root cause of each and fix them. If appropriate, use sub-agents to investigate and fix each issue separately.


<file name="apps/console/src/pages/organizations/access-reviews/CreateCsvAccessSourcePage.tsx">

<violation number="1" location="apps/console/src/pages/organizations/access-reviews/CreateCsvAccessSourcePage.tsx:242">
P2: Disable the Remove button while the file is still being read to avoid stale async updates repopulating csvContent after a user clears the file.</violation>
</file>

Reply with feedback, questions, or to request a fix. Tag @cubic-dev-ai to re-run a review.

Comment thread apps/console/src/pages/organizations/access-reviews/CreateCsvAccessSourcePage.tsx Outdated
gearnode and others added 2 commits May 7, 2026 14:14
Drop the unused id field from the lazy-loaded query and wrap the
multiline JSX fallback passed to Suspense in parentheses to satisfy
@stylistic/jsx-wrap-multilines.

Signed-off-by: Bryan Frimin <bryan@getprobo.com>
If a user clicked Remove between dropping a file and its async text()
resolving, the late resolution would call setCsvContent and repopulate
the just-cleared form state. Disable the button while the read is in
flight so the click can't fire during that window.

Signed-off-by: Cursor Agent <cursoragent@cursor.com>

Co-authored-by: Bryan FRIMIN <bryan@frimin.fr>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants