Skip to content

feat(UI): OpenGraph extension upload dialog BED-6759#2349

Merged
maffkipp merged 21 commits intomainfrom
BED-6759--extension-upload-ui
Feb 13, 2026
Merged

feat(UI): OpenGraph extension upload dialog BED-6759#2349
maffkipp merged 21 commits intomainfrom
BED-6759--extension-upload-ui

Conversation

@maffkipp
Copy link
Copy Markdown
Contributor

@maffkipp maffkipp commented Feb 5, 2026

Description

Adds a Schema Upload dialog to the "OpenGraph Management" admin page that allows users to upload a single OpenGraph schema file at a time. The page and API functionality is currently gated behind the opengraph_extension_management feature flag.

Motivation and Context

Resolves BED-6759

How Has This Been Tested?

Additional test files added to cover the new functionality.

Screenshots (optional):

Screen.Recording.2026-02-06.at.10.36.17.AM.mov

Types of changes=

  • New feature (non-breaking change which adds functionality)

Checklist:

Summary by CodeRabbit

  • New Features

    • Added a schema upload dialog for JSON OpenGraph files (drag or button) with upload progress and retry flows.
    • File drop supports configurable icon and single/multiple file selection.
    • Quick-upload gating now respects specific app paths to prevent launches in excluded areas.
  • Tests

    • Added comprehensive tests covering schema upload flows, progress, errors, retries, and notifications.
  • Accessibility

    • Updated retry action label to "Retry upload".

@maffkipp maffkipp self-assigned this Feb 5, 2026
@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented Feb 5, 2026

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review
📝 Walkthrough

Walkthrough

Adds a single-file JSON SchemaUploadDialog (component, hook, tests), FileDrop customization (multiple/icon), upload progress utility, client API method for PUT /api/v2/extensions, and a quick-upload enablement hook that gates global drag-to-upload by path/permission; Content.tsx updated to use the new gate.

Changes

Cohort / File(s) Summary
Schema upload feature
packages/javascript/bh-shared-ui/src/components/SchemaUploadDialog/SchemaUploadDialog.tsx, packages/javascript/bh-shared-ui/src/components/SchemaUploadDialog/useSchemaUploadHandlers.ts, packages/javascript/bh-shared-ui/src/components/SchemaUploadDialog/index.ts, packages/javascript/bh-shared-ui/src/components/SchemaUploadDialog/SchemaUploadDialog.test.tsx
New dialog component, hook, tests, and re-export enabling single-file JSON schema upload via drag or button; includes upload lifecycle, progress tracking, status transitions, and notification/error handling.
File drop customization
packages/javascript/bh-shared-ui/src/components/FileDrop/FileDrop.tsx
Exposes multiple?: boolean (default true) and icon?: IconDefinition props; input honors multiple and UI icon/message reflect props.
Upload progress utility
packages/javascript/bh-shared-ui/src/components/FileUploadDialog/useFileUploadDialogHandlers.tsx
Added UploadProgress type and exported calculateUploadProgress(); replaced inline progress calc with utility call.
Quick-upload gating
packages/javascript/bh-shared-ui/src/utils/quickUpload.ts, cmd/ui/src/views/Content.tsx
Added QuickUploadExclusionPaths and useQuickUploadEnabled() combining path-exclusion, excluded-IDs, and permission checks; Content.tsx now uses the new hook to gate file-drag/modal launch.
OpenGraph UI integration & accessibility
packages/javascript/bh-shared-ui/src/views/OpenGraphManagement/SchemaUploadCard.tsx, packages/javascript/bh-shared-ui/src/components/FileStatusListItem/FileStatusListItem.tsx
Replaced disabled Upload Button with SchemaUploadDialog in SchemaUploadCard; changed Retry aria-label to "Retry upload".
API client
packages/javascript/js-client-library/src/client.ts
Added uploadSchemaFile(json, options?) method on BHEAPIClient to PUT /api/v2/extensions.

Sequence Diagram

sequenceDiagram
    actor User
    participant UI as FileDrop / SchemaUploadDialog
    participant Handlers as useSchemaUploadHandlers
    participant Client as BHEAPIClient
    participant Backend as Server

    User->>UI: Drag JSON file or click "Upload"
    UI->>Handlers: handleFileDrop(file)
    Handlers->>UI: set file (READY)
    User->>UI: Click Upload
    UI->>Handlers: handleUpload()
    Handlers->>Client: uploadSchemaFile(file, { onUploadProgress })
    Client->>Backend: PUT /api/v2/extensions
    Backend-->>Client: response + progress events
    Client-->>Handlers: onUploadProgress(event)
    Handlers->>UI: update uploadProgress / status (UPLOADING -> DONE/FAILURE)
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Possibly related PRs

Suggested reviewers

  • elikmiller
  • superlinkx
  • cweidenkeller
🚥 Pre-merge checks | ✅ 3
✅ Passed checks (3 passed)
Check name Status Explanation
Title check ✅ Passed The title accurately describes the main change: adding an OpenGraph extension upload dialog to the UI, with a clear reference to the Jira ticket BED-6759.
Description check ✅ Passed The PR description includes all required sections: clear description of changes, motivation/context with ticket reference, testing information, type of change, and a substantially completed checklist with all items marked as done.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch BED-6759--extension-upload-ui

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 and usage tips.

@maffkipp maffkipp added the user interface A pull request containing changes affecting the UI code. label Feb 6, 2026
@maffkipp maffkipp marked this pull request as ready for review February 6, 2026 18:42
@coderabbitai coderabbitai Bot added the enhancement New feature or request label Feb 6, 2026
Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 3

🤖 Fix all issues with AI agents
In
`@packages/javascript/bh-shared-ui/src/components/SchemaUploadDialog/SchemaUploadDialog.test.tsx`:
- Around line 138-145: The failure test uses synchronous queries after the async
upload (inside withoutErrorLogging -> user.click) which can be flaky; change the
assertions to await the async queries instead (use await
screen.findByText('Failed to Upload') and await screen.findByRole('button', {
name: 'Retry upload' })) so the test waits for the error UI to appear, and keep
verifying addNotificationMock was called after those awaits.

In
`@packages/javascript/bh-shared-ui/src/components/SchemaUploadDialog/SchemaUploadDialog.tsx`:
- Line 34: The SchemaUploadDialog component is defined but not exported from the
package barrel; add an index.ts next to the SchemaUploadDialog component that
re-exports it, and update the package components barrel to follow the
established pattern by adding both export * from './SchemaUploadDialog' and
export { default as SchemaUploadDialog } from './SchemaUploadDialog' so parent
projects can import the SchemaUploadDialog symbol.

In
`@packages/javascript/bh-shared-ui/src/components/SchemaUploadDialog/useSchemaUploadHandlers.ts`:
- Around line 55-77: The current upload call in useSchemaUploadHandlers uses
file.file.type directly for the Content-Type header, which can be an empty
string; update the headers passed into uploadSchemaFile.mutate to use a safe
fallback (e.g., default to 'application/octet-stream' or derive from the
filename) when file.file.type is falsy so the request never sends an empty
Content-Type; modify the options.headers assignment in the
uploadSchemaFile.mutate call (where file.file.type is referenced) to compute
contentType = file.file.type || 'application/octet-stream' (or similar) before
calling setUploadProgress/calculateUploadProgress and the onError/onSuccess
handlers that setNewFileStatus and FileStatus.
🧹 Nitpick comments (5)
packages/javascript/js-client-library/src/client.ts (1)

964-966: Consider renaming the json parameter to data or file.

The parameter name json is misleading since the caller passes a File object (from useSchemaUploadHandlers.ts, Line 108). Other upload methods in this file (e.g., uploadFileToIngestJob at Line 939) also use json for the payload parameter, so this is at least internally consistent, but it's still a source of confusion.

♻️ Optional: clarify parameter name
-    uploadSchemaFile = (json: any, options?: RequestOptions) =>
-        this.baseClient.put('/api/v2/extensions', json, options);
+    uploadSchemaFile = (data: any, options?: RequestOptions) =>
+        this.baseClient.put('/api/v2/extensions', data, options);
packages/javascript/bh-shared-ui/src/components/SchemaUploadDialog/useSchemaUploadHandlers.ts (1)

100-109: file property in UploadSchemaParams should not be optional.

The file field is marked optional (file?: File), which means uploadSchemaFile can be called with undefined. While handleUpload guards against this at the hook level, the mutation's type contract should reflect that a file is always required when calling the mutation. Since useUploadSchemaFile is module-private, this is low risk, but tightening the type avoids future misuse.

♻️ Tighten the type
 interface UploadSchemaParams {
-    file?: File;
+    file: File;
     options?: RequestOptions;
 }
packages/javascript/bh-shared-ui/src/components/FileDrop/FileDrop.tsx (2)

39-43: Drag-and-drop does not enforce multiple=false — by design, but worth documenting.

The HTML5 drag-and-drop API does not respect the <input multiple> attribute, so when multiple={false}, users can still drop multiple files via drag-and-drop. The enforcement happens in the consumer (e.g., useSchemaUploadHandlers.handleFileDrop checks files.length === 1). This works, but a brief inline comment would help future maintainers understand why the single-file check isn't here.


82-86: Single-file message hardcodes "JSON file".

The text 'Click here or drag and drop to upload a JSON file' may not be accurate if FileDrop is reused for non-JSON single-file uploads in the future. For now this is fine since it's only used for schema upload, but consider accepting the message as a prop if reuse is expected.

packages/javascript/bh-shared-ui/src/components/SchemaUploadDialog/SchemaUploadDialog.test.tsx (1)

25-26: Clear addNotificationMock between tests to avoid cross-test contamination.

addNotificationMock accumulates calls across all tests since it's never reset. If a preceding test inadvertently triggers a notification, the assertion on line 144 could pass even if the error path didn't actually call it. Add a mockClear() in the existing afterEach.

Proposed fix
-afterEach(() => server.resetHandlers());
+afterEach(() => {
+    server.resetHandlers();
+    addNotificationMock.mockClear();
+});

Also applies to: 72-72

@coderabbitai coderabbitai Bot added the api A pull request containing changes affecting the API code. label Feb 6, 2026
Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🤖 Fix all issues with AI agents
In
`@packages/javascript/bh-shared-ui/src/components/SchemaUploadDialog/SchemaUploadDialog.test.tsx`:
- Around line 25-35: The module-scoped mock addNotificationMock is never cleared
between tests, causing accumulated call counts and false positives; fix by
adding a test teardown that clears or resets the mock (e.g., call
addNotificationMock.mockClear() or vi.clearAllMocks()) in an afterEach/afterAll
hook in SchemaUploadDialog.test.tsx so each test starts with a fresh
addNotificationMock used by the mocked useNotifications provider.
🧹 Nitpick comments (1)
packages/javascript/bh-shared-ui/src/components/SchemaUploadDialog/useSchemaUploadHandlers.ts (1)

100-103: Consider making file required in UploadSchemaParams.

file is declared optional, but apiClient.uploadSchemaFile(undefined, options) would be an invalid call. Since handleUpload always supplies it, making the field required would catch accidental misuse at compile time.

Suggested fix
 interface UploadSchemaParams {
-    file?: File;
+    file: File;
     options?: RequestOptions;
 }

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🤖 Fix all issues with AI agents
In
`@packages/javascript/bh-shared-ui/src/components/SchemaUploadDialog/useSchemaUploadHandlers.ts`:
- Around line 105-109: The upload mutation created in useUploadSchemaFile
currently returns a bare mutation and SchemaUploadDialog has no way to trigger
cache updates; modify useSchemaUploadHandlers to either (A) return the mutation
object from useUploadSchemaFile so SchemaUploadDialog can call
mutation.invalidate or onSuccess callbacks, or (B) accept a QueryClient
parameter (or obtain one via useQueryClient) and call
queryClient.invalidateQueries for the relevant keys (e.g., "schema",
"extensions") in the mutation's onSuccess handler inside useUploadSchemaFile;
ensure the symbol useUploadSchemaFile's mutationFn remains, add an onSuccess
that invalidates queries or expose the mutation so SchemaUploadDialog can supply
callbacks.
🧹 Nitpick comments (1)
packages/javascript/bh-shared-ui/src/components/SchemaUploadDialog/useSchemaUploadHandlers.ts (1)

31-40: Consider client-side file type validation on drop for better UX.

handleFileDrop accepts any file type. While the server should validate the schema file, drag-and-drop bypasses the accept attribute on <input> elements in some browsers. Adding a quick client-side check (e.g., verifying .json extension or application/json MIME type) would give immediate feedback rather than waiting for a server round-trip to reject the file.

💡 Optional: add file type guard
     const handleFileDrop = (files: FileList | null) => {
         if (!files || files.length === 0) return;
 
         if (files?.length === 1) {
+            const droppedFile = files[0];
+            if (droppedFile.type && droppedFile.type !== 'application/json' && !droppedFile.name.endsWith('.json')) {
+                addNotification('Only JSON schema files are supported', 'InvalidFileType');
+                return;
+            }
-            setFile({ file: files[0], status: FileStatus.READY });
+            setFile({ file: droppedFile, status: FileStatus.READY });
             setUploadProgress(0);
         } else {

Comment thread cmd/ui/src/views/Content.tsx Outdated
@maffkipp maffkipp merged commit 486cc34 into main Feb 13, 2026
13 of 14 checks passed
@maffkipp maffkipp deleted the BED-6759--extension-upload-ui branch February 13, 2026 21:29
@github-actions github-actions Bot locked and limited conversation to collaborators Feb 13, 2026
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

api A pull request containing changes affecting the API code. enhancement New feature or request user interface A pull request containing changes affecting the UI code.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants