Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

SPLAT-1442 ckeditor5 plugin #107

Open
wants to merge 31 commits into
base: 3.0
Choose a base branch
from
Open

Conversation

amalija-ramljak
Copy link
Member

@amalija-ramljak amalija-ramljak commented Apr 26, 2024

N.B. documentation/installation instructions have not been written yet

Changes

JS plugin

  • code is versioned alongside the Vue production build, but is not built itself
    • why?: cke5 cannot register pre-built plugins into an editor, the files are built at the same time as the editor itself due to a lot of dependency on singletons. Building independently creates several of the same singleton classes
    • sklepex was a sort of issue with their pre-built editor, and will be addressed in their PR. tl;dr I dug through the classes and exported what the plugin needs
    • ibexa is a non-issue because their editor has to be built with webpack anyway, which is pretty much the only way to make it configurable (yarn ibexa)
  • exports
    • plugin class for the editor
    • function to render the ngrm fields contained in the cke5 output to front (it's cast and saved to database, and rendered as-is, so this was necessary for proper templating)
    • plugin key for config - not super necessary, but does not hurt since we already have more than 1 export
  • plugin flow
    • in the editor, it embeds the entire Vue application as is, but with mode: embed for the extra fields needed
    • when saving, it saves a div with a few data attributes needed for casting back to the editor model
    • when loading back into the editor, there is a delay in showing the selected images due to asynchronous calls being made to fill up Vue's attributes. The editor itself does not allow any form of asynchronous behaviour, so it has to be rendered as empty first
  • plugin configuration
    • endpoints - most of these are functions that take locationId as a parameter, referring to the remote resource location
      • createLocation
      • updateLocation(locationId)
      • deleteLocation(locationId)
      • getSelectedImage(locationId) - retrieve selectedImage data for the Vue app in the editor
      • viewResource(locationId) - render a location on the front web, saved as data param. Additionally receive query params: css_class, variation_group, variation_name, alignment
    • fieldId - to keep Vue instances on the page unique
    • config - Vue config, merged with defaults in the plugin
    • variationGroup - necessary for rendering
  • rendering on the web
    • in cke5's data, the embedded media is saved as a div with some data attributes
    • the front render function provided alongside the plugin uses the viewEndpoint alongside some other attributes to get the rendered field from the backend

Issues to address

  • asynchronous behaviour when loading into the editor - consider a loader/disabled state while waiting?
  • asynchronous behaviour when rendering on front - width/height on div so content doesn't jump around if it's an image? Will it ever be something that's not an image?
  • in general - non-image behaviour?

PHP + config

Configuration

  • added Configuration controller to fetch Vue's config attribute for the editor, is currently done within project code to fetch it only once
  • added bundle configuration for templates with key view_resource - this template is rendered by a controller that is called from JS

Controllers

All of these have been registered under ajax routes

  • aforementioned Configuration controller
  • new RemoteResourceLocation controllers:
    • Create - creates a new location, based on form transformer
    • Delete - deletes a location
    • Update - updates values on a location (if it's not a resource change), also based on form transformer
    • SelectedImage - gets selectedImage data for Vue, logic based on existing templates and twig functions that build the attribute for a full remote media field
  • new RemoteResource controller (might be better under Location?)
    • View - renders configured netgen_remote_media.templates.view_resource template. Default template in bundle is based on some existing rendering template

Services etc.

  • added RemoteResourceService that handles the boilerplate data updating on location and resource objects
  • using that service in the Transformer, can be reverted if needed, but that code was used for extraction and reuse

Vue

  • new selectedImage fields
    • selectedVariation - one of variations
    • cssClass - free text input
  • config option mode for extra fields
    • value embed is used to render additional fields that fill in new selectedImage fields
  • ngrm-change event detail has additional info
    • changedField property that tells the listener what input caused the event to fire
      • value modal is used for changes triggered by something in a modal
      • other values are input name attributes
      • why?: the editor rerenders on every value change and this is mostly used to refocus a text field after ngrm-change is fired

Webpack

  • moved the file copying thing into a webpack plugin
  • added watch script in package.json (plugin is run every time, copying the new built files on every rebuilt change)

Still needed changes/actions

  • check for actual uniqueness of the field id when loaded into the editor (currently using command value, can likely cause issues) - done
  • make endpoints config partially configurable (fallback to default) similarly to Vue config - done
  • recheck config merge - done

Usage

Using the plugin requires certain node modules to be available so it can be built. This is easily possible when building the editor alongside other project assets because all of those should already be included as dependencies, but if using a pre-built editor (sklepex, might be updated to building the editor with webpack instead of this though), the necessary classes should be exported from the source file and needed aliases set in the webpack config.

  • webpack
    • aliasing @ckeditor paths to where the exports can be found if they are not already in the project's JS dependencies
  • plugin registration
    • ibexa - has own rules of registering, might be possible to add the config to the remote-media-ibexa bundle
    • other - find specific framework rules if they already have ckeditor included, like how ibexa has its own
    • or have a file where the editor is initialised, import plugin class from bundle assets and add it to plugins, following ckeditor's documentation
  • rendering on the web
    • import the render file in a JS file that will be included on pages with ckeditor5 output, will likely need a build system

Testing

Currently testable on a Sylius project. Can be tested on sklepex where it's configured already for that project - https://bitbucket.org/forlagshuset/sklepex/pull-requests/819

Manual testing requires adding the plugin to the Ckeditor upon initialisation in the project and following the Usage section above, and various configuration information given

Issues

Does not currently work with ibexa - needs some xslt file preparation for ibexa's rich text handling

@amalija-ramljak amalija-ramljak marked this pull request as draft April 26, 2024 10:19
@amalija-ramljak amalija-ramljak marked this pull request as ready for review May 17, 2024 12:34
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

1 participant