forked from jupyter/nbdime
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Make Cells Display Lazily When Diffing Unchanged Cells
Motivation: During diffing Unchanged cells are displayed, which is not necessary. This is a performance issue when there are many unchanged cells. Related Issues: - jupyter#635 Open Questions: - I am struggling with getting the svg images to build properly. - How can this be tested in JupyterLab? Changes: - Alter Notebooks Widget to only display changed cells by using new linked list of cells. - Add new linked list of cells and lazy version of linked list of cells.
- Loading branch information
Showing
10 changed files
with
610 additions
and
181 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,31 +1,49 @@ | ||
{% extends "nbdimepage.html" %} | ||
{% extends "nbdimepage.html" %} {% block nbdimeheader %} | ||
|
||
{% block nbdimeheader %} | ||
<div id="nbdime-header" class="nbdime-Diff"> | ||
<h3>Notebook Diff</h3> | ||
Enter notebook filenames or URLs in the form below to get started. | ||
|
||
<div id="nbdime-header" class="nbdime-Diff"> | ||
<h3>Notebook Diff</h3> | ||
Enter notebook filenames or URLs in the form below to get started. | ||
<form id="nbdime-diff-form" class="nbdime-forms"> | ||
<fieldset> | ||
<legend>Please input filenames/URLs of notebooks to diff:</legend> | ||
<label>Base:</label> | ||
<input | ||
id="diff-base" | ||
type="text" | ||
name="base" | ||
value="{{ config_data['base']|e }}" | ||
/> | ||
<label>Remote:</label> | ||
<input | ||
id="diff-remote" | ||
type="text" | ||
name="remote" | ||
value="{{ config_data['remote']|e }}" | ||
/> | ||
<input | ||
id="nbdime-run-diff" | ||
type="submit" | ||
name="diff" | ||
value="Diff files" | ||
/> | ||
</fieldset> | ||
</form> | ||
<!-- nbdime-forms --> | ||
<div id="nbdime-header-buttonrow"> | ||
<button id="nbdime-trust" style="display: none">Trust outputs</button> | ||
<button id="nbdime-close" type="checkbox" style="display: none"> | ||
Close tool | ||
</button> | ||
<button id="nbdime-export" type="checkbox" style="display: none"> | ||
Export diff | ||
</button> | ||
</div> | ||
<div id="nbdime-header-banner"> | ||
<span id="nbdime-header-base">Base</span> | ||
<span id="nbdime-header-remote">Remote</span> | ||
</div> | ||
</div> | ||
<!-- ndime-header --> | ||
|
||
<form id="nbdime-diff-form" class="nbdime-forms"> | ||
<fieldset> | ||
<legend>Please input filenames/URLs of notebooks to diff:</legend> | ||
<label>Base:</label> | ||
<input id="diff-base" type="text" name="base" value="{{ config_data['base']|e }}" /> | ||
<label>Remote:</label> | ||
<input id="diff-remote" type="text" name="remote" value="{{ config_data['remote']|e }}" /> | ||
<input id="nbdime-run-diff" type="submit" name="diff" value="Diff files" /> | ||
</fieldset> | ||
</form> <!-- nbdime-forms --> | ||
<div id="nbdime-header-buttonrow"> | ||
<input id="nbdime-hide-unchanged" type="checkbox"><label for="cbox1">Hide unchanged cells</label></input> | ||
<button id="nbdime-trust" style="display: none">Trust outputs</button> | ||
<button id="nbdime-close" type="checkbox" style="display: none">Close tool</button> | ||
<button id="nbdime-export" type="checkbox" style="display: none">Export diff</button> | ||
</div> | ||
<div id=nbdime-header-banner> | ||
<span id="nbdime-header-base">Base</span> | ||
<span id="nbdime-header-remote">Remote</span> | ||
</div> | ||
</div> <!-- ndime-header --> | ||
|
||
{% endblock %} | ||
{% endblock %} |
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,202 @@ | ||
import { Panel, Widget } from "@lumino/widgets"; | ||
import type { CellDiffWidget } from "./"; | ||
|
||
import foldDown from "./fold-down.svg"; | ||
import foldUp from "./fold-up.svg"; | ||
import fold from "./fold.svg"; | ||
|
||
class LinkedListCell extends Panel { | ||
_next: LinkedListCell | LazyDisplayLinkedListCell | null; | ||
_prev: LinkedListCell | LazyDisplayLinkedListCell | null; | ||
renderFunc: () => CellDiffWidget; | ||
_displayed: boolean; | ||
lazy: boolean; | ||
|
||
constructor(renderFunc: () => CellDiffWidget) { | ||
super(); | ||
this._next = null; | ||
this._prev = null; | ||
this.renderFunc = renderFunc; | ||
this._displayed = true; | ||
this.renderCell(); | ||
this.addClass("linked-cell"); | ||
this.lazy = false; | ||
} | ||
|
||
protected renderCell() { | ||
this.addWidget(this.renderFunc()); | ||
this._displayed = true; | ||
} | ||
|
||
get next(): LinkedListCell | LazyDisplayLinkedListCell | null { | ||
return this._next; | ||
} | ||
|
||
set next(nextCell: LinkedListCell | LazyDisplayLinkedListCell | null) { | ||
this._next = nextCell; | ||
if (nextCell === null) { | ||
return; | ||
} | ||
|
||
if (nextCell.lazy) { | ||
console.log("call expandDown"); | ||
nextCell.expandDown(); | ||
} | ||
} | ||
|
||
get prev(): LinkedListCell | LazyDisplayLinkedListCell | null { | ||
return this._prev; | ||
} | ||
|
||
set prev(prevCell: LinkedListCell | LazyDisplayLinkedListCell | null) { | ||
this._prev = prevCell; | ||
if (prevCell === null) { | ||
return; | ||
} | ||
prevCell.next = this; | ||
if (prevCell.lazy) { | ||
prevCell.expandUp(); | ||
} | ||
} | ||
|
||
get displayed(): boolean { | ||
return this._displayed; | ||
} | ||
|
||
expandUp(): void { | ||
return; | ||
} | ||
|
||
expandDown(): void { | ||
return; | ||
} | ||
} | ||
|
||
class LazyDisplayLinkedListCell extends LinkedListCell { | ||
expandButton: HTMLDivElement; | ||
expandButtonDisplayed: boolean; | ||
|
||
// Path: packages/nbdime/src/diff/widget/wrapper_cells.ts | ||
constructor(renderFunc: () => CellDiffWidget) { | ||
super(renderFunc); | ||
this.expandButton = document.createElement("div"); | ||
this.expandButton.className = "jp-expand-output-wrapper"; | ||
this.expandButtonDisplayed = false; | ||
this.addClass("lazy-linked-cell"); | ||
this.lazy = true; | ||
} | ||
|
||
set prev(prevCell: LinkedListCell | LazyDisplayLinkedListCell) { | ||
this._prev = prevCell; | ||
prevCell.next = this; | ||
} | ||
|
||
set next(nextCell: LinkedListCell | LazyDisplayLinkedListCell) { | ||
this._next = nextCell; | ||
} | ||
|
||
protected renderCell() { | ||
this._displayed = false; | ||
} | ||
|
||
expandUp(): void { | ||
if (this._displayed) { | ||
return; | ||
} | ||
if (this.expandButtonDisplayed) { | ||
this._setupFoldButton(); | ||
} else { | ||
this._setupExpandUpButton(); | ||
} | ||
} | ||
|
||
expandDown(): void { | ||
if (this._displayed) { | ||
return; | ||
} | ||
if (this.expandButtonDisplayed) { | ||
this._setupFoldButton(); | ||
} else { | ||
this._setupExpandDownButton(); | ||
} | ||
} | ||
|
||
_setupFoldButton() { | ||
this.expandButton.innerHTML = ""; | ||
const button = this.createButton("Fold"); | ||
button.onclick = (e) => { | ||
e.preventDefault(); | ||
this.showLazyCellUp(); | ||
}; | ||
this.expandButton.appendChild(button); | ||
const widget = new Widget({ node: this.expandButton }); | ||
this.addWidget(widget); | ||
} | ||
|
||
_setupExpandUpButton() { | ||
const button = this.createButton("Up"); | ||
button.onclick = (e) => { | ||
e.preventDefault(); | ||
this.showLazyCellUp(); | ||
}; | ||
this.expandButton.appendChild(button); | ||
const widget = new Widget({ node: this.expandButton }); | ||
this.addWidget(widget); | ||
} | ||
|
||
_setupExpandDownButton() { | ||
const button = this.createButton("Down"); | ||
button.onclick = (e) => { | ||
e.preventDefault(); | ||
this.showLazyCellDown(); | ||
}; | ||
this.expandButton.appendChild(button); | ||
const widget = new Widget({ node: this.expandButton }); | ||
this.addWidget(widget); | ||
} | ||
|
||
createButton(direction: "Up" | "Down" | "Fold"): HTMLAnchorElement { | ||
this.expandButton.innerHTML = ""; | ||
const button = document.createElement("a"); | ||
button.title = `Expand ${direction}`; | ||
button.setAttribute("aria-label", `Expand ${direction}`); | ||
button.innerHTML = this.buttonSvg(direction); | ||
if (direction === "Up") { | ||
button.innerHTML = foldUp; | ||
} else if (direction === "Down") { | ||
button.innerHTML = foldDown; | ||
} else { | ||
button.innerHTML = fold; | ||
} | ||
this.expandButtonDisplayed = true; | ||
return button; | ||
} | ||
|
||
buttonSvg(direction: "Up" | "Down" | "Fold"): string { | ||
if (direction === "Up") { | ||
return foldUp; | ||
} else if (direction === "Down") { | ||
return foldDown; | ||
} else { | ||
return fold; | ||
} | ||
} | ||
|
||
showLazyCellUp() { | ||
this.showLazyCell(); | ||
this._prev?.expandUp(); | ||
} | ||
|
||
showLazyCellDown() { | ||
this.showLazyCell(); | ||
this._next?.expandDown(); | ||
} | ||
|
||
showLazyCell() { | ||
this.addWidget(this.renderFunc()); | ||
this._displayed = true; | ||
this.expandButton.remove(); | ||
} | ||
} | ||
|
||
export { LinkedListCell, LazyDisplayLinkedListCell }; |
Oops, something went wrong.