Skip to content

feat(uploads-manager): add upload progress and time left to uploads manager#4720

Open
pierre-pigeon wants to merge 12 commits into
box:masterfrom
pierre-pigeon:add-counters-to-uploading-file
Open

feat(uploads-manager): add upload progress and time left to uploads manager#4720
pierre-pigeon wants to merge 12 commits into
box:masterfrom
pierre-pigeon:add-counters-to-uploading-file

Conversation

@pierre-pigeon

@pierre-pigeon pierre-pigeon commented Jul 23, 2026

Copy link
Copy Markdown

This PR enriches the modernized uploads manager with per-item byte progress and a smoothed time-remaining (ETA) estimate.

ContentUploader now tracks bytesUploaded/totalBytes from upload progress events and computes an EMA-smoothed ETA.

Summary by CodeRabbit

  • New Features
    • Added an optional feature flag to enable upload ETA display.
    • When enabled (files only), the uploader surfaces byte-level progress (uploaded/total) and a smoothed estimated time remaining.
    • Storybook updated with a modernized “uploads in progress” example reflecting ETA-related fields.
  • Bug Fixes
    • Reset now fully clears prior byte/ETA state, and progress handling ignores invalid totals.
    • Byte/ETA values follow the appropriate upload states (including staged/complete behavior).
  • Tests
    • Added coverage for ETA calculations, progress/byte tracking, reset behavior, and the feature-flag mapping rules.
  • Chores
    • Bumped the uploads manager dependency version.

@pierre-pigeon
pierre-pigeon requested review from a team as code owners July 23, 2026 13:41
@CLAassistant

Copy link
Copy Markdown

CLA assistant check
Thank you for your submission! We really appreciate it. Like many open source projects, we ask that you sign our Contributor License Agreement before we can accept your contribution.


pgolebiowski seems not to be a GitHub user. You need a GitHub account to be able to sign the CLA. If you have already a GitHub account, please add the email address used for this commit to your account.
You have signed the CLA already but the status is still pending? Let us recheck it.

@socket-security

socket-security Bot commented Jul 23, 2026

Copy link
Copy Markdown

Review the following changes in direct dependencies. Learn more about Socket for GitHub.

Diff Package Supply Chain
Security
Vulnerability Quality Maintenance License
Updatednpm/​@​box/​uploads-manager@​1.17.2 ⏵ 2.4.07710010099 +150

View full report

@coderabbitai

coderabbitai Bot commented Jul 23, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: e664b4d4-4fcc-4eb1-a820-e7e7d3f5da65

📥 Commits

Reviewing files that changed from the base of the PR and between 71f4dc3 and 158e721.

📒 Files selected for processing (2)
  • src/elements/content-uploader/utils/__tests__/mapToModernizedUploadItem.test.ts
  • src/elements/content-uploader/utils/mapToModernizedUploadItem.ts
🚧 Files skipped from review as they are similar to previous changes (2)
  • src/elements/content-uploader/utils/tests/mapToModernizedUploadItem.test.ts
  • src/elements/content-uploader/utils/mapToModernizedUploadItem.ts

Walkthrough

ContentUploader now supports optional upload ETA and byte-progress telemetry. ETA state is sampled and smoothed per upload, reset between attempts, and conditionally mapped into modernized upload items. Types, dependency versions, tests, and a Storybook example were updated.

Changes

Upload ETA integration

Layer / File(s) Summary
Upload contracts and modernized mapping
src/common/types/upload.js, src/elements/content-uploader/utils/mapToModernizedUploadItem.ts, src/elements/content-uploader/utils/__tests__/mapToModernizedUploadItem.test.ts, package.json
UploadItem now supports byte and ETA fields. Modernized mapping forwards them only when the ETA flag is enabled, with status-based completion handling. The uploads manager dependency is upgraded to ^2.4.0.
ETA calculation state
src/elements/content-uploader/utils/uploadEta.ts, src/elements/content-uploader/utils/__tests__/uploadEta.test.ts
ETA sampling maintains a sliding window, throttles frequent updates, applies smoothing, and exposes remaining milliseconds after the warm-up period.
Uploader progress and rendering integration
src/elements/content-uploader/ContentUploader.tsx, src/elements/content-uploader/__tests__/ContentUploader.test.js, src/elements/content-uploader/stories/ContentUploader.stories.js
ContentUploader tracks per-item ETA state, updates byte and ETA fields during progress, clears them on reset, passes the feature flag to item mapping, and adds an in-progress Storybook example.

Estimated code review effort: 3 (Moderate) | ~25 minutes

Sequence Diagram(s)

sequenceDiagram
  participant UploadEvent
  participant ContentUploader
  participant updateEta
  participant mapToModernizedUploadItems
  participant UploadsManager
  UploadEvent->>ContentUploader: loaded and total progress
  ContentUploader->>updateEta: update per-item ETA state
  updateEta-->>ContentUploader: smoothed remainingMs
  ContentUploader->>mapToModernizedUploadItems: upload items and ETA flag
  mapToModernizedUploadItems-->>UploadsManager: byte and ETA fields
Loading

Possibly related PRs

Suggested labels: ready-to-merge

Suggested reviewers: jpan-box, olehrybak, reneshen0328

Poem

I’m a rabbit counting bytes in a row,
Smoothing the seconds as uploads go.
ETA sprouts where progress streams,
Resetting cleanly between retry dreams.
Hop, hop—modern uploads glow!

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly summarizes the main change: adding upload progress and ETA support to the uploads manager.
Description check ✅ Passed The description summarizes the change and keeps the required repository template comment intact.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@coderabbitai coderabbitai 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.

Actionable comments posted: 2

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@src/elements/content-uploader/utils/mapToModernizedUploadItem.ts`:
- Around line 63-65: Update mapToModernizedUploadItem so items with
item.isFolder do not populate totalBytes, bytesUploaded, or remainingMs,
regardless of upload status or ETA configuration. Preserve the existing byte and
ETA calculations for non-folder file items.
- Around line 64-66: Update the remainingMs mapping in mapToModernizedUploadItem
so errored and canceled statuses return undefined rather than forwarding the
stale fileItem.remainingMs value. Preserve the existing ETA for active,
non-terminal upload statuses and keep staged/complete behavior unchanged.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: 7753101d-bae6-4a3b-a09d-255e8550dfac

📥 Commits

Reviewing files that changed from the base of the PR and between e8139fd and 821a657.

⛔ Files ignored due to path filters (1)
  • yarn.lock is excluded by !**/yarn.lock, !**/*.lock
📒 Files selected for processing (9)
  • package.json
  • src/common/types/upload.js
  • src/elements/content-uploader/ContentUploader.tsx
  • src/elements/content-uploader/__tests__/ContentUploader.test.js
  • src/elements/content-uploader/stories/ContentUploader.stories.js
  • src/elements/content-uploader/utils/__tests__/mapToModernizedUploadItem.test.ts
  • src/elements/content-uploader/utils/__tests__/uploadEta.test.ts
  • src/elements/content-uploader/utils/mapToModernizedUploadItem.ts
  • src/elements/content-uploader/utils/uploadEta.ts

Comment thread src/elements/content-uploader/utils/mapToModernizedUploadItem.ts
Comment thread src/elements/content-uploader/utils/mapToModernizedUploadItem.ts Outdated
@pierre-pigeon
pierre-pigeon force-pushed the add-counters-to-uploading-file branch from 821a657 to 71f4dc3 Compare July 23, 2026 14:42

@coderabbitai coderabbitai 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.

Actionable comments posted: 1

🧹 Nitpick comments (1)
src/elements/content-uploader/ContentUploader.tsx (1)

1273-1275: 🚀 Performance & Scalability | 🔵 Trivial | ⚡ Quick win

Skip ETA sampling when the feature is disabled.

isUploadEtaEnabled only controls mapping, so every upload still invokes updateEta and allocates sampling arrays while the mapper drops the result. Guard this telemetry block with the feature flag to avoid adding work to the existing progress hot path.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/elements/content-uploader/ContentUploader.tsx` around lines 1273 - 1275,
Guard the ETA telemetry block in the upload progress handler with
isUploadEtaEnabled so updateEta and etaByItem.set are skipped when the feature
is disabled. Preserve the existing progress handling and only sample or store
ETA data when the flag is enabled.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@src/elements/content-uploader/ContentUploader.tsx`:
- Around line 1276-1278: Update handleUploadError and markItemCanceled to clear
item.remainingMs and remove the corresponding etaByItem entry when an upload
fails or is canceled. Preserve ETA updates for in-progress uploads and ensure
failed/canceled rows cannot retain stale time remaining.

---

Nitpick comments:
In `@src/elements/content-uploader/ContentUploader.tsx`:
- Around line 1273-1275: Guard the ETA telemetry block in the upload progress
handler with isUploadEtaEnabled so updateEta and etaByItem.set are skipped when
the feature is disabled. Preserve the existing progress handling and only sample
or store ETA data when the flag is enabled.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: e9847b8e-6c4f-4824-bd01-3829e251a1ed

📥 Commits

Reviewing files that changed from the base of the PR and between 821a657 and 71f4dc3.

⛔ Files ignored due to path filters (1)
  • yarn.lock is excluded by !**/yarn.lock, !**/*.lock
📒 Files selected for processing (9)
  • package.json
  • src/common/types/upload.js
  • src/elements/content-uploader/ContentUploader.tsx
  • src/elements/content-uploader/__tests__/ContentUploader.test.js
  • src/elements/content-uploader/stories/ContentUploader.stories.js
  • src/elements/content-uploader/utils/__tests__/mapToModernizedUploadItem.test.ts
  • src/elements/content-uploader/utils/__tests__/uploadEta.test.ts
  • src/elements/content-uploader/utils/mapToModernizedUploadItem.ts
  • src/elements/content-uploader/utils/uploadEta.ts
🚧 Files skipped from review as they are similar to previous changes (8)
  • package.json
  • src/elements/content-uploader/utils/mapToModernizedUploadItem.ts
  • src/elements/content-uploader/tests/ContentUploader.test.js
  • src/elements/content-uploader/utils/uploadEta.ts
  • src/common/types/upload.js
  • src/elements/content-uploader/utils/tests/uploadEta.test.ts
  • src/elements/content-uploader/utils/tests/mapToModernizedUploadItem.test.ts
  • src/elements/content-uploader/stories/ContentUploader.stories.js

Comment thread src/elements/content-uploader/ContentUploader.tsx
}

const totalBytes = fileItem.totalBytes ?? item.size;
const isFullyUploaded = status === 'staged' || status === 'complete';

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.

let's use constants here instead of strings

Suggested change
const isFullyUploaded = status === 'staged' || status === 'complete';
const isFullyUploaded = status === STATUS_STAGED || status === STATUS_COMPLETE;

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

Comment thread src/elements/content-uploader/utils/mapToModernizedUploadItem.ts
Comment thread package.json
"@box/types": "^2.1.8",
"@box/unified-share-modal": "^2.15.16",
"@box/uploads-manager": "^1.17.2",
"@box/uploads-manager": "^2.4.0",

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.

thanks for updating 👍

@pierre-pigeon
pierre-pigeon requested a review from dealwith July 24, 2026 10:53

@jfox-box jfox-box 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.

Overall LGTM, one nit


// Drop byte/ETA progress from the previous attempt
item.bytesUploaded = 0;
item.remainingMs = undefined;

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.

Do we need to clear item.totalBytes here too?

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.

4 participants