Expose reusable client-side code to build Draftail extensions (#4467)

* Expose Draftail package as global variable for reuse
* Expose Wagtail React components for reuse
* Expose Draftail-related React components for reuse
This commit is contained in:
Thibaud Colas 2018-04-18 00:27:07 +03:00 committed by GitHub
parent 574e7ff3fa
commit c309753378
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
13 changed files with 67 additions and 13 deletions

View file

@ -23,6 +23,7 @@ Changelog
* Added error handling to the Draftail editor (Thibaud Colas)
* Add new `wagtail_icon` template tag to facilitate making admin icons accessible (Sander Tuit)
* Set `ALLOWED_HOSTS` in the project template to allow any host in development (Tom Dyson)
* Expose reusable client-side code to build Draftail extensions (Thibaud Colas)
* Fix: Status button on 'edit page' now links to the correct URL when live and draft slug differ (LB (Ben Johnston))
* Fix: Image title text in the gallery and in the chooser now wraps for long filenames (LB (Ben Johnston), Luiz Boaretto)
* Fix: Move image editor action buttons to the bottom of the form on mobile (Julian Gallo)

View file

@ -11,8 +11,9 @@ export { default as Document } from './decorators/Document';
export { default as ImageBlock } from './blocks/ImageBlock';
export { default as EmbedBlock } from './blocks/EmbedBlock';
export { default as ModalWorkflowSource } from './sources/ModalWorkflowSource';
import ModalWorkflowSource from './sources/ModalWorkflowSource';
import Tooltip from './Tooltip/Tooltip';
import TooltipEntity from './decorators/TooltipEntity';
import EditorFallback from './EditorFallback/EditorFallback';
// 1024x1024 SVG path rendering of the "↵" character, that renders badly in MS Edge.
@ -122,4 +123,8 @@ const initEditor = (selector, options, currentScript) => {
export default {
initEditor,
registerPlugin,
// Components exposed for third-party reuse.
ModalWorkflowSource,
Tooltip,
TooltipEntity,
};

View file

@ -1,6 +1,5 @@
import draftail, {
wrapWagtailIcon,
ModalWorkflowSource,
Link,
Document,
ImageBlock,
@ -133,9 +132,12 @@ describe('Draftail', () => {
});
});
it('#ModalWorkflowSource', () => expect(ModalWorkflowSource).toBeDefined());
it('#Link', () => expect(Link).toBeDefined());
it('#Document', () => expect(Document).toBeDefined());
it('#ImageBlock', () => expect(ImageBlock).toBeDefined());
it('#EmbedBlock', () => expect(EmbedBlock).toBeDefined());
it('#ModalWorkflowSource', () => expect(draftail.ModalWorkflowSource).toBeDefined());
it('#Tooltip', () => expect(draftail.Tooltip).toBeDefined());
it('#TooltipEntity', () => expect(draftail.TooltipEntity).toBeDefined());
});

View file

@ -7,6 +7,7 @@ import Button from './components/Button/Button';
import Icon from './components/Icon/Icon';
import PublicationStatus from './components/PublicationStatus/PublicationStatus';
import LoadingSpinner from './components/LoadingSpinner/LoadingSpinner';
import Portal from './components/Portal/Portal';
import Transition from './components/Transition/Transition';
import Explorer, {
ExplorerToggle,
@ -18,6 +19,7 @@ export {
Icon,
PublicationStatus,
LoadingSpinner,
Portal,
Transition,
Explorer,
ExplorerToggle,

View file

@ -3,6 +3,7 @@ import {
Icon,
PublicationStatus,
LoadingSpinner,
Portal,
Transition,
Explorer,
ExplorerToggle,
@ -26,6 +27,10 @@ describe('wagtail package API', () => {
expect(LoadingSpinner).toBeDefined();
});
it('has Portal', () => {
expect(Portal).toBeDefined();
});
it('has Transition', () => {
expect(Transition).toBeDefined();
});

View file

@ -46,6 +46,8 @@ global.wagtailConfig = {
global.wagtailVersion = '1.6a1';
global.wagtail = {};
global.chooserUrls = {
documentChooser: '/admin/documents/chooser/',
emailLinkChooser: '/admin/choose-email-link/',

View file

@ -188,5 +188,25 @@ To make this easier, Wagtail exposes its React-related dependencies as global va
window.ReactDOM;
// 'react-transition-group/CSSTransitionGroup'
window.CSSTransitionGroup;
Wagtail also exposes some of its own React components. You can reuse:
.. code-block:: javascript
window.wagtail.components.Icon;
window.wagtail.components.Portal;
Pages containing rich text editors also have access to:
.. code-block:: javascript
// 'draft-js'
window.DraftJS;
// 'draftail'
window.Draftail;
// Wagtails Draftail-related APIs and components.
window.draftail;
window.draftail.ModalWorkflowSource;
window.draftail.Tooltip;
window.draftail.TooltipEntity;

View file

@ -141,7 +141,7 @@ Here are the main requirements to create a new entity feature:
* Like for inline styles and blocks, set up the to/from DB conversion.
* The conversion usually is more involved, since entities contain data that needs to be serialised to HTML.
To write the React components, Wagtail exposes its own React and Draft.js dependencies as global variables. Read more about this in :ref:`extending_clientside_components`.
To write the React components, Wagtail exposes its own React, Draft.js and Draftail dependencies as global variables. Read more about this in :ref:`extending_clientside_components`.
To go further, please look at the `Draftail documentation <https://github.com/springload/draftail#formatting-options>`_ as well as the `Draft.js exporter documentation <https://github.com/springload/draftjs_exporter>`_.
Here is a detailed example to showcase how those tools are used in the context of Wagtail.

View file

@ -42,6 +42,7 @@ Other features
* Added error handling to the Draftail editor (Thibaud Colas)
* Add new `wagtail_icon` template tag to facilitate making admin icons accessible (Sander Tuit)
* Set `ALLOWED_HOSTS` in the project template to allow any host in development (Tom Dyson)
* Expose reusable client-side code to build Draftail extensions (Thibaud Colas)
Bug fixes
~~~~~~~~~

View file

@ -1,5 +1,5 @@
import * as Draftail from 'draftail';
import draftail, {
ModalWorkflowSource,
Link,
Document,
ImageBlock,
@ -10,6 +10,8 @@ import draftail, {
* Entry point loaded when the Draftail editor is in use.
*/
// Expose Draftail package as a global.
window.Draftail = Draftail;
// Expose module as a global.
window.draftail = draftail;
@ -17,22 +19,22 @@ window.draftail = draftail;
const plugins = [
{
type: 'DOCUMENT',
source: ModalWorkflowSource,
source: draftail.ModalWorkflowSource,
decorator: Document,
},
{
type: 'LINK',
source: ModalWorkflowSource,
source: draftail.ModalWorkflowSource,
decorator: Link,
},
{
type: 'IMAGE',
source: ModalWorkflowSource,
source: draftail.ModalWorkflowSource,
block: ImageBlock,
},
{
type: 'EMBED',
source: ModalWorkflowSource,
source: draftail.ModalWorkflowSource,
block: EmbedBlock,
},
];

View file

@ -1,10 +1,14 @@
require('./draftail.entry');
describe('draftail.entry', () => {
it('exposes global', () => {
it('exposes module as global', () => {
expect(window.draftail).toBeDefined();
});
it('exposes package as global', () => {
expect(window.Draftail).toBeDefined();
});
it('has defaults registered', () => {
expect(Object.keys(window.draftail.registerPlugin({}))).toEqual(["DOCUMENT", "LINK", "IMAGE", "EMBED", "undefined"]);
});

View file

@ -1,7 +1,13 @@
import { initExplorer } from 'wagtail-client';
import { initExplorer, Icon, Portal } from 'wagtail-client';
// Expose components as globals for third-party reuse.
window.wagtail.components = {
Icon,
Portal,
};
/**
* Admin JS entry point. Add in here code to run once the page is loaded.
* Add in here code to run once the page is loaded.
*/
document.addEventListener('DOMContentLoaded', () => {
const explorerNode = document.querySelector('[data-explorer-menu]');

View file

@ -8,6 +8,10 @@ require('./wagtailadmin.entry');
describe('wagtailadmin.entry', () => {
const [event, listener] = document.addEventListener.mock.calls[0];
it('exposes components for reuse', () => {
expect(Object.keys(window.wagtail.components)).toEqual(['Icon', 'Portal']);
});
it('DOMContentLoaded', () => {
expect(event).toBe('DOMContentLoaded');
});