- Issue created by @kevinquillen
- Assigned to matthieuscarset
Unassigning me from this issue.
I don't know enough about CKEditor API yet.
I was hoping it was a regularDrupal form and I would have made all improvements quickly.
I wish I had availability to learn a whole new API to recreate the forms we have in our Drupal modules in the JS plugin, but I have to step back and focus on something else.
- Issue was unassigned.
- First commit to issue fork.
- πΊπΈUnited States kevinquillen
A plugin can obtain other plugins in its constructor. Core ships with the CKEditor 5 "Notification" plugin, so:
constructor(editor, config) { super(editor); this._notification = this.editor.plugins.get( Notification ); // other code removed }
Then, in the plugin methods you can use that plugin:
if (!SomeCondition) { this._notification.showInfo('There was an error when connecting to OpenAI. Check the server logs for more details.', { namespace: 'openai:error', }); } else { // .... and so on
However, the Notification plugin in CKEditor only handles the storage of notifications. There is no UI component to show them, like a toast or flash message to the user. You have to bring your own library.
I tried using Drupals native Message Javascript API. You can trigger an event with the Notification plugin:. For example:
const notification = this._notification; notification.on( 'show:info:openai:error', ( e, data ) => { const messageId = this._messages.add(data.message, {type: 'error'}); setTimeout(() => { this._messages.remove(messageId); }, 6000, messageId); });
The result of that, when an error notification is detected, is:
This is kind of obtrusive and awkward - and it also requires themes to have the "Messages" block active. What I think would be nicer is appending HTML at the end of the editor frame and writing a status update there. Alternatively, a lightweight toast library that can put the messages within the CKEditor frame, just like the old CKEditor 4 notification plugin used to do: https://ckeditor.com/cke4/addon/notification
- πΊπΈUnited States kevinquillen
This is more where I would like it.
When complete:
I did this with a little bit of code to add a new template for textareas:
function openai_ckeditor_theme() { $theme['textarea_openai'] = [ 'base hook' => 'textarea', ]; return $theme; } /** * Implements hook_theme_suggestions_form_element_alter(). */ function openai_ckeditor_theme_suggestions_form_element_alter(array &$suggestions, array $variables, $hook) { if (isset($variables["element"]["#type"]) && $variables["element"]["#type"] === 'textarea') { // todo: How to tell if this form element is filter enabled with OpenAI plugin? $suggestions[] = 'textarea_openai'; } }
The twig template:
{# /** * @file * Theme override for a 'textarea' #type form element. * * Available variables * - wrapper_attributes: A list of HTML attributes for the wrapper element. * - attributes: A list of HTML attributes for the <textarea> element. * - resizable: An indicator for whether the textarea is resizable. * - required: An indicator for whether the textarea is required. * - value: The textarea content. * * @see template_preprocess_textarea() */ #} {% set classes = [ 'form-textarea', resizable ? 'resize-' ~ resizable, required ? 'required', 'form-element', 'form-element--type-textarea', 'form-element--api-textarea', ] %} <div{{ wrapper_attributes.addClass('form-textarea-wrapper') }}> <textarea{{ attributes.addClass(classes) }}>{{ value }}</textarea> <div id="openai-status"></div> </div>
Back in the plugin:
notification.on( 'show:info:openai:init', ( e, data ) => { // todo: can't we make this work with regular Javascript? // let container = document.getElementById('openai-status'); // const message = document.createTextNode(data.message); // container.appendChild(message); jQuery('div#openai-status').text(data.message); }); notification.on( 'show:info:openai:error', ( e, data ) => { // todo: can't we make this work with regular Javascript? // let container = document.getElementById('openai-status'); // const message = document.createTextNode(data.message); // container.appendChild(message); jQuery('div#openai-status').text(data.message); }); notification.on( 'show:success:openai:complete', ( e, data ) => { // todo: can't we make this work with regular Javascript? // let container = document.getElementById('openai-status'); // const message = document.createTextNode(data.message); // container.appendChild(message); jQuery('div#openai-status').text(data.message); });
This puts the div just under the editor similar to the CKEditor demos - from there it can be styled with CSS to look more appealing.
- Status changed to Needs work
over 1 year ago 6:14pm 20 May 2023 - Status changed to Closed: duplicate
over 1 year ago 5:27pm 21 May 2023 - πΊπΈUnited States kevinquillen
cp_dev opened an empty fork which made the branch unusable. Moving to π Update the UI widget to indicate that network activity is happening in CKEditor. Fixed . Please do not open forks if you are not going to commit work.