Successfully reported this slideshow.
We use your LinkedIn profile and activity data to personalize ads and to show you more relevant ads. You can change your ad preferences anytime.

Volto Extensibility Story: Plone Conference 2018

77 views

Published on

How do you extend a Volto instance? How to use Create-Volto-App for create a basic boilerplate package, how to override components, reuse reducers and actions and create a new ones. How to integrate third party components. Demos and walkthroughs. The Pastanaga SVG icon system. How to add new icons.

Published in: Internet
  • Be the first to comment

  • Be the first to like this

Volto Extensibility Story: Plone Conference 2018

  1. 1. Volto ExtensibilityVolto Extensibility StoryStory Plone Conference 2018, TokyoPlone Conference 2018, Tokyo - - Victor Fernandez de Alba @sneridagh Rob Gietema @robgietema
  2. 2. Who are we?Who are we?
  3. 3. TalksTalks Reinventing Plone: Roadmap to the Modern Web Volto Volto Extensibility Story ← you are here Theming Volto Volto Case Studies Volto as Libary (create-volto-app)
  4. 4. What will we cover?What will we cover?
  5. 5. Bootstrapping a ProjectBootstrapping a Project $ yarn global add @plone/create-volto-app
  6. 6. Bootstrapping a ProjectBootstrapping a Project $ create-volto-app my-volto-app
  7. 7. Running the ProjectRunning the Project $ cd my-volto-app $ yarn start
  8. 8. Static ResourcesStatic Resources $ ls public favicon.ico robots.txt
  9. 9. Override ComponentsOverride Components customizations └─ components └─ theme └─ Logo └─ Logo.svg
  10. 10. InternationalizationInternationalization react-intl
  11. 11. Extracting i18n StringsExtracting i18n Strings $ yarn i18n Extracting messages from source files... Synchronizing messages to pot file... Synchronizing messages to po files... Generating the json files... done!
  12. 12. Making Text TranslatableMaking Text Translatable import { FormattedMessage } from 'react-intl'; <FormattedMessage id="Some string" defaultMessage="Some string" />
  13. 13. Translate AttributesTranslate Attributes import { defineMessages, injectIntl, intlShape } from 'react-intl'; const messages = defineMessages({ site: { id: 'Site', defaultMessage: 'Site', }, });
  14. 14. Translate AttributesTranslate Attributes Pure Functions export default injectIntl(Logo); Classes @injectIntl class Logo extends Component { }
  15. 15. Translate AttributesTranslate Attributes Proptype intl: intlShape.isRequired,
  16. 16. Translate AttributesTranslate Attributes <Link to="/" title={intl.formatMessage(messages.site)}>
  17. 17. Override ViewsOverride Views customizations └─ components └─ theme └─ View └─ SummaryView.jsx
  18. 18. Custom ViewsCustom Views components └─ FullView └─ FullView.jsx
  19. 19. Custom ViewsCustom Views /** * Full view component. * @module components/theme/View/FullView */ import React from 'react'; import PropTypes from 'prop-types'; import Helmet from 'react-helmet'; import { Link } from 'react-router-dom'; import { Container, Image } from 'semantic-ui-react'; import { FormattedMessage } from 'react-intl'; /** * Full view component class. * @function FullView * @param {Object} content Content object. i
  20. 20. Custom ViewsCustom Views components/index.js import FullView from './FullView/FullView'; export { FullView };
  21. 21. Custom ViewsCustom Views config.js import { FullView } from './components'; export const views = { ...defaultViews, layoutViews: { ...defaultViews.layoutViews, full_view: FullView, }, };
  22. 22. Custom WidgetsCustom Widgets components └─ RatingWidget └─ RatingWidget.jsx
  23. 23. Custom WidgetsCustom Widgets components/RatingWidget/RatingWidget.jsx /** * RatingWidget component. * @module components/manage/Widgets/RatingWidget */ import React from 'react'; import PropTypes from 'prop-types'; import { Form, Grid, Icon, Label, Rating } from 'semantic-ui-react'; import { map } from 'lodash'; import { defineMessages, injectIntl, intlShape } from 'react-intl'; const messages = defineMessages({ default: { id: 'Default', defaultMessage: 'Default', }, i i
  24. 24. Custom WidgetsCustom Widgets components/index.js import RatingWidget from './RatingWidget/RatingWidget'; export { RatingWidget };
  25. 25. Custom WidgetsCustom Widgets config.js import { RatingWidget } from './components'; export const widgets = { ...defaultWidgets, id: { ...defaultWidgets.id, rating: RatingWidget, }, };
  26. 26. Pastanaga Icon SystemPastanaga Icon System Injects SVG icons in the markup import myCustomSVG from '~/icons/my-svg.svg'; import { Icon } from '@plone/volto/components'; <Icon name={myCustomSVG} />
  27. 27. Usage ExampleUsage Example import myCustomSVG from './my-svg.svg'; <Icon name={myCustomSVG} color="#eee" title="My icon title" size="24px" className="my-custom-icon-css" onClick={this.handleClick} />
  28. 28. Rich Text Editor SettingsRich Text Editor Settings config.js import React from 'react'; import createInlineStyleButton from 'draft-js-buttons/lib/utils/creat import Icon from '@plone/volto/components/theme/Icon/Icon'; import underlineSVG from '@plone/volto/icons/underline.svg'; const UnderlineButton = createInlineStyleButton({ style: 'UNDERLINE', children: , });
  29. 29. Rich Text Editor SettingsRich Text Editor Settings config.js export const settings = { ...defaultSettings, richTextEditorInlineToolbarButtons: [ UnderlineButton, ...defaultSettings.richTextEditorInlineToolbarButtons, ], };
  30. 30. Actions & ReducersActions & Reducers constants/ActionTypes.js export const GET_FAQ = 'GET_FAQ';
  31. 31. Actions & ReducersActions & Reducers actions/faq/faq.js import { GET_FAQ } from '../../constants/ActionTypes'; export function getFaq() { return { type: GET_FAQ, request: { op: 'get', path: `/@search?portal_type=faq`, }, }; }
  32. 32. Actions & ReducersActions & Reducers actions/index.js import { getFaq } from './faq/faq'; export { getFaq };
  33. 33. Actions & ReducersActions & Reducers reducers/faq/faq.js import { GET_FAQ } from '../../constants/ActionTypes'; const initialState = { error: null, items: [], loaded: false, loading: false, }; export default function faq(state = initialState, action = {}) { switch (action.type) { case `${GET_FAQ}_PENDING`: return { ...state, error: null, loading: true,
  34. 34. Actions & ReducersActions & Reducers reducers/index.js import defaultReducers from '@plone/volto/reducers'; import faq from './faq/faq'; const reducers = { ...defaultReducers, faq, }; export default reducers;
  35. 35. Actions & ReducersActions & Reducers components/FaqView/FaqView.jsx /** * Faq view. * @module components/FaqView/FaqView */ import React, { Component } from 'react'; import PropTypes from 'prop-types'; import { connect } from 'react-redux'; import { bindActionCreators } from 'redux'; import Helmet from 'react-helmet'; import { FormattedMessage } from 'react-intl'; import { Container } from 'semantic-ui-react'; import { getFaq } from '../../actions'; /** i
  36. 36. Join the Sprint!Join the Sprint!
  37. 37. Questions?Questions? Need help implementing Volto? We're available for projects slideshare.net/robgietema

×