feat(uploads-manager): integrate shared feature into ContentUploader#4573
feat(uploads-manager): integrate shared feature into ContentUploader#4573dealwith wants to merge 3 commits into
Conversation
WalkthroughContentUploader maps legacy upload items to UploadsManager item objects, exposes rootFolderId to the mapper, and wires UploadsManagerBP callbacks through bridging handlers that resolve modernized IDs back to legacy UploadItem actions (cancel/retry/remove/toggle). ChangesContentUploader Modernized Uploads Integration
Sequence Diagram(s)sequenceDiagram
participant LegacyState as ContentUploader (state.items)
participant Mapper as mapToModernizedUploadItems
participant UploadsManagerBP as UploadsManagerBP
participant Bridging as Bridging Handlers (findItemByModernizedId)
participant LegacyHandlers as Legacy Handlers (onClick, removeFileFromUploadQueue)
LegacyState->>Mapper: state.items + rootFolderId
Mapper->>UploadsManagerBP: ModernizedUploadItem[]
UploadsManagerBP->>Bridging: onItemCancel(modernizedId)
Bridging->>Bridging: findItemByModernizedId(modernizedId)
Bridging->>LegacyHandlers: onClick(legacyItem)
UploadsManagerBP->>Bridging: onItemRemove(modernizedId)
Bridging->>LegacyHandlers: removeFileFromUploadQueue(legacyItem)
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~25 minutes Possibly related PRs
Suggested labels
Suggested reviewers
Poem
🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
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. Comment |
62792f4 to
55f3e27
Compare
Wire @box/uploads-manager UploadsManager into ContentUploader behind the enableModernizedUploads flag. Maps legacy upload state to the shared feature's item shape and delegates per-item cancel/retry/remove actions to existing handlers.
b7bf9cc to
4acdc6a
Compare
There was a problem hiding this comment.
Actionable comments posted: 2
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
src/elements/content-uploader/__tests__/ContentUploader.test.js (1)
3-3:⚠️ Potential issue | 🔴 Critical | ⚡ Quick winRemove duplicate
UploadsManagerBPimport (build-blocking parse error).
UploadsManagerBPis declared twice, which triggers the exact parser/lint failures shown in CI. Keep only one import.Also applies to: 10-10
🤖 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/__tests__/ContentUploader.test.js` at line 3, There are duplicate imports of UploadsManagerBP causing a parse error; locate both import statements that declare UploadsManagerBP (the import from '`@box/uploads-manager`') and remove the redundant one so UploadsManagerBP is imported only once; ensure any usages rely on the remaining import and that no other alias or name change is introduced.
🧹 Nitpick comments (1)
src/elements/content-uploader/utils/__tests__/mapToModernizedUploadItem.test.ts (1)
10-19: ⚡ Quick winAdd a regression test for folder items without
file.Current fixtures always include
file, so the folder path is untested. Add a case with{ isFolder: true, file: undefined }to ensure mapping (includingid) is safe.Also applies to: 69-79
🤖 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/utils/__tests__/mapToModernizedUploadItem.test.ts` around lines 10 - 19, Add a regression test in mapToModernizedUploadItem.test.ts that constructs a legacy item with isFolder: true and file: undefined (use the existing buildLegacyItem helper) to cover the folder path; call the mapping function under test (mapToModernizedUploadItem or whichever test subject is imported) with that item and assert it returns a valid modernized upload item without throwing and includes a safe id (e.g., non-null/defined) and expected folder-specific fields. Ensure the new test mirrors other fixtures but overrides file: undefined and isFolder: true so the mapping logic that reads file properties is exercised safely.
🤖 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 1226-1229: findItemByModernizedId currently recomputes IDs from
item.file (using getFileId) which fails for folder entries that lack a file;
update findItemByModernizedId to use the same ID derivation contract used when
mapping this.state.items (i.e., reuse the precomputed modernized ID stored on
each UploadItem or the helper that produced it) and explicitly handle folder
items by deriving their ID from the folder-specific fields instead of item.file
so cancel/retry/remove operations find the correct item whether it's a file or
folder.
In `@src/elements/content-uploader/utils/mapToModernizedUploadItem.ts`:
- Around line 31-36: mapToModernizedUploadItem currently calls
getFileId(item.file, rootFolderId) unconditionally which breaks for folder items
that lack item.file; change the id assignment in mapToModernizedUploadItem so it
uses getFileId(item.file, rootFolderId) only when item.file exists and otherwise
returns the same folder-safe fallback used by
ContentUploader.findItemByModernizedId (use the exact same fallback value/logic
from that method to keep lookups consistent). Ensure you reference getFileId,
mapToModernizedUploadItem, and ContentUploader.findItemByModernizedId while
making this conditional fix.
---
Outside diff comments:
In `@src/elements/content-uploader/__tests__/ContentUploader.test.js`:
- Line 3: There are duplicate imports of UploadsManagerBP causing a parse error;
locate both import statements that declare UploadsManagerBP (the import from
'`@box/uploads-manager`') and remove the redundant one so UploadsManagerBP is
imported only once; ensure any usages rely on the remaining import and that no
other alias or name change is introduced.
---
Nitpick comments:
In
`@src/elements/content-uploader/utils/__tests__/mapToModernizedUploadItem.test.ts`:
- Around line 10-19: Add a regression test in mapToModernizedUploadItem.test.ts
that constructs a legacy item with isFolder: true and file: undefined (use the
existing buildLegacyItem helper) to cover the folder path; call the mapping
function under test (mapToModernizedUploadItem or whichever test subject is
imported) with that item and assert it returns a valid modernized upload item
without throwing and includes a safe id (e.g., non-null/defined) and expected
folder-specific fields. Ensure the new test mirrors other fixtures but overrides
file: undefined and isFolder: true so the mapping logic that reads file
properties is exercised safely.
🪄 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
Run ID: 5c857d9c-d038-41d0-af47-52ee7be0952e
📒 Files selected for processing (4)
src/elements/content-uploader/ContentUploader.tsxsrc/elements/content-uploader/__tests__/ContentUploader.test.jssrc/elements/content-uploader/utils/__tests__/mapToModernizedUploadItem.test.tssrc/elements/content-uploader/utils/mapToModernizedUploadItem.ts
|
Review the following changes in direct dependencies. Learn more about Socket for GitHub.
|
|
@Mergifyio queue |
Merge Queue Status
Waiting for any of
All conditions
|
| [STATUS_ERROR]: 'error', | ||
| }; | ||
|
|
||
| export function getModernizedItemId(item: LegacyUploadItem | FolderUploadItem, rootFolderId: string): string { |
There was a problem hiding this comment.
i think the name getModernizedItemId is a bit misleading - it reads like "the item id is modernized" rather than "we're generating an id for the modernized component." also "id" is ambiguous here - i initially read it as the Box item id, not a client-side tracking key.
get also implies retrieving something that already exists. the rest of the repo uses get for these (getFileId, getDataTransferItemId) so i'm not suggesting we fight that convention, but something like getUploadItemKey would make the intent clearer - this is a UI-only lookup key, not a server-side id.
| return getFileId(fileWithOptions, rootFolderId); | ||
| } | ||
| const folderId = item.options?.folderId ?? rootFolderId; | ||
| return `${item.name}_${folderId}`; |
There was a problem hiding this comment.
this could produce duplicate ids if two folders with the same name are uploaded to the same destination. if a user drags two folders both named shared into the uploader, they'd both produce shared_0, and then findItemByModernizedId would always .find() the first one. canceling/removing would act on the wrong item.
the file path avoids this via uploadInitTimestamp (added in #395 for exactly this reason). we should add something similar for folder items so the ids are unique per upload session.
|
|
||
| handleModernizedItemAction = (id: string) => { | ||
| const item = this.findItemByModernizedId(id); | ||
| if (item) { |
There was a problem hiding this comment.
if findItemByModernizedId doesn't find a match, this just proceeds without issue. we should catch any unhandled scenarios here with an else.
| isExpanded={isUploadsManagerExpanded} | ||
| onToggle={this.toggleUploadsManager} | ||
| onItemCancel={this.handleModernizedItemAction} | ||
| onItemRetry={this.handleModernizedItemAction} |
There was a problem hiding this comment.
onItemCancel and onItemRetry both point to the same handler here. i see this gets split into dedicated handlers in #4577, so not blocking.
| status: STATUS_IN_PROGRESS, | ||
| size: 100, | ||
| file: { name: 'foo.pdf' } as File, | ||
| api: {} as never, |
There was a problem hiding this comment.
the as never troubles me, but i'm guessing it's there because the fixtures include api: {} and FolderUploadItem doesn't have an api field in the type definition. however at runtime, addFolderToUploadQueue does put api: folderUpload on the item.
i think the right fix is to add api? to FolderUploadItem so the type matches what actually happens at runtime. that would make these casts unnecessary.
| <ThemingStyles selector={`#${this.id}`} theme={theme} /> | ||
| <UploadsManagerBP items={[]} /> | ||
| <UploadsManagerBP | ||
| items={mapToModernizedUploadItems(items, rootFolderId)} |
There was a problem hiding this comment.
mapToModernizedUploadItems runs on every render without memoization, which means we're re-mapping all items in the queue even when nothing changed. I believe our consuming app sets fileLimit to 100,000 - so this could get expensive. if you can think of a way to optimize this or get ahead of the performance issues that would be great.
jpan-box
left a comment
There was a problem hiding this comment.
requesting some changes. some lower priority, some that i think should be changed.
Wire
@box/uploads-managerUploadsManager component intoContentUploaderbehind theenableModernizedUploadsflag. Maps legacy upload state to the shared feature's item shape and delegates per-item cancel/retry/remove actions to existing handlers.1/5 pr in the queue
Summary by CodeRabbit
Refactor
Tests