Skip to main content
Ctrl+K
Logo image

Plone Training 2023

Trainings

  • Mastering Plone 6 development
    • 1. About Mastering Plone development
    • 2. Introduction
    • 3. The Case Study
    • 4. What is Plone?
    • 5. Installation
    • 6. The Features of Plone
    • 7. Configuring and Customizing Plone "Through The Web"
    • 8. Extending Plone with add-on packages
    • 9. Extending Plone
    • 10. Content types I
    • 11. Content types II: Talk
    • 12. Content types: Reference
    • 13. Customizing Volto Components
    • 14. Volto View Component: A Default View for a "Talk"
    • 15. Develop
    • 16. Behaviors
    • 17. Creating a dynamic frontpage with Volto blocks
    • 18. Programming Plone
    • 19. Turning Talks into Events
    • 20. Vocabularies, Registry-Settings and Control Panels
    • 21. Custom Search
    • 22. Testing in Plone
    • 23. Using Third-Party Behaviors
    • 24. Content types III: Sponsors
    • 25. Upgrade-steps
    • 26. The Sponsors Component
    • 27. Using Volto add-ons
    • 28. Extending Volto with a custom add-on package
    • 29. Extending Volto With a FAQ Block Type
    • 30. Workflow, Roles and Permissions
    • 31. Relations
    • 32. Roundtrip [The voting story] frontend, backend, and REST
      • 32.1. Complex Behaviors [voting story]
      • 32.2. REST API endpoints [voting story]
      • 32.3. Volto Actions and Component State [voting story]
      • 32.4. Permissions [voting story]
    • 33. Releasing your code
    • 34. The code for the training
    • 35. Trainer: Preparation
  • Mastering Plone 5 development
    • 1. About Mastering Plone
    • 2. Introduction
    • 3. What is Plone?
    • 4. Installation & Setup
    • 5. The Case Study
    • 6. The Features of Plone
    • 7. The Anatomy of Plone
    • 8. What's New in Plone 5, 5.1 and Plone 5.2
    • 9. Configuring and Customizing Plone "Through The Web"
    • 10. Theming
    • 11. Extending Plone
    • 12. Extend Plone With Add-On Packages
    • 13. Dexterity I: "Through The Web"
    • 14. Buildout I
    • 15. Write Your Own Add-Ons to Customize Plone
    • 16. Return to Dexterity: Moving contenttypes into Code
    • 17. Views I
    • 18. Page Templates
    • 19. Customizing Existing Templates
    • 20. Views II: A Default View for "Talk"
    • 21. Views III: A Talk List
    • 22. Testing in Plone
    • 23. Behaviors
    • 24. Writing Viewlets
    • 25. Programming Plone
    • 26. IDEs and Editors
    • 27. Dexterity Types II: Growing Up
    • 28. Custom Search
    • 29. Turning Talks into Events
    • 30. User Generated Content
    • 31. Resources
    • 32. Using Third-Party Behaviors
    • 33. Dexterity Types III: Python
    • 34. Dexterity: Reference
    • 35. Relations
    • 36. Manage Settings with Registry, Control Panels and Vocabularies
    • 37. Creating a Dynamic Front Page
    • 38. Creating Reusable Packages
    • 39. More Complex Behaviors
    • 40. A Viewlet for the Votable Behavior
    • 41. Making Our Package Reusable
    • 42. Using starzel.votable_behavior in ploneconf.site
    • 43. Releasing Your Code
    • 44. Buildout II: Getting Ready for Deployment
    • 45. Plone REST API
    • 46. The Future of Plone
    • 47. Optional
    • 48. Using the code for the training
  • Volto Hands-On
    • 1. Introduction
    • 2. Quick Start
    • 3. Project requirements
    • 4. Theming
    • 5. Header
    • 6. Breadcrumbs
    • 7. Footer
    • 8. Edit config and site cleanup
    • 9. Brief introduction to Volto blocks
    • 10. Blocks - Highlight Block
    • 11. Configurable Downloadlink Block
    • 12. Events listing template
    • 13. Sprint content type
  • Volto Add-ons Development
    • 1. Introduction
    • 2. Volto add-ons development
    • 3. Basic working block
    • 4. Improve the block view
    • 5. Block editing with a form
    • 6. Customizable columns
    • 7. Make the block extensible
    • 8. Add-ons - advanced topics
    • 9. Plone integration with Volto blocks
    • 10. About
    • 11. Developer integration with text editors
    • 12. Really short primer on Javascript enhancements
  • Effective Volto
    • About Effective Volto
    • Getting Started
      • 1. Bootstrapping a full Plone 6 project
      • 2. Bootstrapping an Add-on
      • 3. Developer roadmap
    • Architecture
      • 1. Volto Client - Server duality
      • 2. Razzle
      • 3. Webpack
      • 4. Babel
      • 5. Webpack loaders
      • 6. Bootstrap Volto
      • 7. Inside Volto
      • 8. Volto Blocks
      • 9. Configuration Registry
      • 10. Redux
      • 11. CORS
      • 12. Multilingual
    • Backend
      • 1. Plone REST API endpoints
      • 2. Writing an endpoint
      • 3. Writing a serializer or a deserializer
      • 4. Writing a content expansion endpoint
      • 5. Writing a block transform
      • 6. Block field contribute to searchableText
      • 7. Link integrity for blocks
      • 8. Writing Express middleware
    • Add-ons
      • 1. What is a Volto add-on
      • 2. Bootstrap an add-on
      • 3. How does a Volto add-on works?
      • 4. Configure a released Volto Add-on in your project
      • 5. Configure an unreleased add-on from an existing repository
      • 6. Volto views
      • 7. Create a block using BlockDataForm
      • 8. Blocks Layout
      • 9. Block Extensions
      • 10. Block Styling
      • 11. Add-on dependencies
      • 12. Add-on and project configuration pipeline
      • 13. Create a theme add-on
      • 14. Extending Semantic UI
      • 15. Create a custom Listing block variation
      • 16. Integrate with Volto’s asyncConnect for SSR
      • 17. Add-on Internationalization
      • 18. Extend Webpack setup from an add-on with razzle.extend.js
    • Testing
      • 1. Acceptance testing
      • 2. Jest
      • 3. Unit testing
      • 4. Storybook
      • 5. Testing add-ons
    • Deployment
      • 1. Seamless mode
      • 3. Simple deployment
      • 4. Docker
      • 5. release-it
    • Development tools
      • 1. How to setup your development environment using environment variables
      • 2. Environment variables
      • 3. Icons
      • 4. Husky and lint-staged
      • 5. Shortcuts
      • 6. Internationalization
      • 7. Lazyloading components, injectLazyLibs for libraries
      • 8. critical.css
      • 9. Bundle analyzing
      • 10. Component Registry
      • 11. Linters
      • 12. Debugging with Volto
      • 13. VSCode extensions/helpers
      • 14. vim and neovim integration
  • Testing Plone
    • Summary
    • Intro to tests
    • Some theory
    • How to test a Plone add-on
    • Testing setup
    • Unit tests
    • Testing a Dexterity content type
    • Testing a view
    • Acceptance testing
    • Robot tests
    • Continuous Integration
  • Plone 6 Classic UI Theming
    • 1. Preparation for the theming training
    • 2. TTW Customizations
    • 3. Create a theme based on Barceloneta
    • 4. Create a Theme from scratch
    • 5. Create a theme based on Diazo
  • Plone Deployment
    • Introduction
    • Training setup
    • Introduction to Plone stack
    • Plone Docker Images
    • Create a Project
    • Editing your project
    • Server Setup
    • Deploy
  • Plone Workflow
    • Introduction To Workflows
    • Basic Roles and Permissions
    • Local Roles
    • Dynamic Roles
    • Placeful Workflow
    • Multi-chain Workflows
    • Workflow Variables
    • Using GenericSetup to Manage Plone Workflows
  • Migration best practices
    • Migrating Plone
    • In-place migrations
    • Migrating with collective.exportimport
    • Migrate to Volto
    • Migrating from third party systems to Plone

Info

  • Glossary
  • Contributing to Plone Training
    • Building and Checking the Quality of Documentation
    • General Guide to Writing Documentation
    • Authors Guide
  • Teaching
    • 1. Training theory: education, how people learn and process information
    • 2. Before the training: Create material, invite trainees, preparation
    • 3. During training day(s): what to expect, do's and don'ts
    • 4. After the training: Aftercare, keep in touch, learn, improve
11. Configurable Downloadlink Block – Volto Hands-On
  • Repository
  • Suggest edit
  • Open issue
  • .md

Configurable Downloadlink Block

Contents

  • 11.1. Initital Block setups
  • 11.2. Create the schema for your Block
  • 11.3. Implement schema in sidebar
  • 11.4. Create the View

11. Configurable Downloadlink Block#

The next section (skipping the simple text) on plone.org is the Banner with Download Button for Plone. We will use this to learn how to create a Block that is configurable by an editor.

11.1. Initital Block setups#

The initial setup for this Block is the same as for the highlight Block. Create a new folder in src/components/Blocks called download and in there View.jsx as well as Edit.jsx. For now give them the same initial content as we did with the highlight:

import React from 'react';

const View = (props) => {
  return <div>I'm the Highlight view component!</div>;
};

export default View;

And for Edit.jsx correspondingly. Export the blocks via the index.js and register the block in config.js and add it to the page. You can use the same SVG as for the highlight but you can also pick something of you choice from https://pastanaga.io/icons/. All the icons there are available in Volto by default.

11.2. Create the schema for your Block#

First you have to identify what fields the Block needs an editor to be able to edit and of what type. In our case those will be the following:

  • title: The field that contains "Get the latest Plone" in the original

  • description/subtitle: The text underneath the title

  • buttontext: text displayed on the red button

  • buttonlink: where the button should link to

  • other link text: The text underneath the button

  • other link: where the other text (Older releases) will link to

To define these fields we will create a schema inside the new file schema.js within the download folder. Then paste the following into schema.js:

export const schemaDownload = (props) => {
  return {
    required: [],
    fieldsets: [
      {
        id: 'default',
        title: 'Default',
        fields: ['title', 'description'],
      },
      {
        id: 'link',
        title: 'Links',
        fields: ['buttonTitle', 'buttonLink', 'otherLinkText', 'otherLink'],
      },
    ],
    properties: {
      title: {
        title: 'Title',
        widget: 'text',
      },
      description: {
        title: 'Description',
        widget: 'text',
      },
      buttonTitle: {
        title: 'Button Title',
        widget: 'text',
      },
      buttonLink: {
        title: 'Button link',
        widget: 'object_browser',
        mode: 'link',
        allowExternals: true,
      },
      otherLinkText: {
        title: 'Other link text',
        widget: 'text',
      },
      otherLink: {
        title: 'Other link',
        widget: 'object_browser',
        mode: 'link',
        allowExternals: true,
      },
    },
  };
};

export default schemaDownload;

The properties key will contain all the fields, while the fieldsets key assignes the fields to different fieldsets. In the required array you can define certain fields as required. If you have already experience in working with classic Plone, you will notice, that this is very similar to how you would create content types there.

11.3. Implement schema in sidebar#

To implement the schema in the sidebar of your block you will have to create another component called Data.jsx in which the schema will be transformed to proper react inputs. Paste the following into the Data.js block:

import React from 'react';
import { BlockDataForm } from '@plone/volto/components';
import Schema from './schema';

const DownloadData = (props) => {
  const { data, block, onChangeBlock } = props;
  const schema = Schema({ ...props });
  return (
    <BlockDataForm
      schema={schema}
      title={schema.title}
      onChangeField={(id, value) => {
        onChangeBlock(block, {
          ...data,
          [id]: value,
        });
      }}
      formData={data}
      block={block}
    />
  );
};

export default DownloadData;

The BlockDataForm component will transform the schema.js data into a usable sidebar. Last but not least you need to amend Edit.jsx to use that sidebar:

import React from 'react';
import { SidebarPortal } from '@plone/volto/components';
import { withBlockExtensions } from '@plone/volto/helpers';
import DownloadData from './Data';
import View from './View';

const downloadLinkEdit = (props) => {
  const { data, onChangeBlock, block, selected } = props;
  return (
    <>
      <View {...props} />
      <SidebarPortal selected={selected}>
        <DownloadData
          key={block}
          {...props}
          data={data}
          block={block}
          onChangeBlock={onChangeBlock}
        />
      </SidebarPortal>
    </>
  );
};

export default withBlockExtensions(downloadLinkEdit);

11.4. Create the View#

You are now able to edit the content of your Block, but will still see your default "This is the View" text. To change that amend View.jsx as follows:

import React from 'react';
import { Grid, Container } from 'semantic-ui-react';
import { UniversalLink } from '@plone/volto/components';

const downloadLinkView = (props) => {
  const { data } = props;
  return (
    <div className="block download">
      <Container>
        <Grid columns={2}>
          <Grid.Column>
            <h2>{data.title}</h2>
            <p className="description">{data.description}</p>
          </Grid.Column>
          <Grid.Column>
            {data.buttonLink?.length > 0 && data.buttonTitle && (
              <UniversalLink
                href={data.buttonLink[0]['@id']}
                className="ui button"
              >
                {data.buttonTitle}
              </UniversalLink>
            )}
            <br />
            {data.otherLink?.length > 0 && data.otherLinkText && (
              <UniversalLink
                href={data.otherLink[0]['@id']}
                className="other-link"
              >
                {data.otherLinkText}
              </UniversalLink>
            )}
          </Grid.Column>
        </Grid>
      </Container>
    </div>
  );
};

export default downloadLinkView;

Note that all the fields defined in the schema and filled via the sidebar can now be accessed from the data key of the blocks props. You can use console.log(data) to see the details.

To make the block look somewhat like its example we only need to add the following CSS to our custom.overrides:

// Download block

.block.download {
  background: #e8eef2;
  .ui.container {
    padding: 40px 200px;
  }

  h2 {
    font-size: 30px;
    font-weight: bold;
  }
  .description {
    font-size: 21px;
  }

  a.ui.button {
    background: #cc2b00;
    font-size: 18px;
    color: @white;
    border-radius: 6px;
    padding: 14px 20px;
    font-weight: normal;
    margin-bottom: 10px;
  }
  a.other-link {
    color: #175758;
    font-weight: bold;
  }
}

When done the block should look very much like on plone.org.

previous

10. Blocks - Highlight Block

next

12. Events listing template

Contents
  • 11.1. Initital Block setups
  • 11.2. Create the schema for your Block
  • 11.3. Implement schema in sidebar
  • 11.4. Create the View

By Plone Community

© Copyright The text and illustrations in this website are licensed by the Plone Foundation under a Creative Commons Attribution 4.0 International license.