Skip to content

Commit 30094a7

Browse files
committed
#2922 - error handling is moved to ketcher-react
1 parent e5729a3 commit 30094a7

File tree

2 files changed

+125
-106
lines changed

2 files changed

+125
-106
lines changed

example/src/App.tsx

+1-16
Original file line numberDiff line numberDiff line change
@@ -50,8 +50,7 @@ if (enablePolymerEditor) {
5050

5151
const App = () => {
5252
const hiddenButtonsConfig = getHiddenButtonsConfig();
53-
const [hasError, setHasError] = useState(false);
54-
const [errorMessage, setErrorMessage] = useState('');
53+
const [, setErrorMessage] = useState('');
5554
const [showPolymerEditor, setShowPolymerEditor] = useState(false);
5655

5756
const togglePolymerEditor = (toggleValue: boolean) => {
@@ -74,7 +73,6 @@ const App = () => {
7473
<>
7574
<Editor
7675
errorHandler={(message: string) => {
77-
setHasError(true);
7876
setErrorMessage(message.toString());
7977
}}
8078
buttons={hiddenButtonsConfig}
@@ -92,19 +90,6 @@ const App = () => {
9290
}}
9391
togglerComponent={togglerComponent}
9492
/>
95-
{hasError && (
96-
<InfoModal
97-
message={errorMessage}
98-
close={() => {
99-
setHasError(false);
100-
101-
// Focus on editor after modal is closed
102-
const cliparea: HTMLElement | null =
103-
document.querySelector('.cliparea');
104-
cliparea?.focus();
105-
}}
106-
/>
107-
)}
10893
</>
10994
);
11095
};

packages/ketcher-react/src/script/ui/views/components/StructEditor/StructEditor.jsx

+124-90
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,8 @@ class StructEditor extends Component {
7474
constructor(props) {
7575
super(props);
7676
this.state = {
77+
hasError: false,
78+
errorMessage: '',
7779
enableCursor: false,
7880
clientX: 0,
7981
clientY: 0,
@@ -148,117 +150,149 @@ class StructEditor extends Component {
148150
}
149151

150152
componentDidMount() {
151-
this.editor = new Editor(this.editorRef.current, {
152-
...this.props.options,
153-
});
154-
const ketcher = ketcherProvider.getKetcher();
155-
if (ketcher?.editor.macromoleculeConvertionError) {
156-
this.props.onShowMacromoleculesErrorMessage(
157-
ketcher.editor.macromoleculeConvertionError,
158-
);
159-
ketcher.editor.clearMacromoleculeConvertionError();
160-
}
161-
setupEditor(this.editor, this.props);
162-
if (this.props.onInit) this.props.onInit(this.editor);
163-
164-
this.editor.event.message.add((msg) => {
165-
const el = this.logRef.current;
166-
if (msg.info && this.props.showAttachmentPoints) {
167-
try {
168-
const parsedInfo = JSON.parse(msg.info);
169-
el.innerHTML = `Atom Id: ${parsedInfo.atomid}, Bond Id: ${parsedInfo.bondid}`;
170-
} catch (e) {
171-
KetcherLogger.error(
172-
'StructEditor.jsx::StructEditor::componentDidMount',
173-
e,
174-
);
175-
el.innerHTML = msg.info;
176-
}
177-
el.classList.add(classes.visible);
178-
} else {
179-
el.classList.remove(classes.visible);
153+
try {
154+
this.editor = new Editor(this.editorRef.current, {
155+
...this.props.options,
156+
});
157+
const ketcher = ketcherProvider.getKetcher();
158+
if (ketcher?.editor.macromoleculeConvertionError) {
159+
this.props.onShowMacromoleculesErrorMessage(
160+
ketcher.editor.macromoleculeConvertionError,
161+
);
162+
ketcher.editor.clearMacromoleculeConvertionError();
180163
}
181-
});
182-
183-
this.editor.event.cursor.add((csr) => {
184-
let clientX, clientY;
185-
186-
switch (csr.status) {
187-
case 'enable': {
188-
this.editorRef.current.classList.add(classes.enableCursor);
189-
const { left, top, right, bottom } =
190-
this.editorRef.current.getBoundingClientRect();
191-
192-
clientX = csr.cursorPosition.clientX;
193-
clientY = csr.cursorPosition.clientY;
194-
195-
const handShouldBeShown =
196-
clientX >= left &&
197-
clientX <= right &&
198-
clientY >= top &&
199-
clientX <= bottom;
200-
if (!this.state.enableCursor && handShouldBeShown) {
164+
setupEditor(this.editor, this.props);
165+
if (this.props.onInit) this.props.onInit(this.editor);
166+
167+
this.editor.event.message.add((msg) => {
168+
const el = this.logRef.current;
169+
if (msg.info && this.props.showAttachmentPoints) {
170+
try {
171+
const parsedInfo = JSON.parse(msg.info);
172+
el.innerHTML = `Atom Id: ${parsedInfo.atomid}, Bond Id: ${parsedInfo.bondid}`;
173+
} catch (e) {
174+
KetcherLogger.error(
175+
'StructEditor.jsx::StructEditor::componentDidMount',
176+
e,
177+
);
178+
el.innerHTML = msg.info;
179+
}
180+
el.classList.add(classes.visible);
181+
} else {
182+
el.classList.remove(classes.visible);
183+
}
184+
});
185+
186+
this.editor.event.cursor.add((csr) => {
187+
let clientX, clientY;
188+
189+
switch (csr.status) {
190+
case 'enable': {
191+
this.editorRef.current.classList.add(classes.enableCursor);
192+
const { left, top, right, bottom } =
193+
this.editorRef.current.getBoundingClientRect();
194+
195+
clientX = csr.cursorPosition.clientX;
196+
clientY = csr.cursorPosition.clientY;
197+
198+
const handShouldBeShown =
199+
clientX >= left &&
200+
clientX <= right &&
201+
clientY >= top &&
202+
clientX <= bottom;
203+
if (!this.state.enableCursor && handShouldBeShown) {
204+
this.setState({
205+
enableCursor: true,
206+
});
207+
}
208+
break;
209+
}
210+
211+
case 'move': {
212+
this.editorRef.current.classList.add(classes.enableCursor);
201213
this.setState({
202214
enableCursor: true,
215+
clientX,
216+
clientY,
203217
});
218+
break;
204219
}
205-
break;
206-
}
207220

208-
case 'move': {
209-
this.editorRef.current.classList.add(classes.enableCursor);
210-
this.setState({
211-
enableCursor: true,
212-
clientX,
213-
clientY,
214-
});
215-
break;
216-
}
221+
case 'disable': {
222+
this.editorRef.current.classList.remove(classes.enableCursor);
223+
this.setState({
224+
enableCursor: false,
225+
});
226+
break;
227+
}
217228

218-
case 'disable': {
219-
this.editorRef.current.classList.remove(classes.enableCursor);
220-
this.setState({
221-
enableCursor: false,
222-
});
223-
break;
224-
}
229+
case 'leave': {
230+
this.editorRef.current.classList.remove(classes.enableCursor);
231+
this.setState({
232+
enableCursor: false,
233+
});
234+
break;
235+
}
225236

226-
case 'leave': {
227-
this.editorRef.current.classList.remove(classes.enableCursor);
228-
this.setState({
229-
enableCursor: false,
230-
});
231-
break;
232-
}
237+
case 'mouseover': {
238+
this.editorRef.current.classList.add(classes.enableCursor);
239+
this.setState({
240+
enableCursor: true,
241+
});
242+
break;
243+
}
233244

234-
case 'mouseover': {
235-
this.editorRef.current.classList.add(classes.enableCursor);
236-
this.setState({
237-
enableCursor: true,
238-
});
239-
break;
245+
default:
246+
break;
240247
}
248+
});
241249

242-
default:
243-
break;
244-
}
245-
});
246-
247-
this.editor.event.message.dispatch({
248-
info: JSON.stringify(this.props.toolOpts),
249-
});
250+
this.editor.event.message.dispatch({
251+
info: JSON.stringify(this.props.toolOpts),
252+
});
250253

251-
this.editorRef.current.addEventListener('wheel', this.handleWheel);
252-
this.editor.render.observeCanvasResize();
254+
this.editorRef.current.addEventListener('wheel', this.handleWheel);
255+
this.editor.render.observeCanvasResize();
256+
window.addEventListener('error', this.globalErrorHandler);
257+
} catch (error) {
258+
this.setState({ hasError: true, errorMessage: error.message });
259+
}
253260
}
254261

255262
componentWillUnmount() {
256263
removeEditorHandlers(this.editor, this.props);
257264
this.editorRef.current.removeEventListener('wheel', this.handleWheel);
258265
this.editor.render.unobserveCanvasResize();
266+
window.removeEventListener('error', this.globalErrorHandler);
259267
}
260268

269+
globalErrorHandler = (errorEvent) => {
270+
const error = errorEvent.error;
271+
const message =
272+
error && error.message
273+
? 'An error occurred: ' + error.message
274+
: 'Something went wrong. The error is on our side. Please try again later.';
275+
this.setState({ hasError: true, errorMessage: message });
276+
};
277+
278+
handleDismiss = () => {
279+
this.setState({ hasError: false, errorMessage: '' });
280+
const cliparea = document.querySelector('.cliparea');
281+
if (cliparea) {
282+
cliparea.focus();
283+
}
284+
};
285+
261286
render() {
287+
if (this.state.hasError) {
288+
return (
289+
<InfoModal
290+
message={this.state.errorMessage}
291+
close={this.handleDismiss}
292+
/>
293+
);
294+
}
295+
262296
const {
263297
Tag = 'div',
264298
className,

0 commit comments

Comments
 (0)