Skip to content

Add file upload to ChooseFileModal#3990

Open
lukemelia wants to merge 8 commits intomainfrom
cs-8391-deal-with-new-case-upload-ui-needs-to-plugin-where-card
Open

Add file upload to ChooseFileModal#3990
lukemelia wants to merge 8 commits intomainfrom
cs-8391-deal-with-new-case-upload-ui-needs-to-plugin-where-card

Conversation

@lukemelia
Copy link
Contributor

@lukemelia lukemelia commented Feb 12, 2026

Summary

  • Adds an Upload button to the file chooser modal so users can upload new files directly when linking linksTo(FileDef) / linksTo(ImageDef) fields
  • Introduces a reusable FileUploadService Ember service with reactive progress tracking and support for concurrent uploads
  • Adds static acceptTypes to all FileDef subclasses (ImageDef, MarkdownDef, PngDef, JpgDef, SvgDef, GifDef, WebpDef, AvifDef) so the native file picker filters by type
  • Upload button is left-aligned with the file tree; Cancel/Add remain right-aligned

Test plan

  • Existing file chooser tests pass (link file, filter by type, show all files)
  • New test: upload a file via the chooser and verify it links to the card
  • New test: cancelling the file pick keeps the modal open
  • Manual: open a card with linksTo(ImageDef), click link, click Upload, select image → progress shows, file uploads, field populates
  • Manual: verify accept filter restricts native picker (e.g. ImageDef only shows images)

🤖 Generated with Claude Code

@github-actions
Copy link

github-actions bot commented Feb 12, 2026

Preview deployments

@github-actions
Copy link

github-actions bot commented Feb 12, 2026

Host Test Results

    1 files  ±    0      1 suites  ±0   3h 24m 37s ⏱️ + 1h 42m 0s
1 850 tests +    3  1 836 ✅ +    2  13 💤 ± 0  0 ❌ ±0  1 🔥 +1 
3 730 runs  +1 868  3 702 ✅ +1 853  26 💤 +13  1 ❌ +1  1 🔥 +1 

For more details on these errors, see this check.

Results for commit 5564e6c. ± Comparison against base commit 0f4fea2.

♻️ This comment has been updated with latest results.

@lukemelia lukemelia force-pushed the cs-8391-deal-with-new-case-upload-ui-needs-to-plugin-where-card branch from 18f0e79 to 9e7da2f Compare February 12, 2026 23:47
@habdelra habdelra requested a review from Copilot February 13, 2026 20:00
Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

Adds in-modal file uploads to the Operator Mode “Choose File” workflow, including a new Ember upload service, UI updates to show an Upload button/progress, and accept filtering based on FileDef type.

Changes:

  • Introduces FileUploadService + FileUploadTask to drive file picking + binary upload + file-meta refresh.
  • Updates ChooseFileModal to add an Upload button and display upload progress/error inline.
  • Adds static acceptTypes to FileDef subclasses and expands acceptance tests to cover uploading and picker cancellation behavior.

Reviewed changes

Copilot reviewed 11 out of 11 changed files in this pull request and generated 6 comments.

Show a summary per file
File Description
packages/host/tests/acceptance/file-chooser-test.gts Adds acceptance coverage for uploading via the chooser and cancelling the native picker.
packages/host/app/services/file-upload.ts New service that opens a native file picker, uploads the selected file, and exposes task state/progress.
packages/host/app/components/operator-mode/choose-file-modal.gts Adds Upload UI, wires modal to FileUploadService, and loads acceptTypes from the chosen FileDef type.
packages/base/webp-image-def.gts Adds static acceptTypes for WebP.
packages/base/svg-image-def.gts Adds static acceptTypes for SVG.
packages/base/png-image-def.gts Adds static acceptTypes for PNG.
packages/base/markdown-file-def.gts Adds static acceptTypes for Markdown.
packages/base/jpg-image-def.gts Adds static acceptTypes for JPEG.
packages/base/image-file-def.gts Adds static acceptTypes = 'image/*' for general images.
packages/base/gif-image-def.gts Adds static acceptTypes for GIF.
packages/base/avif-image-def.gts Adds static acceptTypes for AVIF.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

@lukemelia lukemelia force-pushed the cs-8391-deal-with-new-case-upload-ui-needs-to-plugin-where-card branch from 9575d34 to bbf956c Compare February 16, 2026 20:24
@lukemelia lukemelia changed the base branch from cs-10080-update-filechooser-to-be-able-to-restrict-choices-to-certain to main February 16, 2026 21:31
@lukemelia lukemelia force-pushed the cs-8391-deal-with-new-case-upload-ui-needs-to-plugin-where-card branch from 1111485 to a03f152 Compare February 16, 2026 22:18
@lukemelia lukemelia requested review from a team and habdelra February 16, 2026 22:38
Copy link
Contributor

@backspace backspace left a comment

Choose a reason for hiding this comment

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

I tried this in the preview deployment, the happy path works but error-handling didn’t for me? Both with a filename with a / (my theory) or one that was too big. I think these can be added in a followup though.

screencast.2026-02-17.11-20-19.mp4

lukemelia and others added 5 commits February 17, 2026 13:11
Adds an Upload button to the file chooser modal so users can upload new
files when linking to FileDef/ImageDef fields. The new FileUploadService
is reusable across the app and supports concurrent uploads with reactive
progress tracking. Also adds static acceptTypes to all FileDef subclasses
so the native file picker filters by type.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
The upload flow involves a multi-step async process (file write to realm,
indexing, modal dismiss) not tracked by Ember's run loop, so waitUntil
is needed here unlike the other DOM-existence checks that were simplified.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…ad states

- Pass File directly as fetch body instead of buffering via arrayBuffer()
- Use file's actual MIME type for Content-Type header
- Include filename, realm URL, and JSON-API error detail in upload failures
- Replace misleading progress bar (stuck at 0%) with indeterminate spinner
- Show disabled "Choose a file…" button during native file picker
- Add "Retry…" button after upload errors
- Disable Add button during both picking and uploading states

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Add a new fileSizeLimitBytes parameter (default 5 MB) alongside the existing
cardSizeLimitBytes (512 KB) so that card instances and files (modules, binaries)
can have independent size limits. Previously both used the same card size limit.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@lukemelia lukemelia force-pushed the cs-8391-deal-with-new-case-upload-ui-needs-to-plugin-where-card branch from a03f152 to 7f2a2c0 Compare February 17, 2026 18:49
Two bugs prevented users from seeing file upload errors:

1. In triggerUpload(), `this.currentUpload = undefined` always ran after
   task.result resolved, clearing the error state before the user could see
   it. Now only clears when the task is not in an error state.

2. The FileUploadService checked body.errors[0].detail for the server error
   message, but the server sends it in body.errors[0].message. Now checks
   both fields so the detailed size limit message is shown.

Also adds acceptance test for oversized file upload with configurable
fileSizeLimitBytes threaded through the host test infrastructure.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@lukemelia
Copy link
Contributor Author

I tried this in the preview deployment, the happy path works but error-handling didn’t for me? Both with a filename with a / (my theory) or one that was too big. I think these can be added in a followup though.

I fixed error handling and increased file size limit for non-card files to 5MB.

ylm added 2 commits February 17, 2026 14:39
After separating card and file size limits, saveSource and
file writes use fileSizeLimitBytes instead of cardSizeLimitBytes.
Updated tests accordingly.
saveSource now checks if the URL ends with .json to determine whether
to apply the card size limit or file size limit. Card instance JSON
files use cardSizeLimitBytes; other files use fileSizeLimitBytes.
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