Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Porting Gutenberg to SilverStripe

Jake Grimley
September 22, 2018

Porting Gutenberg to SilverStripe

Clients want drag and drop editing. WordPress now has Gutenberg. We ported it over to Silverstripe, it was tougher than we imagined. Maybe it has potential for you.

Jake Grimley

September 22, 2018
Tweet

Other Decks in Programming

Transcript

  1. 1
    Jake Grimley
    Founder, Made Media
    @madehq @jakegrimley
    Porting Gutenberg to
    Silverstripe

    View Slide

  2. 2
    • Founded 2002
    • Headcount 30
    • Specialist in e-commerce sites for large cultural institutions
    • Offices Birmingham, London, New York
    • Using SilverStripe since 2012
    • Professional Partner since 2017
    • Niche clients, niche competition
    Made Media

    View Slide

  3. 3
    • Expertise
    • Track Record
    • Creativity
    • Capacity & Compliance
    • CMS
    It started with a pitch

    View Slide

  4. 4
    CMS Enterprisy Well Structured Open Source Wildly Popular
    EpiServer* ✔ ✔
    Drupal ✔ ✔
    SilverStripe ✔ ✔ ✔
    WordPress ✔ ✔
    CMS Positioning

    View Slide

  5. 5
    “WordPress powers 

    27% of the Internet”

    View Slide

  6. 6
    CMS Requirements 2.0
    Before IT Focused Now User Focused
    .Net Flexible
    Permissions/Control Drag And Drop
    Workflows No Rigid Templates
    APIs Personalisation
    Enforce Structure Anti-Structure

    View Slide

  7. 7
    CMS positioning works
    for us, but no longer
    works for the client.

    View Slide

  8. 8
    What’s
    Gutenberg?

    View Slide

  9. 9
    •WordPress Plug-in
    •New WYSIWYG Editor
    •Drag and drop blocks
    •A bit like SquareSpace and Wix
    •Replaces TinyMCE in WP5.0
    •Will take over 80% of the WordPress UI

    View Slide

  10. 10

    View Slide

  11. 11
    •Inevitable transition
    •Direct manipulation always wins

    View Slide

  12. 12
    WP Controversy:
    •Breaks themes
    •Breaks old content
    •Gets in the way of ‘Bloggers’
    •Paradigm Shift for WP

    View Slide

  13. 13
    Why are we
    interested?

    View Slide

  14. 14
    •Made hates traditional WYSIWYG Editors
    •Running out of steam with Markdown
    •Neutralise head-to-head CMS demos
    •Moving toward block paradigm anyway
    •Envisaged hooking in personalisation
    •Looked like an upgrade on Sir Trevor

    View Slide

  15. 15

    View Slide

  16. 16
    How Does
    Gutenberg Work?

    View Slide

  17. 17
    React

    View Slide

  18. 18
    Define Blocks

    View Slide

  19. 19
    const schema = {
    content: {
    type: 'array',
    source: 'children',
    selector: 'p',
    default: [],
    },
    align: {
    type: 'string',
    },
    dropCap: {
    type: 'boolean',
    default: false,
    },
    placeholder: {
    type: 'string',
    },
    width: {
    type: 'string',
    },
    textColor: {
    type: 'string',
    },
    };
    class ParagraphBlock extends paragraph.settings.edit {
    constructor() {
    super( ...arguments );
    }
    return [
    textAlignmentEnabled && isSelected && (

    value={ align }
    onChange={ ( nextAlign ) => {
    setAttributes( { align: nextAlign } );
    } }
    />

    ),
    inspectorEnabled && isSelected && (

    { textSettingsEnabled && (

    { dropCapEnabled && (
    label={ __( 'Drop Cap' ) }
    checked={ !! dropCap }
    onChange={ this.toggleDropCap }
    />
    )}

    )}
    return className={ className ? className : undefined
    }>{ content };
    Define Schema Inspector View
    Saved HTML

    blockAutocompleter( { onReplace } ),
    userAutocompleter(),
    ] }>
    { ( { isExpanded, listBoxId, activeId } ) => (
    tagName="p"
    className={ classnames( 'wp-block-paragraph', {
    'has-background': backgroundColor,
    'has-drop-cap': dropCap,
    } ) }
    style={ {
    backgroundColor: backgroundColor,
    color: textColor,
    fontSize: fontSize ? fontSize + 'px' : undefined,
    textAlign: align,
    } }
    value={ content }
    onChange={ ( nextContent ) => {
    setAttributes( {
    content: nextContent,
    } );
    } }
    />
    Editor View

    View Slide

  20. 20
    How did we port
    to SilverStripe?

    View Slide

  21. 21
    SilverStripe 4 

    React already there

    View Slide

  22. 22

    View Slide

  23. 23

    View Slide

  24. 24
    Start looking at more
    complex, Silverstripe-
    integrated blocks

    View Slide

  25. View Slide

  26. Integrated block
    Editor View
    HTML
    (SilverStripe Field)
    Save HTML
    Parser
    Template
    Related Objects/
    Modules
    Gutenberg / React - Edit View Silverstripe / PHP - Published View
    HTML
    render
    function
    render
    function
    edit
    content

    View Slide

  27. Image Block
    import { __ } from '@wordpress/i18n';
    import { withInstanceId, withState, PanelBody, BaseControl } from '@wordpress/components';
    import { InspectorControls, BlockAlignmentToolbar } from '@wordpress/blocks';
    import { ImageControl } from '../../components';
    import { map, mapValues, extend, isEmpty } from 'lodash';
    const cloudinaryImage = window.cloudinaryImage;
    import './style.scss';
    export const name = 'madehq/image';
    export const settings = {
    title: __( 'Image 2' ),
    description: __( 'This will allow you to pull an image or gallery into content' ),
    icon: 'format-image',
    category: 'common',
    keywords: [ __( 'text' ) ],
    edit({ attributes, setAttributes, isSelected }) {
    const { images, captions, credits } = attributes;
    const updateImages = value => {
    let newImages = mapValues(value, (item, key) => {
    let image = images[key];
    if (!image) {
    return item;
    }

    View Slide

  28. Sidebar Component for Images
    import ReactDOM from 'react-dom';
    import { Component } from '@wordpress/element';
    import { withInstanceId } from '@wordpress/components';
    import {
    forEach,
    keys,
    has,
    map,
    isEmpty,
    omit,
    isArray,
    isObject,
    mapValues,
    values,
    } from 'lodash';
    const cloudinaryImage = window.cloudinaryImage;
    import './style.scss';
    const fileDataCache = {};
    const loadFileData = fileId => {
    if ( fileId in fileDataCache ) {
    return fileDataCache[fileId];
    }
    fileDataCache[fileId] = fetch(`/gutenberg-api/filedata/${fileId}`, { credentials: 'same-origin' })
    .then(response => response.json())
    .then(fileData => {
    return fileData;
    });

    View Slide

  29. View Slide

  30. View Slide

  31. 31
    •WebPack to create alias to image picker, and point
    directly at React component
    •Output field in format Silverstripe expects and
    trigger entwine
    •Mutation observer to see changes in image selector
    - onChange events didn’t work.
    Bridging Javascript UIs

    View Slide

  32. Integrated block
    Editor View
    HTML
    (SilverStripe Field)
    Save HTML
    Parser
    Template
    Related Objects/
    Modules
    Gutenberg / React - Edit View Silverstripe / PHP - Published View
    HTML
    render
    function
    render
    function
    edit
    content

    View Slide

  33. 33
    BatShit Crazy

    View Slide

  34. This would be cleaner…
    JSON Content
    (SilverStripe Field)
    JSON_decode Related Objects/
    Modules
    Gutenberg / React - Edit View Silverstripe / PHP - Published View
    HTML
    render
    function
    Save
    Change
    Edit
    Content

    View Slide

  35. 35
    Gutenberg doesn’t
    store content as JSON

    View Slide

  36. 36
    HTML Rendering of a
    complex widget not
    necessarily identical in edit
    and view mode.

    View Slide

  37. 37
    Never mind the batshit
    here’s the demo

    View Slide

  38. Version 1 Made Media Ltd.
    Prepared by Jake Grimley 97 Icknield Street
    June 21, 2018 Birmingham, B186RU
    mademedia.co.uk
    [email protected]
    © 2018 Made Media Inc. 0121 200 2627

    View Slide

  39. 39
    •Mission Accomplished
    •If there’s any technical debt; future
    made will deal with it

    View Slide

  40. 40
    Where are we
    going with it?

    View Slide

  41. 41
    •Refinement
    •Stability
    •Personalisation

    View Slide

  42. 42
    How does this 

    compete with the 

    ContentBlocks Module?

    View Slide

  43. 43
    • Blocks are the future
    • ContentBlocks Module has much better structure
    • Gutenberg feels more immediate and interactive
    • Maybe we can hook the Gutenberg front-end up
    to the ContentBlocks data objects…
    • It’s the start of a journey..

    View Slide

  44. 44
    Want to get
    involved?

    View Slide

  45. https://github.com/MadeHQ/silverstripe-gutenberg-editor

    View Slide

  46. Thank you!
    46
    @madehq @jakegrimley

    View Slide