Skip to content

Commit

Permalink
feat: Handle remote editor load failure (#27)
Browse files Browse the repository at this point in the history
* feat: Handle remote editor load failure

Empower the user to continue editing with the default, local editor
capable of editing core blocks and notify them of the load failure.

* feat: Allow retrying remote editor load

Empower users to resolve issues themselves.

* feat: Update editor load notice message

Increase the utility of the message.

* refactor: Reduce `useEditorLoadNotice` API surface area

Simplify hook usage.

* task: Capture build results

* task: Capture build output
  • Loading branch information
dcalhoun authored Oct 21, 2024
1 parent a58a46f commit 849118a
Show file tree
Hide file tree
Showing 15 changed files with 143 additions and 57 deletions.

This file was deleted.

8 changes: 7 additions & 1 deletion ReactApp/src/App.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,15 @@
* Internal dependencies
*/
import Editor from './components/Editor';
import EditorLoadNotice from './components/EditorLoadNotice';

function App(props) {
return <Editor {...props} />;
return (
<>
<EditorLoadNotice />
<Editor {...props} />
</>
);
}

export default App;
70 changes: 70 additions & 0 deletions ReactApp/src/components/EditorLoadNotice.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
/**
* WordPress dependencies
*/
import { Notice } from '@wordpress/components';
import { __ } from '@wordpress/i18n';
import { useState, useEffect } from '@wordpress/element';

export default function EditorLoadNotice() {
const { notice, clearNotice } = useEditorLoadNotice();

const actions = [
{
label: 'Retry',
onClick: () => (window.location.href = 'remote.html'),
variant: 'primary',
},
{
label: 'Dismiss',
onClick: clearNotice,
variant: 'secondary',
},
];

if (!notice) {
return null;
}

return (
<div className="editor-load-notice">
<Notice actions={actions} status="warning" isDismissible={false}>
{notice}
</Notice>
</div>
);
}

function useEditorLoadNotice() {
const [notice, setNotice] = useState(null);

useEffect(() => {
const url = new URL(window.location.href);
const error = url.searchParams.get('error');

let message = null;
switch (error) {
case REMOTE_EDITOR_LOAD_ERROR:
message = __(
"Oops! We couldn't load your site's editor and plugins. Don't worry, you can use the default editor for now."
);
break;
default:
message = null;
}

setNotice(message);
}, []);

useEffect(() => {
if (notice) {
const timeout = setTimeout(() => {
setNotice(null);
}, 20000);
return () => clearTimeout(timeout);
}
}, [notice]);

return { notice, clearNotice: () => setNotice(null) };
}

const REMOTE_EDITOR_LOAD_ERROR = 'remote_editor_load_error';
8 changes: 8 additions & 0 deletions ReactApp/src/index.css
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,14 @@ h4 {
display: none;
}

.editor-load-notice {
position: fixed;
bottom: 62px;
left: 16px;
right: 16px;
z-index: 999;
}

/* Toolbar */

.gbkit-editor-toolbar {
Expand Down
5 changes: 4 additions & 1 deletion ReactApp/src/remote.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,10 @@ async function initalizeRemoteEditor() {
createElement(StrictMode, null, createElement(App, settings))
);
} catch (error) {
console.error('Error initializing the remote editor', error);
// Fallback to the local editor and display a notice. Because the remote
// editor loading failed, it is more practical to rely upon the local
// editor's scripts and styles for displaying the notice.
window.location.href = 'index.html?error=remote_editor_load_error';
}
}

Expand Down
1 change: 0 additions & 1 deletion Sources/GutenbergKit/Gutenberg/assets/App-C-YJyckR.js

This file was deleted.

Loading

0 comments on commit 849118a

Please sign in to comment.