Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
48 commits
Select commit Hold shift + click to select a range
1c5af12
added upload notebook modal logic
zyratlo May 28, 2026
65e0f5d
Merge branch 'main' into migration-tool-modal
zyratlo Jun 1, 2026
ea3163a
Merge branch 'main' into migration-tool-modal
zyratlo Jun 5, 2026
83e0bc5
Merge branch 'refs/heads/main' into migration-tool-modal
zyratlo Jun 9, 2026
1b7c6ad
Merge branch 'main' into migration-tool-modal
zyratlo Jun 15, 2026
6230760
remove unused api key input, auth via jwt
zyratlo Jun 24, 2026
299eabb
Merge branch 'refs/heads/main' into migration-tool-modal
zyratlo Jul 20, 2026
ea6a8f9
use @if control flow for the llm spinner text instead of ngIf
zyratlo Jul 23, 2026
09dbe86
Merge branch 'main' into migration-tool-modal
zyratlo Jul 24, 2026
2902918
add expand jupyter panel button to top menu bar
zyratlo Jul 24, 2026
350a205
formatting
zyratlo Jul 24, 2026
57a10bb
Merge branch 'main' into migration-tool-modal
zyratlo Jul 28, 2026
809f996
clear LLM spinner on notebook read and pre-generation errors
zyratlo Jul 28, 2026
3a8aa2b
clear LLM spinner only after workflow persist pipeline settles
zyratlo Jul 28, 2026
3ed3c22
stop elapsed-time timer on workspace destroy
zyratlo Jul 28, 2026
eda1337
show no-models state instead of empty model dropdown on fetch failure
zyratlo Jul 28, 2026
8cd5afa
require model selection before submitting notebook import
zyratlo Jul 28, 2026
07f3213
reuse existing ChangeDetectorRef in workspace timer
zyratlo Jul 28, 2026
f8ca542
notify user when notebook generation returns no workflow
zyratlo Jul 28, 2026
0875a78
use let instead of var for workflowName
zyratlo Jul 28, 2026
f7ca73d
type timerInterval and guard clearInterval against null
zyratlo Jul 28, 2026
0b5ee04
remove unused description control from notebook import form
zyratlo Jul 28, 2026
bb68d62
make elapsed-time default match single-digit minute format
zyratlo Jul 28, 2026
1419ec5
move notebook import modal inline styles into scss classes
zyratlo Jul 28, 2026
62a010f
lowercase new toolbar button tooltips to match existing buttons
zyratlo Jul 28, 2026
c3a355c
use openJupyterNotebookPanel in import success path for consistency
zyratlo Jul 28, 2026
3efd2f1
add specs for notebook import flow and llm waiting timer
zyratlo Jul 28, 2026
1ac44c5
keep unconditional openPanel in notebook import to survive reload map…
zyratlo Jul 28, 2026
7e35830
overwrite empty current workflow on notebook import to avoid duplicate
zyratlo Jul 28, 2026
d2c3ab8
overwrite current workflow on notebook import
zyratlo Jul 28, 2026
d2c2231
refine notebook import modal layout
zyratlo Jul 28, 2026
655c9fa
Merge branch 'main' into migration-tool-modal
zyratlo Jul 31, 2026
8493f97
auto layout generated workflow after notebook import
zyratlo Jul 31, 2026
d9fac6c
Merge branch 'main' into migration-tool-modal
zyratlo Jul 31, 2026
a064498
Merge branch 'main' into migration-tool-modal
zyratlo Jul 31, 2026
672feb2
register jupyter panel component in workspace imports and drop duplic…
zyratlo Jul 31, 2026
f44d5cb
add jupyter logo license header exclude and license-binary attribution
zyratlo Jul 31, 2026
bb929a8
attribute material symbols icons and colored jupyter logo used in the…
zyratlo Jul 31, 2026
dc4b7d8
Merge branch 'main' into migration-tool-modal
zyratlo Aug 3, 2026
7998101
add test cases for coverage
zyratlo Aug 3, 2026
ee5d342
Merge branch 'main' into migration-tool-modal
mengw15 Aug 3, 2026
8002ab1
reuse the single injected modal service in menu component
zyratlo Aug 3, 2026
b4db78f
clear any running elapsed-time interval before starting a new one
zyratlo Aug 3, 2026
b4b1aa4
stop the workspace host from constraining the jupyter panel stacking …
zyratlo Aug 3, 2026
8ee0fda
align the llm spinner time estimate with the import modal
zyratlo Aug 3, 2026
a878780
remove unused Subscription import from menu component
zyratlo Aug 3, 2026
d374180
open the jupyter panel only when the notebook send to jupyter succeeds
zyratlo Aug 3, 2026
e48d9ad
disable the ai-generate button while a conversion is in flight
zyratlo Aug 3, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .licenserc.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@ header:
- 'frontend/src/assets/svg/operator-view-result.svg'
- 'frontend/src/assets/svg/operator-reuse-cache-invalid.svg'
- 'frontend/src/assets/svg/operator-reuse-cache-valid.svg'
- 'frontend/src/assets/notebook_migration_tool/jupyter-logo.svg'
- 'frontend/src/app/common/type/proto/org/apache/texera/amber/core/virtualidentity.ts'
- 'frontend/src/app/common/type/proto/org/apache/texera/amber/core/workflow.ts'
- 'frontend/src/app/common/type/proto/google/protobuf/descriptor.ts'
Expand Down
11 changes: 11 additions & 0 deletions frontend/LICENSE-binary
Original file line number Diff line number Diff line change
Expand Up @@ -224,6 +224,11 @@ Angular / npm packages:
- jschardet@3.1.3
- rxjs@7.8.2

Third-party assets:
- Google Material Symbols icons (psychology, smart_toy)
frontend/src/assets/notebook_migration_tool/tool_popup_diagram.png
https://github.com/google/material-design-icons

--------------------------------------------------------------------------------
Dependencies under the MIT License
--------------------------------------------------------------------------------
Expand Down Expand Up @@ -358,6 +363,12 @@ Angular / npm packages:
- parchment@3.0.0
- quill@2.0.3

Third-party assets:
- Project Jupyter logo
frontend/src/assets/notebook_migration_tool/jupyter-logo.svg
frontend/src/assets/notebook_migration_tool/tool_popup_diagram.png
https://github.com/jupyter/design

--------------------------------------------------------------------------------
Dependencies under the ISC License
--------------------------------------------------------------------------------
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,9 +19,8 @@

.draggable-panel {
position: absolute;
top: 50%;
left: 50%;
margin-top: 200px;
top: 100px;
left: 200px;
width: 660px;
height: 400px;
background-color: #fff;
Expand Down
121 changes: 121 additions & 0 deletions frontend/src/app/workspace/component/menu/menu.component.html
Original file line number Diff line number Diff line change
Expand Up @@ -149,6 +149,26 @@
nz-icon
nzType="info-circle"></i>
</button>
<button
*ngIf="pythonNotebookMigrationEnabled"
nz-button
[disabled]="!isWorkflowModifiable || isWaitingForLLM"
(click)="openImportNotebookModal()"
title="AI generate workflow">
<i
nz-icon
nzType="robot"></i>
</button>
<button
*ngIf="pythonNotebookMigrationEnabled && (jupyterNotebookExists$ | async)"
nz-button
(click)="onClickExpandJupyterNotebookPanel()"
title="expand Jupyter notebook">
<img
class="jupyter-notebook-icon"
src="assets/notebook_migration_tool/jupyter-logo.svg"
alt="Jupyter" />
</button>
</nz-space-compact>
<ng-template #utilities>
<nz-space-compact>
Expand Down Expand Up @@ -456,3 +476,104 @@
</div>
</div>
</div>

<ng-template
#importNotebookModal
let-data>
<form
class="import-modal-form"
[formGroup]="importForm"
nz-form>
<div class="import-modal-diagram">
<img
ngSrc="assets/notebook_migration_tool/tool_popup_diagram.png"
alt="Notebook to Workflow"
width="1646"
height="479" />
</div>

<nz-alert
class="import-modal-warning"
nzType="warning"
nzShowIcon
nzMessage="Generating overwrites your current workflow; the previous version is kept in version history."></nz-alert>

<nz-form-item>
<p class="import-modal-text">
This tool converts a Python Jupyter Notebook into a Texera workflow using LLM capabilities. After you submit a
notebook, the LLM service will generate a corresponding Texera workflow. The conversion time depends on the
notebook’s complexity and can take 1–5 minutes. Once the process is complete, the workflow workspace will reload
with:
</p>
<ol class="import-modal-list">
<li>
The generated workflow ready to use (Note: you will still need to upload the dataset and connect it to the
workflow).
</li>
<li>A floating Jupyter window containing the uploaded notebook for reference.</li>
</ol>
<p class="import-modal-text">
Feel free to navigate away from this tab while you wait for the workflow to generate. Please do not close the
window.
</p>
</nz-form-item>

<nz-form-item>
<nz-form-label [nzNoColon]="true">
<span class="import-modal-label"> Upload Python Jupyter Notebook </span>
</nz-form-label>
<nz-form-control>
<div class="import-modal-upload-row">
<nz-upload
[nzBeforeUpload]="beforeUpload"
[nzShowUploadList]="false">
<button nz-button>
<i
nz-icon
nzType="upload"></i>
</button>
</nz-upload>

<span *ngIf="importForm.get('file')?.value?.name">
Selected file: {{ importForm.get('file')?.value?.name }}
</span>
</div>
</nz-form-control>
</nz-form-item>

<nz-form-item>
<nz-form-label [nzNoColon]="true">
<span class="import-modal-label"> Select Model Type </span>
</nz-form-label>

<nz-form-control>
<ng-container *ngIf="data.models$ | async as models; else loadingTpl">
<nz-select
*ngIf="$any(models).length > 0; else noModelsTpl"
class="import-modal-select"
formControlName="model"
nzPlaceHolder="Select a model">
<nz-option
*ngFor="let model of $any(models)"
[nzValue]="model.name"
[nzLabel]="model.name"></nz-option>
</nz-select>
<ng-template #noModelsTpl>
<nz-select
class="import-modal-select"
nzPlaceHolder="No models available"
[nzDisabled]="true"></nz-select>
</ng-template>
</ng-container>

<ng-template #loadingTpl>
<nz-select
class="import-modal-select"
nzPlaceHolder="Loading models..."
[nzLoading]="true"
[nzDisabled]="true"></nz-select>
</ng-template>
</nz-form-control>
</nz-form-item>
</form>
</ng-template>
65 changes: 65 additions & 0 deletions frontend/src/app/workspace/component/menu/menu.component.scss
Original file line number Diff line number Diff line change
Expand Up @@ -190,3 +190,68 @@ texera-coeditor-user-icon {
::ng-deep .layers-dropdown {
user-select: none;
}

.jupyter-notebook-icon {
height: 1.1em;
width: auto;
vertical-align: -0.2em;
}

.import-modal {
// Tighten the default form-item spacing so the modal fits without scrolling.
&-form nz-form-item {
margin-bottom: 12px;
}

&-diagram {
text-align: center;
margin-bottom: 12px;

img {
max-width: 100%;
height: auto;
border-radius: 8px;
}
}

&-text {
margin: 0;
font-size: 15px;
line-height: 1.4;
font-weight: 500;
user-select: text;
}

&-list {
margin: 4px 0 0;
padding-left: 20px;
font-size: 15px;
line-height: 1.4;
font-weight: 500;
user-select: text;
}

&-label {
font-size: 14px;
font-weight: 700;
}

&-upload-row {
display: inline-flex;
align-items: center;
gap: 8px;

button {
white-space: normal;
}
}

&-select {
width: 50%;
}

&-warning {
display: block;
margin-bottom: 12px;
}
}
Loading
Loading