Skip to content

Commit

Permalink
Merge pull request #178 from ckeditor/i/118
Browse files Browse the repository at this point in the history
Feature: The `<CKEditor>` component contains the built-in [watchdog](https://ckeditor.com/docs/ckeditor5/latest/features/watchdog.html) feature. Closes #118. 

Feature: Introduced the `<CKEditorContext>` component that supports the [context](https://ckeditor.com/docs/ckeditor5/latest/features/collaboration/context-and-collaboration-features.html) feature.

Feature: Added the `id` property which is used to distinguish different documents. When this property changes, the component restarts the underlying editor instead of setting data on it, which allows e.g. for switching between collaboration documents and fixes a couple of issues (e.g. the `onChange` event no longer fires during changing the document). Closes #168. Closes #169.

Feature: The `onError()` callback will be called with two arguments. The first one will be an error object (as it was before the release 3+). A second argument is an object that contains two properties:

  * `{String} phase`: `'initialization'|'runtime'` - Informs when the error has occurred (during the editor/context initialization or after the initialization).
  * `{Boolean} willEditorRestart` - When `true`, it means that the editor component will restart itself.
  * `{Boolean} willContextRestart`- When `true`, it means that the context component will restart itself.

    The `willEditorRestart` property will not appear when the error has occurred in the context feature. 
    The `willContextRestart` property will not appear when the error has occurred in the editor.

---

* _Add to the release summary:_ Both components (`<CKEditor>` and `<CKEditorContext>`) will internally use the [`Watchdog`](https://ckeditor.com/docs/ckeditor5/latest/api/module_watchdog_watchdog-Watchdog.html) class that restarts the [editor](https://ckeditor.com/docs/ckeditor5/latest/api/module_watchdog_editorwatchdog-EditorWatchdog.html) or [context](https://ckeditor.com/docs/ckeditor5/latest/api/module_watchdog_contextwatchdog-ContextWatchdog.html) when an error occurs.

* _Add to the release summary:_ The API of the entry point of the package has changed.

The previous way how the package was imported:

```js
import CKEditor from '@ckeditor/ckeditor5-react';
```

will not work with the release (3+). Use:

```js
import { CKEditor } from '@ckeditor/ckeditor5-react';
```

---

BREAKING CHANGE: The [entry point](https://github.com/ckeditor/ckeditor5-react/blob/master/src/index.js) of the package has changed. The default import was removed since the package provides more than a single component now. Use `import { CKEditor } from '@ckeditor/ckeditor5-react'` instead of `import CKEditor from '@ckeditor/ckeditor5-react';`.

BREAKING CHANGE: The `onInit` property was renamed to `onReady` and can be called multiple times (after the initialization and after the component is ready when an error occurred).
  • Loading branch information
pomek authored Sep 18, 2020
2 parents cabddc9 + a5a3a87 commit ac0ff10
Show file tree
Hide file tree
Showing 16 changed files with 1,044 additions and 278 deletions.
2 changes: 2 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,8 @@
"@ckeditor/ckeditor5-build-classic": "^20.0.0",
"@ckeditor/ckeditor5-dev-env": "^23.0.0",
"@ckeditor/ckeditor5-dev-utils": "^23.0.0",
"@ckeditor/ckeditor5-utils": "^22.0.0",
"@ckeditor/ckeditor5-watchdog": "^22.0.0",
"babel-eslint": "^10.1.0",
"babel-loader": "^8.1.0",
"chai": "^4.2.0",
Expand Down
159 changes: 112 additions & 47 deletions sample/index.html
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
<!DOCTYPE html>
<html lang="en">

<head>
<meta charset="utf-8">
<title>CKEditor 5 – React Component – development sample</title>
Expand All @@ -12,19 +13,112 @@
.button_read-only {
margin: 10px 0;
}

</style>
</head>

<body>
<h1>CKEditor 5 – React Component – development sample</h1>
<p style="text-align: center;">Component's events are logged to the console.</p>
<button id="readOnly" class="button_read-only" disabled>Switch to read-only mode</button>
<div id="root"></div>
<script src="../node_modules/react/umd/react.production.min.js"></script>
<script src="../node_modules/react-dom/umd/react-dom.production.min.js"></script>
<script src="../node_modules/@ckeditor/ckeditor5-build-classic/build/ckeditor.js"></script>
<script src="../dist/ckeditor.js"></script>
<script>
document.addEventListener( 'DOMContentLoaded', () => {
<h1>CKEditor 5 – React Component – development sample</h1>
<p style="text-align: center;">Component's events are logged to the console.</p>
<button id="readOnly" class="button_read-only" disabled>Switch to read-only mode</button>
<button id="simulateError" class="button_read-only" disabled>Simulate an error</button>
<button id="previousDocumentID" class="button_read-only" disabled>Previous document id</button>
<button id="nextDocumentID" class="button_read-only">Next document id</button>
<div id="root"></div>
<script src="../node_modules/react/umd/react.production.min.js"></script>
<script src="../node_modules/react-dom/umd/react-dom.production.min.js"></script>
<script src="../node_modules/@ckeditor/ckeditor5-build-classic/build/ckeditor.js"></script>
<script src="../dist/ckeditor.js"></script>
<script>
// TODO: Move buttons to the App component.
const nextDocumentIDButton = document.getElementById( 'nextDocumentID' );
const previousDocumentIDButton = document.getElementById( 'previousDocumentID' );
const readOnlyButton = document.getElementById( 'readOnly' );
const simulateErrorButton = document.getElementById( 'simulateError' );

class App extends React.Component {
constructor( props ) {
super( props );

this.state = { documents: [ editorContent ], documentID: 0 }
}

render() {
return React.createElement( CKEditor.CKEditor, {
editor: ClassicEditor,
data: this.state.documents[ this.state.documentID ],
id: this.state.documentID,
onReady: editor => {
window.editor = editor;

console.log( 'event: onReady' );
console.log( 'Editor is ready to use! You can use "editor" variable to play with it.' );

readOnlyButton.disabled = false;
simulateErrorButton.disabled = false;
previousDocumentIDButton.disabled = this.state.documentID === 0

editor.ui.view.listenTo( simulateErrorButton, 'click', () => {
setTimeout( () => {
const err = new Error( 'foo' );
err.context = editor;
err.is = () => true;

throw err;
} );
} );

editor.ui.view.listenTo( nextDocumentIDButton, 'click', () => {
this.setState( {
documentID: this.state.documentID + 1,
documents: this.state.documents.length < this.state.documentID + 1 ?
this.state.documents :
[ ...this.state.documents, editorContent ]
} )
} );

editor.ui.view.listenTo( previousDocumentIDButton, 'click', () => {
this.setState( { documentID: Math.max( this.state.documentID - 1, 0 ) } )
} );

editor.ui.view.listenTo( readOnlyButton, 'click', () => {
editor.isReadOnly = !editor.isReadOnly;

if ( editor.isReadOnly ) {
this.innerText = 'Switch to editable mode';
} else {
this.innerText = 'Switch to read-only mode';
}
} );
},
onChange: ( event, editor ) => {
this.updateData();

console.log( 'event: onChange', { event, editor } );
},

onBlur: ( event, editor ) => {
console.log( 'event: onBlur', { event, editor } );
},
onFocus: ( event, editor ) => {
console.log( 'event: onFocus', { event, editor } );
}
} )
}

updateData() {
this.setState( {
documents: this.state.documents.map( ( data, index ) => {
if ( index === this.state.documentID ) {
return editor.getData();
}

return data;
} )
} );
}
}

const editorContent = `
<h2>Sample</h2>
<p>This is an instance of the <a href="https://ckeditor.com/docs/ckeditor5/latest/builds/guides/overview.html#classic-editor">classic editor build</a>.</p>
Expand All @@ -34,43 +128,14 @@ <h2>Sample</h2>
<p>You can use this sample to validate whether your <a href="https://ckeditor.com/docs/ckeditor5/latest/builds/guides/development/custom-builds.html">custom build</a> works fine.</p>
`;

ReactDOM.render(
React.createElement( CKEditor, {
editor: ClassicEditor,
data: editorContent,
onInit: editor => {
window.editor = editor;

console.log( 'event: onInit');
console.log( 'Editor is ready to use! You can use "editor" variable to play with it.' );

const readOnlyButton = document.getElementById( 'readOnly' );

readOnlyButton.disabled = false;

readOnlyButton.addEventListener( 'click', function() {
editor.isReadOnly = !editor.isReadOnly;

if ( editor.isReadOnly ) {
this.innerText = 'Switch to editable mode';
} else {
this.innerText = 'Switch to read-only mode';
}
} );
},
onChange: ( event, editor ) => {
console.log( 'event: onChange', { event, editor } );
},
onBlur: ( event, editor ) => {
console.log( 'event: onBlur', { event, editor } );
},
onFocus: ( event, editor ) => {
console.log( 'event: onFocus', { event, editor } );
}
} ),
document.getElementById( 'root' )
);
} );
</script>
document.addEventListener( 'DOMContentLoaded', () => {
ReactDOM.render(
React.createElement( App ),
document.getElementById( 'root' )
);
} );
</script>
</body>

</html>
Loading

0 comments on commit ac0ff10

Please sign in to comment.