openstack-uicore-foundation 5.0.43 → 5.0.44-beta.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.claude/settings.local.json +22 -1
- package/lib/components/index.js +1 -1
- package/lib/css/components/index.css +1 -1
- package/lib/css/components/index.css.map +1 -1
- package/package-lock.json +22291 -0
- package/package.json +1 -1
- package/readme.md +17 -0
- package/.claude/rules/openstack-uicore-foundation-components.md +0 -67
- package/.claude/rules/openstack-uicore-foundation-project.md +0 -69
- package/.claude/rules/openstack-uicore-foundation-security.md +0 -39
- package/.codegraph/.gitignore +0 -5
- package/docs/plans/2026-04-09-showconfirmdialog-react16-compat.md +0 -83
- package/docs/plans/2026-04-22-dropzone-pooling-ux.md +0 -129
- package/docs/plans/2026-04-23-uploadv3-duplicate-file-max-reached.md +0 -109
- package/docs/plans/2026-04-23-uploadv3-premature-complete-on-202.md +0 -99
- package/docs/plans/2026-07-06-file-size-field-unit-prop.md +0 -20
- package/docs/plans/clickup-barrel-mui-dragalong.md +0 -43
|
@@ -1,99 +0,0 @@
|
|
|
1
|
-
# UploadInputV3 Premature Completion on HTTP 202 Fix Plan
|
|
2
|
-
|
|
3
|
-
Created: 2026-04-23
|
|
4
|
-
Author: smarcet@gmail.com
|
|
5
|
-
Status: VERIFIED
|
|
6
|
-
Approved: Yes
|
|
7
|
-
Iterations: 0
|
|
8
|
-
Worktree: No
|
|
9
|
-
Type: Bugfix
|
|
10
|
-
|
|
11
|
-
## Summary
|
|
12
|
-
|
|
13
|
-
**Symptom:** After uploading a file via UploadInputV3 that triggers HTTP 202 (async server processing), the file immediately shows as "Complete" instead of waiting for polling to confirm the server has finished processing.
|
|
14
|
-
**Trigger:** Upload a file via UploadInputV3. Server returns HTTP 202 with `file_id`. Dropzone's `success` event fires immediately (before polling starts or completes), and V3's `handleFileCompleted` marks the file as `complete: true`.
|
|
15
|
-
**Root Cause:** `src/components/inputs/upload-input-v3/index.js:153` — `handleFileCompleted()` unconditionally marks the file as `complete: true` when Dropzone's `success` event fires, without checking `file._asyncProcessing`. For non-chunked 202 uploads, `_finished()` is called directly by Dropzone (`dropzone.js:2707`), bypassing the `chunksUploaded` override that defers completion for chunked uploads.
|
|
16
|
-
|
|
17
|
-
**Secondary issue:** `wrappedOnUploadComplete` at line 190 is a passthrough — it doesn't mark uploading files as complete. When polling finishes, `onUploadComplete` fires but the `uploadingFiles` entry isn't cleaned up because `complete` was never set (if the guard blocks `handleFileCompleted`).
|
|
18
|
-
|
|
19
|
-
## Investigation
|
|
20
|
-
|
|
21
|
-
- **V3-specific bug.** V2 has zero handling for `success`/`onFileCompleted`/`complete` — it renders only from the `value` prop, which is updated after `onUploadComplete` (correctly waits for polling in the 202 case).
|
|
22
|
-
- **Flow for non-chunked 202:** `xhr.onload` → `file._asyncProcessing = true` → `dropzoneOnLoad(e)` → `_finishedUploading` → `!chunked` → `_finished(files, response, e)` → emits `success` → DropzoneV3 `success` handler → `onFileCompleted` → `handleFileCompleted` marks `complete: true` → file shows "Complete" immediately. Polling starts AFTER `dropzoneOnLoad` returns, but the file already appears done.
|
|
23
|
-
- **Chunking decision:** `file.upload.chunked = options.chunking && (options.forceChunking || file.size > options.chunkSize)`. Config sets `chunking: true` but not `forceChunking` (default `false`), and `chunkSize` defaults to 2MB. Files ≤ 2MB are uploaded as non-chunked, bypassing the `chunksUploaded` override entirely.
|
|
24
|
-
- **`chunksUploaded` override** at `dropzone/index.js:164` correctly defers `done()` for chunked 202 uploads, but is never called for non-chunked uploads.
|
|
25
|
-
- **`wrappedOnUploadComplete`** at `upload-input-v3/index.js:190` just passes through to the parent — it doesn't update `uploadingFiles` state at all.
|
|
26
|
-
|
|
27
|
-
## Behavior Contract
|
|
28
|
-
|
|
29
|
-
**Given:** UploadInputV3 with a file upload that returns HTTP 202 (async processing), where `file._asyncProcessing` is set to `true` on the Dropzone file object
|
|
30
|
-
**When:** Dropzone's `success` event fires (immediately after `_finishedUploading` calls `_finished` for non-chunked uploads, or via `chunksUploaded` for chunked uploads)
|
|
31
|
-
**Currently (bug):** `handleFileCompleted` marks the file as `complete: true` immediately, showing "Complete" in the UI before polling confirms server processing is done
|
|
32
|
-
**Expected (fix):** When `file._asyncProcessing` is true, `handleFileCompleted` does NOT mark the file as complete. The file stays in "Loading" state. When polling finishes and `onUploadComplete` fires (via `wrappedOnUploadComplete`), uploading files are marked complete, enabling the existing useEffect cleanup to remove them when `value` updates.
|
|
33
|
-
**Anti-regression:** Synchronous uploads (HTTP 200) must still mark files as "Complete" immediately via `handleFileCompleted`. File deletion, error display, progress tracking, and the existing server-renamed-filename cleanup must remain intact.
|
|
34
|
-
|
|
35
|
-
## Fix Approach
|
|
36
|
-
|
|
37
|
-
**Chosen:** Guard in V3 handlers
|
|
38
|
-
**Why:** The `_asyncProcessing` flag is already set on the Dropzone file object before `success` fires. V3 just needs to check it in `handleFileCompleted` and mark files complete in `wrappedOnUploadComplete`. No changes to DropzoneJS or DropzoneV3 — purely V3 state management.
|
|
39
|
-
**Alternatives considered:**
|
|
40
|
-
- *Guard in DropzoneV3 success handler* — would work but touches the shared wrapper file used by all upload versions, increasing regression surface.
|
|
41
|
-
- *Override _finishedUploading in DropzoneJS* — fixes at the Dropzone level but patches library internals, fragile across Dropzone upgrades.
|
|
42
|
-
|
|
43
|
-
**Files:**
|
|
44
|
-
- `src/components/inputs/upload-input-v3/index.js` (primary fix — handleFileCompleted guard + wrappedOnUploadComplete)
|
|
45
|
-
- `src/components/inputs/upload-input-v3/__tests__/upload-input-v3.test.js` (reproducing test)
|
|
46
|
-
|
|
47
|
-
**Strategy:**
|
|
48
|
-
1. In `handleFileCompleted`: check `file._asyncProcessing` — if true, return early (don't mark complete)
|
|
49
|
-
2. In `wrappedOnUploadComplete`: before calling the parent callback, mark all uploading files as `complete: true` via `setUploadingFiles`. This ensures cleanup works for both sync (where `handleFileCompleted` already set it) and async (where it was skipped).
|
|
50
|
-
|
|
51
|
-
**Tests:** Add test to `upload-input-v3.test.js` that simulates: file added → file completed with `_asyncProcessing: true` → verify file still shows "Loading" (not "Complete").
|
|
52
|
-
|
|
53
|
-
## Verification Scenario
|
|
54
|
-
|
|
55
|
-
### TS-001: Async Upload Processing State
|
|
56
|
-
**Preconditions:** UploadInputV3 with `maxFiles=1`, server configured to return HTTP 202 for uploads
|
|
57
|
-
|
|
58
|
-
| Step | Action | Expected Result (after fix) |
|
|
59
|
-
|------|--------|-----------------------------|
|
|
60
|
-
| 1 | Upload a file that triggers HTTP 202 async processing | File shows "Loading" with progress bar, NOT "Complete" |
|
|
61
|
-
| 2 | Wait for polling to return `status: 'complete'` and parent to update value | File transitions to "Complete" (from value section), no duplicate entries |
|
|
62
|
-
|
|
63
|
-
## Progress
|
|
64
|
-
|
|
65
|
-
- [x] Task 1: Write Reproducing Test (RED)
|
|
66
|
-
- [x] Task 2: Implement Fix at Root Cause
|
|
67
|
-
- [x] Task 3: Quality Gate
|
|
68
|
-
**Tasks:** 3 | **Done:** 3
|
|
69
|
-
|
|
70
|
-
## Tasks
|
|
71
|
-
|
|
72
|
-
### Task 1: Write Reproducing Test (RED)
|
|
73
|
-
|
|
74
|
-
**Objective:** Encode the Behavior Contract as a failing test BEFORE writing any fix code.
|
|
75
|
-
**Files:** `src/components/inputs/upload-input-v3/__tests__/upload-input-v3.test.js`
|
|
76
|
-
**Entry point:** `UploadInputV3` component (rendered with mock DropzoneV3)
|
|
77
|
-
**Test scenario:**
|
|
78
|
-
1. Render UploadInputV3 with `maxFiles=1` and `value=[]`
|
|
79
|
-
2. Simulate `onAddedFile({ name: 'video.mp4', size: 5000000 })`
|
|
80
|
-
3. Simulate `onFileCompleted({ name: 'video.mp4', size: 5000000, _asyncProcessing: true })`
|
|
81
|
-
4. Assert: file still shows "Loading" (not "Complete") — the `_asyncProcessing` flag should prevent marking as complete
|
|
82
|
-
**DoD:** Test exists, named `test('does not mark file as complete when _asyncProcessing is true')`, runs, fails because `handleFileCompleted` currently ignores `_asyncProcessing` and marks complete unconditionally.
|
|
83
|
-
**Verify:** `npx jest src/components/inputs/upload-input-v3/__tests__/upload-input-v3.test.js --verbose`
|
|
84
|
-
|
|
85
|
-
### Task 2: Implement Fix at Root Cause
|
|
86
|
-
|
|
87
|
-
**Objective:** Minimal change to `handleFileCompleted` and `wrappedOnUploadComplete` to prevent premature completion on HTTP 202.
|
|
88
|
-
**Files:** `src/components/inputs/upload-input-v3/index.js`
|
|
89
|
-
**Strategy:**
|
|
90
|
-
1. In `handleFileCompleted` (line 153): add early return when `file._asyncProcessing` is true
|
|
91
|
-
2. In `wrappedOnUploadComplete` (line 190): add `setUploadingFiles(prev => prev.map(f => ({ ...f, complete: true })))` before calling the parent callback, so all uploading files are marked complete when the server confirms processing is done
|
|
92
|
-
**DoD:** Reproducing test PASSES. Full test suite PASSES. Diff touches root-cause file only.
|
|
93
|
-
**Verify:** `npx jest --verbose`
|
|
94
|
-
|
|
95
|
-
### Task 3: Quality Gate
|
|
96
|
-
|
|
97
|
-
**Objective:** Full suite re-run, build clean.
|
|
98
|
-
**DoD:** Full suite green, build succeeds, no performance regressions.
|
|
99
|
-
**Verify:** `npx jest --verbose && npm run build-dev`
|
|
@@ -1,20 +0,0 @@
|
|
|
1
|
-
# MuiFormikFileSizeField — Selectable Storage Unit (Bytes/KB) Implementation Plan
|
|
2
|
-
|
|
3
|
-
Created: 2026-07-06
|
|
4
|
-
Author: smarcet@gmail.com
|
|
5
|
-
Agent: Claude Code
|
|
6
|
-
Status: PENDING
|
|
7
|
-
Approved: No
|
|
8
|
-
Iterations: 0
|
|
9
|
-
Worktree: No
|
|
10
|
-
Type: Feature
|
|
11
|
-
|
|
12
|
-
> Planning in progress...
|
|
13
|
-
|
|
14
|
-
## Summary
|
|
15
|
-
|
|
16
|
-
**Goal:** Add a prop to `MuiFormikFileSizeField` so the stored (Formik field) value can be expressed in Bytes or KB, while the input keeps displaying MB — allowing the same control to back APIs that use either unit.
|
|
17
|
-
|
|
18
|
-
---
|
|
19
|
-
|
|
20
|
-
_Exploring codebase and gathering requirements..._
|
|
@@ -1,43 +0,0 @@
|
|
|
1
|
-
GOAL
|
|
2
|
-
|
|
3
|
-
Current state: The components barrel (src/components/index.js) exports UploadInputV3 (which imports @mui/material and @mui/icons-material) uncommented, along with 70 additional Mui* components. Any consumer importing from openstack-uicore-foundation/lib/components (the barrel) is forced to resolve @mui/material, @mui/icons-material, @mui/x-date-pickers, spark-md5, dropzone and react-dropzone as installed peerDependencies, even if it uses no MUI component at all. This broke track-chairs build when bumping from 4.2.24 to 4.2.34 (UploadInputV3 was added in 4.2.25), and the same pattern is present on main (v5.x), made worse because the barrel now has 70 uncommented Mui exports (0 in the version right before 4.2.25).
|
|
4
|
-
|
|
5
|
-
Target state: Consumers that don't use MUI (like track-chairs) can update the library without being forced to install the full MUI + spark-md5 + dropzone stack, following the convention already documented in this repo (No barrel imports from lib/) and the pattern already applied to TextEditorV3, CompanyInputV2, MuiStripePayment, etc. (commented out of the barrel but with a standalone webpack entry).
|
|
6
|
-
|
|
7
|
-
TASKS
|
|
8
|
-
|
|
9
|
-
- Audit which of summit-admin's 584 library imports use the barrel (openstack-uicore-foundation/lib/components) vs individual paths, and confirm the 13 barrel imports found don't depend on UploadInputV3/Mui* staying exposed there (summit-admin already uses MUI anyway, low risk for that consumer)
|
|
10
|
-
- Comment out the UploadInputV3 export from src/components/index.js, following the exact same pattern already used for TextEditorV3 (move it under the "// these include 3rd party deps" block); keep its standalone webpack entry (webpack.common.js) untouched so direct imports keep working
|
|
11
|
-
- Fix the 2 summit-admin files that import UploadInputV3 from the barrel before/alongside the release: src/components/upload-dialog/index.js line 26, and src/pages/companies/components/company-dialog.js line 36 (used at lines 481 and 502) — switch both to import from openstack-uicore-foundation/lib/components/inputs/upload-input-v3 directly
|
|
12
|
-
- Update .claude/rules/openstack-uicore-foundation-project.md and the README if the recommended import convention changes
|
|
13
|
-
- Communicate the correct import path to consumers (track-chairs, summit-admin, etc.) to avoid the MUI/spark-md5/dropzone drag-along
|
|
14
|
-
|
|
15
|
-
ACCEPTANCE CRITERIA
|
|
16
|
-
|
|
17
|
-
- A consumer that only imports non-MUI components from openstack-uicore-foundation/lib/components/(individual path) can run yarn install and build without having @mui/material, @mui/icons-material, @mui/x-date-pickers, spark-md5, dropzone or react-dropzone installed
|
|
18
|
-
- The library's webpack build still generates individual entries for each component, including upload-input-v3, without breaking consumers that import it directly (summit-admin)
|
|
19
|
-
- The import convention is documented consistently across README, CLAUDE.md and the actual code
|
|
20
|
-
- No regression in existing tests (jest) or in the library build (yarn build)
|
|
21
|
-
|
|
22
|
-
DEVELOPMENT NOTES
|
|
23
|
-
|
|
24
|
-
Key files:
|
|
25
|
-
src/components/index.js, the main barrel, contains the 70 uncommented Mui* exports and the UploadInputV3 export on line 8
|
|
26
|
-
webpack.common.js, multi-entry build, check the upload-input-v3 and editor-input-v3 entries as reference for the pattern already in use
|
|
27
|
-
src/utils/crypto.js, imports spark-md5 unconditionally, used by dropzone/index.js and by security/methods.js via getSHA256/getRandomBytes even though methods.js never calls getMD5
|
|
28
|
-
package.json, @mui/material, @mui/icons-material, @mui/x-date-pickers, spark-md5, dropzone and react-dropzone are in peerDependencies, not dependencies, consistent with the project's peer deps model
|
|
29
|
-
|
|
30
|
-
Gotchas:
|
|
31
|
-
spark-md5 is not new to UploadInputV3, it was added in v4.2.17 (commit f4474fa) via dropzone/index.js for V1/V2. The real regression in 4.2.25 was that UploadInputV3 was the first component to actually reference @mui/material from the barrel (previously declared as a peer dep but not imported by anything reachable from there) and to add @mui/icons-material as a new peer dep
|
|
32
|
-
On v5.x main the barrel already has 70 uncommented Mui* exports vs 0 before 4.2.25 (all pre-existing, out of scope here), so commenting out UploadInputV3 removes the spark-md5/icons-material-specific drag-along this ticket targets, but a fully MUI-free consumer importing anything else from the barrel still needs MUI because of those 70 exports — tracked separately if it becomes a problem
|
|
33
|
-
summit-admin (5.0.40) already uses MUI extensively, out of 584 imports of the library only 13 use the full barrel (includes UploadInputV3 and MuiFormikUpload), the rest already follow the documented individual-path convention
|
|
34
|
-
track-chairs is the consumer that broke on the 4.2.34 bump, its code was not reviewed in this session, the information about its import pattern comes from the user's initial report
|
|
35
|
-
|
|
36
|
-
Risks:
|
|
37
|
-
Risk: removing UploadInputV3 from the barrel is a breaking change for any consumer relying on that barrel import. Confirmed concretely: summit-admin imports UploadInputV3 from the barrel in src/components/upload-dialog/index.js (line 26) and src/pages/companies/components/company-dialog.js (line 36, used at lines 481 and 502) — both break the moment this ships
|
|
38
|
-
Mitigation: keep the standalone webpack entry, which already exists, and document the alternative import path before removing it from the barrel, communicating the change in release notes. Land the summit-admin import fix in the same window as the openstack-uicore-foundation release (or before it, since importing from the individual path already works today on 5.0.40) to avoid a broken window
|
|
39
|
-
|
|
40
|
-
Out of scope:
|
|
41
|
-
track-chairs code is not investigated in this session, it is outside this repo
|
|
42
|
-
The MUI v9 migration (branch feature/5.x-react-17-x-upgrade, tag v6.0.0-beta.1) is not addressed, it is a separate effort
|
|
43
|
-
This session did not modify code, investigation only
|