Skip to content

feat(python-notebook-migration, frontend): add AI-generate-workflow modal, panel host, and LLM loading spinner - #5273

Open
zyratlo wants to merge 38 commits into
apache:mainfrom
zyratlo:migration-tool-modal
Open

feat(python-notebook-migration, frontend): add AI-generate-workflow modal, panel host, and LLM loading spinner#5273
zyratlo wants to merge 38 commits into
apache:mainfrom
zyratlo:migration-tool-modal

Conversation

@zyratlo

@zyratlo zyratlo commented May 28, 2026

Copy link
Copy Markdown
Contributor

What changes were proposed in this PR?

Adds the user facing entry point for the Python notebook to Texera workflow migration tool: an "AI generate workflow" modal in the workspace menu, a workspace loading overlay with an elapsed time stopwatch shown while the LLM converts, auto layout of the generated workflow, and the <texera-jupyter-notebook-panel> host that embeds the iframe panel component from #5271.

Menu toolbar (menu.component.{ts,html,scss})

  • Two buttons, both gated on the pythonNotebookMigrationEnabled config flag:
    • "AI generate workflow" (robot icon), also gated on workflow modifiability, opens the import modal.
    • "Expand Jupyter notebook" (Jupyter logo), shown only when the current workflow has a stored notebook (jupyterNotebookExists$), reopens the panel.
  • openImportNotebookModal() opens an NzModalService modal to upload a .ipynb and pick a LiteLLM model.
    • Models load via notebookMigrationService.getAvailableModels(), with a loading state and a "no models available" state on fetch failure.
    • Both the file and the model are required before submit.
    • A warning banner states that generating overwrites the current workflow. On submit, a confirmation dialog appears only when the current workflow already has content (operators or comment boxes).
  • onClickImportNotebook(file, model) runs the generation:
    • validates the .ipynb extension, then emits setWaitingForLLM(true) to show the overlay
    • parses the notebook and tags each cell with a metadata.uuid
    • calls sendToAIGenerateWorkflow(...) to get the generated workflow content and the cell to operator mapping
    • always overwrites the current workflow by reusing its wid so persistWorkflow(...) updates that row in place (a never saved workflow becomes a new row), which avoids leaving a duplicate "Untitled workflow"
    • persists the notebook and mapping via storeNotebookAndMapping(...)
    • reloads the workflow onto the live canvas and runs auto layout on the generated operators
    • shows the panel: when the wid is unchanged it sends the notebook and opens the panel directly; when a new row was created it points the URL at the generated workflow so JupyterPanelService.init() sends the notebook and opens the panel (avoids a double "sent to Jupyter" toast)
    • clears the overlay at every terminal state, including file read errors, parse failures, invalid notebooks, and LLM errors

Workspace (workspace.component.{ts,html,scss})

Assets

  • jupyter-logo.svg: icon for the expand button.
  • tool_popup_diagram.png: diagram shown at the top of the modal.

Tests

  • Unit specs for the import flow (modal wiring, upload guard, model required, overwrite behavior, warning and confirm, error paths) and the workspace loading timer.

Any related issues, documentation, discussions?

Closes #4427
Parent issue #4301

How was this PR tested?

npx ng test for the menu and workspace specs. Manual end to end on a branch with the dependency PRs present: enabled the flag, opened the workspace menu, clicked AI generate workflow, picked a sample .ipynb and a LiteLLM model (auth is via the user's Texera JWT, no API key input), confirmed the overwrite prompt, and watched the stopwatch while the conversion ran. The generated workflow appeared in the editor with PythonUDFV2 operators auto laid out, the panel opened with the notebook in the embedded JupyterLab, clicking an operator scrolled its notebook cell into view, and clicking a cell highlighted its operators.

Was this PR authored or co-authored using generative AI tooling?

Generated-by: Claude Code (Claude Opus 4.8)

@github-actions github-actions Bot added the frontend Changes related to the frontend GUI label May 28, 2026
@codecov-commenter

codecov-commenter commented May 28, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 58.56354% with 75 lines in your changes missing coverage. Please review.
✅ Project coverage is 80.37%. Comparing base (0f7a426) to head (bb929a8).
⚠️ Report is 1 commits behind head on main.

Files with missing lines Patch % Lines
...c/app/workspace/component/menu/menu.component.html 18.18% 45 Missing ⚠️
...src/app/workspace/component/menu/menu.component.ts 79.56% 14 Missing and 5 partials ⚠️
...c/app/workspace/component/workspace.component.html 0.00% 11 Missing ⚠️
Additional details and impacted files
@@             Coverage Diff              @@
##               main    #5273      +/-   ##
============================================
- Coverage     80.47%   80.37%   -0.10%     
  Complexity     3875     3875              
============================================
  Files          1162     1162              
  Lines         46264    46447     +183     
  Branches       5153     5170      +17     
============================================
+ Hits          37230    37334     +104     
- Misses         7375     7448      +73     
- Partials       1659     1665       +6     
Flag Coverage Δ *Carryforward flag
access-control-service 70.00% <ø> (ø) Carriedforward from f44d5cb
agent-service 77.42% <ø> (ø) Carriedforward from f44d5cb
amber 75.30% <ø> (ø) Carriedforward from f44d5cb
computing-unit-managing-service 20.49% <ø> (ø) Carriedforward from f44d5cb
config-service 65.97% <ø> (ø) Carriedforward from f44d5cb
file-service 66.80% <ø> (ø) Carriedforward from f44d5cb
frontend 82.99% <58.56%> (-0.24%) ⬇️
notebook-migration-service 78.89% <ø> (ø) Carriedforward from f44d5cb
pyamber 97.36% <ø> (ø) Carriedforward from f44d5cb
workflow-compiling-service 26.31% <ø> (ø) Carriedforward from f44d5cb

*This pull request uses carry forward flags. Click here to find out more.

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@zyratlo
zyratlo marked this pull request as draft June 5, 2026 21:28
zyratlo and others added 2 commits June 9, 2026 09:49
# Conflicts:
#	frontend/src/app/workspace/component/menu/menu.component.ts
#	frontend/src/app/workspace/component/workspace.component.ts
@github-actions

github-actions Bot commented Jun 24, 2026

Copy link
Copy Markdown
Contributor

Automated Reviewer Suggestions

Based on the git blame history of the changed files, we recommend the following reviewers:

  • Committers with relevant context: @parshimers
    You can request their reviews formally with /request-review @parshimers.

  • Contributors with relevant context: @kunwp1, @renovate-bot, @Ma77Ball
    You can notify them by mentioning @kunwp1, @renovate-bot, @Ma77Ball in a comment.

zyratlo added a commit to zyratlo/texera that referenced this pull request Jul 23, 2026
adopt main's reviewed versions for the already merged migration slices: backend notebook-migration-service, frontend migration service, config, build, and sql.

pull the reviewed open PR content from its branches: jupyter panel visibility surface and mini-map button (apache#5265), jupyter notebook iframe panel (apache#5271), and the AI generate workflow modal and panel host (apache#5273).

reconcile app.module.ts by keeping main's JupyterPanelService bootstrap listener and registering JupyterNotebookPanelComponent.
aglinxinyuan pushed a commit to aglinxinyuan/texera that referenced this pull request Jul 25, 2026
…(visibility surface and notebook-exists signal) (apache#5265)

### What changes were proposed in this PR?
Extends `JupyterPanelService` with the panel-visibility surface (a
`BehaviorSubject` plus four open/close/minimize methods) and a reactive
`jupyterNotebookExists$` signal. This PR is the service layer only. The
button that consumes it lives in the workspace top menu bar via apache#5273;
apache#5265 provides the service, apache#5273 consumes it.

**`jupyter-panel.service.ts`:**

- Restores `BehaviorSubject` to the `rxjs` import and re-adds the
`NotificationService` injection.
- Panel-visibility stream: `private jupyterNotebookPanelVisible = new
BehaviorSubject<boolean>(false)` with public
`jupyterNotebookPanelVisible$ =
this.jupyterNotebookPanelVisible.asObservable()`.
- Notebook-exists signal: `private jupyterNotebookExists = new
BehaviorSubject<boolean>(false)` with public `jupyterNotebookExists$`.
`init()` resets it to `false` on every workflow change and sets it to
`true` in the `fetchNotebookAndMapping` success branch (`result === 1`).
It stays `true` through minimize and resets when switching workflows.
The menu button in apache#5273 binds to this to decide whether to show.
  - Four `if (!this.enabled) return;`-gated methods:
- `openPanel(panelName: string)` — flips visibility to `true` when
`panelName === "JupyterNotebookPanel"` (the existing workspace
panel-system convention).
- `closeJupyterNotebookPanel()` — flips visibility to `false`, then
`notebookMigrationService.deleteMapping("mapping_wid_" +
workflowActionService.getWorkflow().wid)`.
    - `minimizeJupyterNotebookPanel()` — flips visibility to `false`.
- `openJupyterNotebookPanel()` — checks
`notebookMigrationService.hasMapping(...)`; warns via
`notificationService.warning("No Jupyter notebook associated with this
workflow.")` and returns if there is no cached mapping, otherwise flips
visibility to `true`.
- `init()`'s subscribe handler: on every workflow change it calls
`closeJupyterNotebookPanel()` (which also does the stale-mapping
cleanup), clears the highlight index, and resets `jupyterNotebookExists`
to `false`; on a successful fetch it sets `jupyterNotebookExists` to
`true`, precomputes the highlight index, and auto-opens via
`openJupyterNotebookPanel()`.

No mini-map changes: the expand control moved out of the mini-map and
into the top menu bar (see apache#5273), so `mini-map.component.*` is back to
its `main` version here.

### Any related issues, documentation, discussions?
Closes apache#5264
Parent issue apache#4301
Builds on apache#5263 (`migration-tool-mapping-highlighting`), merged. The
consuming menu button lives in apache#5273 (`migration-tool-modal`): apache#5265
provides `openJupyterNotebookPanel` and `jupyterNotebookExists$`, apache#5273
consumes them.

### How was this PR tested?
`jupyter-panel.service.spec.ts` adds visibility coverage (enabled-flag
cases for open/close, minimize, and the warn-vs-open branch of
`openJupyterNotebookPanel`; disabled-flag short-circuit cases per
method) and a `jupyterNotebookExists$` case (starts `false`, flips
`true` after a successful fetch).

### Was this PR authored or co-authored using generative AI tooling?
Generated-by: Claude Code (Claude Opus 4.8)

---------

Co-authored-by: Meng Wang <mengw15@uci.edu>
@zyratlo
zyratlo marked this pull request as ready for review July 31, 2026 22:50
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

frontend Changes related to the frontend GUI

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Notebook Migration] 2. Add Notebook Upload Modal

2 participants