Skip to content

Commit bc377c2

Browse files
authored
Add StateDB to save UI state (#103)
1 parent bc8600d commit bc377c2

File tree

3 files changed

+41
-8
lines changed

3 files changed

+41
-8
lines changed

packages/base/src/panelview/components/layers.tsx

Lines changed: 24 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import {
55
IJupyterGISModel
66
} from '@jupytergis/schema';
77
import { DOMUtils } from '@jupyterlab/apputils';
8+
import { IStateDB } from '@jupyterlab/statedb';
89
import {
910
Button,
1011
LabIcon,
@@ -20,7 +21,7 @@ import React, {
2021
import { icons } from '../../constants';
2122
import { nonVisibilityIcon, visibilityIcon } from '../../icons';
2223
import { IControlPanelModel } from '../../types';
23-
import { ILeftPanelClickHandlerParams, ILeftPanelOptions } from '../leftpanel';
24+
import { ILayerPanelOptions, ILeftPanelClickHandlerParams } from '../leftpanel';
2425

2526
const LAYERS_PANEL_CLASS = 'jp-gis-layerPanel';
2627
const LAYER_GROUP_CLASS = 'jp-gis-layerGroup';
@@ -36,10 +37,11 @@ const LAYER_TEXT_CLASS = 'jp-gis-layerText';
3637
* The layers panel widget.
3738
*/
3839
export class LayersPanel extends Panel {
39-
constructor(options: ILeftPanelOptions) {
40+
constructor(options: ILayerPanelOptions) {
4041
super();
4142
this._model = options.model;
4243
this._onSelect = options.onSelect;
44+
this._state = options.state;
4345

4446
this.id = 'jupytergis::layerTree';
4547
this.addClass(LAYERS_PANEL_CLASS);
@@ -49,6 +51,7 @@ export class LayersPanel extends Panel {
4951
<LayersBodyComponent
5052
model={this._model}
5153
onSelect={this._onSelect}
54+
state={this._state}
5255
></LayersBodyComponent>
5356
)
5457
);
@@ -117,6 +120,7 @@ export class LayersPanel extends Panel {
117120
};
118121

119122
private _model: IControlPanelModel | undefined;
123+
private _state: IStateDB;
120124
private _onSelect: ({
121125
type,
122126
item,
@@ -129,6 +133,7 @@ export class LayersPanel extends Panel {
129133
*/
130134
interface IBodyProps {
131135
model: IControlPanelModel;
136+
state: IStateDB;
132137
onSelect: ({ type, item, nodeId }: ILeftPanelClickHandlerParams) => void;
133138
}
134139

@@ -196,6 +201,7 @@ function LayersBodyComponent(props: IBodyProps): JSX.Element {
196201
gisModel={model}
197202
group={layer}
198203
onClick={onItemClick}
204+
state={props.state}
199205
/>
200206
)
201207
)}
@@ -209,14 +215,15 @@ function LayersBodyComponent(props: IBodyProps): JSX.Element {
209215
interface ILayerGroupProps {
210216
gisModel: IJupyterGISModel | undefined;
211217
group: IJGISLayerGroup | undefined;
218+
state: IStateDB;
212219
onClick: ({ type, item, nodeId }: ILeftPanelClickHandlerParams) => void;
213220
}
214221

215222
/**
216223
* The component to handle group of layers.
217224
*/
218225
function LayerGroupComponent(props: ILayerGroupProps): JSX.Element {
219-
const { group, gisModel, onClick } = props;
226+
const { group, gisModel, onClick, state } = props;
220227

221228
if (group === undefined) {
222229
return <></>;
@@ -233,6 +240,13 @@ function LayerGroupComponent(props: ILayerGroupProps): JSX.Element {
233240

234241
useEffect(() => {
235242
setId(DOMUtils.createDomID());
243+
244+
const getExpandedState = async () => {
245+
const groupState = await state.fetch(group.name);
246+
setOpen(groupState ? groupState['expanded'] : false);
247+
};
248+
249+
getExpandedState();
236250
}, []);
237251

238252
/**
@@ -255,6 +269,11 @@ function LayerGroupComponent(props: ILayerGroupProps): JSX.Element {
255269
onClick({ type: 'group', item: name, nodeId: childId, event });
256270
};
257271

272+
const handleExpand = async () => {
273+
state.save(group.name, { expanded: !open });
274+
setOpen(!open);
275+
};
276+
258277
return (
259278
<div
260279
className={`${LAYER_ITEM_CLASS} ${LAYER_GROUP_CLASS}`}
@@ -264,7 +283,7 @@ function LayerGroupComponent(props: ILayerGroupProps): JSX.Element {
264283
data-id={name}
265284
>
266285
<div
267-
onClick={() => setOpen(!open)}
286+
onClick={handleExpand}
268287
onContextMenu={handleRightClick}
269288
className={`${LAYER_GROUP_HEADER_CLASS} ${selected ? ' jp-mod-selected' : ''}`}
270289
onDragOver={Private.onDragOver}
@@ -298,6 +317,7 @@ function LayerGroupComponent(props: ILayerGroupProps): JSX.Element {
298317
gisModel={gisModel}
299318
group={layer}
300319
onClick={onClick}
320+
state={props.state}
301321
/>
302322
)
303323
)}

packages/base/src/panelview/leftpanel.tsx

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import {
44
JupyterGISDoc,
55
SelectionType
66
} from '@jupytergis/schema';
7+
import { IStateDB } from '@jupyterlab/statedb';
78
import { SidePanel } from '@jupyterlab/ui-components';
89
import { Message } from '@lumino/messaging';
910
import { MouseEvent as ReactMouseEvent } from 'react';
@@ -20,6 +21,10 @@ export interface ILeftPanelOptions {
2021
onSelect: ({ type, item, nodeId }: ILeftPanelClickHandlerParams) => void;
2122
}
2223

24+
export interface ILayerPanelOptions extends ILeftPanelOptions {
25+
state: IStateDB;
26+
}
27+
2328
export interface ILeftPanelClickHandlerParams {
2429
type: SelectionType;
2530
item: string;
@@ -32,6 +37,8 @@ export class LeftPanelWidget extends SidePanel {
3237
super();
3338
this.addClass('jGIS-sidepanel-widget');
3439
this._model = options.model;
40+
this._state = options.state;
41+
3542
const header = new ControlPanelHeader();
3643
this.header.addWidget(header);
3744

@@ -45,6 +52,7 @@ export class LeftPanelWidget extends SidePanel {
4552

4653
const layerTree = new LayersPanel({
4754
model: this._model,
55+
state: this._state,
4856
onSelect: this._onSelect
4957
});
5058
layerTree.title.caption = 'Layer tree';
@@ -176,12 +184,14 @@ export class LeftPanelWidget extends SidePanel {
176184

177185
private _lastSelectedNodeId: string;
178186
private _model: IControlPanelModel;
187+
private _state: IStateDB;
179188
}
180189

181190
export namespace LeftPanelWidget {
182191
export interface IOptions {
183192
model: IControlPanelModel;
184193
tracker: IJupyterGISTracker;
194+
state: IStateDB;
185195
}
186196

187197
export interface IProps {

python/jupytergis_lab/src/index.ts

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -23,8 +23,8 @@ import {
2323
} from '@jupyterlab/application';
2424
import { WidgetTracker } from '@jupyterlab/apputils';
2525
import { IMainMenu } from '@jupyterlab/mainmenu';
26+
import { IStateDB } from '@jupyterlab/statedb';
2627
import { ITranslator, nullTranslator } from '@jupyterlab/translation';
27-
2828
import { ContextMenu, Menu } from '@lumino/widgets';
2929
import { notebookRenderePlugin } from './notebookrenderer';
3030

@@ -260,19 +260,22 @@ const controlPanel: JupyterFrontEndPlugin<void> = {
260260
requires: [
261261
ILayoutRestorer,
262262
IJupyterGISDocTracker,
263-
IJGISFormSchemaRegistryToken
263+
IJGISFormSchemaRegistryToken,
264+
IStateDB
264265
],
265266
activate: (
266267
app: JupyterFrontEnd,
267268
restorer: ILayoutRestorer,
268269
tracker: IJupyterGISTracker,
269-
formSchemaRegistry: IJGISFormSchemaRegistry
270+
formSchemaRegistry: IJGISFormSchemaRegistry,
271+
state: IStateDB
270272
) => {
271273
const controlModel = new ControlPanelModel({ tracker });
272274

273275
const leftControlPanel = new LeftPanelWidget({
274276
model: controlModel,
275-
tracker
277+
tracker,
278+
state
276279
});
277280
leftControlPanel.id = 'jupytergis::leftControlPanel';
278281
leftControlPanel.title.caption = 'JupyterGIS Control Panel';

0 commit comments

Comments
 (0)