Skip to content

Commit c67caa6

Browse files
Embedded panels
1 parent 4767259 commit c67caa6

File tree

27 files changed

+664
-809
lines changed

27 files changed

+664
-809
lines changed

package.json

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -72,5 +72,8 @@
7272
"rimraf": "^3.0.2",
7373
"typescript": "^5",
7474
"webpack": "^5.76.3"
75+
},
76+
"dependencies": {
77+
"react-rnd": "^10.5.2"
7578
}
7679
}

packages/base/src/Lumino.tsx

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
import { Widget } from '@lumino/widgets';
2+
import * as React from 'react';
3+
4+
type LuminoProps = {
5+
id?: string;
6+
height?: string | number;
7+
children: Widget;
8+
};
9+
10+
export const Lumino = (props: LuminoProps) => {
11+
const ref = React.useRef<HTMLDivElement>(null);
12+
const { children, id, height } = props;
13+
React.useEffect(() => {
14+
if (ref && ref.current) {
15+
try {
16+
Widget.attach(children, ref.current);
17+
} catch (e) {
18+
console.warn('Exception while attaching Lumino widget.', e);
19+
}
20+
return () => {
21+
try {
22+
if (children.isAttached || children.node.isConnected) {
23+
children.dispose();
24+
Widget.detach(children);
25+
}
26+
} catch (e) {
27+
// no-op.
28+
// console.debug('Exception while detaching Lumino widget.', e);
29+
}
30+
};
31+
}
32+
}, [ref, children]);
33+
return (
34+
<div id={id} ref={ref} style={{ height: height, minHeight: height }} />
35+
);
36+
};
37+
38+
Lumino.defaultProps = {
39+
id: 'lumino-id',
40+
height: '100%',
41+
};
42+
43+
export default Lumino;

packages/base/src/annotations/components/Annotation.tsx

Lines changed: 2 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -9,13 +9,12 @@ import { showDialog, Dialog } from '@jupyterlab/apputils';
99
import { Button } from '@jupyterlab/ui-components';
1010
import React, { useMemo, useState } from 'react';
1111

12-
import { IControlPanelModel } from '@/src/types';
1312
import { Message } from './Message';
1413

1514
export interface IAnnotationProps {
1615
itemId: string;
1716
annotationModel: IAnnotationModel;
18-
rightPanelModel?: IControlPanelModel;
17+
rightPanelModel?: IJupyterGISModel;
1918
children?: JSX.Element[] | JSX.Element;
2019
}
2120

@@ -26,20 +25,10 @@ const Annotation: React.FC<IAnnotationProps> = ({
2625
children,
2726
}) => {
2827
const [messageContent, setMessageContent] = useState('');
29-
const [jgisModel, setJgisModel] = useState<IJupyterGISModel | undefined>(
30-
rightPanelModel?.jGISModel,
31-
);
32-
28+
const jgisModel = rightPanelModel;
3329
const annotation = annotationModel.getAnnotation(itemId);
3430
const contents = useMemo(() => annotation?.contents ?? [], [annotation]);
3531

36-
/**
37-
* Update the model when it changes.
38-
*/
39-
rightPanelModel?.documentChanged.connect((_, widget) => {
40-
setJgisModel(widget?.model);
41-
});
42-
4332
const handleSubmit = () => {
4433
annotationModel.addContent(itemId, messageContent);
4534
setMessageContent('');

packages/base/src/mainview/mainView.tsx

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,15 @@
11
import { MapChange } from '@jupyter/ydoc';
22
import {
33
IAnnotation,
4+
IAnnotationModel,
45
IDict,
56
IGeoTiffSource,
67
IHeatmapLayer,
78
IHillshadeLayer,
89
IImageLayer,
910
IImageSource,
1011
IJGISFilterItem,
12+
IJGISFormSchemaRegistry,
1113
IJGISLayer,
1214
IJGISLayerDocChange,
1315
IJGISLayerTreeDocChange,
@@ -34,6 +36,7 @@ import {
3436
import { showErrorMessage } from '@jupyterlab/apputils';
3537
import { IObservableMap, ObservableMap } from '@jupyterlab/observables';
3638
import { User } from '@jupyterlab/services';
39+
import { IStateDB } from '@jupyterlab/statedb';
3740
import { CommandRegistry } from '@lumino/commands';
3841
import { JSONValue, UUID } from '@lumino/coreutils';
3942
import { ContextMenu } from '@lumino/widgets';
@@ -90,6 +93,7 @@ import CollaboratorPointers, { ClientPointer } from './CollaboratorPointers';
9093
import { FollowIndicator } from './FollowIndicator';
9194
import TemporalSlider from './TemporalSlider';
9295
import { MainViewModel } from './mainviewmodel';
96+
import { LeftPanelComponent, RightPanelComponent } from '../panelview';
9397

9498
type OlLayerTypes =
9599
| TileLayer
@@ -102,6 +106,9 @@ type OlLayerTypes =
102106
| ImageLayer<any>;
103107
interface IProps {
104108
viewModel: MainViewModel;
109+
state?: IStateDB;
110+
formSchemaRegistry?: IJGISFormSchemaRegistry;
111+
annotationModel?: IAnnotationModel;
105112
}
106113

107114
interface IStates {
@@ -123,6 +130,11 @@ interface IStates {
123130
export class MainView extends React.Component<IProps, IStates> {
124131
constructor(props: IProps) {
125132
super(props);
133+
this._state = props.state;
134+
135+
this._formSchemaRegistry = props.formSchemaRegistry;
136+
137+
this._annotationModel = props.annotationModel;
126138

127139
// Enforce the map to take the full available width in the case of Jupyter Notebook viewer
128140
const el = document.getElementById('main-panel');
@@ -2220,6 +2232,21 @@ export class MainView extends React.Component<IProps, IStates> {
22202232
scale={this.state.scale}
22212233
/>
22222234
</div>
2235+
2236+
{this._state && (
2237+
<LeftPanelComponent
2238+
model={this._model}
2239+
commands={this._commands}
2240+
state={this._state}
2241+
></LeftPanelComponent>
2242+
)}
2243+
{this._formSchemaRegistry && this._annotationModel && (
2244+
<RightPanelComponent
2245+
model={this._model}
2246+
formSchemaRegistry={this._formSchemaRegistry}
2247+
annotationModel={this._annotationModel}
2248+
></RightPanelComponent>
2249+
)}
22232250
</>
22242251
);
22252252
}
@@ -2240,4 +2267,7 @@ export class MainView extends React.Component<IProps, IStates> {
22402267
private _originalFeatures: IDict<Feature<Geometry>[]> = {};
22412268
private _highlightLayer: VectorLayer<VectorSource>;
22422269
private _updateCenter: CallableFunction;
2270+
private _state?: IStateDB;
2271+
private _formSchemaRegistry?: IJGISFormSchemaRegistry;
2272+
private _annotationModel?: IAnnotationModel;
22432273
}
Lines changed: 22 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,22 +1,40 @@
1+
import { IAnnotationModel, IJGISFormSchemaRegistry } from '@jupytergis/schema';
12
import { ReactWidget } from '@jupyterlab/apputils';
3+
import { IStateDB } from '@jupyterlab/statedb';
24
import * as React from 'react';
35

46
import { MainView } from './mainView';
57
import { MainViewModel } from './mainviewmodel';
68

9+
export interface IOptions {
10+
mainViewModel: MainViewModel;
11+
state?: IStateDB;
12+
formSchemaRegistry?: IJGISFormSchemaRegistry;
13+
annotationModel?: IAnnotationModel;
14+
}
15+
716
export class JupyterGISMainViewPanel extends ReactWidget {
817
/**
918
* Construct a `JupyterGISPanel`.
1019
*/
11-
constructor(options: { mainViewModel: MainViewModel }) {
20+
constructor(options: IOptions) {
1221
super();
13-
this._mainViewModel = options.mainViewModel;
22+
this._state = options.state;
1423
this.addClass('jp-jupytergis-panel');
24+
this._options = options;
1525
}
1626

1727
render(): JSX.Element {
18-
return <MainView viewModel={this._mainViewModel} />;
28+
return (
29+
<MainView
30+
state={this._state}
31+
viewModel={this._options.mainViewModel}
32+
formSchemaRegistry={this._options.formSchemaRegistry}
33+
annotationModel={this._options.annotationModel}
34+
/>
35+
);
1936
}
2037

21-
private _mainViewModel: MainViewModel;
38+
private _state?: IStateDB;
39+
private _options: IOptions;
2240
}
Lines changed: 7 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -1,38 +1,28 @@
1-
import { IAnnotationModel } from '@jupytergis/schema';
2-
import { PanelWithToolbar, ReactWidget } from '@jupyterlab/ui-components';
1+
import { IAnnotationModel, IJupyterGISModel } from '@jupytergis/schema';
32
import React, { Component } from 'react';
43

54
import Annotation from '@/src/annotations/components/Annotation';
6-
import { IControlPanelModel } from '@/src/types';
75

86
interface IAnnotationPanelProps {
97
annotationModel: IAnnotationModel;
10-
rightPanelModel: IControlPanelModel;
8+
rightPanelModel: IJupyterGISModel;
119
}
1210

1311
export class AnnotationsPanel extends Component<IAnnotationPanelProps> {
1412
constructor(props: IAnnotationPanelProps) {
1513
super(props);
1614

15+
console.log(props.annotationModel);
16+
1717
const updateCallback = () => {
1818
this.forceUpdate();
1919
};
2020

2121
this._annotationModel = props.annotationModel;
2222
this._rightPanelModel = props.rightPanelModel;
2323

24-
this._annotationModel.modelChanged.connect(async () => {
25-
// await this._annotationModel?.context?.ready;
26-
27-
this._annotationModel?.model?.sharedMetadataChanged.disconnect(
28-
updateCallback,
29-
);
30-
this._annotationModel = props.annotationModel;
31-
this._annotationModel?.model?.sharedMetadataChanged.connect(
32-
updateCallback,
33-
);
34-
this.forceUpdate();
35-
});
24+
this._annotationModel?.model?.sharedMetadataChanged.connect(updateCallback);
25+
this.forceUpdate();
3626
}
3727

3828
render(): JSX.Element {
@@ -59,37 +49,5 @@ export class AnnotationsPanel extends Component<IAnnotationPanelProps> {
5949
}
6050

6151
private _annotationModel: IAnnotationModel;
62-
private _rightPanelModel: IControlPanelModel;
63-
}
64-
65-
export class Annotations extends PanelWithToolbar {
66-
constructor(options: Annotations.IOptions) {
67-
super({});
68-
69-
this.title.label = 'Annotations';
70-
this.addClass('jgis-scrollable');
71-
72-
this._annotationModel = options.annotationModel;
73-
this._rightPanelModel = options.rightPanelModel;
74-
75-
this._widget = ReactWidget.create(
76-
<AnnotationsPanel
77-
rightPanelModel={this._rightPanelModel}
78-
annotationModel={this._annotationModel}
79-
/>,
80-
);
81-
82-
this.addWidget(this._widget);
83-
}
84-
85-
private _widget: ReactWidget;
86-
private _annotationModel: IAnnotationModel;
87-
private _rightPanelModel: IControlPanelModel;
88-
}
89-
90-
export namespace Annotations {
91-
export interface IOptions {
92-
annotationModel: IAnnotationModel;
93-
rightPanelModel: IControlPanelModel;
94-
}
52+
private _rightPanelModel: IJupyterGISModel;
9553
}

0 commit comments

Comments
 (0)