-
Notifications
You must be signed in to change notification settings - Fork 29
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Widget with toolbar and sidepanel in cell output #419
Widget with toolbar and sidepanel in cell output #419
Conversation
60ef40e
to
fe38083
Compare
Integration tests report: appsharing.space |
I keep it as draft as I can't find a way to handle the resize event, which leads to toolbar elements hidden. |
937f7a7
to
68d24a2
Compare
It should work now. |
Please update snapshots |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Here are the 2 main changes that could be ported to JupyterCAD.
Other changes may be related to JupyterGIS only.
packages/base/src/widget.ts
Outdated
/** | ||
* A main area widget designed to be used as Notebook cell output widget, to ease the | ||
* integration of toolbar and tracking. | ||
*/ | ||
export class JupyterGISOutputWidget | ||
extends MainAreaWidget<JupyterGISPanel> | ||
implements IJupyterGISOutputWidget | ||
{ | ||
constructor(options: JupyterGISOutputWidget.IOptions) { | ||
super(options); | ||
this.addClass(CELL_OUTPUT_WIDGET_CLASS); | ||
this.model = options.model; | ||
|
||
const resizeObserver = new ResizeObserver(() => { | ||
// Send a resize message to the widget, to update the child size. | ||
MessageLoop.sendMessage(this, Widget.ResizeMessage.UnknownSize); | ||
}); | ||
resizeObserver.observe(this.node); | ||
} | ||
|
||
readonly model: IJupyterGISModel; | ||
} | ||
|
||
export namespace JupyterGISOutputWidget { | ||
export interface IOptions extends MainAreaWidget.IOptions<JupyterGISPanel> { | ||
model: IJupyterGISModel; | ||
} | ||
} | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The widget displayed in cell output.
const content = new JupyterGISPanel({ model }); | ||
const toolbar = new ToolbarWidget({ | ||
commands, | ||
model, | ||
externalCommands: externalCommands.getCommands() | ||
}); | ||
this._jgisWidget = new JupyterGISOutputWidget({ | ||
model, | ||
content, | ||
toolbar | ||
}); | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Where it is created in the notebook renderer.
for more information, see https://pre-commit.ci
a795d35
to
7f18130
Compare
@@ -72,7 +72,9 @@ def __init__( | |||
ydoc = Doc() | |||
|
|||
super().__init__( | |||
comm_metadata=dict(ymodel_name="@jupytergis:widget", **comm_metadata), | |||
comm_metadata=dict( | |||
ymodel_name="@jupytergis:widget", cwd=os.getcwd(), **comm_metadata |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Do we really need this? cc. @davidbrochart for awareness
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It is required to be able to add local layer from the widget buttons.
It could probably be removed if we don't use file path relative to the JGIS project file.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It is required to be able to add local layer from the widget buttons
Once the JGIS file is created, we know its "cwd" is the path to the file, right? Since we know that path in the front-end already, we may not need to pass this info from Python?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, it is not used if a path is provided.
But we want to create a GISDocument
without file, no ?
doc = GISDocument()
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
In that case, we can assume the "cwd" is the Notebook path, and since we have the notebook tracker handy, we can get its path?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
arf
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
All this situation is not great. We need a better approach but I don't have a good quick solution to suggest.
See #426 (comment)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Are the widgets supported in console ? I don't know how to display it in console.
If not, we don't need the path, it is useful for the buttons only, not for the API I think.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Otherwise something like the following should work in the front-end :
const currentWidget = app.shell.currentWidget;
let currentPath: string | undefined = undefined;
if (currentWidget instanceof NotebookPanel && notebookTracker) {
currentPath = notebookTracker.currentWidget?.context.localPath;
} else if (currentWidget instanceof ConsolePanel && consoleTracker) {
currentPath = consoleTracker.currentWidget?.sessionContext.path;
}
if (currentPath) {
this.jupyterGISModel.filePath = PathExt.join(
PathExt.dirname(currentPath),
'unsaved_project'
);
}
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That should work in most cases. It's only when people changed did os.chdir
that it will break this. But I guess we can live with this.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Beautiful 🤩
header.title.label = this._currentModel.filePath; | ||
this._annotationModel.model = | ||
options.tracker.currentWidget?.model || undefined; | ||
// await changed.context.ready; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
// await changed.context.ready; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, thanks for remind me this.
It seems to work without, but I don't know if it was necessary and should be kept somehow.
@@ -22,6 +28,10 @@ export class JupyterGISWidget | |||
super(options); | |||
} | |||
|
|||
get model(): IJupyterGISModel { | |||
return this.context.model; | |||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🤩
This refactor to pass around model
instead of context
feels so much simpler!!
@brichet it would be amazing to release this feature before the hackathon on Wednesday. How do you feel about that? I didn't approve because although I read the entire PR, I don't feel I have the expertise to "approve" on this project yet. I have a lot to learn from you all! :) |
…g the API without file
for more information, see https://pre-commit.ci
…that can be updated between the model creation and the widget creation.
if (currentWidgetPath) { | ||
this.jupyterGISModel.filePath = PathExt.join( | ||
PathExt.dirname(currentWidgetPath), | ||
'unsaved_project' |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Instead of giving this file path, what would it take to create the file from the front-end? If no file name is provided, we create an "untitled" file, if a new file path is provided (something we don't know) we create the file.
In replacement of what is removed in https://github.com/geojupyter/jupytergis/pull/426/files
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think it is also nice to be able to debug without creating a file. And to add a save()
method to the API, to be able to save the document.
But indeed, if the path is provided and does not exist, we could create it from the frontend.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think it is also nice to be able to debug without creating a file. And to add a save() method to the API, to be able to save the document.
💯 💯 💯
Some more information about the changes in this PR. There are still issues with the widgets when deleting a cell output.
The last solution I can think of (my preference) is to use some kind of |
After some discussion with @martinRenou and @trungleduc the best is probably to go the first option temporary.
The idea is to fix this behavior upstream in |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@martinRenou for me it is ready.
My only concern is commented below, and I don't know if this code is tested somewhere.
this._annotationModel.contextChanged.connect(async () => { | ||
await this._annotationModel?.context?.ready; | ||
this._annotationModel.modelChanged.connect(async () => { | ||
// await this._annotationModel?.context?.ready; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@gjmooney do you remember if this await was required ? Should we restore something similar, now we removed the context ?
you are tracking |
Should be fixed with QuantStack/yjs-widgets#20 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks great!
Let's merge :D
Fixes #397
This PR:
JupyterGISOutputWidget
) extending main area widget, to be used in the cell output. It extends the main area widget to ease the integration of the toolbar, but it could a simplest widget (to be discussed ?)adds a simplified context interface to share the same interface between document widget (main area) andallows the commands to work with both widgets.JupyterGISOutputWidget
, andlocalPath
property of the context instead ofpath
, to avoid bringing theRTC:
prefix.EDIT
IJupyterGISModel
) or the document path (also contained in the model). The newJupyterGISOutputWidget
is not a document widget and do not have a properContext
. This PR remove the use of the context and use directly the model instead, which can easily be retrieved fromJupyterGISOutputWidget
orJupyterGISWidget
, the 2 widget tracked by theWidgetTracker
.Checklist
Resolves #XXX
.Failing lint checks can be resolved with:
pre-commit run --all-files
jlpm run lint
📚 Documentation preview: https://jupytergis--419.org.readthedocs.build/en/419/
💡 JupyterLite preview: https://jupytergis--419.org.readthedocs.build/en/419/lite