Skip to content

Commit d665532

Browse files
authored
Turn into class component and hook kernelspy (#382)
If we want to have the kernelspy handler to control the papyri browser from the outside, we need to turn the functional component into a class one for access the methods instead of having closures. -- Create component ref and hook into the kernelspy. This using the IPython extension and using `?` on an existing object, it should pop out the right docstring. %load_ext papyri import numpy as np np.einsum?
2 parents f6c56a3 + fdbb53f commit d665532

File tree

2 files changed

+102
-64
lines changed

2 files changed

+102
-64
lines changed

papyri-lab/src/index.tsx

+2-1
Original file line numberDiff line numberDiff line change
@@ -86,9 +86,10 @@ const plugin: JupyterFrontEndPlugin<void> = {
8686
}
8787

8888
const kernelSpy = new KernelSpyModel(notebookTracker);
89-
kernelSpy.questionMarkSubmitted.connect((_, args) => {
89+
kernelSpy.questionMarkSubmitted.connect((_, args: any) => {
9090
console.info('KSpy questionMarkSubmitted args:', args);
9191
if (args !== undefined) {
92+
widget.content.updateSeachTerm(args.qualname);
9293
console.info('DO your thing here.');
9394
}
9495
});

papyri-lab/src/widgets.tsx

+100-63
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ import { requestAPI } from './handler';
22
import { MyPapyri, RENDERERS, SearchContext } from './papyri-comp';
33
import { ReactWidget } from '@jupyterlab/apputils';
44
import { ThemeProvider } from '@myst-theme/providers';
5-
import React, { useState } from 'react';
5+
import React from 'react';
66

77
// this is a papyri react component that in the end should
88
// have navigation UI and a myst renderer to display the
@@ -14,33 +14,57 @@ import React, { useState } from 'react';
1414
//
1515
// I'm going to guess it will need some configuration hook for when we click on links.
1616
//
17-
const PapyriComponent = (): JSX.Element => {
18-
// list of a few pages in the database that matches
19-
// the current query
20-
const [possibilities, setPossibilities] = useState([]);
21-
const [navs, setNavs] = useState<string[]>([]);
22-
const [root, setRoot] = useState({});
17+
//
18+
class PapyriComponent extends React.Component {
19+
state = {
20+
possibilities: [],
21+
navs: [],
22+
root: {},
23+
searchterm: ''
24+
};
25+
constructor(props: any) {
26+
super(props);
27+
this.state = {
28+
possibilities: [],
29+
navs: [],
30+
root: {},
31+
searchterm: ''
32+
};
33+
}
2334

24-
const [searchTerm, setSearchTerm] = useState('');
35+
setPossibilities(pos: any) {
36+
this.setState({ possibilities: pos });
37+
}
2538

26-
// callback when typing in the input field.
27-
const onChange = async (event: any) => {
28-
setSearchTerm(event.target.value);
29-
search(event.target.value);
30-
};
39+
setNavs(navs: any) {
40+
this.setState({ navs: navs });
41+
}
3142

32-
const back = async () => {
33-
navs.pop();
34-
const pen = navs.pop();
43+
setRoot(root: any) {
44+
this.setState({ root: root });
45+
}
46+
47+
setSearchTerm(searchterm: string) {
48+
this.setState({ searchterm: searchterm });
49+
}
50+
51+
async handleInputChange(event: any) {
52+
console.log('on change, this is', this);
53+
this.setSearchTerm(event.target.value);
54+
this.search(event.target.value);
55+
}
56+
57+
async back() {
58+
this.state.navs.pop();
59+
const pen = this.state.navs.pop();
3560
if (pen !== undefined) {
3661
console.log('Setting search term', pen);
37-
await setSearchTerm(pen);
62+
await this.setSearchTerm(pen);
3863
console.log('... and searchg for ', pen);
39-
await search(pen);
64+
await this.search(pen);
4065
}
41-
};
42-
43-
const search = async (query: string) => {
66+
}
67+
async search(query: string) {
4468
const res = await requestAPI<any>('get-example', {
4569
body: query,
4670
method: 'post'
@@ -49,69 +73,82 @@ const PapyriComponent = (): JSX.Element => {
4973
// response has body (MyST–json if the query has an exact match)
5074
// and data if we have some close matches.
5175
if (res.body !== null) {
52-
setNavs([...navs, query]);
53-
setRoot(res.body);
54-
setPossibilities([]);
76+
this.setNavs([...this.state.navs, query]);
77+
this.setRoot(res.body);
78+
this.setPossibilities([]);
5579
} else {
56-
setRoot({});
57-
setPossibilities(res.data);
80+
this.setRoot({});
81+
this.setPossibilities(res.data);
5882
}
59-
};
83+
}
84+
85+
async onClick(query: string) {
86+
console.log('On click trigger', query, 'this is', this);
6087

61-
const onClick = async (query: string) => {
62-
console.log('On click trigger', query);
63-
setSearchTerm(query);
88+
this.setSearchTerm(query);
6489
try {
65-
search(query);
90+
this.search(query);
6691
} catch (e) {
6792
console.error(e);
6893
}
6994
return false;
70-
};
95+
}
7196

72-
return (
73-
<React.StrictMode>
74-
<input onChange={onChange} value={searchTerm} />
75-
<button onClick={back}>Back</button>
76-
<ul>
77-
{possibilities.map(e => {
78-
return (
79-
<li>
80-
<a
81-
href={e}
82-
onClick={async () => {
83-
await onClick(e);
84-
}}
85-
>
86-
{e}
87-
</a>
88-
</li>
89-
);
90-
})}
91-
</ul>
92-
<div className="view">
93-
<SearchContext.Provider value={onClick}>
94-
<ThemeProvider renderers={RENDERERS}>
95-
<MyPapyri node={root} />
96-
</ThemeProvider>
97-
</SearchContext.Provider>
98-
</div>
99-
</React.StrictMode>
100-
);
101-
};
97+
render(): JSX.Element {
98+
return (
99+
<React.StrictMode>
100+
<input
101+
onChange={this.handleInputChange.bind(this)}
102+
value={this.state.searchterm}
103+
/>
104+
<button onClick={this.back}>Back</button>
105+
<ul>
106+
{this.state.possibilities.map((e: any) => {
107+
return (
108+
<li>
109+
<a
110+
href={e}
111+
onClick={async () => {
112+
await this.onClick(e);
113+
}}
114+
>
115+
{e}
116+
</a>
117+
</li>
118+
);
119+
})}
120+
</ul>
121+
<div className="view">
122+
<SearchContext.Provider value={this.onClick.bind(this)}>
123+
<ThemeProvider renderers={RENDERERS}>
124+
<MyPapyri node={this.state.root} />
125+
</ThemeProvider>
126+
</SearchContext.Provider>
127+
</div>
128+
</React.StrictMode>
129+
);
130+
}
131+
}
102132

103133
// This seem to be the way to have an adapter between lumino and react, and
104134
// allow to render react inside a JupyterLab panel
105135
export class PapyriPanel extends ReactWidget {
136+
comp: any;
106137
constructor() {
107138
super();
108139
this.addClass('jp-ReactWidget');
109140
this.id = 'papyri-browser';
110141
this.title.label = 'Papyri browser';
111142
this.title.closable = true;
143+
this.comp = React.createRef();
144+
}
145+
146+
updateSeachTerm(str: string) {
147+
this.comp.current.setSearchTerm(str);
148+
this.comp.current.search(str);
112149
}
113150

114151
render(): JSX.Element {
115-
return <PapyriComponent />;
152+
return <PapyriComponent ref={this.comp} />;
116153
}
117154
}

0 commit comments

Comments
 (0)